validate SemPredEvalParser tests
This commit is contained in:
parent
2716bbd62d
commit
ba76b053a7
|
@ -224,36 +224,40 @@ public class Generator {
|
|||
|
||||
private TestFile buildSemPredEvalParser() throws Exception {
|
||||
TestFile file = new TestFile("SemPredEvalParser");
|
||||
file.addParserTest(input, "SimpleValidate", "T", "s",
|
||||
TestMethod tm = file.addParserTest(input, "SimpleValidate", "T", "s",
|
||||
"x",
|
||||
"",
|
||||
"line 1:0 no viable alternative at input 'x'\n");
|
||||
file.addParserTest(input, "SimpleValidate2", "T", "s",
|
||||
tm.debug = true;
|
||||
tm = file.addParserTest(input, "SimpleValidate2", "T", "s",
|
||||
"3 4 x",
|
||||
"alt 2\n" + "alt 2\n",
|
||||
"line 1:4 no viable alternative at input 'x'\n");
|
||||
tm.debug = true;
|
||||
file.addParserTest(input, "AtomWithClosureInTranslatedLRRule", "T", "start",
|
||||
"a+b+a",
|
||||
"",
|
||||
null);
|
||||
file.addParserTest(input, "ValidateInDFA", "T", "s",
|
||||
tm = file.addParserTest(input, "ValidateInDFA", "T", "s",
|
||||
"x ; y",
|
||||
"",
|
||||
"line 1:0 no viable alternative at input 'x'\n" +
|
||||
"line 1:4 no viable alternative at input 'y'\n");
|
||||
file.addParserTest(input, "Simple", "T", "s",
|
||||
tm.debug = true;
|
||||
tm = file.addParserTest(input, "Simple", "T", "s",
|
||||
"x y 3",
|
||||
"alt 2\n" + "alt 2\n" + "alt 3\n",
|
||||
null);
|
||||
// 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.
|
||||
tm.debug = true;
|
||||
file.addParserTest(input, "Order", "T", "s",
|
||||
"x y",
|
||||
"alt 1\n" + "alt 1\n",
|
||||
null);
|
||||
// We have n-2 predicates for n alternatives. pick first alt
|
||||
file.addParserTest(input, "2UnpredicatedAlts", "T", "s",
|
||||
tm = file.addParserTest(input, "2UnpredicatedAlts", "T", "s",
|
||||
"x; y",
|
||||
"alt 1\n" +
|
||||
"alt 1\n",
|
||||
|
@ -261,7 +265,8 @@ public class Generator {
|
|||
"line 1:0 reportAmbiguity d=0 (a): ambigAlts={1, 2}, input='x'\n" +
|
||||
"line 1:3 reportAttemptingFullContext d=0 (a), input='y'\n" +
|
||||
"line 1:3 reportAmbiguity d=0 (a): ambigAlts={1, 2}, input='y'\n");
|
||||
file.addParserTest(input, "2UnpredicatedAltsAndOneOrthogonalAlt", "T", "s",
|
||||
tm.debug = true;
|
||||
tm = file.addParserTest(input, "2UnpredicatedAltsAndOneOrthogonalAlt", "T", "s",
|
||||
"34; x; y",
|
||||
"alt 1\n" + "alt 2\n" + "alt 2\n",
|
||||
"line 1:4 reportAttemptingFullContext d=0 (a), input='x'\n" +
|
||||
|
@ -271,24 +276,28 @@ public class Generator {
|
|||
// The parser consumes ID and moves to the 2nd token INT.
|
||||
// To properly evaluate the predicates after matching ID INT,
|
||||
// we must correctly see come back to starting index so LT(1) works
|
||||
file.addParserTest(input, "RewindBeforePredEval", "T", "s",
|
||||
tm.debug = true;
|
||||
tm = file.addParserTest(input, "RewindBeforePredEval", "T", "s",
|
||||
"y 3 x 4",
|
||||
"alt 2\n" + "alt 1\n",
|
||||
null);
|
||||
// checks that we throw exception if all alts
|
||||
// are covered with a predicate and none succeeds
|
||||
tm.debug = true;
|
||||
file.addParserTest(input, "NoTruePredsThrowsNoViableAlt", "T", "s",
|
||||
"y 3 x 4",
|
||||
"",
|
||||
"line 1:0 no viable alternative at input 'y'\n");
|
||||
file.addParserTest(input, "ToLeft", "T", "s",
|
||||
tm = file.addParserTest(input, "ToLeft", "T", "s",
|
||||
"x x y",
|
||||
"alt 2\n" + "alt 2\n" + "alt 2\n",
|
||||
null);
|
||||
file.addParserTest(input, "UnpredicatedPathsInAlt", "T", "s",
|
||||
tm.debug = true;
|
||||
tm = file.addParserTest(input, "UnpredicatedPathsInAlt", "T", "s",
|
||||
"x 4",
|
||||
"alt 1\n",
|
||||
null);
|
||||
tm.debug = true;
|
||||
file.addParserTest(input, "ActionHidesPreds", "T", "s",
|
||||
"x x y",
|
||||
"alt 1\n" + "alt 1\n" + "alt 1\n",
|
||||
|
@ -298,20 +307,22 @@ public class Generator {
|
|||
* the predicates assuming that all necessary information is available.
|
||||
* The i++ action is done outside of the prediction and so it is executed.
|
||||
*/
|
||||
file.addParserTest(input, "ToLeftWithVaryingPredicate", "T", "s",
|
||||
tm = file.addParserTest(input, "ToLeftWithVaryingPredicate", "T", "s",
|
||||
"x x y",
|
||||
"i=1\n" + "alt 2\n" + "i=2\n" + "alt 1\n" + "i=3\n" + "alt 2\n",
|
||||
null);
|
||||
tm.debug = true;
|
||||
/**
|
||||
* In this case, we're passing a parameter into a rule that uses that
|
||||
* information to predict the alternatives. This is the special case
|
||||
* where we know exactly which context we are in. The context stack
|
||||
* is empty and we have not dipped into the outer context to make a decision.
|
||||
*/
|
||||
file.addParserTest(input, "PredicateDependentOnArg", "T", "s",
|
||||
tm = file.addParserTest(input, "PredicateDependentOnArg", "T", "s",
|
||||
"a b",
|
||||
"alt 2\n" + "alt 1\n",
|
||||
null);
|
||||
tm.debug = true;
|
||||
/** In this case, we have to ensure that the predicates are not
|
||||
tested during the closure after recognizing the 1st ID. The
|
||||
closure will fall off the end of 'a' 1st time and reach into the
|
||||
|
@ -322,61 +333,70 @@ public class Generator {
|
|||
simulation doesn't crash with context object issues when it
|
||||
encounters preds during FOLLOW.
|
||||
*/
|
||||
file.addParserTest(input, "PredicateDependentOnArg2", "T", "s",
|
||||
tm = file.addParserTest(input, "PredicateDependentOnArg2", "T", "s",
|
||||
"a b",
|
||||
"",
|
||||
null);
|
||||
// uses ID ';' or ID '.' lookahead to solve s. preds not tested.
|
||||
file.addParserTest(input, "DependentPredNotInOuterCtxShouldBeIgnored", "T", "s",
|
||||
tm.debug = true;
|
||||
// uses ID ';' or ID '.' lookahead to solve s. preds not tested.
|
||||
tm = file.addParserTest(input, "DependentPredNotInOuterCtxShouldBeIgnored", "T", "s",
|
||||
"a;",
|
||||
"alt 2\n",
|
||||
null);
|
||||
file.addParserTest(input, "IndependentPredNotPassedOuterCtxToAvoidCastException", "T", "s",
|
||||
tm.debug = true;
|
||||
tm = file.addParserTest(input, "IndependentPredNotPassedOuterCtxToAvoidCastException", "T", "s",
|
||||
"a;",
|
||||
"alt 2\n",
|
||||
null);
|
||||
/** During a global follow operation, we still collect semantic
|
||||
tm.debug = true;
|
||||
/** During a global follow operation, we still collect semantic
|
||||
* predicates as long as they are not dependent on local context
|
||||
*/
|
||||
file.addParserTest(input, "PredsInGlobalFOLLOW", "T", "s",
|
||||
tm = file.addParserTest(input, "PredsInGlobalFOLLOW", "T", "s",
|
||||
"a!",
|
||||
"eval=true\n" + /* now we are parsing */ "parse\n",
|
||||
null);
|
||||
/** We cannot collect predicates that are dependent on local context if
|
||||
tm.debug = true;
|
||||
/** We cannot collect predicates that are dependent on local context if
|
||||
* we are doing a global follow. They appear as if they were not there at all.
|
||||
*/
|
||||
file.addParserTest(input, "DepedentPredsInGlobalFOLLOW","T", "s",
|
||||
tm = file.addParserTest(input, "DepedentPredsInGlobalFOLLOW","T", "s",
|
||||
"a!",
|
||||
"eval=true\n" + "parse\n",
|
||||
null);
|
||||
/** Regular non-forced actions can create side effects used by semantic
|
||||
tm.debug = true;
|
||||
/** Regular non-forced actions can create side effects used by semantic
|
||||
* predicates and so we cannot evaluate any semantic predicate
|
||||
* encountered after having seen a regular action. This includes
|
||||
* during global follow operations.
|
||||
*/
|
||||
file.addParserTest(input, "ActionsHidePredsInGlobalFOLLOW", "T", "s",
|
||||
tm = file.addParserTest(input, "ActionsHidePredsInGlobalFOLLOW", "T", "s",
|
||||
"a!",
|
||||
"eval=true\n" + "parse\n",
|
||||
null);
|
||||
file.addParserTestsWithErrors(input, "PredTestedEvenWhenUnAmbig", "T", "primary",
|
||||
tm.debug = true;
|
||||
tm = file.addParserTestsWithErrors(input, "PredTestedEvenWhenUnAmbig", "T", "primary",
|
||||
"abc", "ID abc\n", null,
|
||||
"enum", "", "line 1:0 no viable alternative at input 'enum'\n");
|
||||
tm.debug = true;
|
||||
/**
|
||||
* This is a regression test for antlr/antlr4#218 "ANTLR4 EOF Related Bug".
|
||||
* https://github.com/antlr/antlr4/issues/218
|
||||
*/
|
||||
file.addParserTest(input, "DisabledAlternative", "T", "cppCompilationUnit",
|
||||
tm = file.addParserTest(input, "DisabledAlternative", "T", "cppCompilationUnit",
|
||||
"hello",
|
||||
"",
|
||||
null);
|
||||
tm.debug = true;
|
||||
/** Loopback doesn't eval predicate at start of alt */
|
||||
file.addParserTestsWithErrors(input, "PredFromAltTestedInLoopBack", "T", "file_",
|
||||
tm = file.addParserTestsWithErrors(input, "PredFromAltTestedInLoopBack", "T", "file_",
|
||||
"s\n\n\nx\n",
|
||||
"(file_ (para (paraContent s) \n \n) (para (paraContent \n x \n)) <EOF>)\n",
|
||||
"(file_ (para (paraContent s) \\n \\n) (para (paraContent \\n x \\n)) <EOF>)\n",
|
||||
"line 5:2 mismatched input '<EOF>' expecting '\n'\n",
|
||||
"s\n\n\nx\n\n",
|
||||
"(file_ (para (paraContent s) \n \n) (para (paraContent \n x) \n \n) <EOF>)\n",
|
||||
"(file_ (para (paraContent s) \\n \\n) (para (paraContent \\n x) \\n \\n) <EOF>)\n",
|
||||
null);
|
||||
tm.debug = true;
|
||||
return file;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ s : {<LL_EXACT_AMBIG_DETECTION()>} a ';' a ';' a;
|
|||
a : INT {<writeln("\"alt 1\"")>}
|
||||
| ID {<writeln("\"alt 2\"")>} // must pick this one for ID since pred is false
|
||||
| ID {<writeln("\"alt 3\"")>}
|
||||
| {<false>}? ID {console.log(\"alt 4\");}
|
||||
| {<false>}? ID {<writeln("\"alt 4\"")>}
|
||||
;
|
||||
ID : 'a'..'z'+ ;
|
||||
INT : '0'..'9'+;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
grammar <grammarName>;
|
||||
@members {<InitMember("i","0")>}
|
||||
@members {<InitIntMember("i","0")>}
|
||||
s : a+ ;
|
||||
a : {<SetMember("i","1")>} ID {<MemberEquals("i","1")>}? {<writeln("\"alt 1\"")>}
|
||||
| {<SetMember("i","2")>} ID {<MemberEquals("i","2")>}? {<writeln("\"alt 2\"")>}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
grammar <grammarName>;
|
||||
@members {
|
||||
this.p = function(v) {
|
||||
<Declare_pred()>
|
||||
}
|
||||
s : e {} {<true:Invoke_pred()>}? {<writeln("\"parse\"")>} '!' ;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
grammar <grammarName>;
|
||||
s : b[2] ';' | b[2] '.' ; // decision in s drills down to ctx-dependent pred in a;
|
||||
b[int i] : a[i] ;
|
||||
a[int i]" +
|
||||
a[int i]
|
||||
: {<ValEquals("$i","1")>}? ID {<writeln("\"alt 1\"")>}
|
||||
| {<ValEquals("$i","2")>}? ID {<writeln("\"alt 2\"")>}
|
||||
;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
grammar <grammarName>;
|
||||
@members {<InitMember("enumKeyword",true)>}
|
||||
@members {<InitBooleanMember("enumKeyword",true)>}
|
||||
primary
|
||||
: ID {<writeln("\"ID \"+$ID.text")>}
|
||||
| {!<GetMember("enumKeyword")>}? 'enum' {<writeln("\"enum\"")>}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
grammar <grammarName>;
|
||||
@members {i=0}
|
||||
@members {<InitIntMember("i","0")>}
|
||||
s : a[2] a[1];
|
||||
"a[int i]" +
|
||||
" : {<ValEquals("$i","1")>}? ID {<writeln("\"alt 1\"")>}
|
||||
a[int i]
|
||||
: {<ValEquals("$i","1")>}? ID {<writeln("\"alt 1\"")>}
|
||||
| {<ValEquals("$i","2")>}? ID {<writeln("\"alt 2\"")>}
|
||||
;
|
||||
ID : 'a'..'z'+ ;
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
grammar <grammarName>;
|
||||
@members {i=0}
|
||||
@members {<InitIntMember("i","0")>}
|
||||
s : a[2] a[1];
|
||||
a[int i]" +
|
||||
: {<ValEquals("$i","1")>}? ID {<writeln("\"alt 1\"")>}
|
||||
| {<ValEquals("$i","2")>}? ID {<writeln("\"alt 2\"")>}
|
||||
a[int i]
|
||||
: {<ValEquals("$i","1")>}? ID
|
||||
| {<ValEquals("$i","2")>}? ID
|
||||
;
|
||||
ID : 'a'..'z'+ ;
|
||||
INT : '0'..'9'+;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
grammar <grammarName>;
|
||||
@members {this.i=0}
|
||||
s : ({<AddMember("i","1")>\n<PlusMember("\"i=\"","i"):writeln()>} a)+ ;
|
||||
@members {<InitIntMember("i","0")>}
|
||||
s : ({<AddMember("i","1")>
|
||||
<PlusMember("\"i=\"","i"):writeln()>} a)+ ;
|
||||
a : {<ModMemberEquals("i","2","0")>}? ID {<writeln("\"alt 1\"")>}
|
||||
| {<ModMemberNotEquals("i","2","0")>}? ID {<writeln("\"alt 2\"")>}
|
||||
;
|
||||
|
|
|
@ -109,7 +109,9 @@ DeclareLocal(s,v) ::= "Object <s> = <v>;"
|
|||
|
||||
AssignLocal(s,v) ::= "<s> = <v>;"
|
||||
|
||||
InitMember(n,v) ::= <%this.<n> = <v>;%>
|
||||
InitIntMember(n,v) ::= <%int <n> = <v>;%>
|
||||
|
||||
InitBooleanMember(n,v) ::= <%boolean <n> = <v>;%>
|
||||
|
||||
GetMember(n) ::= <%this.<n>%>
|
||||
|
||||
|
@ -119,11 +121,11 @@ AddMember(n,v) ::= <%this.<n> += <v>;%>
|
|||
|
||||
PlusMember(v,n) ::= <%<v> + this.<n>%>
|
||||
|
||||
MemberEquals(n,v) ::= <%this.<n> === <v>%>
|
||||
MemberEquals(n,v) ::= <%this.<n> == <v>%>
|
||||
|
||||
ModMemberEquals(n,m,v) ::= <%this.<n> % m === <v>%>
|
||||
ModMemberEquals(n,m,v) ::= <%this.<n> % <m> == <v>%>
|
||||
|
||||
ModMemberNotEquals(n,m,v) ::= <%this.<n> % m != <v>%>
|
||||
ModMemberNotEquals(n,m,v) ::= <%this.<n> % <m> != <v>%>
|
||||
|
||||
DumpDFA() ::= "this.dumpDFA();"
|
||||
|
||||
|
@ -141,7 +143,7 @@ Column() ::= "this.getCharPositionInLine()"
|
|||
|
||||
Text() ::= "this.getText()"
|
||||
|
||||
ValEquals(a,b) ::= <%<a>===<b>%>
|
||||
ValEquals(a,b) ::= <%<a>==<b>%>
|
||||
|
||||
TextEquals(a) ::= <%this.getText().equals("<a>")%>
|
||||
|
||||
|
@ -149,7 +151,7 @@ PlusText(a) ::= <%"<a>" + this.getText()%>
|
|||
|
||||
InputText() ::= "this._input.getText()"
|
||||
|
||||
LTEquals(i, v) ::= <%this._input.LT(<i>).text===<v>%>
|
||||
LTEquals(i, v) ::= <%this._input.LT(<i>).getText().equals(<v>)%>
|
||||
|
||||
LANotEquals(i, v) ::= <%this._input.LA(<i>)!=<v>%>
|
||||
|
||||
|
@ -161,7 +163,7 @@ GetExpectedTokenNames() ::= "this.getExpectedTokens().toString(this.tokenNames)"
|
|||
|
||||
WriteRuleInvocationStack() ::= "System.out.println(getRuleInvocationStack());"
|
||||
|
||||
LL_EXACT_AMBIG_DETECTION() ::= <<this._interp.predictionMode = antlr4.atn.PredictionMode.LL_EXACT_AMBIG_DETECTION;>>
|
||||
LL_EXACT_AMBIG_DETECTION() ::= <<_interp.setPredictionMode(PredictionMode.LL_EXACT_AMBIG_DETECTION);>>
|
||||
|
||||
PositionAdjustingLexer() ::= <<
|
||||
|
||||
|
@ -320,10 +322,10 @@ Declare_foo() ::= <<public void foo() {System.out.println("foo");}>>
|
|||
|
||||
Invoke_foo() ::= "this.foo();"
|
||||
|
||||
Declare_pred() ::= <<this.pred = function(v) {
|
||||
document.getElementById('output').value += 'eval=" + v.toString() + '\\n';
|
||||
Declare_pred() ::= <<boolean pred(boolean v) {
|
||||
System.out.println("eval="+v);
|
||||
return v;
|
||||
};
|
||||
}
|
||||
>>
|
||||
|
||||
Invoke_pred(v) ::= <<this.pred(<v>)>>
|
||||
|
|
|
@ -79,7 +79,7 @@ public class TestFullContextParsing extends BaseTest {
|
|||
String testFullContextIF_THEN_ELSEParse(String input) throws Exception {
|
||||
String grammar = "grammar T;\n" +
|
||||
"s \n" +
|
||||
"@init {this._interp.predictionMode = antlr4.atn.PredictionMode.LL_EXACT_AMBIG_DETECTION;}\n" +
|
||||
"@init {_interp.setPredictionMode(PredictionMode.LL_EXACT_AMBIG_DETECTION);}\n" +
|
||||
"@after {this.dumpDFA();}\n" +
|
||||
" : '{' stat* '}' ;\n" +
|
||||
"stat: 'if' ID 'then' stat ('else' ID)?\n" +
|
||||
|
@ -136,7 +136,7 @@ public class TestFullContextParsing extends BaseTest {
|
|||
public void testLoopsSimulateTailRecursion() throws Exception {
|
||||
String grammar = "grammar T;\n" +
|
||||
"prog\n" +
|
||||
"@init {this._interp.predictionMode = antlr4.atn.PredictionMode.LL_EXACT_AMBIG_DETECTION;}\n" +
|
||||
"@init {_interp.setPredictionMode(PredictionMode.LL_EXACT_AMBIG_DETECTION);}\n" +
|
||||
" : expr_or_assign*;\n" +
|
||||
"expr_or_assign\n" +
|
||||
" : expr '++' {System.out.println(\"fail.\");}\n" +
|
||||
|
@ -158,7 +158,7 @@ public class TestFullContextParsing extends BaseTest {
|
|||
public void testAmbiguityNoLoop() throws Exception {
|
||||
String grammar = "grammar T;\n" +
|
||||
"prog\n" +
|
||||
"@init {this._interp.predictionMode = antlr4.atn.PredictionMode.LL_EXACT_AMBIG_DETECTION;}\n" +
|
||||
"@init {_interp.setPredictionMode(PredictionMode.LL_EXACT_AMBIG_DETECTION);}\n" +
|
||||
" : expr expr {System.out.println(\"alt 1\");}\n" +
|
||||
" | expr\n" +
|
||||
" ;\n" +
|
||||
|
@ -176,7 +176,7 @@ public class TestFullContextParsing extends BaseTest {
|
|||
String testExprAmbiguity(String input) throws Exception {
|
||||
String grammar = "grammar T;\n" +
|
||||
"s\n" +
|
||||
"@init {this._interp.predictionMode = antlr4.atn.PredictionMode.LL_EXACT_AMBIG_DETECTION;}\n" +
|
||||
"@init {_interp.setPredictionMode(PredictionMode.LL_EXACT_AMBIG_DETECTION);}\n" +
|
||||
": expr[0] {System.out.println($expr.ctx.toStringTree(this));};\n" +
|
||||
" expr[int _p]\n" +
|
||||
" : ID \n" +
|
||||
|
|
|
@ -15,7 +15,7 @@ public class TestSemPredEvalParser extends BaseTest {
|
|||
"ID : 'a'..'z'+ ;\n" +
|
||||
"INT : '0'..'9'+;\n" +
|
||||
"WS : (' '|'\\n') -> skip ;";
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "x", false);
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "x", true);
|
||||
assertEquals("", found);
|
||||
assertEquals("line 1:0 no viable alternative at input 'x'\n", this.stderrDuringParse);
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ public class TestSemPredEvalParser extends BaseTest {
|
|||
"ID : 'a'..'z'+ ;\n" +
|
||||
"INT : '0'..'9'+;\n" +
|
||||
"WS : (' '|'\\n') -> skip ;";
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "3 4 x", false);
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "3 4 x", true);
|
||||
assertEquals("alt 2\nalt 2\n", found);
|
||||
assertEquals("line 1:4 no viable alternative at input 'x'\n", this.stderrDuringParse);
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ public class TestSemPredEvalParser extends BaseTest {
|
|||
"ID : 'a'..'z'+ ;\n" +
|
||||
"INT : '0'..'9'+;\n" +
|
||||
"WS : (' '|'\\n') -> skip ;";
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "x ; y", false);
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "x ; y", true);
|
||||
assertEquals("", found);
|
||||
assertEquals("line 1:0 no viable alternative at input 'x'\nline 1:4 no viable alternative at input 'y'\n", this.stderrDuringParse);
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ public class TestSemPredEvalParser extends BaseTest {
|
|||
"ID : 'a'..'z'+ ;\n" +
|
||||
"INT : '0'..'9'+;\n" +
|
||||
"WS : (' '|'\\n') -> skip ;";
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "x y 3", false);
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "x y 3", true);
|
||||
assertEquals("alt 2\nalt 2\nalt 3\n", found);
|
||||
assertNull(this.stderrDuringParse);
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ public class TestSemPredEvalParser extends BaseTest {
|
|||
@Test
|
||||
public void test2UnpredicatedAlts() throws Exception {
|
||||
String grammar = "grammar T;\n" +
|
||||
"s : {this._interp.predictionMode = antlr4.atn.PredictionMode.LL_EXACT_AMBIG_DETECTION;} a ';' a; // do 2x: once in ATN, next in DFA\n" +
|
||||
"s : {_interp.setPredictionMode(PredictionMode.LL_EXACT_AMBIG_DETECTION);} a ';' a; // do 2x: once in ATN, next in DFA\n" +
|
||||
"a : ID {System.out.println(\"alt 1\");}\n" +
|
||||
" | ID {System.out.println(\"alt 2\");}\n" +
|
||||
" | {false}? ID {System.out.println(\"alt 3\");}\n" +
|
||||
|
@ -109,7 +109,7 @@ public class TestSemPredEvalParser extends BaseTest {
|
|||
"ID : 'a'..'z'+ ;\n" +
|
||||
"INT : '0'..'9'+;\n" +
|
||||
"WS : (' '|'\\n') -> skip ;";
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "x; y", false);
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "x; y", true);
|
||||
assertEquals("alt 1\nalt 1\n", found);
|
||||
assertEquals("line 1:0 reportAttemptingFullContext d=0 (a), input='x'\nline 1:0 reportAmbiguity d=0 (a): ambigAlts={1, 2}, input='x'\nline 1:3 reportAttemptingFullContext d=0 (a), input='y'\nline 1:3 reportAmbiguity d=0 (a): ambigAlts={1, 2}, input='y'\n", this.stderrDuringParse);
|
||||
}
|
||||
|
@ -117,16 +117,16 @@ public class TestSemPredEvalParser extends BaseTest {
|
|||
@Test
|
||||
public void test2UnpredicatedAltsAndOneOrthogonalAlt() throws Exception {
|
||||
String grammar = "grammar T;\n" +
|
||||
"s : {this._interp.predictionMode = antlr4.atn.PredictionMode.LL_EXACT_AMBIG_DETECTION;} a ';' a ';' a;\n" +
|
||||
"s : {_interp.setPredictionMode(PredictionMode.LL_EXACT_AMBIG_DETECTION);} a ';' a ';' a;\n" +
|
||||
"a : INT {System.out.println(\"alt 1\");}\n" +
|
||||
" | ID {System.out.println(\"alt 2\");} // must pick this one for ID since pred is false\n" +
|
||||
" | ID {System.out.println(\"alt 3\");}\n" +
|
||||
" | {false}? ID {console.log(\\\"alt 4\\\");}\n" +
|
||||
" | {false}? ID {System.out.println(\"alt 4\");}\n" +
|
||||
" ;\n" +
|
||||
"ID : 'a'..'z'+ ;\n" +
|
||||
"INT : '0'..'9'+;\n" +
|
||||
"WS : (' '|'\\n') -> skip ;";
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "34; x; y", false);
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "34; x; y", true);
|
||||
assertEquals("alt 1\nalt 2\nalt 2\n", found);
|
||||
assertEquals("line 1:4 reportAttemptingFullContext d=0 (a), input='x'\nline 1:4 reportAmbiguity d=0 (a): ambigAlts={2, 3}, input='x'\nline 1:7 reportAttemptingFullContext d=0 (a), input='y'\nline 1:7 reportAmbiguity d=0 (a): ambigAlts={2, 3}, input='y'\n", this.stderrDuringParse);
|
||||
}
|
||||
|
@ -135,13 +135,13 @@ public class TestSemPredEvalParser extends BaseTest {
|
|||
public void testRewindBeforePredEval() throws Exception {
|
||||
String grammar = "grammar T;\n" +
|
||||
"s : a a;\n" +
|
||||
"a : {this._input.LT(1).text===\"x\"}? ID INT {System.out.println(\"alt 1\");}\n" +
|
||||
" | {this._input.LT(1).text===\"y\"}? ID INT {System.out.println(\"alt 2\");}\n" +
|
||||
"a : {this._input.LT(1).getText().equals(\"x\")}? ID INT {System.out.println(\"alt 1\");}\n" +
|
||||
" | {this._input.LT(1).getText().equals(\"y\")}? ID INT {System.out.println(\"alt 2\");}\n" +
|
||||
" ;\n" +
|
||||
"ID : 'a'..'z'+ ;\n" +
|
||||
"INT : '0'..'9'+;\n" +
|
||||
"WS : (' '|'\\n') -> skip ;";
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "y 3 x 4", false);
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "y 3 x 4", true);
|
||||
assertEquals("alt 2\nalt 1\n", found);
|
||||
assertNull(this.stderrDuringParse);
|
||||
}
|
||||
|
@ -171,7 +171,7 @@ public class TestSemPredEvalParser extends BaseTest {
|
|||
"ID : 'a'..'z'+ ;\n" +
|
||||
"INT : '0'..'9'+;\n" +
|
||||
"WS : (' '|'\\n') -> skip ;";
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "x x y", false);
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "x x y", true);
|
||||
assertEquals("alt 2\nalt 2\nalt 2\n", found);
|
||||
assertNull(this.stderrDuringParse);
|
||||
}
|
||||
|
@ -190,7 +190,7 @@ public class TestSemPredEvalParser extends BaseTest {
|
|||
"ID : 'a'..'z'+ ;\n" +
|
||||
"INT : '0'..'9'+;\n" +
|
||||
"WS : (' '|'\\n') -> skip ;";
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "x 4", false);
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "x 4", true);
|
||||
assertEquals("alt 1\n", found);
|
||||
assertNull(this.stderrDuringParse);
|
||||
}
|
||||
|
@ -198,10 +198,10 @@ public class TestSemPredEvalParser extends BaseTest {
|
|||
@Test
|
||||
public void testActionHidesPreds() throws Exception {
|
||||
String grammar = "grammar T;\n" +
|
||||
"@members {this.i = 0;}\n" +
|
||||
"@members {int i = 0;}\n" +
|
||||
"s : a+ ;\n" +
|
||||
"a : {this.i = 1;} ID {this.i === 1}? {System.out.println(\"alt 1\");}\n" +
|
||||
" | {this.i = 2;} ID {this.i === 2}? {System.out.println(\"alt 2\");}\n" +
|
||||
"a : {this.i = 1;} ID {this.i == 1}? {System.out.println(\"alt 1\");}\n" +
|
||||
" | {this.i = 2;} ID {this.i == 2}? {System.out.println(\"alt 2\");}\n" +
|
||||
" ;\n" +
|
||||
"ID : 'a'..'z'+ ;\n" +
|
||||
"INT : '0'..'9'+;\n" +
|
||||
|
@ -214,15 +214,16 @@ public class TestSemPredEvalParser extends BaseTest {
|
|||
@Test
|
||||
public void testToLeftWithVaryingPredicate() throws Exception {
|
||||
String grammar = "grammar T;\n" +
|
||||
"@members {this.i=0}\n" +
|
||||
"s : ({this.i += 1;\\nSystem.out.println(\"i=\" + this.i);} a)+ ;\n" +
|
||||
"a : {this.i % m === 0}? ID {System.out.println(\"alt 1\");}\n" +
|
||||
" | {this.i % m != 0}? ID {System.out.println(\"alt 2\");}\n" +
|
||||
"@members {int i = 0;}\n" +
|
||||
"s : ({this.i += 1;\n" +
|
||||
" System.out.println(\"i=\" + this.i);} a)+ ;\n" +
|
||||
"a : {this.i % 2 == 0}? ID {System.out.println(\"alt 1\");}\n" +
|
||||
" | {this.i % 2 != 0}? ID {System.out.println(\"alt 2\");}\n" +
|
||||
" ;\n" +
|
||||
"ID : 'a'..'z'+ ;\n" +
|
||||
"INT : '0'..'9'+;\n" +
|
||||
"WS : (' '|'\\n') -> skip ;";
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "x x y", false);
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "x x y", true);
|
||||
assertEquals("i=1\nalt 2\ni=2\nalt 1\ni=3\nalt 2\n", found);
|
||||
assertNull(this.stderrDuringParse);
|
||||
}
|
||||
|
@ -230,16 +231,16 @@ public class TestSemPredEvalParser extends BaseTest {
|
|||
@Test
|
||||
public void testPredicateDependentOnArg() throws Exception {
|
||||
String grammar = "grammar T;\n" +
|
||||
"@members {i=0}\n" +
|
||||
"@members {int i = 0;}\n" +
|
||||
"s : a[2] a[1];\n" +
|
||||
"\"a[int i]\" +\n" +
|
||||
"\" : {$i===1}? ID {System.out.println(\"alt 1\");}\n" +
|
||||
" | {$i===2}? ID {System.out.println(\"alt 2\");}\n" +
|
||||
"a[int i]\n" +
|
||||
" : {$i==1}? ID {System.out.println(\"alt 1\");}\n" +
|
||||
" | {$i==2}? ID {System.out.println(\"alt 2\");}\n" +
|
||||
" ;\n" +
|
||||
"ID : 'a'..'z'+ ;\n" +
|
||||
"INT : '0'..'9'+;\n" +
|
||||
"WS : (' '|'\\n') -> skip ;";
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "a b", false);
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "a b", true);
|
||||
assertEquals("alt 2\nalt 1\n", found);
|
||||
assertNull(this.stderrDuringParse);
|
||||
}
|
||||
|
@ -247,16 +248,16 @@ public class TestSemPredEvalParser extends BaseTest {
|
|||
@Test
|
||||
public void testPredicateDependentOnArg2() throws Exception {
|
||||
String grammar = "grammar T;\n" +
|
||||
"@members {i=0}\n" +
|
||||
"@members {int i = 0;}\n" +
|
||||
"s : a[2] a[1];\n" +
|
||||
"a[int i]\" +\n" +
|
||||
" : {$i===1}? ID {System.out.println(\"alt 1\");}\n" +
|
||||
" | {$i===2}? ID {System.out.println(\"alt 2\");}\n" +
|
||||
"a[int i]\n" +
|
||||
" : {$i==1}? ID \n" +
|
||||
" | {$i==2}? ID \n" +
|
||||
" ;\n" +
|
||||
"ID : 'a'..'z'+ ;\n" +
|
||||
"INT : '0'..'9'+;\n" +
|
||||
"WS : (' '|'\\n') -> skip ;";
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "a b", false);
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "a b", true);
|
||||
assertEquals("", found);
|
||||
assertNull(this.stderrDuringParse);
|
||||
}
|
||||
|
@ -266,14 +267,14 @@ public class TestSemPredEvalParser extends BaseTest {
|
|||
String grammar = "grammar T;\n" +
|
||||
"s : b[2] ';' | b[2] '.' ; // decision in s drills down to ctx-dependent pred in a;\n" +
|
||||
"b[int i] : a[i] ;\n" +
|
||||
"a[int i]\" +\n" +
|
||||
" : {$i===1}? ID {System.out.println(\"alt 1\");}\n" +
|
||||
" | {$i===2}? ID {System.out.println(\"alt 2\");}\n" +
|
||||
"a[int i]\n" +
|
||||
" : {$i==1}? ID {System.out.println(\"alt 1\");}\n" +
|
||||
" | {$i==2}? ID {System.out.println(\"alt 2\");}\n" +
|
||||
" ;\n" +
|
||||
"ID : 'a'..'z'+ ;\n" +
|
||||
"INT : '0'..'9'+;\n" +
|
||||
"WS : (' '|'\\n') -> skip ;";
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "a;", false);
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "a;", true);
|
||||
assertEquals("alt 2\n", found);
|
||||
assertNull(this.stderrDuringParse);
|
||||
}
|
||||
|
@ -290,7 +291,7 @@ public class TestSemPredEvalParser extends BaseTest {
|
|||
"ID : 'a'..'z'+ ;\n" +
|
||||
"INT : '0'..'9'+;\n" +
|
||||
"WS : (' '|'\\n') -> skip ;";
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "a;", false);
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "a;", true);
|
||||
assertEquals("alt 2\n", found);
|
||||
assertNull(this.stderrDuringParse);
|
||||
}
|
||||
|
@ -299,10 +300,10 @@ public class TestSemPredEvalParser extends BaseTest {
|
|||
public void testPredsInGlobalFOLLOW() throws Exception {
|
||||
String grammar = "grammar T;\n" +
|
||||
"@members {\n" +
|
||||
"this.pred = function(v) {\n" +
|
||||
" document.getElementById('output').value += 'eval=\" + v.toString() + '\\n';\n" +
|
||||
"boolean pred(boolean v) {\n" +
|
||||
" System.out.println(\"eval=\"+v);\n" +
|
||||
" return v;\n" +
|
||||
"};\n" +
|
||||
"}\n" +
|
||||
"}\n" +
|
||||
"s : e {this.pred(true)}? {System.out.println(\"parse\");} '!' ;\n" +
|
||||
"t : e {this.pred(false)}? ID ;\n" +
|
||||
|
@ -310,7 +311,7 @@ public class TestSemPredEvalParser extends BaseTest {
|
|||
"ID : 'a'..'z'+ ;\n" +
|
||||
"INT : '0'..'9'+;\n" +
|
||||
"WS : (' '|'\\n') -> skip ;";
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "a!", false);
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "a!", true);
|
||||
assertEquals("eval=true\nparse\n", found);
|
||||
assertNull(this.stderrDuringParse);
|
||||
}
|
||||
|
@ -319,19 +320,19 @@ public class TestSemPredEvalParser extends BaseTest {
|
|||
public void testDepedentPredsInGlobalFOLLOW() throws Exception {
|
||||
String grammar = "grammar T;\n" +
|
||||
"@members {\n" +
|
||||
"this.pred = function(v) {\n" +
|
||||
" document.getElementById('output').value += 'eval=\" + v.toString() + '\\n';\n" +
|
||||
"boolean pred(boolean v) {\n" +
|
||||
" System.out.println(\"eval=\"+v);\n" +
|
||||
" return v;\n" +
|
||||
"};\n" +
|
||||
"}\n" +
|
||||
"}\n" +
|
||||
"s : a[99] ;\n" +
|
||||
"a[int i] : e {this.pred($i===99)}? {System.out.println(\"parse\");} '!' ;\n" +
|
||||
"b[int i] : e {this.pred($i===99)}? ID ;\n" +
|
||||
"a[int i] : e {this.pred($i==99)}? {System.out.println(\"parse\");} '!' ;\n" +
|
||||
"b[int i] : e {this.pred($i==99)}? ID ;\n" +
|
||||
"e : ID | ; // non-LL(1) so we use ATN\n" +
|
||||
"ID : 'a'..'z'+ ;\n" +
|
||||
"INT : '0'..'9'+;\n" +
|
||||
"WS : (' '|'\\n') -> skip ;";
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "a!", false);
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "a!", true);
|
||||
assertEquals("eval=true\nparse\n", found);
|
||||
assertNull(this.stderrDuringParse);
|
||||
}
|
||||
|
@ -340,11 +341,10 @@ public class TestSemPredEvalParser extends BaseTest {
|
|||
public void testActionsHidePredsInGlobalFOLLOW() throws Exception {
|
||||
String grammar = "grammar T;\n" +
|
||||
"@members {\n" +
|
||||
"this.p = function(v) {\n" +
|
||||
"this.pred = function(v) {\n" +
|
||||
" document.getElementById('output').value += 'eval=\" + v.toString() + '\\n';\n" +
|
||||
"boolean pred(boolean v) {\n" +
|
||||
" System.out.println(\"eval=\"+v);\n" +
|
||||
" return v;\n" +
|
||||
"};\n" +
|
||||
"}\n" +
|
||||
"}\n" +
|
||||
"s : e {} {this.pred(true)}? {System.out.println(\"parse\");} '!' ;\n" +
|
||||
"t : e {} {this.pred(false)}? ID ;\n" +
|
||||
|
@ -352,21 +352,21 @@ public class TestSemPredEvalParser extends BaseTest {
|
|||
"ID : 'a'..'z'+ ;\n" +
|
||||
"INT : '0'..'9'+;\n" +
|
||||
"WS : (' '|'\\n') -> skip ;";
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "a!", false);
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "a!", true);
|
||||
assertEquals("eval=true\nparse\n", found);
|
||||
assertNull(this.stderrDuringParse);
|
||||
}
|
||||
|
||||
String testPredTestedEvenWhenUnAmbig(String input) throws Exception {
|
||||
String grammar = "grammar T;\n" +
|
||||
"@members {this.enumKeyword = true;}\n" +
|
||||
"@members {boolean enumKeyword = true;}\n" +
|
||||
"primary\n" +
|
||||
" : ID {System.out.println(\"ID \"+$ID.text);}\n" +
|
||||
" | {!this.enumKeyword}? 'enum' {System.out.println(\"enum\");}\n" +
|
||||
" ;\n" +
|
||||
"ID : [a-z]+ ;\n" +
|
||||
"WS : [ \\t\\n\\r]+ -> skip ;";
|
||||
return execParser("T.g4", grammar, "TParser", "TLexer", "primary", input, false);
|
||||
return execParser("T.g4", grammar, "TParser", "TLexer", "primary", input, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -390,7 +390,7 @@ public class TestSemPredEvalParser extends BaseTest {
|
|||
"content: anything | {false}? .;\n" +
|
||||
"anything: ANY_CHAR;\n" +
|
||||
"ANY_CHAR: [_a-zA-Z0-9];";
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "cppCompilationUnit", "hello", false);
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "cppCompilationUnit", "hello", true);
|
||||
assertEquals("", found);
|
||||
assertNull(this.stderrDuringParse);
|
||||
}
|
||||
|
@ -405,20 +405,20 @@ public class TestSemPredEvalParser extends BaseTest {
|
|||
"NL : '\\n' ;\n" +
|
||||
"s : 's' ;\n" +
|
||||
"X : 'x' ;";
|
||||
return execParser("T.g4", grammar, "TParser", "TLexer", "file_", input, false);
|
||||
return execParser("T.g4", grammar, "TParser", "TLexer", "file_", input, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPredFromAltTestedInLoopBack_1() throws Exception {
|
||||
String found = testPredFromAltTestedInLoopBack("s\n\n\nx\n");
|
||||
assertEquals("(file_ (para (paraContent s) \n \n) (para (paraContent \n x \n)) <EOF>)\n", found);
|
||||
assertEquals("(file_ (para (paraContent s) \\n \\n) (para (paraContent \\n x \\n)) <EOF>)\n", found);
|
||||
assertEquals("line 5:2 mismatched input '<EOF>' expecting '\n'\n", this.stderrDuringParse);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPredFromAltTestedInLoopBack_2() throws Exception {
|
||||
String found = testPredFromAltTestedInLoopBack("s\n\n\nx\n\n");
|
||||
assertEquals("(file_ (para (paraContent s) \n \n) (para (paraContent \n x) \n \n) <EOF>)\n", found);
|
||||
assertEquals("(file_ (para (paraContent s) \\n \\n) (para (paraContent \\n x) \\n \\n) <EOF>)\n", found);
|
||||
assertNull(this.stderrDuringParse);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,626 +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;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
public class TestSemPredEvalParser extends BaseTest {
|
||||
// TEST VALIDATING PREDS
|
||||
|
||||
@Test public void testSimpleValidate() throws Exception {
|
||||
String grammar =
|
||||
"grammar T;\n" +
|
||||
"s : a ;\n" +
|
||||
"a : {false}? ID {System.out.println(\"alt 1\");}\n" +
|
||||
" | {true}? INT {System.out.println(\"alt 2\");}\n" +
|
||||
" ;\n" +
|
||||
"ID : 'a'..'z'+ ;\n" +
|
||||
"INT : '0'..'9'+;\n" +
|
||||
"WS : (' '|'\\n') -> skip ;\n";
|
||||
|
||||
/*String found = */execParser("T.g4", grammar, "TParser", "TLexer", "s",
|
||||
"x", false);
|
||||
|
||||
String expecting = "line 1:0 no viable alternative at input 'x'\n";
|
||||
assertEquals(expecting, stderrDuringParse);
|
||||
}
|
||||
|
||||
@Test public void testSimpleValidate2() throws Exception {
|
||||
String grammar =
|
||||
"grammar T;\n" +
|
||||
"s : a a a;\n" +
|
||||
"a : {false}? ID {System.out.println(\"alt 1\");}\n" +
|
||||
" | {true}? INT {System.out.println(\"alt 2\");}\n" +
|
||||
" ;\n" +
|
||||
"ID : 'a'..'z'+ ;\n" +
|
||||
"INT : '0'..'9'+;\n" +
|
||||
"WS : (' '|'\\n') -> skip ;\n";
|
||||
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s",
|
||||
"3 4 x", false);
|
||||
String expecting =
|
||||
"alt 2\n" +
|
||||
"alt 2\n";
|
||||
assertEquals(expecting, found);
|
||||
|
||||
expecting = "line 1:4 no viable alternative at input 'x'\n";
|
||||
assertEquals(expecting, stderrDuringParse);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a regression test for antlr/antlr4#196
|
||||
* "element+ in expression grammar doesn't parse properly"
|
||||
* https://github.com/antlr/antlr4/issues/196
|
||||
*/
|
||||
@Test public void testAtomWithClosureInTranslatedLRRule() throws Exception {
|
||||
String grammar =
|
||||
"grammar T;\n" +
|
||||
"start : e[0] EOF;\n" +
|
||||
"e[int _p]\n" +
|
||||
" : ( 'a'\n" +
|
||||
" | 'b'+\n" +
|
||||
" )\n" +
|
||||
" ( {3 >= $_p}? '+' e[4]\n" +
|
||||
" )*\n" +
|
||||
" ;\n";
|
||||
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "start",
|
||||
"a+b+a", false);
|
||||
String expecting = "";
|
||||
assertEquals(expecting, found);
|
||||
assertNull(stderrDuringParse);
|
||||
}
|
||||
|
||||
@Test public void testValidateInDFA() throws Exception {
|
||||
String grammar =
|
||||
"grammar T;\n" +
|
||||
"s : a ';' a;\n" +
|
||||
// ';' helps us to resynchronize without consuming
|
||||
// 2nd 'a' reference. We our testing that the DFA also
|
||||
// throws an exception if the validating predicate fails
|
||||
"a : {false}? ID {System.out.println(\"alt 1\");}\n" +
|
||||
" | {true}? INT {System.out.println(\"alt 2\");}\n" +
|
||||
" ;\n" +
|
||||
"ID : 'a'..'z'+ ;\n" +
|
||||
"INT : '0'..'9'+;\n" +
|
||||
"WS : (' '|'\\n') -> skip ;\n";
|
||||
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s",
|
||||
"x ; y", false);
|
||||
String expecting = "";
|
||||
assertEquals(expecting, found);
|
||||
|
||||
expecting =
|
||||
"line 1:0 no viable alternative at input 'x'\n" +
|
||||
"line 1:4 no viable alternative at input 'y'\n";
|
||||
assertEquals(expecting, stderrDuringParse);
|
||||
}
|
||||
|
||||
// TEST DISAMBIG PREDS
|
||||
|
||||
@Test public void testSimple() throws Exception {
|
||||
String grammar =
|
||||
"grammar T;\n" +
|
||||
"s : a a a;\n" + // do 3x: once in ATN, next in DFA then INT in ATN
|
||||
"a : {false}? ID {System.out.println(\"alt 1\");}\n" +
|
||||
" | {true}? ID {System.out.println(\"alt 2\");}\n" +
|
||||
" | INT {System.out.println(\"alt 3\");}\n" +
|
||||
" ;\n" +
|
||||
"ID : 'a'..'z'+ ;\n" +
|
||||
"INT : '0'..'9'+;\n" +
|
||||
"WS : (' '|'\\n') -> skip ;\n";
|
||||
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s",
|
||||
"x y 3", false);
|
||||
String expecting =
|
||||
"alt 2\n" +
|
||||
"alt 2\n" +
|
||||
"alt 3\n";
|
||||
assertEquals(expecting, found);
|
||||
}
|
||||
|
||||
@Test public void testOrder() throws Exception {
|
||||
// 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;
|
||||
// action blocks lookahead from falling off of 'a'
|
||||
// and looking into 2nd 'a' ref. !ctx dependent pred
|
||||
"a : ID {System.out.println(\"alt 1\");}\n" +
|
||||
" | {true}? ID {System.out.println(\"alt 2\");}\n" +
|
||||
" ;\n" +
|
||||
"ID : 'a'..'z'+ ;\n" +
|
||||
"INT : '0'..'9'+;\n" +
|
||||
"WS : (' '|'\\n') -> skip ;\n";
|
||||
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s",
|
||||
"x y", false);
|
||||
String expecting =
|
||||
"alt 1\n" +
|
||||
"alt 1\n";
|
||||
assertEquals(expecting, found);
|
||||
}
|
||||
|
||||
@Test public void test2UnpredicatedAlts() throws Exception {
|
||||
// We have n-2 predicates for n alternatives. pick first alt
|
||||
String grammar =
|
||||
"grammar T;\n" +
|
||||
"@header {" +
|
||||
"import java.util.*;" +
|
||||
"}" +
|
||||
"s : {_interp.setPredictionMode(PredictionMode.LL_EXACT_AMBIG_DETECTION);}\n" +
|
||||
" a ';' a;\n" + // do 2x: once in ATN, next in DFA
|
||||
"a : ID {System.out.println(\"alt 1\");}\n" +
|
||||
" | ID {System.out.println(\"alt 2\");}\n" +
|
||||
" | {false}? ID {System.out.println(\"alt 3\");}\n" +
|
||||
" ;\n" +
|
||||
"ID : 'a'..'z'+ ;\n" +
|
||||
"INT : '0'..'9'+;\n" +
|
||||
"WS : (' '|'\\n') -> skip ;\n";
|
||||
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s",
|
||||
"x; y", true);
|
||||
String expecting =
|
||||
"alt 1\n" +
|
||||
"alt 1\n";
|
||||
assertEquals(expecting, found);
|
||||
assertEquals("line 1:0 reportAttemptingFullContext d=0 (a), input='x'\n" +
|
||||
"line 1:0 reportAmbiguity d=0 (a): ambigAlts={1, 2}, input='x'\n" +
|
||||
"line 1:3 reportAttemptingFullContext d=0 (a), input='y'\n" +
|
||||
"line 1:3 reportAmbiguity d=0 (a): ambigAlts={1, 2}, input='y'\n",
|
||||
this.stderrDuringParse);
|
||||
}
|
||||
|
||||
@Test public void test2UnpredicatedAltsAndOneOrthogonalAlt() throws Exception {
|
||||
String grammar =
|
||||
"grammar T;\n" +
|
||||
"@header {" +
|
||||
"import java.util.*;" +
|
||||
"}" +
|
||||
"s : {_interp.setPredictionMode(PredictionMode.LL_EXACT_AMBIG_DETECTION);}\n" +
|
||||
" a ';' a ';' a;\n" +
|
||||
"a : INT {System.out.println(\"alt 1\");}\n" +
|
||||
" | ID {System.out.println(\"alt 2\");}\n" + // must pick this one for ID since pred is false
|
||||
" | ID {System.out.println(\"alt 3\");}\n" +
|
||||
" | {false}? ID {System.out.println(\"alt 4\");}\n" +
|
||||
" ;\n" +
|
||||
"ID : 'a'..'z'+ ;\n" +
|
||||
"INT : '0'..'9'+;\n" +
|
||||
"WS : (' '|'\\n') -> skip ;\n";
|
||||
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s",
|
||||
"34; x; y", true);
|
||||
String expecting =
|
||||
"alt 1\n" +
|
||||
"alt 2\n" +
|
||||
"alt 2\n";
|
||||
assertEquals(expecting, found);
|
||||
assertEquals("line 1:4 reportAttemptingFullContext d=0 (a), input='x'\n" +
|
||||
"line 1:4 reportAmbiguity d=0 (a): ambigAlts={2, 3}, input='x'\n" +
|
||||
"line 1:7 reportAttemptingFullContext d=0 (a), input='y'\n" +
|
||||
"line 1:7 reportAmbiguity d=0 (a): ambigAlts={2, 3}, input='y'\n",
|
||||
this.stderrDuringParse);
|
||||
}
|
||||
|
||||
@Test public void testRewindBeforePredEval() throws Exception {
|
||||
// The parser consumes ID and moves to the 2nd token INT.
|
||||
// To properly evaluate the predicates after matching ID INT,
|
||||
// we must correctly see come back to starting index so LT(1) works
|
||||
String grammar =
|
||||
"grammar T;\n" +
|
||||
"s : a a;\n" +
|
||||
"a : {_input.LT(1).getText().equals(\"x\")}? ID INT {System.out.println(\"alt 1\");}\n" +
|
||||
" | {_input.LT(1).getText().equals(\"y\")}? ID INT {System.out.println(\"alt 2\");}\n" +
|
||||
" ;\n" +
|
||||
"ID : 'a'..'z'+ ;\n" +
|
||||
"INT : '0'..'9'+;\n" +
|
||||
"WS : (' '|'\\n') -> skip ;\n";
|
||||
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s",
|
||||
"y 3 x 4", false);
|
||||
String expecting =
|
||||
"alt 2\n" +
|
||||
"alt 1\n";
|
||||
assertEquals(expecting, found);
|
||||
}
|
||||
|
||||
@Test public void testNoTruePredsThrowsNoViableAlt() throws Exception {
|
||||
// checks that we throw exception if all alts
|
||||
// are covered with a predicate and none succeeds
|
||||
String grammar =
|
||||
"grammar T;\n" +
|
||||
"s : a a;\n" +
|
||||
"a : {false}? ID INT {System.out.println(\"alt 1\");}\n" +
|
||||
" | {false}? ID INT {System.out.println(\"alt 2\");}\n" +
|
||||
" ;\n" +
|
||||
"ID : 'a'..'z'+ ;\n" +
|
||||
"INT : '0'..'9'+;\n" +
|
||||
"WS : (' '|'\\n') -> skip ;\n";
|
||||
|
||||
execParser("T.g4", grammar, "TParser", "TLexer", "s",
|
||||
"y 3 x 4", false);
|
||||
String expecting = "line 1:0 no viable alternative at input 'y'\n";
|
||||
String result = stderrDuringParse;
|
||||
assertEquals(expecting, result);
|
||||
}
|
||||
|
||||
@Test public void testToLeft() throws Exception {
|
||||
String grammar =
|
||||
"grammar T;\n" +
|
||||
"s : a+ ;\n" +
|
||||
"a : {false}? ID {System.out.println(\"alt 1\");}\n" +
|
||||
" | {true}? ID {System.out.println(\"alt 2\");}\n" +
|
||||
" ;\n" +
|
||||
"ID : 'a'..'z'+ ;\n" +
|
||||
"INT : '0'..'9'+;\n" +
|
||||
"WS : (' '|'\\n') -> skip ;\n";
|
||||
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s",
|
||||
"x x y", false);
|
||||
String expecting =
|
||||
"alt 2\n" +
|
||||
"alt 2\n" +
|
||||
"alt 2\n";
|
||||
assertEquals(expecting, found);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnpredicatedPathsInAlt() throws Exception{
|
||||
String grammar =
|
||||
"grammar T;\n" +
|
||||
"s : a {System.out.println(\"alt 1\");}\n" +
|
||||
" | b {System.out.println(\"alt 2\");}\n" +
|
||||
" ;\n" +
|
||||
"a : {false}? ID INT\n" +
|
||||
" | ID INT\n" +
|
||||
" ;\n" +
|
||||
"b : ID ID\n" +
|
||||
" ;\n" +
|
||||
"ID : 'a'..'z'+ ;\n" +
|
||||
"INT : '0'..'9'+;\n" +
|
||||
"WS : (' '|'\\n') -> skip ;\n";
|
||||
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s",
|
||||
"x 4", false);
|
||||
String expecting =
|
||||
"alt 1\n";
|
||||
assertEquals(expecting, found);
|
||||
|
||||
expecting = null;
|
||||
assertEquals(expecting, stderrDuringParse);
|
||||
}
|
||||
|
||||
@Test public void testActionHidesPreds() throws Exception {
|
||||
// can't see preds, resolves to first alt found (1 in this case)
|
||||
String grammar =
|
||||
"grammar T;\n" +
|
||||
"@parser::members {int i;}\n" +
|
||||
"s : a+ ;\n" +
|
||||
"a : {i=1;} ID {i==1}? {System.out.println(\"alt 1\");}\n" +
|
||||
" | {i=2;} ID {i==2}? {System.out.println(\"alt 2\");}\n" +
|
||||
" ;\n" +
|
||||
"ID : 'a'..'z'+ ;\n" +
|
||||
"INT : '0'..'9'+;\n" +
|
||||
"WS : (' '|'\\n') -> skip ;\n";
|
||||
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s",
|
||||
"x x y", false);
|
||||
String expecting =
|
||||
"alt 1\n" +
|
||||
"alt 1\n" +
|
||||
"alt 1\n";
|
||||
assertEquals(expecting, found);
|
||||
}
|
||||
|
||||
/** In this case, we use predicates that depend on global information
|
||||
* like we would do for a symbol table. We simply execute
|
||||
* the predicates assuming that all necessary information is available.
|
||||
* The i++ action is done outside of the prediction and so it is executed.
|
||||
*/
|
||||
@Test public void testToLeftWithVaryingPredicate() throws Exception {
|
||||
String grammar =
|
||||
"grammar T;\n" +
|
||||
"@parser::members {int i=0;}\n" +
|
||||
"s : ({i++; System.out.println(\"i=\"+i);} a)+ ;\n" +
|
||||
"a : {i % 2 == 0}? ID {System.out.println(\"alt 1\");}\n" +
|
||||
" | {i % 2 != 0}? ID {System.out.println(\"alt 2\");}\n" +
|
||||
" ;\n" +
|
||||
"ID : 'a'..'z'+ ;\n" +
|
||||
"INT : '0'..'9'+;\n" +
|
||||
"WS : (' '|'\\n') -> skip ;\n";
|
||||
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s",
|
||||
"x x y", false);
|
||||
String expecting =
|
||||
"i=1\n" +
|
||||
"alt 2\n" +
|
||||
"i=2\n" +
|
||||
"alt 1\n" +
|
||||
"i=3\n" +
|
||||
"alt 2\n";
|
||||
assertEquals(expecting, found);
|
||||
}
|
||||
|
||||
/**
|
||||
* In this case, we're passing a parameter into a rule that uses that
|
||||
* information to predict the alternatives. This is the special case
|
||||
* where we know exactly which context we are in. The context stack
|
||||
* is empty and we have not dipped into the outer context to make a decision.
|
||||
*/
|
||||
@Test public void testPredicateDependentOnArg() throws Exception {
|
||||
String grammar =
|
||||
"grammar T;\n" +
|
||||
"@parser::members {int i=0;}\n" +
|
||||
"s : a[2] a[1];\n" +
|
||||
"a[int i]" +
|
||||
" : {$i==1}? ID {System.out.println(\"alt 1\");}\n" +
|
||||
" | {$i==2}? ID {System.out.println(\"alt 2\");}\n" +
|
||||
" ;\n" +
|
||||
"ID : 'a'..'z'+ ;\n" +
|
||||
"INT : '0'..'9'+;\n" +
|
||||
"WS : (' '|'\\n') -> skip ;\n";
|
||||
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s",
|
||||
"a b", false);
|
||||
String expecting =
|
||||
"alt 2\n" +
|
||||
"alt 1\n";
|
||||
assertEquals(expecting, found);
|
||||
}
|
||||
|
||||
/** In this case, we have to ensure that the predicates are not
|
||||
tested during the closure after recognizing the 1st ID. The
|
||||
closure will fall off the end of 'a' 1st time and reach into the
|
||||
a[1] rule invocation. It should not execute predicates because it
|
||||
does not know what the parameter is. The context stack will not
|
||||
be empty and so they should be ignored. It will not affect
|
||||
recognition, however. We are really making sure the ATN
|
||||
simulation doesn't crash with context object issues when it
|
||||
encounters preds during FOLLOW.
|
||||
*/
|
||||
@Test public void testPredicateDependentOnArg2() throws Exception {
|
||||
String grammar =
|
||||
"grammar T;\n" +
|
||||
"s : a[2] a[1];\n" +
|
||||
"a[int i]" +
|
||||
" : {$i==1}? ID\n" +
|
||||
" | {$i==2}? ID\n" +
|
||||
" ;\n" +
|
||||
"ID : 'a'..'z'+ ;\n" +
|
||||
"INT : '0'..'9'+;\n" +
|
||||
"WS : (' '|'\\n') -> skip ;\n";
|
||||
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s",
|
||||
"a b", false);
|
||||
String expecting =
|
||||
"";
|
||||
assertEquals(expecting, found);
|
||||
}
|
||||
|
||||
@Test public void testDependentPredNotInOuterCtxShouldBeIgnored() throws Exception {
|
||||
// uses ID ';' or ID '.' lookahead to solve s. preds not tested.
|
||||
String grammar =
|
||||
"grammar T;\n" +
|
||||
"s : b[2] ';' | b[2] '.' ;\n" + // decision in s drills down to ctx-dependent pred in a;
|
||||
"b[int i] : a[i] ;\n" +
|
||||
"a[int i]" +
|
||||
" : {$i==1}? ID {System.out.println(\"alt 1\");}\n" +
|
||||
" | {$i==2}? ID {System.out.println(\"alt 2\");}\n" +
|
||||
" ;" +
|
||||
"ID : 'a'..'z'+ ;\n" +
|
||||
"INT : '0'..'9'+;\n" +
|
||||
"WS : (' '|'\\n') -> skip ;\n";
|
||||
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s",
|
||||
"a;", false);
|
||||
String expecting =
|
||||
"alt 2\n";
|
||||
assertEquals(expecting, found);
|
||||
}
|
||||
|
||||
@Test public void testIndependentPredNotPassedOuterCtxToAvoidCastException() throws Exception {
|
||||
String grammar =
|
||||
"grammar T;\n" +
|
||||
"s : b ';' | b '.' ;\n" +
|
||||
"b : a ;\n" +
|
||||
"a" +
|
||||
" : {false}? ID {System.out.println(\"alt 1\");}\n" +
|
||||
" | {true}? ID {System.out.println(\"alt 2\");}\n" +
|
||||
" ;" +
|
||||
"ID : 'a'..'z'+ ;\n" +
|
||||
"INT : '0'..'9'+;\n" +
|
||||
"WS : (' '|'\\n') -> skip ;\n";
|
||||
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s",
|
||||
"a;", false);
|
||||
String expecting =
|
||||
"alt 2\n";
|
||||
assertEquals(expecting, found);
|
||||
}
|
||||
|
||||
/** During a global follow operation, we still collect semantic
|
||||
* predicates as long as they are not dependent on local context
|
||||
*/
|
||||
@Test public void testPredsInGlobalFOLLOW() throws Exception {
|
||||
String grammar =
|
||||
"grammar T;\n" +
|
||||
"@parser::members {" +
|
||||
"void f(Object s) {System.out.println(s);}\n" +
|
||||
"boolean p(boolean v) {System.out.println(\"eval=\"+v); return v;}\n" +
|
||||
"}\n" +
|
||||
"s : e {p(true)}? {f(\"parse\");} '!' ;\n" +
|
||||
"t : e {p(false)}? ID ;\n" +
|
||||
"e : ID | ;\n" + // non-LL(1) so we use ATN
|
||||
"ID : 'a'..'z'+ ;\n" +
|
||||
"INT : '0'..'9'+;\n" +
|
||||
"WS : (' '|'\\n') -> skip ;\n";
|
||||
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s",
|
||||
"a!", false);
|
||||
String expecting =
|
||||
"eval=true\n" + // now we are parsing
|
||||
"parse\n";
|
||||
assertEquals(expecting, found);
|
||||
}
|
||||
|
||||
/** We cannot collect predicates that are dependent on local context if
|
||||
* we are doing a global follow. They appear as if they were not there at all.
|
||||
*/
|
||||
@Test public void testDepedentPredsInGlobalFOLLOW() throws Exception {
|
||||
String grammar =
|
||||
"grammar T;\n" +
|
||||
"@parser::members {" +
|
||||
"void f(Object s) {System.out.println(s);}\n" +
|
||||
"boolean p(boolean v) {System.out.println(\"eval=\"+v); return v;}\n" +
|
||||
"}\n" +
|
||||
"s : a[99] ;\n" +
|
||||
"a[int i] : e {p($i==99)}? {f(\"parse\");} '!' ;\n" +
|
||||
"b[int i] : e {p($i==99)}? ID ;\n" +
|
||||
"e : ID | ;\n" + // non-LL(1) so we use ATN
|
||||
"ID : 'a'..'z'+ ;\n" +
|
||||
"INT : '0'..'9'+;\n" +
|
||||
"WS : (' '|'\\n') -> skip ;\n";
|
||||
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s",
|
||||
"a!", false);
|
||||
String expecting =
|
||||
"eval=true\n" +
|
||||
"parse\n";
|
||||
assertEquals(expecting, found);
|
||||
}
|
||||
|
||||
/** Regular non-forced actions can create side effects used by semantic
|
||||
* predicates and so we cannot evaluate any semantic predicate
|
||||
* encountered after having seen a regular action. This includes
|
||||
* during global follow operations.
|
||||
*/
|
||||
@Test public void testActionsHidePredsInGlobalFOLLOW() throws Exception {
|
||||
String grammar =
|
||||
"grammar T;\n" +
|
||||
"@parser::members {" +
|
||||
"void f(Object s) {System.out.println(s);}\n" +
|
||||
"boolean p(boolean v) {System.out.println(\"eval=\"+v); return v;}\n" +
|
||||
"}\n" +
|
||||
"s : e {} {p(true)}? {f(\"parse\");} '!' ;\n" +
|
||||
"t : e {} {p(false)}? ID ;\n" +
|
||||
"e : ID | ;\n" + // non-LL(1) so we use ATN
|
||||
"ID : 'a'..'z'+ ;\n" +
|
||||
"INT : '0'..'9'+;\n" +
|
||||
"WS : (' '|'\\n') -> skip ;\n";
|
||||
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s",
|
||||
"a!", false);
|
||||
String expecting =
|
||||
"eval=true\n" +
|
||||
"parse\n";
|
||||
assertEquals(expecting, found);
|
||||
}
|
||||
|
||||
@Test public void testPredTestedEvenWhenUnAmbig() throws Exception {
|
||||
String grammar =
|
||||
"grammar T;\n" +
|
||||
"\n" +
|
||||
"@parser::members {boolean enumKeyword = true;}\n" +
|
||||
"\n" +
|
||||
"primary\n" +
|
||||
" : ID {System.out.println(\"ID \"+$ID.text);}\n" +
|
||||
" | {!enumKeyword}? 'enum' {System.out.println(\"enum\");}\n" +
|
||||
" ;\n" +
|
||||
"\n" +
|
||||
"ID : [a-z]+ ;\n" +
|
||||
"\n" +
|
||||
"WS : [ \\t\\n\\r]+ -> skip ;\n";
|
||||
|
||||
String found = execParser("T.g4", grammar, "TParser", "TLexer", "primary",
|
||||
"abc", false);
|
||||
assertEquals("ID abc\n", found);
|
||||
|
||||
execParser("T.g4", grammar, "TParser", "TLexer", "primary",
|
||||
"enum", false);
|
||||
assertEquals("line 1:0 no viable alternative at input 'enum'\n", stderrDuringParse);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a regression test for antlr/antlr4#218 "ANTLR4 EOF Related Bug".
|
||||
* https://github.com/antlr/antlr4/issues/218
|
||||
*/
|
||||
@Test public void testDisabledAlternative() {
|
||||
String grammar =
|
||||
"grammar AnnotProcessor;\n" +
|
||||
"\n" +
|
||||
"cppCompilationUnit : content+ EOF;\n" +
|
||||
"\n" +
|
||||
"content: anything | {false}? .;\n" +
|
||||
"\n" +
|
||||
"anything: ANY_CHAR;\n" +
|
||||
"\n" +
|
||||
"ANY_CHAR: [_a-zA-Z0-9];\n";
|
||||
|
||||
String input = "hello";
|
||||
String found = execParser("AnnotProcessor.g4", grammar, "AnnotProcessorParser", "AnnotProcessorLexer", "cppCompilationUnit",
|
||||
input, false);
|
||||
assertEquals("", found);
|
||||
assertNull(stderrDuringParse);
|
||||
}
|
||||
|
||||
/** Loopback doesn't eval predicate at start of alt */
|
||||
@Test public void testPredFromAltTestedInLoopBack() {
|
||||
String grammar =
|
||||
"grammar T2;\n" +
|
||||
"\n" +
|
||||
"file\n" +
|
||||
"@after {System.out.println($ctx.toStringTree(this));}\n" +
|
||||
" : para para EOF ;" +
|
||||
"para: paraContent NL NL ;\n"+
|
||||
"paraContent : ('s'|'x'|{_input.LA(2)!=NL}? NL)+ ;\n"+
|
||||
"NL : '\\n' ;\n"+
|
||||
"S : 's' ;\n"+
|
||||
"X : 'x' ;\n";
|
||||
|
||||
String input = "s\n\n\nx\n";
|
||||
String found = execParser("T2.g4", grammar, "T2Parser", "T2Lexer", "file",
|
||||
input, true);
|
||||
assertEquals("(file (para (paraContent s) \\n \\n) (para (paraContent \\n x \\n)) <EOF>)\n", found);
|
||||
assertEquals(stderrDuringParse, "line 5:2 mismatched input '<EOF>' expecting '\n'\n");
|
||||
|
||||
input = "s\n\n\nx\n\n";
|
||||
found = execParser("T2.g4", grammar, "T2Parser", "T2Lexer", "file",
|
||||
input, true);
|
||||
assertEquals("(file (para (paraContent s) \\n \\n) (para (paraContent \\n x) \\n \\n) <EOF>)\n", found);
|
||||
|
||||
assertNull(stderrDuringParse);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue