From 68b9798d6f543b93bb66502e4826b06218170c57 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Sun, 4 Nov 2012 13:32:45 -0600 Subject: [PATCH] LL1Analyzer adds EOF to expected tokens set if closure reaches end of start rule. --- .../org/antlr/v4/runtime/atn/LL1Analyzer.java | 35 ++++++++++++------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/runtime/Java/src/org/antlr/v4/runtime/atn/LL1Analyzer.java b/runtime/Java/src/org/antlr/v4/runtime/atn/LL1Analyzer.java index caa7c4f05..c22cbdd67 100644 --- a/runtime/Java/src/org/antlr/v4/runtime/atn/LL1Analyzer.java +++ b/runtime/Java/src/org/antlr/v4/runtime/atn/LL1Analyzer.java @@ -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(), seeThruPreds); + PredictionContext lookContext = ctx != null ? PredictionContext.fromRuleContext(s.atn, ctx) : null; + _LOOK(s, lookContext, + r, new HashSet(), 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 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) );