forked from jasder/antlr
LL1Analyzer adds EOF to expected tokens set if closure reaches end of start rule.
This commit is contained in:
parent
a62775c4ba
commit
68b9798d6f
|
@ -29,6 +29,7 @@
|
|||
|
||||
package org.antlr.v4.runtime.atn;
|
||||
|
||||
import org.antlr.v4.runtime.IntStream;
|
||||
import org.antlr.v4.runtime.RuleContext;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
import org.antlr.v4.runtime.misc.IntervalSet;
|
||||
|
@ -63,7 +64,7 @@ public class LL1Analyzer {
|
|||
boolean seeThruPreds = false; // fail to get lookahead upon pred
|
||||
_LOOK(s.transition(alt - 1).target,
|
||||
PredictionContext.EMPTY,
|
||||
look[alt], lookBusy, seeThruPreds);
|
||||
look[alt], lookBusy, seeThruPreds, false);
|
||||
// Wipe out lookahead for this alternative if we found nothing
|
||||
// or we had a predicate when we !seeThruPreds
|
||||
if ( look[alt].size()==0 || look[alt].contains(HIT_PRED) ) {
|
||||
|
@ -73,15 +74,21 @@ public class LL1Analyzer {
|
|||
return look;
|
||||
}
|
||||
|
||||
/** Get lookahead, using ctx if we reach end of rule. If ctx is EMPTY, don't chase FOLLOW.
|
||||
* If ctx is null, EPSILON is in set if we can reach end of rule.
|
||||
*/
|
||||
/**
|
||||
* Get lookahead, using {@code ctx} if we reach end of rule. If {@code ctx}
|
||||
* is {@code null} or {@link RuleContext#EMPTY EMPTY}, don't chase FOLLOW.
|
||||
* If {@code ctx} is {@code null}, {@link Token#EPSILON EPSILON} is in set
|
||||
* if we can reach end of rule. If {@code ctx} is
|
||||
* {@link RuleContext#EMPTY EMPTY}, {@link IntStream#EOF EOF} is in set if
|
||||
* we can reach end of rule.
|
||||
*/
|
||||
@NotNull
|
||||
public IntervalSet LOOK(@NotNull ATNState s, @Nullable RuleContext ctx) {
|
||||
IntervalSet r = new IntervalSet();
|
||||
boolean seeThruPreds = true; // ignore preds; get all lookahead
|
||||
_LOOK(s, PredictionContext.fromRuleContext(s.atn, ctx),
|
||||
r, new HashSet<ATNConfig>(), seeThruPreds);
|
||||
PredictionContext lookContext = ctx != null ? PredictionContext.fromRuleContext(s.atn, ctx) : null;
|
||||
_LOOK(s, lookContext,
|
||||
r, new HashSet<ATNConfig>(), seeThruPreds, true);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -95,7 +102,7 @@ public class LL1Analyzer {
|
|||
protected void _LOOK(@NotNull ATNState s, @Nullable PredictionContext ctx,
|
||||
@NotNull IntervalSet look,
|
||||
@NotNull Set<ATNConfig> lookBusy,
|
||||
boolean seeThruPreds)
|
||||
boolean seeThruPreds, boolean addEOF)
|
||||
{
|
||||
// System.out.println("_LOOK("+s.stateNumber+", ctx="+ctx);
|
||||
ATNConfig c = new ATNConfig(s, 0, ctx);
|
||||
|
@ -105,13 +112,17 @@ public class LL1Analyzer {
|
|||
if ( ctx==null ) {
|
||||
look.add(Token.EPSILON);
|
||||
return;
|
||||
}
|
||||
} else if (ctx.isEmpty() && addEOF) {
|
||||
look.add(Token.EOF);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ctx != PredictionContext.EMPTY ) {
|
||||
// run thru all possible stack tops in ctx
|
||||
for (SingletonPredictionContext p : ctx) {
|
||||
ATNState returnState = atn.states.get(p.returnState);
|
||||
// System.out.println("popping back to "+retState);
|
||||
_LOOK(returnState, p.parent, look, lookBusy, seeThruPreds);
|
||||
_LOOK(returnState, p.parent, look, lookBusy, seeThruPreds, addEOF);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -123,18 +134,18 @@ public class LL1Analyzer {
|
|||
if ( t.getClass() == RuleTransition.class ) {
|
||||
PredictionContext newContext =
|
||||
SingletonPredictionContext.create(ctx, ((RuleTransition)t).followState.stateNumber);
|
||||
_LOOK(t.target, newContext, look, lookBusy, seeThruPreds);
|
||||
_LOOK(t.target, newContext, look, lookBusy, seeThruPreds, addEOF);
|
||||
}
|
||||
else if ( t instanceof PredicateTransition ) {
|
||||
if ( seeThruPreds ) {
|
||||
_LOOK(t.target, ctx, look, lookBusy, seeThruPreds);
|
||||
_LOOK(t.target, ctx, look, lookBusy, seeThruPreds, addEOF);
|
||||
}
|
||||
else {
|
||||
look.add(HIT_PRED);
|
||||
}
|
||||
}
|
||||
else if ( t.isEpsilon() ) {
|
||||
_LOOK(t.target, ctx, look, lookBusy, seeThruPreds);
|
||||
_LOOK(t.target, ctx, look, lookBusy, seeThruPreds, addEOF);
|
||||
}
|
||||
else if ( t.getClass() == WildcardTransition.class ) {
|
||||
look.addAll( IntervalSet.of(Token.MIN_USER_TOKEN_TYPE, atn.maxTokenType) );
|
||||
|
|
Loading…
Reference in New Issue