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 5d3d05489..61ae46fff 100755 --- a/runtime/Java/src/org/antlr/v4/runtime/atn/ParserATNSimulator.java +++ b/runtime/Java/src/org/antlr/v4/runtime/atn/ParserATNSimulator.java @@ -798,6 +798,8 @@ public class ParserATNSimulator extends ATNSimulator { public List getPredicatePredictions(IntervalSet ambigAlts, SemanticContext[] altToPred) { List pairs = new ArrayList(); int firstUnpredicated = ATN.INVALID_ALT_NUMBER; + // keep track of the position in pairs where the unpredicated choice should go + int firstUnpredicatedIndex = -1; for (int i = 1; i < altToPred.length; i++) { SemanticContext pred = altToPred[i]; // find first unpredicated but ambig alternative, if any. @@ -809,6 +811,7 @@ public class ParserATNSimulator extends ATNSimulator { pred==SemanticContext.NONE && firstUnpredicated==ATN.INVALID_ALT_NUMBER ) { firstUnpredicated = i; + firstUnpredicatedIndex = pairs.size(); } if ( pred!=null && pred!=SemanticContext.NONE ) { pairs.add(new DFAState.PredPrediction(pred, i)); @@ -817,7 +820,7 @@ public class ParserATNSimulator extends ATNSimulator { if ( pairs.isEmpty() ) pairs = null; else if ( firstUnpredicated!=ATN.INVALID_ALT_NUMBER ) { // add default prediction if we found null predicate - pairs.add(new DFAState.PredPrediction(null, firstUnpredicated)); + pairs.add(firstUnpredicatedIndex, new DFAState.PredPrediction(null, firstUnpredicated)); } // System.out.println(Arrays.toString(altToPred)+"->"+pairs); return pairs; diff --git a/tool/test/org/antlr/v4/test/TestSemPredEvalParser.java b/tool/test/org/antlr/v4/test/TestSemPredEvalParser.java index 5467c898a..7d0ed955f 100644 --- a/tool/test/org/antlr/v4/test/TestSemPredEvalParser.java +++ b/tool/test/org/antlr/v4/test/TestSemPredEvalParser.java @@ -105,11 +105,9 @@ public class TestSemPredEvalParser extends BaseTest { } @Test public void testOrder() throws Exception { - // Predicates disambiguate and so we don't arbitrarily choose the first alt - // Here, there are n-1 predicates for n=2 alts and so we simulate - // the nth predicate as !(others). We do that by testing the - // predicates first and then try the on predicated alternatives. - // Since the 2nd alternative has a true predicate, we always choose that one + // Under new predicate ordering rules (see antlr/antlr4#29), the first + // alt with an acceptable config (unpredicated, or predicated and evaluates + // to true) is chosen. String grammar = "grammar T;\n" + "s : a {} a;\n" + // do 2x: once in ATN, next in DFA; @@ -125,8 +123,8 @@ public class TestSemPredEvalParser extends BaseTest { String found = execParser("T.g", grammar, "TParser", "TLexer", "s", "x y", false); String expecting = - "alt 2\n" + - "alt 2\n"; + "alt 1\n" + + "alt 1\n"; assertEquals(expecting, found); }