TestSemPredEvalParser for Java is working

This commit is contained in:
Sam Harwell 2015-01-25 16:26:49 -06:00
parent 42ba8c4530
commit 98bb519f8a
53 changed files with 880 additions and 802 deletions

View File

@ -1,7 +1,8 @@
TestFolders ::= [
"CompositeLexers": [],
"LexerExec": [],
"ParseTrees": []
"ParseTrees": [],
"SemPredEvalParser": []
]
//TestTemplates ::= [

View File

@ -0,0 +1,39 @@
// We have n-2 predicates for n alternatives. pick first alt
TestType() ::= "Parser"
Options ::= [
"Debug": true
]
Grammar ::= [
"T": {<grammar("T")>}
]
Input() ::= "x; y"
Rule() ::= "s"
Output() ::= <<
alt 1
alt 1<\n>
>>
Errors() ::= <<
line 1:0 reportAttemptingFullContext d=0 (a), input='x'
line 1:0 reportAmbiguity d=0 (a): ambigAlts={1, 2}, input='x'
line 1:3 reportAttemptingFullContext d=0 (a), input='y'
line 1:3 reportAmbiguity d=0 (a): ambigAlts={1, 2}, input='y'<\n>
>>
grammar(grammarName) ::= <<
grammar <grammarName>;
s : {<LL_EXACT_AMBIG_DETECTION()>} a ';' a; // do 2x: once in ATN, next in DFA
a : ID {<writeln("\"alt 1\"")>}
| ID {<writeln("\"alt 2\"")>}
| {<False()>}? ID {<writeln("\"alt 3\"")>}
;
ID : 'a'..'z'+ ;
INT : '0'..'9'+;
WS : (' '|'\n') -> skip ;
>>

View File

@ -0,0 +1,39 @@
TestType() ::= "Parser"
Options ::= [
"Debug": true
]
Grammar ::= [
"T": {<grammar("T")>}
]
Input() ::= "34; x; y"
Rule() ::= "s"
Output() ::= <<
alt 1
alt 2
alt 2<\n>
>>
Errors() ::= <<
line 1:4 reportAttemptingFullContext d=0 (a), input='x'
line 1:4 reportAmbiguity d=0 (a): ambigAlts={2, 3}, input='x'
line 1:7 reportAttemptingFullContext d=0 (a), input='y'
line 1:7 reportAmbiguity d=0 (a): ambigAlts={2, 3}, input='y'<\n>
>>
grammar(grammarName) ::= <<
grammar <grammarName>;
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 {<writeln("\"alt 4\"")>}
;
ID : 'a'..'z'+ ;
INT : '0'..'9'+;
WS : (' '|'\n') -> skip ;
>>

View File

@ -1,3 +1,26 @@
TestType() ::= "Parser"
Options ::= [
"Debug": false
]
Grammar ::= [
"T": {<grammar("T")>}
]
Input() ::= "x x y"
Rule() ::= "s"
Output() ::= <<
alt 1
alt 1
alt 1<\n>
>>
Errors() ::= ""
grammar(grammarName) ::= <<
grammar <grammarName>;
@members {<InitIntMember("i","0")>}
s : a+ ;
@ -7,3 +30,4 @@ a : {<SetMember("i","1")>} ID {<MemberEquals("i","1")>}? {<writeln("\"alt 1\"")>
ID : 'a'..'z'+ ;
INT : '0'..'9'+;
WS : (' '|'\n') -> skip ;
>>

View File

@ -0,0 +1,39 @@
/** 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.
*/
TestType() ::= "Parser"
Options ::= [
"Debug": true
]
Grammar ::= [
"T": {<grammar("T")>}
]
Input() ::= "a!"
Rule() ::= "s"
Output() ::= <<
eval=true
parse<\n>
>>
Errors() ::= ""
grammar(grammarName) ::= <<
grammar <grammarName>;
@members {
<Declare_pred()>
}
s : e {} {<True():Invoke_pred()>}? {<writeln("\"parse\"")>} '!' ;
t : e {} {<False():Invoke_pred()>}? ID ;
e : ID | ; // non-LL(1) so we use ATN
ID : 'a'..'z'+ ;
INT : '0'..'9'+;
WS : (' '|'\n') -> skip ;
>>

View File

@ -0,0 +1,26 @@
TestType() ::= "Parser"
Options ::= [
"Debug": false
]
Grammar ::= [
"T": {<grammar("T")>}
]
Input() ::= "a+b+a"
Rule() ::= "start"
Output() ::= ""
Errors() ::= ""
grammar(grammarName) ::= <<
grammar <grammarName>;
start : e[0] EOF;
e[int _p]
: ( 'a' | 'b'+ ) ( {3 >= $_p}? '+' e[4] )*
;
>>

View File

@ -0,0 +1,38 @@
/** 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.
*/
TestType() ::= "Parser"
Options ::= [
"Debug": true
]
Grammar ::= [
"T": {<grammar("T")>}
]
Input() ::= "a!"
Rule() ::= "s"
Output() ::= <<
eval=true
parse<\n>
>>
Errors() ::= ""
grammar(grammarName) ::= <<
grammar <grammarName>;
@members {
<Declare_pred()>
}
s : a[99] ;
a[int i] : e {<ValEquals("$i","99"):Invoke_pred()>}? {<writeln("\"parse\"")>} '!' ;
b[int i] : e {<ValEquals("$i","99"):Invoke_pred()>}? ID ;
e : ID | ; // non-LL(1) so we use ATN
ID : 'a'..'z'+ ;
INT : '0'..'9'+;
WS : (' '|'\n') -> skip ;
>>

View File

@ -1,3 +1,26 @@
// uses ID ';' or ID '.' lookahead to solve s. preds not tested.
TestType() ::= "Parser"
Options ::= [
"Debug": true
]
Grammar ::= [
"T": {<grammar("T")>}
]
Input() ::= "a;"
Rule() ::= "s"
Output() ::= <<
alt 2<\n>
>>
Errors() ::= ""
grammar(grammarName) ::= <<
grammar <grammarName>;
s : b[2] ';' | b[2] '.' ; // decision in s drills down to ctx-dependent pred in a;
b[int i] : a[i] ;
@ -9,3 +32,4 @@ ID : 'a'..'z'+ ;
INT : '0'..'9'+;
WS : (' '|'\n') -> skip ;
>>

View File

@ -0,0 +1,31 @@
/**
* This is a regression test for antlr/antlr4#218 "ANTLR4 EOF Related Bug".
* https://github.com/antlr/antlr4/issues/218
*/
TestType() ::= "Parser"
Options ::= [
"Debug": true
]
Grammar ::= [
"T": {<grammar("T")>}
]
Input() ::= "hello"
Rule() ::= "cppCompilationUnit"
Output() ::= <<
>>
Errors() ::= ""
grammar(grammarName) ::= <<
grammar <grammarName>;
cppCompilationUnit : content+ EOF;
content: anything | {<False()>}? .;
anything: ANY_CHAR;
ANY_CHAR: [_a-zA-Z0-9];
>>

View File

@ -0,0 +1,32 @@
TestType() ::= "Parser"
Options ::= [
"Debug": true
]
Grammar ::= [
"T": {<grammar("T")>}
]
Input() ::= "a;"
Rule() ::= "s"
Output() ::= <<
alt 2<\n>
>>
Errors() ::= ""
grammar(grammarName) ::= <<
grammar <grammarName>;
s : b ';' | b '.' ;
b : a ;
a
: {<False()>}? ID {<writeln("\"alt 1\"")>}
| {<True()>}? ID {<writeln("\"alt 2\"")>}
;
ID : 'a'..'z'+ ;
INT : '0'..'9'+;
WS : (' '|'\n') -> skip ;
>>

View File

@ -0,0 +1,31 @@
//TestFolders ::= [
//]
TestTemplates ::= [
"SimpleValidate": [],
"SimpleValidate2": [],
"AtomWithClosureInTranslatedLRRule": [],
"ValidateInDFA": [],
"Simple": [],
"Order": [],
"2UnpredicatedAlts": [],
"2UnpredicatedAltsAndOneOrthogonalAlt": [],
"RewindBeforePredEval": [],
"NoTruePredsThrowsNoViableAlt": [],
"ToLeft": [],
"UnpredicatedPathsInAlt": [],
"ActionHidesPreds": [],
"ToLeftWithVaryingPredicate": [],
"PredicateDependentOnArg": [],
"PredicateDependentOnArg2": [],
"DependentPredNotInOuterCtxShouldBeIgnored": [],
"IndependentPredNotPassedOuterCtxToAvoidCastException": [],
"PredsInGlobalFOLLOW": [],
"DepedentPredsInGlobalFOLLOW": [],
"ActionsHidePredsInGlobalFOLLOW": [],
"PredTestedEvenWhenUnAmbig_1": [],
"PredTestedEvenWhenUnAmbig_2": [],
"DisabledAlternative": [],
"PredFromAltTestedInLoopBack_1": [],
"PredFromAltTestedInLoopBack_2": []
]

View File

@ -0,0 +1,34 @@
// checks that we throw exception if all alts
// are covered with a predicate and none succeeds
TestType() ::= "Parser"
Options ::= [
"Debug": false
]
Grammar ::= [
"T": {<grammar("T")>}
]
Input() ::= "y 3 x 4"
Rule() ::= "s"
Output() ::= <<
>>
Errors() ::= <<
line 1:0 no viable alternative at input 'y'<\n>
>>
grammar(grammarName) ::= <<
grammar <grammarName>;
s : a a;
a : {<False()>}? ID INT {<writeln("\"alt 1\"")>}
| {<False()>}? ID INT {<writeln("\"alt 2\"")>}
;
ID : 'a'..'z'+ ;
INT : '0'..'9'+;
WS : (' '|'\n') -> skip ;
>>

View File

@ -0,0 +1,37 @@
// 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.
TestType() ::= "Parser"
Options ::= [
"Debug": false
]
Grammar ::= [
"T": {<grammar("T")>}
]
Input() ::= "x y"
Rule() ::= "s"
Output() ::= <<
alt 1
alt 1<\n>
>>
Errors() ::= ""
grammar(grammarName) ::= <<
grammar <grammarName>;
s : a {} a; // 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 {<writeln("\"alt 1\"")>}
| {<True()>}? ID {<writeln("\"alt 2\"")>}
;
ID : 'a'..'z'+ ;
INT : '0'..'9'+;
WS : (' '|'\n') -> skip ;
>>

View File

@ -1,3 +1,18 @@
/** Loopback doesn't eval predicate at start of alt */
TestType() ::= "Parser"
Options ::= [
"Debug": true
]
Grammar ::= [
"T": {<grammar("T")>}
]
Rule() ::= "file_"
grammar(grammarName) ::= <<
grammar <grammarName>;
file_
@after {<ToStringTree("$ctx"):writeln()>}
@ -7,3 +22,4 @@ paraContent : ('s'|'x'|{<LANotEquals("2","NL")>}? NL)+ ;
NL : '\n' ;
s : 's' ;
X : 'x' ;
>>

View File

@ -0,0 +1,12 @@
import "PredFromAltTestedInLoopBack.stg"
Input() ::= "s<\n><\n><\n>x<\n>"
Output() ::= <<
(file_ (para (paraContent s) \n \n) (para (paraContent \n x \n)) \<EOF>)<\n>
>>
Errors() ::= <<
line 5:0 mismatched input '\<EOF>' expecting '
'<\n>
>>

View File

@ -0,0 +1,9 @@
import "PredFromAltTestedInLoopBack.stg"
Input() ::= "s<\n><\n><\n>x<\n><\n>"
Output() ::= <<
(file_ (para (paraContent s) \n \n) (para (paraContent \n x) \n \n) \<EOF>)<\n>
>>
Errors() ::= ""

View File

@ -1,3 +1,16 @@
TestType() ::= "Parser"
Options ::= [
"Debug": true
]
Grammar ::= [
"T": {<grammar("T")>}
]
Rule() ::= "primary"
grammar(grammarName) ::= <<
grammar <grammarName>;
@members {<InitBooleanMember("enumKeyword",True())>}
primary
@ -6,3 +19,4 @@ primary
;
ID : [a-z]+ ;
WS : [ \t\n\r]+ -> skip ;
>>

View File

@ -0,0 +1,9 @@
import "PredTestedEvenWhenUnAmbig.stg"
Input() ::= "abc"
Output() ::= <<
ID abc<\n>
>>
Errors() ::= ""

View File

@ -0,0 +1,10 @@
import "PredTestedEvenWhenUnAmbig.stg"
Input() ::= "enum"
Output() ::= <<
>>
Errors() ::= <<
line 1:0 no viable alternative at input 'enum'<\n>
>>

View File

@ -0,0 +1,40 @@
/**
* 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.
*/
TestType() ::= "Parser"
Options ::= [
"Debug": true
]
Grammar ::= [
"T": {<grammar("T")>}
]
Input() ::= "a b"
Rule() ::= "s"
Output() ::= <<
alt 2
alt 1<\n>
>>
Errors() ::= ""
grammar(grammarName) ::= <<
grammar <grammarName>;
@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\"")>}
;
ID : 'a'..'z'+ ;
INT : '0'..'9'+;
WS : (' '|'\n') -> skip ;
>>

View File

@ -0,0 +1,42 @@
/**
* 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.
*/
TestType() ::= "Parser"
Options ::= [
"Debug": true
]
Grammar ::= [
"T": {<grammar("T")>}
]
Input() ::= "a b"
Rule() ::= "s"
Output() ::= <<
>>
Errors() ::= ""
grammar(grammarName) ::= <<
grammar <grammarName>;
@members {<InitIntMember("i","0")>}
s : a[2] a[1];
a[int i]
: {<ValEquals("$i","1")>}? ID
| {<ValEquals("$i","2")>}? ID
;
ID : 'a'..'z'+ ;
INT : '0'..'9'+;
WS : (' '|'\n') -> skip ;
>>

View File

@ -0,0 +1,38 @@
/** During a global follow operation, we still collect semantic
* predicates as long as they are not dependent on local context
*/
TestType() ::= "Parser"
Options ::= [
"Debug": true
]
Grammar ::= [
"T": {<grammar("T")>}
]
Input() ::= "a!"
Rule() ::= "s"
Output() ::= <<
eval=true
<! now we are parsing !>
parse<\n>
>>
Errors() ::= ""
grammar(grammarName) ::= <<
grammar <grammarName>;
@members {
<Declare_pred()>
}
s : e {<True():Invoke_pred()>}? {<writeln("\"parse\"")>} '!' ;
t : e {<False():Invoke_pred()>}? ID ;
e : ID | ; // non-LL(1) so we use ATN
ID : 'a'..'z'+ ;
INT : '0'..'9'+;
WS : (' '|'\n') -> skip ;
>>

View File

@ -0,0 +1,35 @@
// 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
TestType() ::= "Parser"
Options ::= [
"Debug": true
]
Grammar ::= [
"T": {<grammar("T")>}
]
Input() ::= "y 3 x 4"
Rule() ::= "s"
Output() ::= <<
alt 2
alt 1<\n>
>>
Errors() ::= ""
grammar(grammarName) ::= <<
grammar <grammarName>;
s : a a;
a : {<LTEquals("1", "\"x\"")>}? ID INT {<writeln("\"alt 1\"")>}
| {<LTEquals("1", "\"y\"")>}? ID INT {<writeln("\"alt 2\"")>}
;
ID : 'a'..'z'+ ;
INT : '0'..'9'+;
WS : (' '|'\n') -> skip ;
>>

View File

@ -1,3 +1,26 @@
TestType() ::= "Parser"
Options ::= [
"Debug": true
]
Grammar ::= [
"T": {<grammar("T")>}
]
Input() ::= "x y 3"
Rule() ::= "s"
Output() ::= <<
alt 2
alt 2
alt 3<\n>
>>
Errors() ::= ""
grammar(grammarName) ::= <<
grammar <grammarName>;
s : a a a; // do 3x: once in ATN, next in DFA then INT in ATN
a : {<False()>}? ID {<writeln("\"alt 1\"")>}
@ -7,3 +30,4 @@ a : {<False()>}? ID {<writeln("\"alt 1\"")>}
ID : 'a'..'z'+ ;
INT : '0'..'9'+;
WS : (' '|'\n') -> skip ;
>>

View File

@ -0,0 +1,30 @@
TestType() ::= "Parser"
Options ::= [
"Debug": true
]
Grammar ::= [
"T": {<grammar("T")>}
]
Input() ::= "x"
Rule() ::= "s"
Output() ::= ""
Errors() ::= <<
line 1:0 no viable alternative at input 'x'<\n>
>>
grammar(grammarName) ::= <<
grammar <grammarName>;
s : a ;
a : {<False()>}? ID {<writeln("\"alt 1\"")>}
| {<True()>}? INT {<writeln("\"alt 2\"")>}
;
ID : 'a'..'z'+ ;
INT : '0'..'9'+;
WS : (' '|'\n') -> skip ;
>>

View File

@ -0,0 +1,33 @@
TestType() ::= "Parser"
Options ::= [
"Debug": true
]
Grammar ::= [
"T": {<grammar("T")>}
]
Input() ::= "3 4 x"
Rule() ::= "s"
Output() ::= <<
alt 2
alt 2<\n>
>>
Errors() ::= <<
line 1:4 no viable alternative at input 'x'<\n>
>>
grammar(grammarName) ::= <<
grammar <grammarName>;
s : a a a;
a : {<False()>}? ID {<writeln("\"alt 1\"")>}
| {<True()>}? INT {<writeln("\"alt 2\"")>}
;
ID : 'a'..'z'+ ;
INT : '0'..'9'+;
WS : (' '|'\n') -> skip ;
>>

View File

@ -0,0 +1,32 @@
TestType() ::= "Parser"
Options ::= [
"Debug": true
]
Grammar ::= [
"T": {<grammar("T")>}
]
Input() ::= "x x y"
Rule() ::= "s"
Output() ::= <<
alt 2
alt 2
alt 2<\n>
>>
Errors() ::= ""
grammar(grammarName) ::= <<
grammar <grammarName>;
s : a+ ;
a : {<False()>}? ID {<writeln("\"alt 1\"")>}
| {<True()>}? ID {<writeln("\"alt 2\"")>}
;
ID : 'a'..'z'+ ;
INT : '0'..'9'+;
WS : (' '|'\n') -> skip ;
>>

View File

@ -0,0 +1,43 @@
/** 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.
*/
TestType() ::= "Parser"
Options ::= [
"Debug": true
]
Grammar ::= [
"T": {<grammar("T")>}
]
Input() ::= "x x y"
Rule() ::= "s"
Output() ::= <<
i=1
alt 2
i=2
alt 1
i=3
alt 2<\n>
>>
Errors() ::= ""
grammar(grammarName) ::= <<
grammar <grammarName>;
@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\"")>}
;
ID : 'a'..'z'+ ;
INT : '0'..'9'+;
WS : (' '|'\n') -> skip ;
>>

View File

@ -0,0 +1,34 @@
TestType() ::= "Parser"
Options ::= [
"Debug": true
]
Grammar ::= [
"T": {<grammar("T")>}
]
Input() ::= "x 4"
Rule() ::= "s"
Output() ::= <<
alt 1<\n>
>>
Errors() ::= ""
grammar(grammarName) ::= <<
grammar <grammarName>;
s : a {<writeln("\"alt 1\"")>}
| b {<writeln("\"alt 2\"")>}
;
a : {<False()>}? ID INT
| ID INT
;
b : ID ID
;
ID : 'a'..'z'+ ;
INT : '0'..'9'+;
WS : (' '|'\n') -> skip ;
>>

View File

@ -1,3 +1,26 @@
TestType() ::= "Parser"
Options ::= [
"Debug": true
]
Grammar ::= [
"T": {<grammar("T")>}
]
Input() ::= "x ; y"
Rule() ::= "s"
Output() ::= <<
>>
Errors() ::= <<
line 1:0 no viable alternative at input 'x'
line 1:4 no viable alternative at input 'y'<\n>
>>
grammar(grammarName) ::= <<
grammar <grammarName>;
s : a ';' a;
// ';' helps us to resynchronize without consuming
@ -9,3 +32,4 @@ a : {<False()>}? ID {<writeln("\"alt 1\"")>}
ID : 'a'..'z'+ ;
INT : '0'..'9'+;
WS : (' '|'\n') -> skip ;
>>

View File

@ -109,7 +109,7 @@ public class Antlr4TestGeneratorMojo extends AbstractMojo {
List<ST> templates = new ArrayList<ST>();
for (String template : testTemplates) {
STGroup testGroup = new STGroupFile(templateFolder + "/" + template + STGroup.GROUP_FILE_EXTENSION);
testGroup.importTemplates(targetGroup);
importLanguageTemplates(testGroup, targetGroup);
ST testType = testGroup.getInstanceOf("TestType");
if (testType == null) {
getLog().warn(String.format("Unable to generate tests for %s: no TestType specified.", template));
@ -143,6 +143,29 @@ public class Antlr4TestGeneratorMojo extends AbstractMojo {
}
}
private void importLanguageTemplates(STGroup testGroup, STGroup languageGroup) {
// make sure the test group is loaded
testGroup.load();
if (testGroup == languageGroup) {
assert false : "Attempted to import the language group into itself.";
return;
}
if (testGroup.getImportedGroups().isEmpty()) {
testGroup.importTemplates(languageGroup);
return;
}
if (testGroup.getImportedGroups().contains(languageGroup)) {
return;
}
for (STGroup importedGroup : testGroup.getImportedGroups()) {
importLanguageTemplates(importedGroup, languageGroup);
}
}
public void writeFile(File file, String content) throws IOException {
file.getParentFile().mkdirs();

View File

@ -6,16 +6,16 @@
package org.antlr.mojo.antlr4.testgen;
import org.stringtemplate.v4.Interpreter;
import org.stringtemplate.v4.ModelAdaptor;
import org.stringtemplate.v4.ST;
import org.stringtemplate.v4.STGroup;
import org.stringtemplate.v4.misc.ObjectModelAdaptor;
import org.stringtemplate.v4.misc.STNoSuchPropertyException;
/**
*
* @author sam
*/
public class STGroupModelAdaptor extends ObjectModelAdaptor {
public class STGroupModelAdaptor implements ModelAdaptor {
@Override
public Object getProperty(Interpreter interp, ST self, Object o, Object property, String propertyName) throws STNoSuchPropertyException {
@ -29,7 +29,18 @@ public class STGroupModelAdaptor extends ObjectModelAdaptor {
return template;
}
return super.getProperty(interp, self, o, property, propertyName);
if ("name".equalsIgnoreCase(propertyName)) {
return group.getName();
}
for (STGroup importedGroup : group.getImportedGroups()) {
Object result = getProperty(interp, self, importedGroup, property, propertyName);
if (result != null) {
return result;
}
}
return null;
}
}

View File

@ -158,188 +158,9 @@ public class Generator {
list.add(buildParserErrors());
list.add(buildParserExec());
list.add(buildSemPredEvalLexer());
list.add(buildSemPredEvalParser());
return list;
}
private JUnitTestFile buildSemPredEvalParser() throws Exception {
JUnitTestFile file = new JUnitTestFile("SemPredEvalParser");
JUnitTestMethod tm = file.addParserTest(input, "SimpleValidate", "T", "s",
"x",
"",
"line 1:0 no viable alternative at input 'x'\n");
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);
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");
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
tm = file.addParserTest(input, "2UnpredicatedAlts", "T", "s",
"x; y",
"alt 1\n" +
"alt 1\n",
"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");
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" +
"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");
// 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
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");
tm = file.addParserTest(input, "ToLeft", "T", "s",
"x x y",
"alt 2\n" + "alt 2\n" + "alt 2\n",
null);
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",
null);
/** 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.
*/
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.
*/
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
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.
*/
tm = file.addParserTest(input, "PredicateDependentOnArg2", "T", "s",
"a b",
"",
null);
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);
tm.debug = true;
tm = file.addParserTest(input, "IndependentPredNotPassedOuterCtxToAvoidCastException", "T", "s",
"a;",
"alt 2\n",
null);
tm.debug = true;
/** During a global follow operation, we still collect semantic
* predicates as long as they are not dependent on local context
*/
tm = file.addParserTest(input, "PredsInGlobalFOLLOW", "T", "s",
"a!",
"eval=true\n" + /* now we are parsing */ "parse\n",
null);
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.
*/
tm = file.addParserTest(input, "DepedentPredsInGlobalFOLLOW","T", "s",
"a!",
"eval=true\n" + "parse\n",
null);
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.
*/
tm = file.addParserTest(input, "ActionsHidePredsInGlobalFOLLOW", "T", "s",
"a!",
"eval=true\n" + "parse\n",
null);
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
*/
tm = file.addParserTest(input, "DisabledAlternative", "T", "cppCompilationUnit",
"hello",
"",
null);
tm.debug = true;
/** Loopback doesn't eval predicate at start of alt */
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",
"line 5:0 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",
null);
tm.debug = true;
return file;
}
private JUnitTestFile buildSemPredEvalLexer() throws Exception {
JUnitTestFile file = new JUnitTestFile("SemPredEvalLexer");
LexerTestMethod tm = file.addLexerTest(input, "DisableRule", "L",

View File

@ -1,9 +0,0 @@
grammar <grammarName>;
s : {<LL_EXACT_AMBIG_DETECTION()>} a ';' a; // do 2x: once in ATN, next in DFA
a : ID {<writeln("\"alt 1\"")>}
| ID {<writeln("\"alt 2\"")>}
| {<False()>}? ID {<writeln("\"alt 3\"")>}
;
ID : 'a'..'z'+ ;
INT : '0'..'9'+;
WS : (' '|'\n') -> skip ;

View File

@ -1,10 +0,0 @@
grammar <grammarName>;
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 {<writeln("\"alt 4\"")>}
;
ID : 'a'..'z'+ ;
INT : '0'..'9'+;
WS : (' '|'\n') -> skip ;

View File

@ -1,10 +0,0 @@
grammar <grammarName>;
@members {
<Declare_pred()>
}
s : e {} {<True():Invoke_pred()>}? {<writeln("\"parse\"")>} '!' ;
t : e {} {<False():Invoke_pred()>}? ID ;
e : ID | ; // non-LL(1) so we use ATN
ID : 'a'..'z'+ ;
INT : '0'..'9'+;
WS : (' '|'\n') -> skip ;

View File

@ -1,6 +0,0 @@
grammar <grammarName>;
start : e[0] EOF;
e[int _p]
: ( 'a' | 'b'+ ) ( {3 >= $_p}? '+' e[4] )*
;

View File

@ -1,11 +0,0 @@
grammar <grammarName>;
@members {
<Declare_pred()>
}
s : a[99] ;
a[int i] : e {<ValEquals("$i","99"):Invoke_pred()>}? {<writeln("\"parse\"")>} '!' ;
b[int i] : e {<ValEquals("$i","99"):Invoke_pred()>}? ID ;
e : ID | ; // non-LL(1) so we use ATN
ID : 'a'..'z'+ ;
INT : '0'..'9'+;
WS : (' '|'\n') -> skip ;

View File

@ -1,5 +0,0 @@
grammar <grammarName>;
cppCompilationUnit : content+ EOF;
content: anything | {<False()>}? .;
anything: ANY_CHAR;
ANY_CHAR: [_a-zA-Z0-9];

View File

@ -1,10 +0,0 @@
grammar <grammarName>;
s : b ';' | b '.' ;
b : a ;
a
: {<False()>}? ID {<writeln("\"alt 1\"")>}
| {<True()>}? ID {<writeln("\"alt 2\"")>}
;
ID : 'a'..'z'+ ;
INT : '0'..'9'+;
WS : (' '|'\n') -> skip ;

View File

@ -1,8 +0,0 @@
grammar <grammarName>;
s : a a;
a : {<False()>}? ID INT {<writeln("\"alt 1\"")>}
| {<False()>}? ID INT {<writeln("\"alt 2\"")>}
;
ID : 'a'..'z'+ ;
INT : '0'..'9'+;
WS : (' '|'\n') -> skip ;

View File

@ -1,10 +0,0 @@
grammar <grammarName>;
s : a {} a; // 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 {<writeln("\"alt 1\"")>}
| {<True()>}? ID {<writeln("\"alt 2\"")>}
;
ID : 'a'..'z'+ ;
INT : '0'..'9'+;
WS : (' '|'\n') -> skip ;

View File

@ -1,10 +0,0 @@
grammar <grammarName>;
@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\"")>}
;
ID : 'a'..'z'+ ;
INT : '0'..'9'+;
WS : (' '|'\n') -> skip ;

View File

@ -1,10 +0,0 @@
grammar <grammarName>;
@members {<InitIntMember("i","0")>}
s : a[2] a[1];
a[int i]
: {<ValEquals("$i","1")>}? ID
| {<ValEquals("$i","2")>}? ID
;
ID : 'a'..'z'+ ;
INT : '0'..'9'+;
WS : (' '|'\n') -> skip ;

View File

@ -1,10 +0,0 @@
grammar <grammarName>;
@members {
<Declare_pred()>
}
s : e {<True():Invoke_pred()>}? {<writeln("\"parse\"")>} '!' ;
t : e {<False():Invoke_pred()>}? ID ;
e : ID | ; // non-LL(1) so we use ATN
ID : 'a'..'z'+ ;
INT : '0'..'9'+;
WS : (' '|'\n') -> skip ;

View File

@ -1,8 +0,0 @@
grammar <grammarName>;
s : a a;
a : {<LTEquals("1", "\"x\"")>}? ID INT {<writeln("\"alt 1\"")>}
| {<LTEquals("1", "\"y\"")>}? ID INT {<writeln("\"alt 2\"")>}
;
ID : 'a'..'z'+ ;
INT : '0'..'9'+;
WS : (' '|'\n') -> skip ;

View File

@ -1,8 +0,0 @@
grammar <grammarName>;
s : a ;
a : {<False()>}? ID {<writeln("\"alt 1\"")>}
| {<True()>}? INT {<writeln("\"alt 2\"")>}
;
ID : 'a'..'z'+ ;
INT : '0'..'9'+;
WS : (' '|'\n') -> skip ;

View File

@ -1,8 +0,0 @@
grammar <grammarName>;
s : a a a;
a : {<False()>}? ID {<writeln("\"alt 1\"")>}
| {<True()>}? INT {<writeln("\"alt 2\"")>}
;
ID : 'a'..'z'+ ;
INT : '0'..'9'+;
WS : (' '|'\n') -> skip ;

View File

@ -1,8 +0,0 @@
grammar <grammarName>;
s : a+ ;
a : {<False()>}? ID {<writeln("\"alt 1\"")>}
| {<True()>}? ID {<writeln("\"alt 2\"")>}
;
ID : 'a'..'z'+ ;
INT : '0'..'9'+;
WS : (' '|'\n') -> skip ;

View File

@ -1,10 +0,0 @@
grammar <grammarName>;
@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\"")>}
;
ID : 'a'..'z'+ ;
INT : '0'..'9'+;
WS : (' '|'\n') -> skip ;

View File

@ -1,12 +0,0 @@
grammar <grammarName>;
s : a {<writeln("\"alt 1\"")>}
| b {<writeln("\"alt 2\"")>}
;
a : {<False()>}? ID INT
| ID INT
;
b : ID ID
;
ID : 'a'..'z'+ ;
INT : '0'..'9'+;
WS : (' '|'\n') -> skip ;

View File

@ -1,454 +0,0 @@
package org.antlr.v4.test.rt.java;
import org.junit.Test;
import static org.junit.Assert.*;
public class TestSemPredEvalParser extends BaseTest {
/* this file and method are generated, any edit will be overwritten by the next generation */
@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 ;";
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);
}
/* this file and method are generated, any edit will be overwritten by the next generation */
@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 ;";
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);
}
/* this file and method are generated, any edit will be overwritten by the next generation */
@Test
public void testAtomWithClosureInTranslatedLRRule() throws Exception {
String grammar = "grammar T;\n" +
"start : e[0] EOF;\n" +
"e[int _p]\n" +
" : ( 'a' | 'b'+ ) ( {3 >= $_p}? '+' e[4] )*\n" +
" ;";
String found = execParser("T.g4", grammar, "TParser", "TLexer", "start", "a+b+a", false);
assertEquals("", found);
assertNull(this.stderrDuringParse);
}
/* this file and method are generated, any edit will be overwritten by the next generation */
@Test
public void testValidateInDFA() throws Exception {
String grammar = "grammar T;\n" +
"s : a ';' a;\n" +
"// ';' helps us to resynchronize without consuming\n" +
"// 2nd 'a' reference. We our testing that the DFA also\n" +
"// throws an exception if the validating predicate fails\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 ;";
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);
}
/* this file and method are generated, any edit will be overwritten by the next generation */
@Test
public void testSimple() throws Exception {
String grammar = "grammar T;\n" +
"s : a a a; // do 3x: once in ATN, next in DFA then INT in ATN\n" +
"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 ;";
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);
}
/* this file and method are generated, any edit will be overwritten by the next generation */
@Test
public void testOrder() throws Exception {
String grammar = "grammar T;\n" +
"s : a {} a; // do 2x: once in ATN, next in DFA;\n" +
"// action blocks lookahead from falling off of 'a'\n" +
"// and looking into 2nd 'a' ref. !ctx dependent pred\n" +
"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 ;";
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "x y", false);
assertEquals("alt 1\nalt 1\n", found);
assertNull(this.stderrDuringParse);
}
/* this file and method are generated, any edit will be overwritten by the next generation */
@Test
public void test2UnpredicatedAlts() throws Exception {
String grammar = "grammar T;\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" +
" ;\n" +
"ID : 'a'..'z'+ ;\n" +
"INT : '0'..'9'+;\n" +
"WS : (' '|'\\n') -> skip ;";
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);
}
/* this file and method are generated, any edit will be overwritten by the next generation */
@Test
public void test2UnpredicatedAltsAndOneOrthogonalAlt() throws Exception {
String grammar = "grammar T;\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 {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", 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);
}
/* this file and method are generated, any edit will be overwritten by the next generation */
@Test
public void testRewindBeforePredEval() throws Exception {
String grammar = "grammar T;\n" +
"s : a a;\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", true);
assertEquals("alt 2\nalt 1\n", found);
assertNull(this.stderrDuringParse);
}
/* this file and method are generated, any edit will be overwritten by the next generation */
@Test
public void testNoTruePredsThrowsNoViableAlt() throws Exception {
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 ;";
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "y 3 x 4", false);
assertEquals("", found);
assertEquals("line 1:0 no viable alternative at input 'y'\n", this.stderrDuringParse);
}
/* this file and method are generated, any edit will be overwritten by the next generation */
@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 ;";
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);
}
/* this file and method are generated, any edit will be overwritten by the next generation */
@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 ;";
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "x 4", true);
assertEquals("alt 1\n", found);
assertNull(this.stderrDuringParse);
}
/* this file and method are generated, any edit will be overwritten by the next generation */
@Test
public void testActionHidesPreds() throws Exception {
String grammar = "grammar T;\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" +
" ;\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);
assertEquals("alt 1\nalt 1\nalt 1\n", found);
assertNull(this.stderrDuringParse);
}
/* this file and method are generated, any edit will be overwritten by the next generation */
@Test
public void testToLeftWithVaryingPredicate() throws Exception {
String grammar = "grammar T;\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", true);
assertEquals("i=1\nalt 2\ni=2\nalt 1\ni=3\nalt 2\n", found);
assertNull(this.stderrDuringParse);
}
/* this file and method are generated, any edit will be overwritten by the next generation */
@Test
public void testPredicateDependentOnArg() throws Exception {
String grammar = "grammar T;\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" +
" ;\n" +
"ID : 'a'..'z'+ ;\n" +
"INT : '0'..'9'+;\n" +
"WS : (' '|'\\n') -> skip ;";
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "a b", true);
assertEquals("alt 2\nalt 1\n", found);
assertNull(this.stderrDuringParse);
}
/* this file and method are generated, any edit will be overwritten by the next generation */
@Test
public void testPredicateDependentOnArg2() throws Exception {
String grammar = "grammar T;\n" +
"@members {int i = 0;}\n" +
"s : a[2] a[1];\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", true);
assertEquals("", found);
assertNull(this.stderrDuringParse);
}
/* this file and method are generated, any edit will be overwritten by the next generation */
@Test
public void testDependentPredNotInOuterCtxShouldBeIgnored() throws Exception {
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" +
" ;\n" +
"ID : 'a'..'z'+ ;\n" +
"INT : '0'..'9'+;\n" +
"WS : (' '|'\\n') -> skip ;";
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "a;", true);
assertEquals("alt 2\n", found);
assertNull(this.stderrDuringParse);
}
/* this file and method are generated, any edit will be overwritten by the next generation */
@Test
public void testIndependentPredNotPassedOuterCtxToAvoidCastException() throws Exception {
String grammar = "grammar T;\n" +
"s : b ';' | b '.' ;\n" +
"b : a ;\n" +
"a\n" +
" : {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 ;";
String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "a;", true);
assertEquals("alt 2\n", found);
assertNull(this.stderrDuringParse);
}
/* this file and method are generated, any edit will be overwritten by the next generation */
@Test
public void testPredsInGlobalFOLLOW() throws Exception {
String grammar = "grammar T;\n" +
"@members {\n" +
"boolean pred(boolean v) {\n" +
" System.out.println(\"eval=\"+v);\n" +
" return v;\n" +
"}\n" +
"}\n" +
"s : e {this.pred(true)}? {System.out.println(\"parse\");} '!' ;\n" +
"t : e {this.pred(false)}? 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!", true);
assertEquals("eval=true\nparse\n", found);
assertNull(this.stderrDuringParse);
}
/* this file and method are generated, any edit will be overwritten by the next generation */
@Test
public void testDepedentPredsInGlobalFOLLOW() throws Exception {
String grammar = "grammar T;\n" +
"@members {\n" +
"boolean pred(boolean v) {\n" +
" System.out.println(\"eval=\"+v);\n" +
" return v;\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" +
"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!", true);
assertEquals("eval=true\nparse\n", found);
assertNull(this.stderrDuringParse);
}
/* this file and method are generated, any edit will be overwritten by the next generation */
@Test
public void testActionsHidePredsInGlobalFOLLOW() throws Exception {
String grammar = "grammar T;\n" +
"@members {\n" +
"boolean pred(boolean v) {\n" +
" System.out.println(\"eval=\"+v);\n" +
" return v;\n" +
"}\n" +
"}\n" +
"s : e {} {this.pred(true)}? {System.out.println(\"parse\");} '!' ;\n" +
"t : e {} {this.pred(false)}? 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!", true);
assertEquals("eval=true\nparse\n", found);
assertNull(this.stderrDuringParse);
}
/* this file and method are generated, any edit will be overwritten by the next generation */
String testPredTestedEvenWhenUnAmbig(String input) throws Exception {
String grammar = "grammar T;\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, true);
}
/* this file and method are generated, any edit will be overwritten by the next generation */
@Test
public void testPredTestedEvenWhenUnAmbig_1() throws Exception {
String found = testPredTestedEvenWhenUnAmbig("abc");
assertEquals("ID abc\n", found);
assertNull(this.stderrDuringParse);
}
/* this file and method are generated, any edit will be overwritten by the next generation */
@Test
public void testPredTestedEvenWhenUnAmbig_2() throws Exception {
String found = testPredTestedEvenWhenUnAmbig("enum");
assertEquals("", found);
assertEquals("line 1:0 no viable alternative at input 'enum'\n", this.stderrDuringParse);
}
/* this file and method are generated, any edit will be overwritten by the next generation */
@Test
public void testDisabledAlternative() throws Exception {
String grammar = "grammar T;\n" +
"cppCompilationUnit : content+ EOF;\n" +
"content: anything | {false}? .;\n" +
"anything: ANY_CHAR;\n" +
"ANY_CHAR: [_a-zA-Z0-9];";
String found = execParser("T.g4", grammar, "TParser", "TLexer", "cppCompilationUnit", "hello", true);
assertEquals("", found);
assertNull(this.stderrDuringParse);
}
/* this file and method are generated, any edit will be overwritten by the next generation */
String testPredFromAltTestedInLoopBack(String input) throws Exception {
String grammar = "grammar T;\n" +
"file_\n" +
"@after {System.out.println($ctx.toStringTree(this));}\n" +
" : para para EOF ;\n" +
"para: paraContent NL NL ;\n" +
"paraContent : ('s'|'x'|{this._input.LA(2)!=NL}? NL)+ ;\n" +
"NL : '\\n' ;\n" +
"s : 's' ;\n" +
"X : 'x' ;";
return execParser("T.g4", grammar, "TParser", "TLexer", "file_", input, true);
}
/* this file and method are generated, any edit will be overwritten by the next generation */
@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("line 5:0 mismatched input '<EOF>' expecting '\n'\n", this.stderrDuringParse);
}
/* this file and method are generated, any edit will be overwritten by the next generation */
@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);
assertNull(this.stderrDuringParse);
}
}

View File

@ -98,7 +98,7 @@ public void test<test.name>() throws Exception {
<test.AfterGrammar>
<endif>
String input =<writeStringLiteral(test.Input)>;
String found = execParser("<grammar>.g4", grammar, "<grammar>Parser", "<grammar>Lexer", "<test.Rule>", input, <writeBoolean(test.Debug)>);
String found = execParser("<grammar>.g4", grammar, "<grammar>Parser", "<grammar>Lexer", "<test.Rule>", input, <writeBoolean(test.Options.("Debug"))>);
assertEquals(<writeStringLiteral(test.Output)>, found);
<if(!isEmpty.(test.Errors))>
assertEquals(<writeStringLiteral(test.Errors)>, this.stderrDuringParse);