1 package antlr;
2
3 * <b>SOFTWARE RIGHTS</b>
5 * <p>
6 * ANTLR 2.5.0 MageLang Institute, 1998
7 * <p>
8 * We reserve no legal rights to the ANTLR--it is fully in the
9 * public domain. An individual or company may do whatever
10 * they wish with source code distributed with ANTLR or the
11 * code generated by ANTLR, including the incorporation of
12 * ANTLR, or its output, into commerical software.
13 * <p>
14 * We encourage users to develop software with ANTLR. However,
15 * we do ask that credit is given to us for developing
16 * ANTLR. By "credit", we mean that if you use ANTLR or
17 * incorporate any source code into one of your programs
18 * (commercial product, research project, or otherwise) that
19 * you acknowledge this fact somewhere in the documentation,
20 * research report, etc... If you like ANTLR and have
21 * developed a nice tool with the output, please mention that
22 * you developed it using ANTLR. In addition, we ask that the
23 * headers remain intact in our source code. As long as these
24 * guidelines are kept, we expect to continue enhancing this
25 * system and expect to make other tools available as they are
26 * completed.
27 * <p>
28 * The ANTLR gang:
29 * @version ANTLR 2.5.0 MageLang Institute, 1998
30 * @author Terence Parr, <a href=http://www.MageLang.com>MageLang Institute</a>
31 * @author <br>John Lilley, <a href=http://www.Empathy.com>Empathy Software</a>
32 */
33 import antlr.collections.impl.BitSet;
34 import antlr.collections.impl.Vector;
35
36 * the lookahead for any particular lookahead computation
38 * for a <b>single</b> lookahead depth. Final lookahead
39 * information is a simple bit set, but intermediate
40 * stages need computation cycle and FOLLOW information.
41 *
42 * <p>
43 * Concerning the <tt>cycle</tt> variable.
44 * If lookahead is computed for a RuleEnd node, then
45 * computation is part of a FOLLOW cycle for this rule.
46 * If lookahead is computed for a RuleBlock node, the
47 * computation is part of a FIRST cycle to this rule.
48 *
49 * <p>
50 * Concerning the <tt>epsilonDepth</tt> variable.
51 * This is not the depth relative to the rule reference
52 * that epsilon was encountered. That value is
53 * <pre>
54 * initial_k - epsilonDepth + 1
55 * </pre>
56 * Also, lookahead depths past rule ref for local follow are:
57 * <pre>
58 * initial_k - (initial_k - epsilonDepth)
59 * </pre>
60 * Used for rule references. If we try
61 * to compute look(k, ruleref) and there are fewer
62 * than k lookahead terminals before the end of the
63 * the rule, epsilon will be returned (don't want to
64 * pass the end of the rule). We must track when the
65 * the lookahead got stuck. For example,
66 * <pre>
67 * a : b A B E F G;
68 * b : C ;
69 * </pre>
70 * LOOK(5, ref-to(b)) is {<EPSILON>} with depth = 4, which
71 * indicates that at 2 (5-4+1) tokens ahead, end of rule was reached.
72 * Therefore, the token at 4=5-(5-4) past rule ref b must be
73 * included in the set == F.
74 * The situation is complicated by the fact that a computation
75 * may hit the end of a rule at many different depths. For example,
76 * <pre>
77 * a : b A B C ;
78 * b : E F // epsilon depth of 1 relative to initial k=3
79 * | G // epsilon depth of 2
80 * ;
81 * </pre>
82 * Here, LOOK(3,ref-to(b)) returns epsilon, but the depths are
83 * {1, 2}; i.e., 3-(3-1) and 3-(3-2). Those are the lookahead depths
84 * past the rule ref needed for the local follow.
85 *
86 * <p>
87 * This is null unless an epsilon is created.
88 *
89 * @see antlr.Lookahead#combineWith(Lookahead)
90 */
91 public class Lookahead implements Cloneable {
92
93 BitSet fset;
94
95 String cycle;
96
97 BitSet epsilonDepth;
98 * is used to avoid having a bit in the set for Epsilon as it
100 * conflicts with parsing binary files.
101 */
102 boolean hasEpsilon = false;
103
104
105 public Lookahead() {
106 fset = new BitSet();
107 }
108
109 public Lookahead(BitSet p) {
110 fset = p;
111 }
112
113 public Lookahead(String c) {
114 this();
115 cycle = c;
116 }
117
118 public Object clone() {
119 Lookahead p=null;
120 try {
121 p = (Lookahead)super.clone();
122 p.fset = (BitSet)fset.clone();
123 p.cycle = cycle; if ( epsilonDepth!=null ) {
125 p.epsilonDepth = (BitSet)epsilonDepth.clone();
126 }
127 }
128 catch (CloneNotSupportedException e) {
129 throw new InternalError();
130 }
131 return p;
132 }
133 public void combineWith(Lookahead q) {
134 if ( cycle==null ) { cycle = q.cycle;
136 }
137
138 if ( q.containsEpsilon() ) {
139 hasEpsilon = true;
140 }
141
142 if ( epsilonDepth!=null ) {
144 if ( q.epsilonDepth!=null ) {
145 epsilonDepth.orInPlace(q.epsilonDepth);
146 }
147 }
148 else if ( q.epsilonDepth!=null ) {
149 epsilonDepth = (BitSet)q.epsilonDepth.clone();
150 }
151 fset.orInPlace(q.fset);
152 }
153 public boolean containsEpsilon() { return hasEpsilon; }
154 * Only the Epsilon "bit" and bitset are considered.
156 */
157 public Lookahead intersection(Lookahead q) {
158 Lookahead p = new Lookahead(fset.and(q.fset));
159 if ( this.hasEpsilon && q.hasEpsilon ) {
160 p.setEpsilon();
161 }
162 return p;
163 }
164 public boolean nil() {
165 return fset.nil() && !hasEpsilon;
166 }
167 public static Lookahead of(int el) {
168 Lookahead look = new Lookahead();
169 look.fset.add(el);
170 return look;
171 }
172 public void resetEpsilon() { hasEpsilon=false; }
173 public void setEpsilon() { hasEpsilon = true; }
174 public String toString() {
175 String e="",b,f="",d="";
176 b = fset.toString(",");
177 if ( containsEpsilon() ) {
178 e="+<epsilon>";
179 }
180 if ( cycle!=null ) {
181 f="; FOLLOW("+cycle+")";
182 }
183 if ( epsilonDepth != null ) {
184 d = "; depths="+epsilonDepth.toString(",");
185 }
186 return b+e+f+d;
187
188 }
189 public String toString(String separator, CharFormatter formatter) {
190 String e="",b,f="",d="";
191 b = fset.toString(separator, formatter);
192 if ( containsEpsilon() ) {
193 e="+<epsilon>";
194 }
195 if ( cycle!=null ) {
196 f="; FOLLOW("+cycle+")";
197 }
198 if ( epsilonDepth != null ) {
199 d = "; depths="+epsilonDepth.toString(",");
200 }
201 return b+e+f+d;
202 }
203 public String toString(String separator, CharFormatter formatter, Grammar g) {
204 if (g instanceof LexerGrammar) {
205 return toString(separator, formatter);
206 }
207 else {
208 return toString(separator, g.tokenManager.getVocabulary());
209 }
210 }
211 public String toString(String separator, Vector vocab) {
212 String b,f="",d="";
213 b = fset.toString(separator, vocab);
214 if ( cycle!=null ) {
215 f="; FOLLOW("+cycle+")";
216 }
217 if ( epsilonDepth != null ) {
218 d = "; depths="+epsilonDepth.toString(",");
219 }
220 return b+f+d;
221 }
222 }
223