Lookaheadpublic class Lookahead extends Object implements CloneableThis object holds all information needed to represent
the lookahead for any particular lookahead computation
for a single lookahead depth. Final lookahead
information is a simple bit set, but intermediate
stages need computation cycle and FOLLOW information.
Concerning the cycle variable.
If lookahead is computed for a RuleEnd node, then
computation is part of a FOLLOW cycle for this rule.
If lookahead is computed for a RuleBlock node, the
computation is part of a FIRST cycle to this rule.
Concerning the epsilonDepth variable.
This is not the depth relative to the rule reference
that epsilon was encountered. That value is
initial_k - epsilonDepth + 1
Also, lookahead depths past rule ref for local follow are:
initial_k - (initial_k - epsilonDepth)
Used for rule references. If we try
to compute look(k, ruleref) and there are fewer
than k lookahead terminals before the end of the
the rule, epsilon will be returned (don't want to
pass the end of the rule). We must track when the
the lookahead got stuck. For example,
a : b A B E F G;
b : C ;
LOOK(5, ref-to(b)) is {} with depth = 4, which
indicates that at 2 (5-4+1) tokens ahead, end of rule was reached.
Therefore, the token at 4=5-(5-4) past rule ref b must be
included in the set == F.
The situation is complicated by the fact that a computation
may hit the end of a rule at many different depths. For example,
a : b A B C ;
b : E F // epsilon depth of 1 relative to initial k=3
| G // epsilon depth of 2
;
Here, LOOK(3,ref-to(b)) returns epsilon, but the depths are
{1, 2}; i.e., 3-(3-1) and 3-(3-2). Those are the lookahead depths
past the rule ref needed for the local follow.
This is null unless an epsilon is created. |
Fields Summary |
---|
BitSet | fsetactual bitset of the lookahead | String | cycleis this computation part of a computation cycle? | BitSet | epsilonDepthWhat k values were being computed when end of rule hit? | boolean | hasEpsilonDoes this lookahead depth include Epsilon token type? This
is used to avoid having a bit in the set for Epsilon as it
conflicts with parsing binary files. |
Constructors Summary |
---|
public Lookahead()
fset = new BitSet();
| public Lookahead(BitSet p)create a new lookahead set with the LL(1) set to the parameter
fset = p;
| public Lookahead(String c)create an empty lookahead set, but with cycle
this();
cycle = c;
|
Methods Summary |
---|
public java.lang.Object | clone()Make a deep copy of everything in this object
Lookahead p = null;
try {
p = (Lookahead)super.clone();
p.fset = (BitSet)fset.clone();
p.cycle = cycle; // strings are immutable
if (epsilonDepth != null) {
p.epsilonDepth = (BitSet)epsilonDepth.clone();
}
}
catch (CloneNotSupportedException e) {
throw new InternalError();
}
return p;
| public void | combineWith(persistence.antlr.Lookahead q)
if (cycle == null) { // track at least one cycle
cycle = q.cycle;
}
if (q.containsEpsilon()) {
hasEpsilon = true;
}
// combine epsilon depths
if (epsilonDepth != null) {
if (q.epsilonDepth != null) {
epsilonDepth.orInPlace(q.epsilonDepth);
}
}
else if (q.epsilonDepth != null) {
epsilonDepth = (BitSet)q.epsilonDepth.clone();
}
fset.orInPlace(q.fset);
| public boolean | containsEpsilon()
return hasEpsilon;
| public persistence.antlr.Lookahead | intersection(persistence.antlr.Lookahead q)What is the intersection of two lookahead depths?
Only the Epsilon "bit" and bitset are considered.
Lookahead p = new Lookahead(fset.and(q.fset));
if (this.hasEpsilon && q.hasEpsilon) {
p.setEpsilon();
}
return p;
| public boolean | nil()
return fset.nil() && !hasEpsilon;
| public static persistence.antlr.Lookahead | of(int el)
Lookahead look = new Lookahead();
look.fset.add(el);
return look;
| public void | resetEpsilon()
hasEpsilon = false;
| public void | setEpsilon()
hasEpsilon = true;
| public java.lang.String | toString()
String e = "",b,f = "",d = "";
b = fset.toString(",");
if (containsEpsilon()) {
e = "+<epsilon>";
}
if (cycle != null) {
f = "; FOLLOW(" + cycle + ")";
}
if (epsilonDepth != null) {
d = "; depths=" + epsilonDepth.toString(",");
}
return b + e + f + d;
| public java.lang.String | toString(java.lang.String separator, persistence.antlr.CharFormatter formatter)
String e = "",b,f = "",d = "";
b = fset.toString(separator, formatter);
if (containsEpsilon()) {
e = "+<epsilon>";
}
if (cycle != null) {
f = "; FOLLOW(" + cycle + ")";
}
if (epsilonDepth != null) {
d = "; depths=" + epsilonDepth.toString(",");
}
return b + e + f + d;
| public java.lang.String | toString(java.lang.String separator, persistence.antlr.CharFormatter formatter, persistence.antlr.Grammar g)
if (g instanceof LexerGrammar) {
return toString(separator, formatter);
}
else {
return toString(separator, g.tokenManager.getVocabulary());
}
| public java.lang.String | toString(java.lang.String separator, persistence.antlr.collections.impl.Vector vocab)
String b,f = "",d = "";
b = fset.toString(separator, vocab);
if (cycle != null) {
f = "; FOLLOW(" + cycle + ")";
}
if (epsilonDepth != null) {
d = "; depths=" + epsilonDepth.toString(",");
}
return b + f + d;
|
|