forked from jasder/antlr
add {} in primary alt block to prevent ID|INT from becoming SET, which breaks code gen needs.
This commit is contained in:
parent
bd51907c5e
commit
9c1e58db7c
|
@ -1,6 +1,8 @@
|
||||||
grammar T;
|
grammar T;
|
||||||
s : f f EOF;
|
s : e ';' ;
|
||||||
f : | x;
|
e : e '*' e
|
||||||
x : 'a' 'b';
|
| ID
|
||||||
|
| INT
|
||||||
|
;
|
||||||
INT : '0'..'9'+;
|
INT : '0'..'9'+;
|
||||||
WS : (' '|'\n') {skip();} ;
|
WS : (' '|'\n') {skip();} ;
|
||||||
|
|
|
@ -37,7 +37,7 @@ recRule(ruleName, precArgDef, argName, primaryAlts, opAlts, setResultAction,
|
||||||
userRetvals, leftRecursiveRuleRefLabels) ::=
|
userRetvals, leftRecursiveRuleRefLabels) ::=
|
||||||
<<
|
<<
|
||||||
<ruleName>[<precArgDef>]<if(userRetvals)> returns [<userRetvals>]<endif>
|
<ruleName>[<precArgDef>]<if(userRetvals)> returns [<userRetvals>]<endif>
|
||||||
: ( <primaryAlts:{alt | <alt.altText> }; separator="\n | ">
|
: ( {} <primaryAlts:{alt | <alt.altText> }; separator="\n | ">
|
||||||
)
|
)
|
||||||
( <opAlts; separator="\n | ">
|
( <opAlts; separator="\n | ">
|
||||||
)*
|
)*
|
||||||
|
|
|
@ -276,6 +276,59 @@ public class TestLeftRecursion extends BaseTest {
|
||||||
runTests(grammar, tests, "s");
|
runTests(grammar, tests, "s");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAmbigLR() throws Exception {
|
||||||
|
String grammar =
|
||||||
|
"// START: g\n" +
|
||||||
|
"grammar Expr;\n" +
|
||||||
|
"// END: g\n" +
|
||||||
|
"\n" +
|
||||||
|
"// START:stat\n" +
|
||||||
|
"prog: stat ;\n" +
|
||||||
|
"\n" +
|
||||||
|
"stat: expr NEWLINE -> printExpr\n" +
|
||||||
|
" | ID '=' expr NEWLINE -> assign\n" +
|
||||||
|
" | NEWLINE -> blank\n" +
|
||||||
|
" ;\n" +
|
||||||
|
"// END:stat\n" +
|
||||||
|
"\n" +
|
||||||
|
"// START:expr\n" +
|
||||||
|
"expr: expr ('*'|'/') expr -> MulDiv\n" +
|
||||||
|
" | expr ('+'|'-') expr -> AddSub\n" +
|
||||||
|
" | INT -> int\n" +
|
||||||
|
" | ID -> id\n" +
|
||||||
|
" | '(' expr ')' -> parens\n" +
|
||||||
|
" ;\n" +
|
||||||
|
"// END:expr\n" +
|
||||||
|
"\n" +
|
||||||
|
"// show marginal cost of adding a clear/wipe command for memory\n" +
|
||||||
|
"\n" +
|
||||||
|
"// START:tokens\n" +
|
||||||
|
"MUL : '*' ; // assigns token name to '*' used above in grammar\n" +
|
||||||
|
"DIV : '/' ;\n" +
|
||||||
|
"ADD : '+' ;\n" +
|
||||||
|
"SUB : '-' ;\n" +
|
||||||
|
"ID : [a-zA-Z]+ ; // match identifiers\n" +
|
||||||
|
"INT : [0-9]+ ; // match integers\n" +
|
||||||
|
"NEWLINE:'\\r'? '\\n' ; // return newlines to parser (is end-statement signal)\n" +
|
||||||
|
"WS : [ \\t]+ -> skip ; // toss out whitespace\n" +
|
||||||
|
"// END:tokens\n";
|
||||||
|
String result = execParser("Expr.g4", grammar, "ExprParser", "ExprLexer", "prog", "1\n", true);
|
||||||
|
assertNull(stderrDuringParse);
|
||||||
|
|
||||||
|
result = execParser("Expr.g4", grammar, "ExprParser", "ExprLexer", "prog", "a = 5\n", true);
|
||||||
|
assertNull(stderrDuringParse);
|
||||||
|
|
||||||
|
result = execParser("Expr.g4", grammar, "ExprParser", "ExprLexer", "prog", "b = 6\n", true);
|
||||||
|
assertNull(stderrDuringParse);
|
||||||
|
|
||||||
|
result = execParser("Expr.g4", grammar, "ExprParser", "ExprLexer", "prog", "a+b*2\n", true);
|
||||||
|
assertNull(stderrDuringParse);
|
||||||
|
|
||||||
|
result = execParser("Expr.g4", grammar, "ExprParser", "ExprLexer", "prog", "(1+2)*3\n", true);
|
||||||
|
assertNull(stderrDuringParse);
|
||||||
|
}
|
||||||
|
|
||||||
public void runTests(String grammar, String[] tests, String startRule) {
|
public void runTests(String grammar, String[] tests, String startRule) {
|
||||||
rawGenerateAndBuildRecognizer("T.g", grammar, "TParser", "TLexer");
|
rawGenerateAndBuildRecognizer("T.g", grammar, "TParser", "TLexer");
|
||||||
writeRecognizerAndCompile("TParser",
|
writeRecognizerAndCompile("TParser",
|
||||||
|
|
Loading…
Reference in New Issue