diff --git a/runtime/Java/src/org/antlr/v4/runtime/atn/ParserATNSimulator.java b/runtime/Java/src/org/antlr/v4/runtime/atn/ParserATNSimulator.java index 51b31e458..b01bbea3e 100755 --- a/runtime/Java/src/org/antlr/v4/runtime/atn/ParserATNSimulator.java +++ b/runtime/Java/src/org/antlr/v4/runtime/atn/ParserATNSimulator.java @@ -565,21 +565,28 @@ public class ParserATNSimulator extends ATNSimulator { int nalts = decState.getNumberOfTransitions(); List predPredictions = predicateDFAState(D, D.configset, outerContext, nalts); - IntervalSet conflictingAlts = getConflictingAltsFromConfigSet(D.configset); - if ( D.predicates.size() < conflictingAlts.size() ) { - reportInsufficientPredicates(dfa, startIndex, input.index(), - conflictingAlts, - decState, - getPredsForAmbigAlts(conflictingAlts, D.configset, nalts), - D.configset, - false); + if ( predPredictions!=null ) { + IntervalSet conflictingAlts = getConflictingAltsFromConfigSet(D.configset); + if ( D.predicates.size() < conflictingAlts.size() ) { + reportInsufficientPredicates(dfa, startIndex, input.index(), + conflictingAlts, + decState, + getPredsForAmbigAlts(conflictingAlts, D.configset, nalts), + D.configset, + false); + } + input.seek(startIndex); + predictedAlt = evalSemanticContext(predPredictions, outerContext); + if ( predictedAlt!=ATN.INVALID_ALT_NUMBER ) { + return predictedAlt; + } + + if (D.prediction == ATN.INVALID_ALT_NUMBER) { + throw noViableAlt(input, outerContext, D.configset, startIndex); + } + + predictedAlt = D.prediction; } - input.seek(startIndex); - predictedAlt = evalSemanticContext(predPredictions, outerContext); - if ( predictedAlt!=ATN.INVALID_ALT_NUMBER ) { - return predictedAlt; - } - throw noViableAlt(input, outerContext, D.configset, startIndex); } if ( D.isAcceptState ) return predictedAlt; @@ -736,14 +743,9 @@ public class ParserATNSimulator extends ATNSimulator { // we have a validating predicate; test it // Update DFA so reach becomes accept state with predicate predPredictions = getPredicatePredictions(conflictingAlts, altToPred); - if ( D.isCtxSensitive ) { -// D.ctxToPredicates.put(outerContext, predPredictions); - } - else { - D.predicates = predPredictions; - } + D.predicates = predPredictions; + D.prediction = ATN.INVALID_ALT_NUMBER; // make sure we use preds } - D.prediction = ATN.INVALID_ALT_NUMBER; // make sure we use preds return predPredictions; } @@ -754,11 +756,18 @@ public class ParserATNSimulator extends ATNSimulator { // REACH=[1|1|[]|0:0, 1|2|[]|0:1] SemanticContext[] altToPred = new SemanticContext[nalts +1]; int n = altToPred.length; - for (int i = 0; i < n; i++) altToPred[i] = SemanticContext.NONE; - int nPredAlts = 0; for (ATNConfig c : configs) { - if ( c.semanticContext!=SemanticContext.NONE && ambigAlts.contains(c.alt) ) { + if ( ambigAlts.contains(c.alt) ) { altToPred[c.alt] = SemanticContext.or(altToPred[c.alt], c.semanticContext); + } + } + + int nPredAlts = 0; + for (int i = 0; i < n; i++) { + if (altToPred[i] == null) { + altToPred[i] = SemanticContext.NONE; + } + else if (altToPred[i] != SemanticContext.NONE) { nPredAlts++; } } @@ -817,10 +826,12 @@ public class ParserATNSimulator extends ATNSimulator { predictedAlt = pair.alt; // default prediction break; } + + boolean evaluatedResult = pair.pred.eval(parser, outerContext); if ( debug || dfa_debug ) { - System.out.println("eval pred "+pair+"="+pair.pred.eval(parser, outerContext)); + System.out.println("eval pred "+pair+"="+evaluatedResult); } - if ( pair.pred.eval(parser, outerContext) ) { + if ( evaluatedResult ) { if ( debug || dfa_debug ) System.out.println("PREDICT "+pair.alt); predictedAlt = pair.alt; break; diff --git a/runtime/Java/src/org/antlr/v4/runtime/atn/SemanticContext.java b/runtime/Java/src/org/antlr/v4/runtime/atn/SemanticContext.java index 505011579..5c1c64ba2 100644 --- a/runtime/Java/src/org/antlr/v4/runtime/atn/SemanticContext.java +++ b/runtime/Java/src/org/antlr/v4/runtime/atn/SemanticContext.java @@ -189,14 +189,15 @@ public abstract class SemanticContext { } public static SemanticContext and(SemanticContext a, SemanticContext b) { - if ( a == NONE ) return b; - if ( b == NONE ) return a; + if ( a == null || a == NONE ) return b; + if ( b == null || b == NONE ) return a; return new AND(a, b); } public static SemanticContext or(SemanticContext a, SemanticContext b) { - if ( a == NONE ) return b; - if ( b == NONE ) return a; + if ( a == null ) return b; + if ( b == null ) return a; + if ( a == NONE || b == NONE ) return NONE; return new OR(a, b); } } diff --git a/tool/test/org/antlr/v4/test/TestSemPredEvalParser.java b/tool/test/org/antlr/v4/test/TestSemPredEvalParser.java index 776e711f1..5467c898a 100644 --- a/tool/test/org/antlr/v4/test/TestSemPredEvalParser.java +++ b/tool/test/org/antlr/v4/test/TestSemPredEvalParser.java @@ -274,7 +274,7 @@ public class TestSemPredEvalParser extends BaseTest { "alt 1\n"; assertEquals(expecting, found); - expecting = ""; + expecting = null; assertEquals(expecting, stderrDuringParse); }