From 8c03dbacf8dca5e26ad3f598590ca4fc155f6c25 Mon Sep 17 00:00:00 2001 From: Terence Parr Date: Sat, 21 Jul 2012 15:29:07 -0700 Subject: [PATCH 1/3] Resolves #41. EOF cannot follow s. would need s' : s EOF ; for that. updating unit test TestParserExec.testOptional --- .../org/antlr/v4/test/TestParserExec.java | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/tool/test/org/antlr/v4/test/TestParserExec.java b/tool/test/org/antlr/v4/test/TestParserExec.java index 45c27422a..2cb3e4a9e 100644 --- a/tool/test/org/antlr/v4/test/TestParserExec.java +++ b/tool/test/org/antlr/v4/test/TestParserExec.java @@ -164,32 +164,33 @@ public class TestParserExec extends BaseTest { /** - * This test is meant to detect regressions of bug antlr/antlr4#41. - * https://github.com/antlr/antlr4/issues/41 + * Related to https://github.com/antlr/antlr4/issues/41. EOF is + * not viable after "if x" since EOF not viable after stat. */ @Test public void testOptional() throws Exception { String grammar = "grammar T;\n" + - "s : a | 'x';\n" + - "a : 'a' s ('b' s)?;\n" + "stat : ifstat | 'x';\n" + + "ifstat : 'if' stat ('else' stat)?;\n" + + "WS : [ \\n\\t]+ -> skip ;" ; - String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "x", false); + String found = execParser("T.g4", grammar, "TParser", "TLexer", "stat", "x", false); assertEquals("", found); assertNull(this.stderrDuringParse); - found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "axbx", false); + found = execParser("T.g4", grammar, "TParser", "TLexer", "stat", "if x else x", false); assertEquals("", found); assertNull(this.stderrDuringParse); - found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "ax", false); + found = execParser("T.g4", grammar, "TParser", "TLexer", "stat", "if x", false); assertEquals("", found); - assertNull(this.stderrDuringParse); + assertEquals("line 1:4 no viable alternative at input ''\n", this.stderrDuringParse); - found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "aaxbx", false); + found = execParser("T.g4", grammar, "TParser", "TLexer", "stat", "if if x else x", false); assertEquals("", found); - assertNull(this.stderrDuringParse); + assertEquals("line 1:14 no viable alternative at input ''\n", this.stderrDuringParse); } /** From 7a4a269615e0e2558f633e28277d66fd4d0e0abd Mon Sep 17 00:00:00 2001 From: Terence Parr Date: Sat, 21 Jul 2012 15:36:56 -0700 Subject: [PATCH 2/3] fix test so no error due to EOF. --- tool/test/org/antlr/v4/test/TestParserExec.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tool/test/org/antlr/v4/test/TestParserExec.java b/tool/test/org/antlr/v4/test/TestParserExec.java index 2cb3e4a9e..04fca1e25 100644 --- a/tool/test/org/antlr/v4/test/TestParserExec.java +++ b/tool/test/org/antlr/v4/test/TestParserExec.java @@ -201,6 +201,7 @@ public class TestParserExec extends BaseTest { public void testIfIfElse() throws Exception { String grammar = "grammar T;\n" + + "s : stmt EOF ;\n" + "stmt : ifStmt | ID;\n" + "ifStmt : 'if' ID stmt ('else' stmt | {_input.LA(1) != ELSE}?);\n" + "ELSE : 'else';\n" + @@ -208,11 +209,12 @@ public class TestParserExec extends BaseTest { "WS : (' ' | '\\t')+ -> skip;\n" ; - String found = execParser("T.g4", grammar, "TParser", "TLexer", "stmt", + String found = execParser("T.g4", grammar, "TParser", "TLexer", "s", "if x if x a else b", true); String expecting = ""; assertEquals(expecting, found); - assertNull(this.stderrDuringParse); + assertEquals("line 1:12 reportAttemptingFullContext d=1, input='else'\n", + this.stderrDuringParse); } } From 9539572ee7155ca403d0cb6bf9ee0d74fee4d0c1 Mon Sep 17 00:00:00 2001 From: Terence Parr Date: Sat, 21 Jul 2012 16:27:00 -0700 Subject: [PATCH 3/3] simplify test. --- tool/playground/T.g | 36 ++++++++++++++++--- tool/playground/TestT.java | 6 ++-- .../org/antlr/v4/test/TestLeftRecursion.java | 15 +------- 3 files changed, 36 insertions(+), 21 deletions(-) diff --git a/tool/playground/T.g b/tool/playground/T.g index bd82e2b53..12c9c3ad3 100644 --- a/tool/playground/T.g +++ b/tool/playground/T.g @@ -1,8 +1,34 @@ grammar T; +s : stat ; +stat: expr[0] NEWLINE + | ID '=' expr[0] NEWLINE + | NEWLINE + ; -s : ID b ; -b : INT ; +expr[int _p] + : ( INT + | ID + | '(' expr[0] ')' + ) + ( {5 >= $_p}? ('*'|'/') expr[6] + | {4 >= $_p}? ('+'|'-') expr[5] + )* + ; -ID : [a-zA-Z]+ ; -INT : [0-9]+ ; -WS : [ \t\n\r]+ -> skip ; +/* +expr: expr ('*'|'/') expr # MulDiv + | expr ('+'|'-') expr # AddSub + | INT # int + | ID # id + | '(' expr ')' # parens + ; +*/ + +MUL : '*' ; // assigns token name to '*' used above in grammar +DIV : '/' ; +ADD : '+' ; +SUB : '-' ; +ID : [a-zA-Z]+ ; // match identifiers +INT : [0-9]+ ; // match integers +NEWLINE:'\r'? '\n' ; // return newlines to parser (is end-statement signal) +WS : [ \t]+ -> skip ; // toss out whitespace diff --git a/tool/playground/TestT.java b/tool/playground/TestT.java index b9cdfc19d..d57757d8f 100644 --- a/tool/playground/TestT.java +++ b/tool/playground/TestT.java @@ -1,6 +1,7 @@ import org.antlr.v4.runtime.CharStream; import org.antlr.v4.runtime.CommonTokenFactory; import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.DiagnosticErrorListener; import org.antlr.v4.runtime.ParserRuleContext; import org.antlr.v4.runtime.UnbufferedCharStream; @@ -23,8 +24,9 @@ public class TestT { CommonTokenStream tokens = new CommonTokenStream(lex); TParser parser = new TParser(tokens); - ParserRuleContext tree = parser.s(); - tree.save(parser, "/tmp/t.ps"); + parser.addErrorListener(new DiagnosticErrorListener()); + ParserRuleContext tree = parser.s(); +// tree.save(parser, "/tmp/t.ps"); } } diff --git a/tool/test/org/antlr/v4/test/TestLeftRecursion.java b/tool/test/org/antlr/v4/test/TestLeftRecursion.java index 5fe3503fb..b9b48c091 100644 --- a/tool/test/org/antlr/v4/test/TestLeftRecursion.java +++ b/tool/test/org/antlr/v4/test/TestLeftRecursion.java @@ -297,31 +297,19 @@ public class TestLeftRecursion extends BaseTest { @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" + @@ -329,8 +317,7 @@ public class TestLeftRecursion extends BaseTest { "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"; + "WS : [ \\t]+ -> skip ; // toss out whitespace\n"; String result = execParser("Expr.g4", grammar, "ExprParser", "ExprLexer", "prog", "1\n", true); assertNull(stderrDuringParse);