validated ParserExec tests

This commit is contained in:
ericvergnaud 2014-10-25 00:06:47 +08:00
parent e03c7d44e5
commit 6067aee458
16 changed files with 159 additions and 499 deletions

View File

@ -7,6 +7,7 @@ import org.stringtemplate.v4.STGroup;
public class CompositeParserTestMethod extends ParserTestMethod {
public Grammar[] slaveGrammars;
public boolean slaveIsLexer = false;
public CompositeParserTestMethod(String name, String grammarName,
String startRule, String input, String expectedOutput,

View File

@ -1,5 +1,7 @@
package org.antlr.v4.test.rt.gen;
import static org.junit.Assert.assertEquals;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
@ -13,6 +15,7 @@ import java.util.List;
import java.util.Map;
import org.antlr.v4.test.rt.java.BaseTest;
import org.junit.Test;
import org.stringtemplate.v4.ST;
import org.stringtemplate.v4.STGroup;
import org.stringtemplate.v4.STGroupFile;
@ -1230,8 +1233,8 @@ public class Generator {
private TestFile buildParserExec() throws Exception {
TestFile file = new TestFile("ParserExec");
file.addParserTest(input, "Labels", "T", "a", "abc 34", "", null);
file.addParserTest(input, "ListLabelsOnSet", "T", "a", "abc 34", "", null);
file.addParserTest(input, "Labels", "T", "a", "abc 34;", "", null);
file.addParserTest(input, "ListLabelsOnSet", "T", "a", "abc 34;", "", null);
file.addParserTest(input, "AorB", "T", "a", "34", "alt 2\n", null);
file.addParserTest(input, "Basic", "T", "a", "abc 34", "abc34\n", null);
file.addParserTest(input, "APlus", "T", "a", "a b c", "abc\n", null);
@ -1268,6 +1271,28 @@ public class Generator {
file.addParserTest(input, "LabelAliasingAcrossLabeledAlternatives", "T", "start", "xy", "x\ny\n", null);
file.addParserTest(input, "PredictionIssue334", "T", "file_", "a", "(file_ (item a) <EOF>)\n", null);
file.addParserTest(input, "ListLabelForClosureContext", "T", "expression", "a", "", null);
/**
* This test ensures that {@link ParserATNSimulator} produces a correct
* result when the grammar contains multiple explicit references to
* {@code EOF} inside of parser rules.
*/
file.addParserTest(input, "MultipleEOFHandling", "T", "prog", "x", "", null);
/**
* This test ensures that {@link ParserATNSimulator} does not produce a
* {@link StackOverflowError} when it encounters an {@code EOF} transition
* inside a closure.
*/
file.addParserTest(input, "EOFInClosure", "T", "prog", "x", "", null);
/**
* This is a regression test for antlr/antlr4#561 "Issue with parser
* generation in 4.2.2"
* https://github.com/antlr/antlr4/issues/561
*/
file.addParserTests(input, "ReferenceToATN", "T", "a",
"", "\n",
"a 34 c", "a34c\n");
CompositeParserTestMethod tm = file.addCompositeParserTest(input, "AlternateQuotes", "ModeTagsParser", "file_", "", "", null, "ModeTagsLexer");
tm.slaveIsLexer = true;
return file;
}

View File

@ -0,0 +1,6 @@
parser grammar ModeTagsParser;
options { tokenVocab=ModeTagsLexer; } // use tokens from ModeTagsLexer.g4
file_: (tag | TEXT)* ;
tag : '«' ID '»'
| '«' '/' ID '»'
;

View File

@ -0,0 +1,8 @@
lexer grammar ModeTagsLexer;
// Default mode rules (the SEA)
OPEN : '«' -> mode(ISLAND) ; // switch to ISLAND mode
TEXT : ~'«'+ ; // clump all text together
mode ISLAND;
CLOSE : '»' -> mode(DEFAULT_MODE) ; // back to SEA mode
SLASH : '/' ;
ID : [a-zA-Z]+ ; // match/send ID in tag to parser

View File

@ -0,0 +1,3 @@
grammar <grammarName>;
prog : stat EOF;
stat : 'x' ('y' | EOF)*?;

View File

@ -1,7 +1,7 @@
grammar <grammarName>;
ifStatement
@after {
<LocalVar()>items = $ctx.elseIfStatement()
<DeclareLocal("items = $ctx.elseIfStatement()")>
}
: 'if' expression
( ( 'then'

View File

@ -0,0 +1,2 @@
grammar <grammarName>;
prog : ('x' | 'x' 'y') EOF EOF;

View File

@ -0,0 +1,5 @@
grammar <grammarName>;
a : (ID|ATN)* ATN? {<writeln("$text")>} ;
ID : 'a'..'z'+ ;
ATN : '0'..'9'+;
WS : (' '|'\n') -> skip ;

View File

@ -49,12 +49,16 @@ ParserTestMethod(test) ::= <<
public void test<test.name>() throws Exception {
<test.slaveGrammars:{ grammar |
String slave_<grammar.grammarName> = <grammar.lines:{ line | "<line>};separator="\\n\" +\n", wrap, anchor>";
<if(test.slaveIsLexer)>
rawGenerateAndBuildRecognizer("<grammar.grammarName>.g4", slave_<grammar.grammarName>, null, "<grammar.grammarName>");
<else>
mkdir(tmpdir);
writeFile(tmpdir, "<grammar.grammarName>.g4", slave_<grammar.grammarName>);
<endif>
};separator="\n", wrap, anchor>
String grammar = <test.grammar.lines:{ line | "<line>};separator="\\n\" +\n", wrap, anchor>";
<test.afterGrammar>
String found = execParser("<test.grammar.grammarName>.g4", grammar, "<test.grammar.grammarName>Parser", "<test.grammar.grammarName>Lexer", "<test.startRule>", "<test.input>", false);
String found = execParser("<test.grammar.grammarName>.g4", grammar, "<test.grammar.grammarName><if(!test.slaveIsLexer)>Parser<endif>", "<if(test.slaveIsLexer)><first(test.slaveGrammars).grammarName><else><test.grammar.grammarName>Lexer<endif>", "<test.startRule>", "<test.input>", false);
assertEquals("<test.expectedOutput>", found);
<if(test.expectedErrors)>
assertEquals("<test.expectedErrors>", this.stderrDuringParse);
@ -97,7 +101,7 @@ write(s) ::= <<System.out.print(<s>);>>
assert(s) ::= <<console.assert(<s>);>>
LocalVar() ::= "var "
DeclareLocal(s) ::= "Object <s>;"
InitMember(n,v) ::= <%this.<n> = <v>;%>
@ -121,9 +125,9 @@ Pass() ::= ""
BuildParseTrees() ::= "this.buildParseTrees = true;"
BailErrorStrategy() ::= <%this._errHandler = new antlr4.error.BailErrorStrategy();%>
BailErrorStrategy() ::= <%setErrorHandler(new BailErrorStrategy());%>
ToStringTree(s) ::= <%<s>.toStringTree(null, this);%>
ToStringTree(s) ::= <%<s>.toStringTree(this)%>
Column() ::= "this.getCharPositionInLine()"

View File

@ -177,7 +177,7 @@ public class TestFullContextParsing extends BaseTest {
String grammar = "grammar T;\n" +
"s\n" +
"@init {this._interp.predictionMode = antlr4.atn.PredictionMode.LL_EXACT_AMBIG_DETECTION;}\n" +
": expr[0] {System.out.println($expr.ctx.toStringTree(null, this););};\n" +
": expr[0] {System.out.println($expr.ctx.toStringTree(this));};\n" +
" expr[int _p]\n" +
" : ID \n" +
" ( \n" +

View File

@ -7,7 +7,7 @@ public class TestLeftRecursion extends BaseTest {
String testSimple(String input) throws Exception {
String grammar = "grammar T;\n" +
"s @after {System.out.println($ctx.toStringTree(null, this););} : a ;\n" +
"s @after {System.out.println($ctx.toStringTree(this));} : a ;\n" +
"a : a ID\n" +
" | ID\n" +
" ;\n" +
@ -39,7 +39,7 @@ public class TestLeftRecursion extends BaseTest {
String testDirectCallToLeftRecursiveRule(String input) throws Exception {
String grammar = "grammar T;\n" +
"a @after {System.out.println($ctx.toStringTree(null, this););} : a ID\n" +
"a @after {System.out.println($ctx.toStringTree(this));} : a ID\n" +
" | ID\n" +
" ;\n" +
"ID : 'a'..'z'+ ;\n" +
@ -71,7 +71,7 @@ public class TestLeftRecursion extends BaseTest {
@Test
public void testSemPred() throws Exception {
String grammar = "grammar T;\n" +
"s @after {System.out.println($ctx.toStringTree(null, this););} : a ;\n" +
"s @after {System.out.println($ctx.toStringTree(this));} : a ;\n" +
"a : a {true}? ID\n" +
" | ID\n" +
" ;\n" +
@ -84,7 +84,7 @@ public class TestLeftRecursion extends BaseTest {
String testTernaryExpr(String input) throws Exception {
String grammar = "grammar T;\n" +
"s @after {System.out.println($ctx.toStringTree(null, this););} : e EOF ; // must indicate EOF can follow or 'a<EOF>' won't match\n" +
"s @after {System.out.println($ctx.toStringTree(this));} : e EOF ; // must indicate EOF can follow or 'a<EOF>' won't match\n" +
"e : e '*' e\n" +
" | e '+' e\n" +
" |<assoc=right> e '?' e ':' e\n" +
@ -161,7 +161,7 @@ public class TestLeftRecursion extends BaseTest {
String testExpressions(String input) throws Exception {
String grammar = "grammar T;\n" +
"s @after {System.out.println($ctx.toStringTree(null, this););} : e EOF ; // must indicate EOF can follow\n" +
"s @after {System.out.println($ctx.toStringTree(this));} : e EOF ; // must indicate EOF can follow\n" +
"e : e '.' ID\n" +
" | e '.' 'this'\n" +
" | '-' e\n" +
@ -227,7 +227,7 @@ public class TestLeftRecursion extends BaseTest {
String testJavaExpressions(String input) throws Exception {
String grammar = "grammar T;\n" +
"s @after {System.out.println($ctx.toStringTree(null, this););} : e EOF ; // must indicate EOF can follow\n" +
"s @after {System.out.println($ctx.toStringTree(this));} : e EOF ; // must indicate EOF can follow\n" +
"expressionList\n" +
" : e (',' e)*\n" +
" ;\n" +
@ -371,7 +371,7 @@ public class TestLeftRecursion extends BaseTest {
String testDeclarations(String input) throws Exception {
String grammar = "grammar T;\n" +
"s @after {System.out.println($ctx.toStringTree(null, this););} : declarator EOF ; // must indicate EOF can follow\n" +
"s @after {System.out.println($ctx.toStringTree(this));} : declarator EOF ; // must indicate EOF can follow\n" +
"declarator\n" +
" : declarator '[' e ']'\n" +
" | declarator '[' ']'\n" +
@ -501,7 +501,7 @@ public class TestLeftRecursion extends BaseTest {
String testLabelsOnOpSubrule(String input) throws Exception {
String grammar = "grammar T;\n" +
"s @after {System.out.println($ctx.toStringTree(null, this););} : e;\n" +
"s @after {System.out.println($ctx.toStringTree(this));} : e;\n" +
"e : a=e op=('*'|'/') b=e {}\n" +
" | INT {}\n" +
" | '(' x=e ')' {}\n" +
@ -792,7 +792,7 @@ public class TestLeftRecursion extends BaseTest {
public void testPrecedenceFilterConsidersContext() throws Exception {
String grammar = "grammar T;\n" +
"prog \n" +
"@after {System.out.println($ctx.toStringTree(null, this););}\n" +
"@after {System.out.println($ctx.toStringTree(this));}\n" +
": statement* EOF {};\n" +
"statement: letterA | statement letterA 'b' ;\n" +
"letterA: 'a';";

View File

@ -26,7 +26,7 @@ public class TestListeners extends BaseTest {
"\n" +
"s\n" +
"@after {\n" +
"System.out.println($ctx.r.toStringTree(null, this););\n" +
"System.out.println($ctx.r.toStringTree(this));\n" +
"var walker = new antlr4.tree.ParseTreeWalker();\n" +
"walker.walk(new this.LeafListener(), $ctx.r);\n" +
"\n" +
@ -71,7 +71,7 @@ public class TestListeners extends BaseTest {
"\n" +
"s\n" +
"@after {\n" +
"System.out.println($ctx.r.toStringTree(null, this););\n" +
"System.out.println($ctx.r.toStringTree(this));\n" +
"var walker = new antlr4.tree.ParseTreeWalker();\n" +
"walker.walk(new this.LeafListener(), $ctx.r);\n" +
"\n" +
@ -128,7 +128,7 @@ public class TestListeners extends BaseTest {
"\n" +
"s\n" +
"@after {\n" +
"System.out.println($ctx.r.toStringTree(null, this););\n" +
"System.out.println($ctx.r.toStringTree(this));\n" +
"var walker = new antlr4.tree.ParseTreeWalker();\n" +
"walker.walk(new this.LeafListener(), $ctx.r);\n" +
"\n" +
@ -187,7 +187,7 @@ public class TestListeners extends BaseTest {
"\n" +
"s\n" +
"@after {\n" +
"System.out.println($ctx.r.toStringTree(null, this););\n" +
"System.out.println($ctx.r.toStringTree(this));\n" +
"var walker = new antlr4.tree.ParseTreeWalker();\n" +
"walker.walk(new this.LeafListener(), $ctx.r);\n" +
"\n" +
@ -233,7 +233,7 @@ public class TestListeners extends BaseTest {
"\n" +
"s\n" +
"@after {\n" +
"System.out.println($ctx.r.toStringTree(null, this););\n" +
"System.out.println($ctx.r.toStringTree(this));\n" +
"var walker = new antlr4.tree.ParseTreeWalker();\n" +
"walker.walk(new this.LeafListener(), $ctx.r);\n" +
"\n" +

View File

@ -13,7 +13,7 @@ public class TestParseTrees extends BaseTest {
"this.buildParseTrees = true;\n" +
"}\n" +
"@after {\n" +
"System.out.println($r.ctx.toStringTree(null, this););\n" +
"System.out.println($r.ctx.toStringTree(this));\n" +
"}\n" +
" : r=a ;\n" +
"a : 'x' { \n" +
@ -32,7 +32,7 @@ public class TestParseTrees extends BaseTest {
"this.buildParseTrees = true;\n" +
"}\n" +
"@after {\n" +
"System.out.println($r.ctx.toStringTree(null, this););\n" +
"System.out.println($r.ctx.toStringTree(this));\n" +
"}\n" +
" : r=a ;\n" +
"a : 'x' 'y'\n" +
@ -50,7 +50,7 @@ public class TestParseTrees extends BaseTest {
"this.buildParseTrees = true;\n" +
"}\n" +
"@after {\n" +
"System.out.println($r.ctx.toStringTree(null, this););\n" +
"System.out.println($r.ctx.toStringTree(this));\n" +
"}\n" +
" : r=a ;\n" +
"a : 'x' | 'y'\n" +
@ -68,7 +68,7 @@ public class TestParseTrees extends BaseTest {
"this.buildParseTrees = true;\n" +
"}\n" +
"@after {\n" +
"System.out.println($r.ctx.toStringTree(null, this););\n" +
"System.out.println($r.ctx.toStringTree(this));\n" +
"}\n" +
" : r=a ;\n" +
"a : ('x' | 'y')* 'z'\n" +
@ -86,7 +86,7 @@ public class TestParseTrees extends BaseTest {
"this.buildParseTrees = true;\n" +
"}\n" +
"@after {\n" +
"System.out.println($r.ctx.toStringTree(null, this););\n" +
"System.out.println($r.ctx.toStringTree(this));\n" +
"}\n" +
" : r=a ;\n" +
"a : b 'x'\n" +
@ -106,7 +106,7 @@ public class TestParseTrees extends BaseTest {
"this.buildParseTrees = true;\n" +
"}\n" +
"@after {\n" +
"System.out.println($r.ctx.toStringTree(null, this););\n" +
"System.out.println($r.ctx.toStringTree(this));\n" +
"}\n" +
" : r=a ;\n" +
"a : 'x' 'y'\n" +
@ -126,7 +126,7 @@ public class TestParseTrees extends BaseTest {
"this.buildParseTrees = true;\n" +
"}\n" +
"@after {\n" +
"System.out.println($r.ctx.toStringTree(null, this););\n" +
"System.out.println($r.ctx.toStringTree(this));\n" +
"}\n" +
" : r=a ;\n" +
"a : 'x' | 'y'\n" +
@ -147,7 +147,7 @@ public class TestParseTrees extends BaseTest {
"this.buildParseTrees = true;\n" +
"}\n" +
"@after {\n" +
"System.out.println($r.ctx.toStringTree(null, this););\n" +
"System.out.println($r.ctx.toStringTree(this));\n" +
"}\n" +
" : r=a ;\n" +
"a : 'x' 'y'* '!'\n" +

View File

@ -13,7 +13,7 @@ public class TestParserExec extends BaseTest {
"ID : 'a'..'z'+ ;\n" +
"INT : '0'..'9'+;\n" +
"WS : (' '|'\\n') -> skip ;";
String found = execParser("T.g4", grammar, "TParser", "TLexer", "a", "abc 34", false);
String found = execParser("T.g4", grammar, "TParser", "TLexer", "a", "abc 34;", false);
assertEquals("", found);
assertNull(this.stderrDuringParse);
}
@ -27,7 +27,7 @@ public class TestParserExec extends BaseTest {
"INT : '0'..'9'+;\n" +
"FLOAT : [0-9]+ '.' [0-9]+;\n" +
"WS : (' '|'\\n') -> skip ;";
String found = execParser("T.g4", grammar, "TParser", "TLexer", "a", "abc 34", false);
String found = execParser("T.g4", grammar, "TParser", "TLexer", "a", "abc 34;", false);
assertEquals("", found);
assertNull(this.stderrDuringParse);
}
@ -331,10 +331,10 @@ public class TestParserExec extends BaseTest {
public void testPredictionIssue334() throws Exception {
String grammar = "grammar T;\n" +
"file_ @init{\n" +
"this._errHandler = new antlr4.error.BailErrorStrategy();\n" +
"setErrorHandler(new BailErrorStrategy());\n" +
"} \n" +
"@after {\n" +
"System.out.println($ctx.toStringTree(null, this););\n" +
"System.out.println($ctx.toStringTree(this));\n" +
"}\n" +
" : item (SEMICOLON item)* SEMICOLON? EOF ;\n" +
"item : A B?;\n" +
@ -352,7 +352,7 @@ public class TestParserExec extends BaseTest {
String grammar = "grammar T;\n" +
"ifStatement\n" +
"@after {\n" +
"var items = $ctx.elseIfStatement() \n" +
"Object items = $ctx.elseIfStatement(); \n" +
"}\n" +
" : 'if' expression\n" +
" ( ( 'then'\n" +
@ -374,5 +374,70 @@ public class TestParserExec extends BaseTest {
assertNull(this.stderrDuringParse);
}
@Test
public void testMultipleEOFHandling() throws Exception {
String grammar = "grammar T;\n" +
"prog : ('x' | 'x' 'y') EOF EOF;";
String found = execParser("T.g4", grammar, "TParser", "TLexer", "prog", "x", false);
assertEquals("", found);
assertNull(this.stderrDuringParse);
}
@Test
public void testEOFInClosure() throws Exception {
String grammar = "grammar T;\n" +
"prog : stat EOF;\n" +
"stat : 'x' ('y' | EOF)*?;";
String found = execParser("T.g4", grammar, "TParser", "TLexer", "prog", "x", false);
assertEquals("", found);
assertNull(this.stderrDuringParse);
}
String testReferenceToATN(String input) throws Exception {
String grammar = "grammar T;\n" +
"a : (ID|ATN)* ATN? {System.out.println($text);} ;\n" +
"ID : 'a'..'z'+ ;\n" +
"ATN : '0'..'9'+;\n" +
"WS : (' '|'\\n') -> skip ;";
return execParser("T.g4", grammar, "TParser", "TLexer", "a", input, false);
}
@Test
public void testReferenceToATN_1() throws Exception {
String found = testReferenceToATN("");
assertEquals("\n", found);
assertNull(this.stderrDuringParse);
}
@Test
public void testReferenceToATN_2() throws Exception {
String found = testReferenceToATN("a 34 c");
assertEquals("a34c\n", found);
assertNull(this.stderrDuringParse);
}
@Test
public void testAlternateQuotes() throws Exception {
String slave_ModeTagsLexer = "lexer grammar ModeTagsLexer;\n" +
"// Default mode rules (the SEA)\n" +
"OPEN : '«' -> mode(ISLAND) ; // switch to ISLAND mode\n" +
"TEXT : ~'«'+ ; // clump all text together\n" +
"mode ISLAND;\n" +
"CLOSE : '»' -> mode(DEFAULT_MODE) ; // back to SEA mode\n" +
"SLASH : '/' ;\n" +
"ID : [a-zA-Z]+ ; // match/send ID in tag to parser";
rawGenerateAndBuildRecognizer("ModeTagsLexer.g4", slave_ModeTagsLexer, null, "ModeTagsLexer");
String grammar = "parser grammar ModeTagsParser;\n" +
"options { tokenVocab=ModeTagsLexer; } // use tokens from ModeTagsLexer.g4\n" +
"file_: (tag | TEXT)* ;\n" +
"tag : '«' ID '»'\n" +
" | '«' '/' ID '»'\n" +
" ;";
String found = execParser("ModeTagsParser.g4", grammar, "ModeTagsParser", "ModeTagsLexer", "file_", "", false);
assertEquals("", found);
assertNull(this.stderrDuringParse);
}
}

View File

@ -398,7 +398,7 @@ public class TestSemPredEvalParser extends BaseTest {
String testPredFromAltTestedInLoopBack(String input) throws Exception {
String grammar = "grammar T;\n" +
"file_\n" +
"@after {System.out.println($ctx.toStringTree(null, this););}\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" +

View File

@ -33,9 +33,7 @@ package org.antlr.v4.test.tool;
import org.junit.Ignore;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.*;
/** Test parser execution.
*
@ -69,300 +67,14 @@ import static org.junit.Assert.assertTrue;
* the remaining input to match.
*/
public class TestParserExec extends BaseTest {
@Test public void testLabels() throws Exception {
String grammar =
"grammar T;\n" +
"a : b1=b b2+=b* b3+=';' ;\n" +
"b : id=ID val+=INT*;\n" +
"ID : 'a'..'z'+ ;\n" +
"INT : '0'..'9'+;\n" +
"WS : (' '|'\\n') -> skip ;\n";
String found = execParser("T.g4", grammar, "TParser", "TLexer", "a",
"abc 34;", false);
assertEquals("", found);
assertEquals(null, stderrDuringParse);
}
/**
* This is a regression test for #270 "Fix operator += applied to a set of
* tokens".
* https://github.com/antlr/antlr4/issues/270
*/
@Test public void testListLabelOnSet() {
String grammar =
"grammar T;\n" +
"a : b b* ';' ;\n" +
"b : ID val+=(INT | FLOAT)*;\n" +
"ID : 'a'..'z'+ ;\n" +
"INT : '0'..'9'+;\n" +
"FLOAT : [0-9]+ '.' [0-9]+;\n" +
"WS : (' '|'\\n') -> skip ;\n";
String found = execParser("T.g4", grammar, "TParser", "TLexer", "a",
"abc 34;", false);
assertEquals("", found);
assertEquals(null, stderrDuringParse);
}
@Test public void testBasic() throws Exception {
String grammar =
"grammar T;\n" +
"a : ID INT {System.out.println($text);} ;\n" +
"ID : 'a'..'z'+ ;\n" +
"INT : '0'..'9'+;\n" +
"WS : (' '|'\\n') -> skip ;\n";
String found = execParser("T.g4", grammar, "TParser", "TLexer", "a",
"abc 34", false);
assertEquals("abc34\n", found);
}
@Test public void testAorB() throws Exception {
String grammar =
"grammar T;\n" +
"a : ID {System.out.println(\" alt 1\");}" +
" | INT {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", "a",
"34", false);
assertEquals("alt 2\n", found);
}
@Test public void testAPlus() throws Exception {
String grammar =
"grammar T;\n" +
"a : ID+ {System.out.println($text);} ;\n" +
"ID : 'a'..'z'+ ;\n" +
"WS : (' '|'\\n') -> skip ;\n";
String found = execParser("T.g4", grammar, "TParser", "TLexer", "a",
"a b c", false);
assertEquals("abc\n", found);
}
// force complex decision
@Test public void testAorAPlus() throws Exception {
String grammar =
"grammar T;\n" +
"a : (ID|ID)+ {System.out.println($text);} ;\n" +
"ID : 'a'..'z'+ ;\n" +
"WS : (' '|'\\n') -> skip ;\n";
String found = execParser("T.g4", grammar, "TParser", "TLexer", "a",
"a b c", false);
assertEquals("abc\n", found);
}
private static final String ifIfElseGrammarFormat =
"grammar T;\n" +
"start : statement+ ;\n" +
"statement : 'x' | ifStatement;\n" +
"ifStatement : 'if' 'y' statement %s {System.out.println($text);};\n" +
"ID : 'a'..'z'+ ;\n" +
"WS : (' '|'\\n') -> channel(HIDDEN);\n";
@Test public void testIfIfElseGreedyBinding1() throws Exception {
final String input = "if y if y x else x";
final String expectedInnerBound = "if y x else x\nif y if y x else x\n";
String grammar = String.format(ifIfElseGrammarFormat, "('else' statement)?");
String found = execParser("T.g4", grammar, "TParser", "TLexer", "start", input, false);
assertEquals(expectedInnerBound, found);
}
@Test public void testIfIfElseGreedyBinding2() throws Exception {
final String input = "if y if y x else x";
final String expectedInnerBound = "if y x else x\nif y if y x else x\n";
String grammar = String.format(ifIfElseGrammarFormat, "('else' statement|)");
String found = execParser("T.g4", grammar, "TParser", "TLexer", "start", input, false);
assertEquals(expectedInnerBound, found);
}
@Test public void testIfIfElseNonGreedyBinding() throws Exception {
final String input = "if y if y x else x";
final String expectedOuterBound = "if y x\nif y if y x else x\n";
String grammar = String.format(ifIfElseGrammarFormat, "('else' statement)??");
String found = execParser("T.g4", grammar, "TParser", "TLexer", "start", input, false);
assertEquals(expectedOuterBound, found);
grammar = String.format(ifIfElseGrammarFormat, "(|'else' statement)");
found = execParser("T.g4", grammar, "TParser", "TLexer", "start", input, false);
assertEquals(expectedOuterBound, found);
}
@Test public void testAStar() throws Exception {
String grammar =
"grammar T;\n" +
"a : ID* {System.out.println($text);} ;\n" +
"ID : 'a'..'z'+ ;\n" +
"WS : (' '|'\\n') -> skip ;\n";
String found = execParser("T.g4", grammar, "TParser", "TLexer", "a",
"", false);
assertEquals("\n", found);
found = execParser("T.g4", grammar, "TParser", "TLexer", "a",
"a b c", false);
assertEquals("abc\n", found);
}
@Test public void testLL1OptionalBlock() throws Exception {
String grammar =
"grammar T;\n" +
"a : (ID|{}INT)? {System.out.println($text);} ;\n" +
"ID : 'a'..'z'+ ;\n" +
"INT : '0'..'9'+ ;\n" +
"WS : (' '|'\\n') -> skip ;\n";
String found = execParser("T.g4", grammar, "TParser", "TLexer", "a",
"", false);
assertEquals("\n", found);
found = execParser("T.g4", grammar, "TParser", "TLexer", "a",
"a", false);
assertEquals("a\n", found);
}
// force complex decision
@Test public void testAorAStar() throws Exception {
String grammar =
"grammar T;\n" +
"a : (ID|ID)* {System.out.println($text);} ;\n" +
"ID : 'a'..'z'+ ;\n" +
"WS : (' '|'\\n') -> skip ;\n";
String found = execParser("T.g4", grammar, "TParser", "TLexer", "a",
"", false);
assertEquals("\n", found);
found = execParser("T.g4", grammar, "TParser", "TLexer", "a",
"a b c", false);
assertEquals("abc\n", found);
}
@Test public void testAorBPlus() throws Exception {
String grammar =
"grammar T;\n" +
"a : (ID|INT{;})+ {System.out.println($text);} ;\n" +
"ID : 'a'..'z'+ ;\n" +
"INT : '0'..'9'+;\n" +
"WS : (' '|'\\n') -> skip ;\n";
String found = execParser("T.g4", grammar, "TParser", "TLexer", "a",
"a 34 c", false);
assertEquals("a34c\n", found);
}
@Test public void testAorBStar() throws Exception {
String grammar =
"grammar T;\n" +
"a : (ID|INT{;})* {System.out.println($text);} ;\n" +
"ID : 'a'..'z'+ ;\n" +
"INT : '0'..'9'+;\n" +
"WS : (' '|'\\n') -> skip ;\n";
String found = execParser("T.g4", grammar, "TParser", "TLexer", "a",
"", false);
assertEquals("\n", found);
found = execParser("T.g4", grammar, "TParser", "TLexer", "a",
"a 34 c", false);
assertEquals("a34c\n", found);
}
/**
* This test is meant to detect regressions of bug antlr/antlr4#41.
* https://github.com/antlr/antlr4/issues/41
*/
@Test
public void testOptional1() throws Exception {
String grammar =
"grammar T;\n" +
"stat : ifstat | 'x';\n" +
"ifstat : 'if' stat ('else' stat)?;\n" +
"WS : [ \\n\\t]+ -> skip ;"
;
String found = execParser("T.g4", grammar, "TParser", "TLexer", "stat", "x", false);
assertEquals("", found);
assertNull(this.stderrDuringParse);
}
@Test
public void testOptional2() throws Exception {
String grammar =
"grammar T;\n" +
"stat : ifstat | 'x';\n" +
"ifstat : 'if' stat ('else' stat)?;\n" +
"WS : [ \\n\\t]+ -> skip ;"
;
String found = execParser("T.g4", grammar, "TParser", "TLexer", "stat", "if x else x", false);
assertEquals("", found);
assertNull(this.stderrDuringParse);
}
@Test
public void testOptional3() throws Exception {
String grammar =
"grammar T;\n" +
"stat : ifstat | 'x';\n" +
"ifstat : 'if' stat ('else' stat)?;\n" +
"WS : [ \\n\\t]+ -> skip ;"
;
String found = execParser("T.g4", grammar, "TParser", "TLexer", "stat", "if x", false);
assertEquals("", found);
assertNull(this.stderrDuringParse);
}
@Test
public void testOptional4() throws Exception {
String grammar =
"grammar T;\n" +
"stat : ifstat | 'x';\n" +
"ifstat : 'if' stat ('else' stat)?;\n" +
"WS : [ \\n\\t]+ -> skip ;"
;
String found = execParser("T.g4", grammar, "TParser", "TLexer", "stat", "if if x else x", false);
assertEquals("", found);
assertNull(this.stderrDuringParse);
}
/**
* This test is meant to test the expected solution to antlr/antlr4#42.
* https://github.com/antlr/antlr4/issues/42
*/
@Test
public void testPredicatedIfIfElse() 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" +
"ID : [a-zA-Z]+;\n" +
"WS : [ \\n\\t]+ -> skip;\n"
;
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);
}
/**
* This is a regression test for antlr/antlr4#118.
* https://github.com/antlr/antlr4/issues/118
*/
@Ignore("Performance impact of passing this test may not be worthwhile")
// TODO: port to test framework (not ported because test currently fails)
@Test public void testStartRuleWithoutEOF() {
String grammar =
"grammar T;\n"+
@ -382,146 +94,12 @@ public class TestParserExec extends BaseTest {
assertNull(this.stderrDuringParse);
}
/**
* This is a regression test for antlr/antlr4#195 "label 'label' type
* mismatch with previous definition: TOKEN_LABEL!=RULE_LABEL"
* https://github.com/antlr/antlr4/issues/195
*/
@Test public void testLabelAliasingAcrossLabeledAlternatives() throws Exception {
String grammar =
"grammar T;\n" +
"start : a* EOF;\n" +
"a\n" +
" : label=subrule {System.out.println($label.text);} #One\n" +
" | label='y' {System.out.println($label.text);} #Two\n" +
" ;\n" +
"subrule : 'x';\n" +
"WS : (' '|'\\n') -> skip ;\n";
String found = execParser("T.g4", grammar, "TParser", "TLexer", "start",
"xy", false);
assertEquals("x\ny\n", found);
}
/**
* This is a regression test for antlr/antlr4#334 "BailErrorStrategy: bails
* out on proper input".
* https://github.com/antlr/antlr4/issues/334
*/
@Test public void testPredictionIssue334() {
String grammar =
"grammar T;\n" +
"\n" +
"file @init{setErrorHandler(new BailErrorStrategy());} \n" +
"@after {System.out.println($ctx.toStringTree(this));}\n" +
" : item (SEMICOLON item)* SEMICOLON? EOF ;\n" +
"item : A B?;\n" +
"\n" +
"\n" +
"\n" +
"SEMICOLON: ';';\n" +
"\n" +
"A : 'a'|'A';\n" +
"B : 'b'|'B';\n" +
"\n" +
"WS : [ \\r\\t\\n]+ -> skip;\n";
String input = "a";
String found = execParser("T.g4", grammar, "TParser", "TLexer", "file", input, false);
assertEquals("(file (item a) <EOF>)\n", found);
assertNull(stderrDuringParse);
}
/**
* This is a regressino test for antlr/antlr4#299 "Repeating subtree not
* accessible in visitor".
* https://github.com/antlr/antlr4/issues/299
*/
@Test public void testListLabelForClosureContext() throws Exception {
String grammar =
"grammar T;\n" +
"ifStatement\n" +
"@after { List<? extends ElseIfStatementContext> items = $ctx.elseIfStatement(); }\n" +
" : 'if' expression\n" +
" ( ( 'then'\n" +
" executableStatement*\n" +
" elseIfStatement* // <--- problem is here\n" +
" elseStatement?\n" +
" 'end' 'if'\n" +
" ) | executableStatement )\n" +
" ;\n" +
"\n" +
"elseIfStatement\n" +
" : 'else' 'if' expression 'then' executableStatement*\n" +
" ;\n"
+ "expression : 'a' ;\n"
+ "executableStatement : 'a' ;\n"
+ "elseStatement : 'a' ;\n";
String input = "a";
String found = execParser("T.g4", grammar, "TParser", "TLexer", "expression", input, false);
assertEquals("", found);
assertNull(stderrDuringParse);
}
/**
* This test ensures that {@link ParserATNSimulator} produces a correct
* result when the grammar contains multiple explicit references to
* {@code EOF} inside of parser rules.
*/
@Test
public void testMultipleEOFHandling() throws Exception {
String grammar =
"grammar T;\n" +
"prog : ('x' | 'x' 'y') EOF EOF;\n";
String input = "x";
String found = execParser("T.g4", grammar, "TParser", "TLexer", "prog", input, false);
assertEquals("", found);
assertNull(stderrDuringParse);
}
/**
* This test ensures that {@link ParserATNSimulator} does not produce a
* {@link StackOverflowError} when it encounters an {@code EOF} transition
* inside a closure.
*/
@Test
public void testEOFInClosure() throws Exception {
String grammar =
"grammar T;\n" +
"prog : stat EOF;\n" +
"stat : 'x' ('y' | EOF)*?;\n";
String input = "x";
String found = execParser("T.g4", grammar, "TParser", "TLexer", "prog", input, false);
assertEquals("", found);
assertNull(stderrDuringParse);
}
/**
* This is a regression test for antlr/antlr4#561 "Issue with parser
* generation in 4.2.2"
* https://github.com/antlr/antlr4/issues/561
*/
@Test public void testReferenceToATN() throws Exception {
String grammar =
"grammar T;\n" +
"a : (ID|ATN)* ATN? {System.out.println($text);} ;\n" +
"ID : 'a'..'z'+ ;\n" +
"ATN : '0'..'9'+;\n" +
"WS : (' '|'\\n') -> skip ;\n";
String found = execParser("T.g4", grammar, "TParser", "TLexer", "a",
"", false);
assertEquals("\n", found);
found = execParser("T.g4", grammar, "TParser", "TLexer", "a",
"a 34 c", false);
assertEquals("a34c\n", found);
}
/**
* This is a regression test for antlr/antlr4#588 "ClassCastException during
* semantic predicate handling".
* https://github.com/antlr/antlr4/issues/588
*/
// TODO: port to test framework (can we simplify the Psl grammar?)
@Test public void testFailedPredicateExceptionState() throws Exception {
String grammar = load("Psl.g4", "UTF-8");
String found = execParser("Psl.g4", grammar, "PslParser", "PslLexer", "floating_constant", " . 234", false);
@ -529,50 +107,13 @@ public class TestParserExec extends BaseTest {
assertEquals("line 1:6 rule floating_constant DEC:A floating-point constant cannot have internal white space\n", stderrDuringParse);
}
/**
* This is a regression test for antlr/antlr4#563 "Inconsistent token
* handling in ANTLR4".
* https://github.com/antlr/antlr4/issues/563
*/
@Test public void testAlternateQuotes() throws Exception {
String lexerGrammar =
"lexer grammar ModeTagsLexer;\n" +
"\n" +
"// Default mode rules (the SEA)\n" +
"OPEN : '«' -> mode(ISLAND) ; // switch to ISLAND mode\n" +
"TEXT : ~'«'+ ; // clump all text together\n" +
"\n" +
"mode ISLAND;\n" +
"CLOSE : '»' -> mode(DEFAULT_MODE) ; // back to SEA mode \n" +
"SLASH : '/' ;\n" +
"ID : [a-zA-Z]+ ; // match/send ID in tag to parser\n";
String parserGrammar =
"parser grammar ModeTagsParser;\n" +
"\n" +
"options { tokenVocab=ModeTagsLexer; } // use tokens from ModeTagsLexer.g4\n" +
"\n" +
"file: (tag | TEXT)* ;\n" +
"\n" +
"tag : '«' ID '»'\n" +
" | '«' '/' ID '»'\n" +
" ;";
boolean success = rawGenerateAndBuildRecognizer("ModeTagsLexer.g4",
lexerGrammar,
null,
"ModeTagsLexer");
assertTrue(success);
String found = execParser("ModeTagsParser.g4", parserGrammar, "ModeTagsParser", "ModeTagsLexer", "file", "", false);
assertEquals("", found);
assertNull(stderrDuringParse);
}
/**
* This is a regression test for antlr/antlr4#672 "Initialization failed in
* locals".
* https://github.com/antlr/antlr4/issues/672
*/
// TODO: port to test framework (missing templates)
@Test public void testAttributeValueInitialization() throws Exception {
String grammar =
"grammar Data; \n" +