Add tests for ungrammatical tree patterns. Fixes #413
This commit is contained in:
parent
4f0c14dcee
commit
3c51f7ad7b
|
@ -37,6 +37,7 @@ import org.antlr.v4.runtime.ListTokenSource;
|
||||||
import org.antlr.v4.runtime.Parser;
|
import org.antlr.v4.runtime.Parser;
|
||||||
import org.antlr.v4.runtime.ParserInterpreter;
|
import org.antlr.v4.runtime.ParserInterpreter;
|
||||||
import org.antlr.v4.runtime.ParserRuleContext;
|
import org.antlr.v4.runtime.ParserRuleContext;
|
||||||
|
import org.antlr.v4.runtime.RecognitionException;
|
||||||
import org.antlr.v4.runtime.Token;
|
import org.antlr.v4.runtime.Token;
|
||||||
import org.antlr.v4.runtime.atn.ATN;
|
import org.antlr.v4.runtime.atn.ATN;
|
||||||
import org.antlr.v4.runtime.misc.MultiMap;
|
import org.antlr.v4.runtime.misc.MultiMap;
|
||||||
|
@ -114,6 +115,11 @@ public class ParseTreePatternMatcher {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fixes https://github.com/antlr/antlr4/issues/413
|
||||||
|
// "Tree pattern compilation doesn't check for a complete parse"
|
||||||
|
public static class StartRuleDoesNotConsumeFullPattern extends RuntimeException {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the backing field for {@link #getLexer()}.
|
* This is the backing field for {@link #getLexer()}.
|
||||||
*/
|
*/
|
||||||
|
@ -222,10 +228,18 @@ public class ParseTreePatternMatcher {
|
||||||
tree = parserInterp.parse(patternRuleIndex);
|
tree = parserInterp.parse(patternRuleIndex);
|
||||||
// System.out.println("pattern tree = "+tree.toStringTree(parserInterp));
|
// System.out.println("pattern tree = "+tree.toStringTree(parserInterp));
|
||||||
}
|
}
|
||||||
|
catch (RecognitionException re) {
|
||||||
|
throw re;
|
||||||
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
throw new CannotInvokeStartRule(e);
|
throw new CannotInvokeStartRule(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure tree pattern compilation checks for a complete parse
|
||||||
|
if ( tokens.LA(1)!=Token.EOF ) {
|
||||||
|
throw new StartRuleDoesNotConsumeFullPattern();
|
||||||
|
}
|
||||||
|
|
||||||
return new ParseTreePattern(this, pattern, patternRuleIndex, tree);
|
return new ParseTreePattern(this, pattern, patternRuleIndex, tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,9 @@ package org.antlr.v4.test;
|
||||||
|
|
||||||
import org.antlr.v4.runtime.CharStream;
|
import org.antlr.v4.runtime.CharStream;
|
||||||
import org.antlr.v4.runtime.CommonTokenStream;
|
import org.antlr.v4.runtime.CommonTokenStream;
|
||||||
|
import org.antlr.v4.runtime.InputMismatchException;
|
||||||
import org.antlr.v4.runtime.Lexer;
|
import org.antlr.v4.runtime.Lexer;
|
||||||
|
import org.antlr.v4.runtime.NoViableAltException;
|
||||||
import org.antlr.v4.runtime.Parser;
|
import org.antlr.v4.runtime.Parser;
|
||||||
import org.antlr.v4.runtime.Token;
|
import org.antlr.v4.runtime.Token;
|
||||||
import org.antlr.v4.runtime.TokenStream;
|
import org.antlr.v4.runtime.TokenStream;
|
||||||
|
@ -119,6 +121,81 @@ public class TestParseTreeMatcher extends BaseTest {
|
||||||
assertEquals(expected, results);
|
assertEquals(expected, results);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCompilingPatternConsumesAllTokens() throws Exception {
|
||||||
|
String grammar =
|
||||||
|
"grammar X2;\n" +
|
||||||
|
"s : ID '=' expr ';' ;\n" +
|
||||||
|
"expr : ID | INT ;\n" +
|
||||||
|
"ID : [a-z]+ ;\n" +
|
||||||
|
"INT : [0-9]+ ;\n" +
|
||||||
|
"WS : [ \\r\\n\\t]+ -> skip ;\n";
|
||||||
|
boolean ok =
|
||||||
|
rawGenerateAndBuildRecognizer("X2.g4", grammar, "X2Parser", "X2Lexer", false);
|
||||||
|
assertTrue(ok);
|
||||||
|
|
||||||
|
ParseTreePatternMatcher m = getPatternMatcher("X2");
|
||||||
|
|
||||||
|
boolean failed = false;
|
||||||
|
try {
|
||||||
|
m.compile("<ID> = <expr> ; extra", m.getParser().getRuleIndex("s"));
|
||||||
|
}
|
||||||
|
catch (ParseTreePatternMatcher.StartRuleDoesNotConsumeFullPattern e) {
|
||||||
|
failed = true;
|
||||||
|
}
|
||||||
|
assertTrue(failed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPatternMatchesStartRule() throws Exception {
|
||||||
|
String grammar =
|
||||||
|
"grammar X2;\n" +
|
||||||
|
"s : ID '=' expr ';' ;\n" +
|
||||||
|
"expr : ID | INT ;\n" +
|
||||||
|
"ID : [a-z]+ ;\n" +
|
||||||
|
"INT : [0-9]+ ;\n" +
|
||||||
|
"WS : [ \\r\\n\\t]+ -> skip ;\n";
|
||||||
|
boolean ok =
|
||||||
|
rawGenerateAndBuildRecognizer("X2.g4", grammar, "X2Parser", "X2Lexer", false);
|
||||||
|
assertTrue(ok);
|
||||||
|
|
||||||
|
ParseTreePatternMatcher m = getPatternMatcher("X2");
|
||||||
|
|
||||||
|
boolean failed = false;
|
||||||
|
try {
|
||||||
|
m.compile("<ID> ;", m.getParser().getRuleIndex("s"));
|
||||||
|
}
|
||||||
|
catch (InputMismatchException e) {
|
||||||
|
failed = true;
|
||||||
|
}
|
||||||
|
assertTrue(failed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPatternMatchesStartRule2() throws Exception {
|
||||||
|
String grammar =
|
||||||
|
"grammar X2;\n" +
|
||||||
|
"s : ID '=' expr ';' | expr ';' ;\n" +
|
||||||
|
"expr : ID | INT ;\n" +
|
||||||
|
"ID : [a-z]+ ;\n" +
|
||||||
|
"INT : [0-9]+ ;\n" +
|
||||||
|
"WS : [ \\r\\n\\t]+ -> skip ;\n";
|
||||||
|
boolean ok =
|
||||||
|
rawGenerateAndBuildRecognizer("X2.g4", grammar, "X2Parser", "X2Lexer", false);
|
||||||
|
assertTrue(ok);
|
||||||
|
|
||||||
|
ParseTreePatternMatcher m = getPatternMatcher("X2");
|
||||||
|
|
||||||
|
boolean failed = false;
|
||||||
|
try {
|
||||||
|
m.compile("<ID> <ID> ;", m.getParser().getRuleIndex("s"));
|
||||||
|
}
|
||||||
|
catch (NoViableAltException e) {
|
||||||
|
failed = true;
|
||||||
|
}
|
||||||
|
assertTrue(failed);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testHiddenTokensNotSeenByTreePatternParser() throws Exception {
|
public void testHiddenTokensNotSeenByTreePatternParser() throws Exception {
|
||||||
String grammar =
|
String grammar =
|
||||||
|
|
Loading…
Reference in New Issue