From 9c1e58db7cbf6e5707694ed271911ce7085c9abb Mon Sep 17 00:00:00 2001 From: Terence Parr Date: Tue, 27 Mar 2012 16:21:01 -0700 Subject: [PATCH] add {} in primary alt block to prevent ID|INT from becoming SET, which breaks code gen needs. --- tool/playground/T.g | 8 +-- .../v4/tool/templates/LeftRecursiveRules.stg | 2 +- .../org/antlr/v4/test/TestLeftRecursion.java | 53 +++++++++++++++++++ 3 files changed, 59 insertions(+), 4 deletions(-) diff --git a/tool/playground/T.g b/tool/playground/T.g index eebbe9ddd1..9949f8074f 100644 --- a/tool/playground/T.g +++ b/tool/playground/T.g @@ -1,6 +1,8 @@ grammar T; -s : f f EOF; -f : | x; -x : 'a' 'b'; +s : e ';' ; +e : e '*' e + | ID + | INT + ; INT : '0'..'9'+; WS : (' '|'\n') {skip();} ; diff --git a/tool/resources/org/antlr/v4/tool/templates/LeftRecursiveRules.stg b/tool/resources/org/antlr/v4/tool/templates/LeftRecursiveRules.stg index 9ac580e884..7c0bcddc2e 100644 --- a/tool/resources/org/antlr/v4/tool/templates/LeftRecursiveRules.stg +++ b/tool/resources/org/antlr/v4/tool/templates/LeftRecursiveRules.stg @@ -37,7 +37,7 @@ recRule(ruleName, precArgDef, argName, primaryAlts, opAlts, setResultAction, userRetvals, leftRecursiveRuleRefLabels) ::= << [] returns [] - : ( }; separator="\n | "> + : ( {} }; separator="\n | "> ) ( )* diff --git a/tool/test/org/antlr/v4/test/TestLeftRecursion.java b/tool/test/org/antlr/v4/test/TestLeftRecursion.java index f5b8400f92..205f737c89 100644 --- a/tool/test/org/antlr/v4/test/TestLeftRecursion.java +++ b/tool/test/org/antlr/v4/test/TestLeftRecursion.java @@ -276,6 +276,59 @@ public class TestLeftRecursion extends BaseTest { 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) { rawGenerateAndBuildRecognizer("T.g", grammar, "TParser", "TLexer"); writeRecognizerAndCompile("TParser",