validate FullContextParsing tests

This commit is contained in:
ericvergnaud 2014-10-25 01:07:31 +08:00
parent e39ac5a197
commit 31812721c8
5 changed files with 27 additions and 376 deletions

View File

@ -1,7 +1,5 @@
package org.antlr.v4.test.rt.gen;
import static org.junit.Assert.assertEquals;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
@ -846,11 +844,12 @@ public class Generator {
private TestFile buildFullContextParsing() throws Exception {
TestFile file = new TestFile("FullContextParsing");
file.addParserTest(input, "AmbigYieldsCtxSensitiveDFA", "T", "s", "abc",
TestMethod tm = file.addParserTest(input, "AmbigYieldsCtxSensitiveDFA", "T", "s", "abc",
"Decision 0:\n" +
"s0-ID->:s1^=>1\n",
"line 1:0 reportAttemptingFullContext d=0 (s), input='abc'\n");
file.addParserTestsWithErrors(input, "CtxSensitiveDFA", "T", "s",
tm.debug = true;
tm = file.addParserTestsWithErrors(input, "CtxSensitiveDFA", "T", "s",
"$ 34 abc",
"Decision 1:\n" +
"s0-INT->s1\n" +
@ -863,7 +862,8 @@ public class Generator {
"s1-ID->:s2^=>1\n",
"line 1:5 reportAttemptingFullContext d=1 (e), input='34abc'\n" +
"line 1:5 reportContextSensitivity d=1 (e), input='34abc'\n");
file.addParserTest(input, "CtxSensitiveDFATwoDiffInput", "T", "s",
tm.debug = true;
tm = file.addParserTest(input, "CtxSensitiveDFATwoDiffInput", "T", "s",
"$ 34 abc @ 34 abc",
"Decision 2:\n" +
"s0-INT->s1\n" +
@ -872,14 +872,16 @@ public class Generator {
"line 1:2 reportContextSensitivity d=2 (e), input='34'\n" +
"line 1:14 reportAttemptingFullContext d=2 (e), input='34abc'\n" +
"line 1:14 reportContextSensitivity d=2 (e), input='34abc'\n");
file.addParserTest(input, "SLLSeesEOFInLLGrammar", "T", "s",
tm.debug = true;
tm = file.addParserTest(input, "SLLSeesEOFInLLGrammar", "T", "s",
"34 abc",
"Decision 0:\n" +
"s0-INT->s1\n" +
"s1-ID->:s2^=>1\n",
"line 1:3 reportAttemptingFullContext d=0 (e), input='34abc'\n" +
"line 1:0 reportContextSensitivity d=0 (e), input='34'\n");
file.addParserTestsWithErrors(input, "FullContextIF_THEN_ELSEParse", "T", "s",
tm.debug = true;
tm = file.addParserTestsWithErrors(input, "FullContextIF_THEN_ELSEParse", "T", "s",
"{ if x then return }",
"Decision 1:\n" +
"s0-'}'->:s1=>2\n",
@ -923,19 +925,22 @@ public class Generator {
"line 1:19 reportContextSensitivity d=1 (stat), input='else'\n" +
"line 2:27 reportAttemptingFullContext d=1 (stat), input='else'\n" +
"line 2:36 reportAmbiguity d=1 (stat): ambigAlts={1, 2}, input='elsefoo}'\n");
file.addParserTest(input, "LoopsSimulateTailRecursion", "T", "prog",
tm.debug = true;
tm = file.addParserTest(input, "LoopsSimulateTailRecursion", "T", "prog",
"a(i)<-x",
"pass: a(i)<-x\n",
"line 1:3 reportAttemptingFullContext d=3 (expr_primary), input='a(i)'\n" +
"line 1:7 reportAmbiguity d=3 (expr_primary): ambigAlts={2, 3}, input='a(i)<-x'\n");
file.addParserTest(input, "AmbiguityNoLoop", "T", "prog",
tm.debug = true;
tm = file.addParserTest(input, "AmbiguityNoLoop", "T", "prog",
"a@",
"alt 1\n",
"line 1:2 reportAttemptingFullContext d=0 (prog), input='a@'\n" +
"line 1:2 reportAmbiguity d=0 (prog): ambigAlts={1, 2}, input='a@'\n" +
"line 1:2 reportAttemptingFullContext d=1 (expr), input='a@'\n" +
"line 1:2 reportContextSensitivity d=1 (expr), input='a@'\n");
file.addParserTestsWithErrors(input, "ExprAmbiguity", "T", "s",
tm.debug = true;
tm = file.addParserTestsWithErrors(input, "ExprAmbiguity", "T", "s",
"a+b",
"(expr a + (expr b))\n",
"line 1:1 reportAttemptingFullContext d=1 (expr), input='+'\n" +
@ -946,6 +951,7 @@ public class Generator {
"line 1:2 reportContextSensitivity d=1 (expr), input='+b'\n" +
"line 1:3 reportAttemptingFullContext d=1 (expr), input='*'\n" +
"line 1:5 reportAmbiguity d=1 (expr): ambigAlts={1, 2}, input='*c'\n");
tm.debug = true;
return file;
}

View File

@ -12,6 +12,7 @@ public abstract class TestMethod {
public String input;
public String expectedOutput;
public String expectedErrors;
public boolean debug = false;
protected TestMethod(String name, String grammarName, String input,
String expectedOutput, String expectedErrors, Integer index) {

View File

@ -58,7 +58,7 @@ public void test<test.name>() throws Exception {
};separator="\n", wrap, anchor>
String grammar = <test.grammar.lines:{ line | "<line>};separator="\\n\" +\n", wrap, anchor>";
<test.afterGrammar>
String found = execParser("<test.grammar.grammarName>.g4", grammar, "<test.grammar.grammarName><if(!test.slaveIsLexer)>Parser<endif>", "<if(test.slaveIsLexer)><first(test.slaveGrammars).grammarName><else><test.grammar.grammarName>Lexer<endif>", "<test.startRule>", "<test.input>", false);
String found = execParser("<test.grammar.grammarName>.g4", grammar, "<test.grammar.grammarName><if(!test.slaveIsLexer)>Parser<endif>", "<if(test.slaveIsLexer)><first(test.slaveGrammars).grammarName><else><test.grammar.grammarName>Lexer<endif>", "<test.startRule>", "<test.input>", <test.debug>);
assertEquals("<test.expectedOutput>", found);
<if(test.expectedErrors)>
assertEquals("<test.expectedErrors>", this.stderrDuringParse);
@ -76,7 +76,7 @@ CompositeParserTestMethod(test) ::= <<
AbstractParserTestMethod(test) ::= <<
String test<test.name>(String input) throws Exception {
String grammar = <test.grammar.lines:{ line | "<line>};separator="\\n\" +\n", wrap, anchor>";
return execParser("<test.grammar.grammarName>.g4", grammar, "<test.grammar.grammarName>Parser", "<test.grammar.grammarName>Lexer", "<test.startRule>", input, false);
return execParser("<test.grammar.grammarName>.g4", grammar, "<test.grammar.grammarName>Parser", "<test.grammar.grammarName>Lexer", "<test.startRule>", input, <test.debug>);
}
>>

View File

@ -12,7 +12,7 @@ public class TestFullContextParsing extends BaseTest {
" : ID | ID {} ;\n" +
"ID : 'a'..'z'+;\n" +
"WS : (' '|'\\t'|'\\n')+ -> skip ;";
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "abc", false);
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "abc", true);
assertEquals("Decision 0:\ns0-ID->:s1^=>1\n", found);
assertEquals("line 1:0 reportAttemptingFullContext d=0 (s), input='abc'\n", this.stderrDuringParse);
}
@ -27,7 +27,7 @@ public class TestFullContextParsing extends BaseTest {
"ID : 'a'..'z'+ ;\n" +
"INT : '0'..'9'+ ;\n" +
"WS : (' '|'\\t'|'\\n')+ -> skip ;";
return execParser("T.g4", grammar, "TParser", "TLexer", "s", input, false);
return execParser("T.g4", grammar, "TParser", "TLexer", "s", input, true);
}
@Test
@ -55,7 +55,7 @@ public class TestFullContextParsing extends BaseTest {
"ID : 'a'..'z'+ ;\n" +
"INT : '0'..'9'+ ;\n" +
"WS : (' '|'\\t'|'\\n')+ -> skip ;";
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "$ 34 abc @ 34 abc", false);
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "$ 34 abc @ 34 abc", true);
assertEquals("Decision 2:\ns0-INT->s1\ns1-ID->:s2^=>1\n", found);
assertEquals("line 1:5 reportAttemptingFullContext d=2 (e), input='34abc'\nline 1:2 reportContextSensitivity d=2 (e), input='34'\nline 1:14 reportAttemptingFullContext d=2 (e), input='34abc'\nline 1:14 reportContextSensitivity d=2 (e), input='34abc'\n", this.stderrDuringParse);
}
@ -71,7 +71,7 @@ public class TestFullContextParsing extends BaseTest {
"ID : 'a'..'z'+ ;\n" +
"INT : '0'..'9'+ ;\n" +
"WS : (' '|'\\t'|'\\n')+ -> skip ;";
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "34 abc", false);
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "34 abc", true);
assertEquals("Decision 0:\ns0-INT->s1\ns1-ID->:s2^=>1\n", found);
assertEquals("line 1:3 reportAttemptingFullContext d=0 (e), input='34abc'\nline 1:0 reportContextSensitivity d=0 (e), input='34'\n", this.stderrDuringParse);
}
@ -87,7 +87,7 @@ public class TestFullContextParsing extends BaseTest {
" ;\n" +
"ID : 'a'..'z'+ ;\n" +
"WS : (' '|'\\t'|'\\n')+ -> skip ;";
return execParser("T.g4", grammar, "TParser", "TLexer", "s", input, false);
return execParser("T.g4", grammar, "TParser", "TLexer", "s", input, true);
}
@Test
@ -149,7 +149,7 @@ public class TestFullContextParsing extends BaseTest {
" | ID\n" +
" ;\n" +
"ID : [a-z]+ ;";
String found = execParser("T.g4", grammar, "TParser", "TLexer", "prog", "a(i)<-x", false);
String found = execParser("T.g4", grammar, "TParser", "TLexer", "prog", "a(i)<-x", true);
assertEquals("pass: a(i)<-x\n", found);
assertEquals("line 1:3 reportAttemptingFullContext d=3 (expr_primary), input='a(i)'\nline 1:7 reportAmbiguity d=3 (expr_primary): ambigAlts={2, 3}, input='a(i)<-x'\n", this.stderrDuringParse);
}
@ -168,7 +168,7 @@ public class TestFullContextParsing extends BaseTest {
" ;\n" +
"ID : [a-z]+ ;\n" +
"WS : [ \\r\\n\\t]+ -> skip ;";
String found = execParser("T.g4", grammar, "TParser", "TLexer", "prog", "a@", false);
String found = execParser("T.g4", grammar, "TParser", "TLexer", "prog", "a@", true);
assertEquals("alt 1\n", found);
assertEquals("line 1:2 reportAttemptingFullContext d=0 (prog), input='a@'\nline 1:2 reportAmbiguity d=0 (prog): ambigAlts={1, 2}, input='a@'\nline 1:2 reportAttemptingFullContext d=1 (expr), input='a@'\nline 1:2 reportContextSensitivity d=1 (expr), input='a@'\n", this.stderrDuringParse);
}
@ -187,7 +187,7 @@ public class TestFullContextParsing extends BaseTest {
" ;\n" +
"ID : [a-zA-Z]+ ;\n" +
"WS : [ \\r\\n\\t]+ -> skip ;";
return execParser("T.g4", grammar, "TParser", "TLexer", "s", input, false);
return execParser("T.g4", grammar, "TParser", "TLexer", "s", input, true);
}
@Test

View File

@ -1,356 +0,0 @@
/*
* [The "BSD license"]
* Copyright (c) 2012 Terence Parr
* Copyright (c) 2012 Sam Harwell
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.test.tool;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
/*
cover these cases:
dead end
single alt
single alt + preds
conflict
conflict + preds
*/
public class TestFullContextParsing extends BaseTest {
@Test public void testAmbigYieldsCtxSensitiveDFA() {
String grammar =
"grammar T;\n"+
"s" +
"@after {dumpDFA();}\n" +
" : ID | ID {;} ;\n" +
"ID : 'a'..'z'+ ;\n"+
"WS : (' '|'\\t'|'\\n')+ -> skip ;\n";
String result = execParser("T.g4", grammar, "TParser", "TLexer", "s",
"abc", true);
String expecting =
"Decision 0:\n" +
"s0-ID->:s1^=>1\n"; // ctx sensitive
assertEquals(expecting, result);
assertEquals("line 1:0 reportAttemptingFullContext d=0 (s), input='abc'\n",
this.stderrDuringParse);
}
public String testCtxSensitiveDFA(String input) {
String grammar =
"grammar T;\n"+
"s @after {dumpDFA();}\n" +
" : '$' a | '@' b ;\n" +
"a : e ID ;\n" +
"b : e INT ID ;\n" +
"e : INT | ;\n" +
"ID : 'a'..'z'+ ;\n"+
"INT : '0'..'9'+ ;\n"+
"WS : (' '|'\\t'|'\\n')+ -> skip ;\n";
return execParser("T.g4", grammar, "TParser", "TLexer", "s", input, true);
}
@Test
public void testCtxSensitiveDFA1() {
String result = testCtxSensitiveDFA("$ 34 abc");
String expecting =
"Decision 1:\n" +
"s0-INT->s1\n" +
"s1-ID->:s2^=>1\n";
assertEquals(expecting, result);
assertEquals("line 1:5 reportAttemptingFullContext d=1 (e), input='34abc'\n" +
"line 1:2 reportContextSensitivity d=1 (e), input='34'\n",
this.stderrDuringParse);
}
@Test
public void testCtxSensitiveDFA2() {
String result = testCtxSensitiveDFA("@ 34 abc");
String expecting =
"Decision 1:\n" +
"s0-INT->s1\n" +
"s1-ID->:s2^=>1\n";
assertEquals(expecting, result);
assertEquals("line 1:5 reportAttemptingFullContext d=1 (e), input='34abc'\n" +
"line 1:5 reportContextSensitivity d=1 (e), input='34abc'\n",
this.stderrDuringParse);
}
@Test public void testCtxSensitiveDFATwoDiffInput() {
String grammar =
"grammar T;\n"+
"s @after {dumpDFA();}\n" +
" : ('$' a | '@' b)+ ;\n" +
"a : e ID ;\n" +
"b : e INT ID ;\n" +
"e : INT | ;\n" +
"ID : 'a'..'z'+ ;\n"+
"INT : '0'..'9'+ ;\n"+
"WS : (' '|'\\t'|'\\n')+ -> skip ;\n";
String result = execParser("T.g4", grammar, "TParser", "TLexer", "s",
"$ 34 abc @ 34 abc", true);
String expecting =
"Decision 2:\n" +
"s0-INT->s1\n" +
"s1-ID->:s2^=>1\n";
assertEquals(expecting, result);
assertEquals("line 1:5 reportAttemptingFullContext d=2 (e), input='34abc'\n" +
"line 1:2 reportContextSensitivity d=2 (e), input='34'\n" +
"line 1:14 reportAttemptingFullContext d=2 (e), input='34abc'\n" +
"line 1:14 reportContextSensitivity d=2 (e), input='34abc'\n",
this.stderrDuringParse);
}
@Test
public void testSLLSeesEOFInLLGrammar() {
String grammar =
"grammar T;\n"+
"s @after {dumpDFA();}\n" +
" : a ;\n" +
"a : e ID ;\n" +
"b : e INT ID ;\n" +
"e : INT | ;\n" +
"ID : 'a'..'z'+ ;\n"+
"INT : '0'..'9'+ ;\n"+
"WS : (' '|'\\t'|'\\n')+ -> skip ;\n";
String result = execParser("T.g4", grammar, "TParser", "TLexer", "s",
"34 abc", true);
String expecting =
"Decision 0:\n" +
"s0-INT->s1\n" +
"s1-ID->:s2^=>1\n"; // Must point at accept state
assertEquals(expecting, result);
assertEquals("line 1:3 reportAttemptingFullContext d=0 (e), input='34abc'\n" +
"line 1:0 reportContextSensitivity d=0 (e), input='34'\n",
this.stderrDuringParse);
}
@Test public void testFullContextIF_THEN_ELSEParse() {
String grammar =
"grammar T;\n"+
"s" +
"@init {_interp.setPredictionMode(PredictionMode.LL_EXACT_AMBIG_DETECTION);}\n" +
"@after {dumpDFA();}\n" +
" : '{' stat* '}'" +
" ;\n" +
"stat: 'if' ID 'then' stat ('else' ID)?\n" +
" | 'return'\n" +
" ;" +
"ID : 'a'..'z'+ ;\n"+
"WS : (' '|'\\t'|'\\n')+ -> skip ;\n";
String input = "{ if x then return }";
String result = execParser("T.g4", grammar, "TParser", "TLexer", "s",
input, true);
String expecting =
"Decision 1:\n" +
"s0-'}'->:s1=>2\n";
assertEquals(expecting, result);
assertEquals(null, this.stderrDuringParse);
input = "{ if x then return else foo }";
result = execParser("T.g4", grammar, "TParser", "TLexer", "s",
input, true);
expecting =
"Decision 1:\n" +
"s0-'else'->:s1^=>1\n";
assertEquals(expecting, result);
// Technically, this input sequence is not ambiguous because else
// uniquely predicts going into the optional subrule. else cannot
// be matched by exiting stat since that would only match '}' or
// the start of a stat. But, we are using the theory that
// SLL(1)=LL(1) and so we are avoiding full context parsing
// by declaring all else clause parsing to be ambiguous.
assertEquals("line 1:19 reportAttemptingFullContext d=1 (stat), input='else'\n" +
"line 1:19 reportContextSensitivity d=1 (stat), input='else'\n",
this.stderrDuringParse);
input =
"{ if x then if y then return else foo }";
result = execParser("T.g4", grammar, "TParser", "TLexer", "s",
input, true);
expecting =
"Decision 1:\n" +
"s0-'}'->:s2=>2\n" +
"s0-'else'->:s1^=>1\n";
assertEquals(expecting, result);
assertEquals("line 1:29 reportAttemptingFullContext d=1 (stat), input='else'\n" +
"line 1:38 reportAmbiguity d=1 (stat): ambigAlts={1, 2}, input='elsefoo}'\n",
this.stderrDuringParse);
// should not be ambiguous because the second 'else bar' clearly
// indicates that the first else should match to the innermost if.
// LL_EXACT_AMBIG_DETECTION makes us keep going to resolve
input =
"{ if x then if y then return else foo else bar }";
result = execParser("T.g4", grammar, "TParser", "TLexer", "s",
input, true);
expecting =
"Decision 1:\n" +
"s0-'else'->:s1^=>1\n";
assertEquals(expecting, result);
assertEquals("line 1:29 reportAttemptingFullContext d=1 (stat), input='else'\n" +
"line 1:38 reportContextSensitivity d=1 (stat), input='elsefooelse'\n" +
"line 1:38 reportAttemptingFullContext d=1 (stat), input='else'\n" +
"line 1:38 reportContextSensitivity d=1 (stat), input='else'\n",
this.stderrDuringParse);
input =
"{ if x then return else foo\n" +
"if x then if y then return else foo }";
result = execParser("T.g4", grammar, "TParser", "TLexer", "s",
input, true);
expecting =
"Decision 1:\n" +
"s0-'}'->:s2=>2\n" +
"s0-'else'->:s1^=>1\n";
assertEquals(expecting, result);
assertEquals("line 1:19 reportAttemptingFullContext d=1 (stat), input='else'\n" +
"line 1:19 reportContextSensitivity d=1 (stat), input='else'\n" +
"line 2:27 reportAttemptingFullContext d=1 (stat), input='else'\n" +
"line 2:36 reportAmbiguity d=1 (stat): ambigAlts={1, 2}, input='elsefoo}'\n",
this.stderrDuringParse);
input =
"{ if x then return else foo\n" +
"if x then if y then return else foo }";
result = execParser("T.g4", grammar, "TParser", "TLexer", "s",
input, true);
expecting =
"Decision 1:\n" +
"s0-'}'->:s2=>2\n" +
"s0-'else'->:s1^=>1\n";
assertEquals(expecting, result);
assertEquals("line 1:19 reportAttemptingFullContext d=1 (stat), input='else'\n" +
"line 1:19 reportContextSensitivity d=1 (stat), input='else'\n" +
"line 2:27 reportAttemptingFullContext d=1 (stat), input='else'\n" +
"line 2:36 reportAmbiguity d=1 (stat): ambigAlts={1, 2}, input='elsefoo}'\n",
this.stderrDuringParse);
}
/**
* Tests predictions for the following case involving closures.
* http://www.antlr.org/wiki/display/~admin/2011/12/29/Flaw+in+ANTLR+v3+LL(*)+analysis+algorithm
*/
@Test
public void testLoopsSimulateTailRecursion() throws Exception {
String grammar =
"grammar T;\n" +
"prog\n" +
"@init {_interp.setPredictionMode(PredictionMode.LL_EXACT_AMBIG_DETECTION);}\n" +
" : expr_or_assign*;\n" +
"expr_or_assign\n" +
" : expr '++' {System.out.println(\"fail.\");}\n" +
" | expr {System.out.println(\"pass: \"+$expr.text);}\n" +
" ;\n" +
"expr: expr_primary ('<-' ID)? ;\n" +
"expr_primary\n" +
" : '(' ID ')'\n" +
" | ID '(' ID ')'\n" +
" | ID\n" +
" ;\n" +
"ID : [a-z]+ ;\n" +
"";
String found = execParser("T.g4", grammar, "TParser", "TLexer", "prog", "a(i)<-x", true);
assertEquals("pass: a(i)<-x\n", found);
String expecting =
"line 1:3 reportAttemptingFullContext d=3 (expr_primary), input='a(i)'\n" +
"line 1:7 reportAmbiguity d=3 (expr_primary): ambigAlts={2, 3}, input='a(i)<-x'\n";
assertEquals(expecting, this.stderrDuringParse);
}
@Test
public void testAmbiguityNoLoop() throws Exception {
// simpler version of testLoopsSimulateTailRecursion, no loops
String grammar =
"grammar T;\n" +
"prog\n" +
"@init {_interp.setPredictionMode(PredictionMode.LL_EXACT_AMBIG_DETECTION);}\n" +
" : expr expr {System.out.println(\"alt 1\");}\n" +
" | expr\n" +
" ;\n" +
"expr: '@'\n" +
" | ID '@'\n" +
" | ID\n" +
" ;\n" +
"ID : [a-z]+ ;\n" +
"WS : [ \\r\\n\\t]+ -> skip ;\n";
String found = execParser("T.g4", grammar, "TParser", "TLexer", "prog", "a@", true);
assertEquals("alt 1\n", found);
String expecting =
"line 1:2 reportAttemptingFullContext d=0 (prog), input='a@'\n" +
"line 1:2 reportAmbiguity d=0 (prog): ambigAlts={1, 2}, input='a@'\n" +
"line 1:2 reportAttemptingFullContext d=1 (expr), input='a@'\n" +
"line 1:2 reportContextSensitivity d=1 (expr), input='a@'\n";
assertEquals(expecting, this.stderrDuringParse);
}
@Test
public void testExprAmbiguity() throws Exception {
// translated left-recursive expr rule to test ambig detection
String grammar =
"grammar T;\n" +
"s\n" +
"@init {_interp.setPredictionMode(PredictionMode.LL_EXACT_AMBIG_DETECTION);}\n" +
" : expr[0] {System.out.println($expr.ctx.toStringTree(this));} ;\n" +
"\n" +
"expr[int _p]\n" +
" : ID\n" +
" ( {5 >= $_p}? '*' expr[6]\n" +
" | {4 >= $_p}? '+' expr[5]\n" +
" )*\n" +
" ;\n" +
"\n" +
"ID : [a-zA-Z]+ ; // match identifiers\n" +
"WS : [ \\t\\r\\n]+ -> skip ; // toss out whitespace\n";
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "a+b", true);
assertEquals("(expr a + (expr b))\n", found);
String expecting =
"line 1:1 reportAttemptingFullContext d=1 (expr), input='+'\n" +
"line 1:2 reportContextSensitivity d=1 (expr), input='+b'\n";
assertEquals(expecting, this.stderrDuringParse);
found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "a+b*c", true);
assertEquals("(expr a + (expr b * (expr c)))\n", found);
expecting =
"line 1:1 reportAttemptingFullContext d=1 (expr), input='+'\n" +
"line 1:2 reportContextSensitivity d=1 (expr), input='+b'\n" +
"line 1:3 reportAttemptingFullContext d=1 (expr), input='*'\n" +
"line 1:5 reportAmbiguity d=1 (expr): ambigAlts={1, 2}, input='*c'\n";
assertEquals(expecting, this.stderrDuringParse);
}
}