forked from jasder/antlr
pass a lexer and a parser to the tree pattern match or instead of the classes.
This commit is contained in:
parent
599896cf1b
commit
e68757717f
|
@ -62,8 +62,6 @@ public abstract class Recognizer<Symbol, ATNInterpreter extends ATNSimulator> {
|
||||||
/** If this recognizer was generated, it will have a serialized ATN
|
/** If this recognizer was generated, it will have a serialized ATN
|
||||||
* representation of the grammar.
|
* representation of the grammar.
|
||||||
*
|
*
|
||||||
* Provide a dummy return value here to support backward compatibility.
|
|
||||||
*
|
|
||||||
* For interpreters, we don't know their serialized ATN despite having
|
* For interpreters, we don't know their serialized ATN despite having
|
||||||
* created the interpreter from it.
|
* created the interpreter from it.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -31,7 +31,6 @@
|
||||||
package org.antlr.v4.runtime.tree.pattern;
|
package org.antlr.v4.runtime.tree.pattern;
|
||||||
|
|
||||||
import org.antlr.v4.runtime.ANTLRInputStream;
|
import org.antlr.v4.runtime.ANTLRInputStream;
|
||||||
import org.antlr.v4.runtime.CharStream;
|
|
||||||
import org.antlr.v4.runtime.CommonTokenStream;
|
import org.antlr.v4.runtime.CommonTokenStream;
|
||||||
import org.antlr.v4.runtime.Lexer;
|
import org.antlr.v4.runtime.Lexer;
|
||||||
import org.antlr.v4.runtime.ListTokenSource;
|
import org.antlr.v4.runtime.ListTokenSource;
|
||||||
|
@ -39,7 +38,6 @@ 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.Token;
|
import org.antlr.v4.runtime.Token;
|
||||||
import org.antlr.v4.runtime.TokenStream;
|
|
||||||
import org.antlr.v4.runtime.atn.ATN;
|
import org.antlr.v4.runtime.atn.ATN;
|
||||||
import org.antlr.v4.runtime.atn.ATNDeserializationOptions;
|
import org.antlr.v4.runtime.atn.ATNDeserializationOptions;
|
||||||
import org.antlr.v4.runtime.atn.ATNDeserializer;
|
import org.antlr.v4.runtime.atn.ATNDeserializer;
|
||||||
|
@ -51,7 +49,6 @@ import org.antlr.v4.runtime.tree.TerminalNode;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -86,13 +83,9 @@ public class ParseTreePatternMatcher {
|
||||||
|
|
||||||
public ParseTreePatternMatcher() { }
|
public ParseTreePatternMatcher() { }
|
||||||
|
|
||||||
public ParseTreePatternMatcher(Class<? extends Lexer> lexerClass,
|
public ParseTreePatternMatcher(Lexer lexer, Parser parser) {
|
||||||
Class<? extends Parser> parserClass)
|
this.lexer = lexer;
|
||||||
{
|
this.parser = parser;
|
||||||
this.lexerClass = lexerClass;
|
|
||||||
this.parserClass = parserClass;
|
|
||||||
|
|
||||||
lazyInit();
|
|
||||||
String sATN = parser.getSerializedATN();
|
String sATN = parser.getSerializedATN();
|
||||||
ATNDeserializationOptions deserializationOptions = new ATNDeserializationOptions();
|
ATNDeserializationOptions deserializationOptions = new ATNDeserializationOptions();
|
||||||
deserializationOptions.setGenerateRuleBypassTransitions(true);
|
deserializationOptions.setGenerateRuleBypassTransitions(true);
|
||||||
|
@ -106,25 +99,6 @@ public class ParseTreePatternMatcher {
|
||||||
this.escape = escapeLeft;
|
this.escape = escapeLeft;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void lazyInit() {
|
|
||||||
try {
|
|
||||||
if ( lexer==null ) {
|
|
||||||
Class<? extends Lexer> c = lexerClass.asSubclass(Lexer.class);
|
|
||||||
Constructor<? extends Lexer> ctor = c.getConstructor(CharStream.class);
|
|
||||||
lexer = ctor.newInstance((CharStream)null);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( parser==null ) {
|
|
||||||
Class<? extends Parser> pc = parserClass.asSubclass(Parser.class);
|
|
||||||
Constructor<? extends Parser> pctor = pc.getConstructor(TokenStream.class);
|
|
||||||
parser = pctor.newInstance((TokenStream)null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
throw new CannotCreateLexerOrParser(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean matches(ParseTree tree, String patternRuleName, String pattern) {
|
public boolean matches(ParseTree tree, String patternRuleName, String pattern) {
|
||||||
ParseTreePattern p = compile(patternRuleName, pattern);
|
ParseTreePattern p = compile(patternRuleName, pattern);
|
||||||
ParseTreeMatch m = matches_(tree, p.patternTree, p);
|
ParseTreeMatch m = matches_(tree, p.patternTree, p);
|
||||||
|
@ -243,7 +217,6 @@ public class ParseTreePatternMatcher {
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<? extends Token> tokenize(String pattern) {
|
public List<? extends Token> tokenize(String pattern) {
|
||||||
lazyInit();
|
|
||||||
// make maps for quick look up
|
// make maps for quick look up
|
||||||
Map<String, Integer> tokenNameToType = toMap(parser.getTokenNames(), 0);
|
Map<String, Integer> tokenNameToType = toMap(parser.getTokenNames(), 0);
|
||||||
Map<String, Integer> ruleNameToIndex = toMap(parser.getRuleNames(), 0);
|
Map<String, Integer> ruleNameToIndex = toMap(parser.getRuleNames(), 0);
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
package org.antlr.v4.test;
|
package org.antlr.v4.test;
|
||||||
|
|
||||||
|
import org.antlr.v4.runtime.CharStream;
|
||||||
|
import org.antlr.v4.runtime.Lexer;
|
||||||
|
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.tree.ParseTree;
|
import org.antlr.v4.runtime.tree.ParseTree;
|
||||||
import org.antlr.v4.runtime.tree.pattern.ParseTreePattern;
|
import org.antlr.v4.runtime.tree.pattern.ParseTreePattern;
|
||||||
import org.antlr.v4.runtime.tree.pattern.ParseTreePatternMatcher;
|
import org.antlr.v4.runtime.tree.pattern.ParseTreePatternMatcher;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
@ -81,9 +86,7 @@ public class TestParseTreeMatcher extends BaseTest {
|
||||||
rawGenerateAndBuildRecognizer("X1.g4", grammar, "X1Parser", "X1Lexer", false);
|
rawGenerateAndBuildRecognizer("X1.g4", grammar, "X1Parser", "X1Lexer", false);
|
||||||
assertTrue(ok);
|
assertTrue(ok);
|
||||||
|
|
||||||
ParseTreePatternMatcher p =
|
ParseTreePatternMatcher p = getMatcher("X1");
|
||||||
new ParseTreePatternMatcher(loadLexerClassFromTempDir("X1Lexer"),
|
|
||||||
loadParserClassFromTempDir("X1Parser"));
|
|
||||||
|
|
||||||
List<? extends Token> tokens = p.tokenize("<ID> = <expr> ;");
|
List<? extends Token> tokens = p.tokenize("<ID> = <expr> ;");
|
||||||
String results = tokens.toString();
|
String results = tokens.toString();
|
||||||
|
@ -104,9 +107,7 @@ public class TestParseTreeMatcher extends BaseTest {
|
||||||
rawGenerateAndBuildRecognizer("X2.g4", grammar, "X2Parser", "X2Lexer", false);
|
rawGenerateAndBuildRecognizer("X2.g4", grammar, "X2Parser", "X2Lexer", false);
|
||||||
assertTrue(ok);
|
assertTrue(ok);
|
||||||
|
|
||||||
ParseTreePatternMatcher p =
|
ParseTreePatternMatcher p = getMatcher("X2");
|
||||||
new ParseTreePatternMatcher(loadLexerClassFromTempDir("X2Lexer"),
|
|
||||||
loadParserClassFromTempDir("X2Parser"));
|
|
||||||
|
|
||||||
ParseTreePattern t = p.compile("s", "<ID> = <expr> ;");
|
ParseTreePattern t = p.compile("s", "<ID> = <expr> ;");
|
||||||
String results = t.patternTree.toStringTree(p.getParser());
|
String results = t.patternTree.toStringTree(p.getParser());
|
||||||
|
@ -125,9 +126,7 @@ public class TestParseTreeMatcher extends BaseTest {
|
||||||
rawGenerateAndBuildRecognizer("X2.g4", grammar, "X2Parser", "X2Lexer", false);
|
rawGenerateAndBuildRecognizer("X2.g4", grammar, "X2Parser", "X2Lexer", false);
|
||||||
assertTrue(ok);
|
assertTrue(ok);
|
||||||
|
|
||||||
ParseTreePatternMatcher p =
|
ParseTreePatternMatcher p = getMatcher("X2");
|
||||||
new ParseTreePatternMatcher(loadLexerClassFromTempDir("X2Lexer"),
|
|
||||||
loadParserClassFromTempDir("X2Parser"));
|
|
||||||
|
|
||||||
ParseTreePattern t = p.compile("s", "<ID> = <ID> ;");
|
ParseTreePattern t = p.compile("s", "<ID> = <ID> ;");
|
||||||
String results = t.patternTree.toStringTree(p.getParser());
|
String results = t.patternTree.toStringTree(p.getParser());
|
||||||
|
@ -135,6 +134,20 @@ public class TestParseTreeMatcher extends BaseTest {
|
||||||
assertEquals(expected, results);
|
assertEquals(expected, results);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ParseTreePatternMatcher getMatcher(String name) throws Exception {
|
||||||
|
Class<? extends Lexer> lexerClass = loadLexerClassFromTempDir(name+"Lexer");
|
||||||
|
Class<? extends Parser> parserClass = loadParserClassFromTempDir(name+"Parser");
|
||||||
|
Class<? extends Lexer> c = lexerClass.asSubclass(Lexer.class);
|
||||||
|
Constructor<? extends Lexer> ctor = c.getConstructor(CharStream.class);
|
||||||
|
Lexer lexer = ctor.newInstance((CharStream)null);
|
||||||
|
|
||||||
|
Class<? extends Parser> pc = parserClass.asSubclass(Parser.class);
|
||||||
|
Constructor<? extends Parser> pctor = pc.getConstructor(TokenStream.class);
|
||||||
|
Parser parser = pctor.newInstance((TokenStream)null);
|
||||||
|
|
||||||
|
return new ParseTreePatternMatcher(lexer, parser);
|
||||||
|
}
|
||||||
|
|
||||||
@Test public void testIDNodeMatches() throws Exception {
|
@Test public void testIDNodeMatches() throws Exception {
|
||||||
String grammar =
|
String grammar =
|
||||||
"grammar X3;\n" +
|
"grammar X3;\n" +
|
||||||
|
@ -144,7 +157,7 @@ public class TestParseTreeMatcher extends BaseTest {
|
||||||
|
|
||||||
String input = "x ;";
|
String input = "x ;";
|
||||||
String pattern = "<ID>;";
|
String pattern = "<ID>;";
|
||||||
checkPatternMatch("X3.g4", grammar, "s", input, pattern, "X3Parser", "X3Lexer");
|
checkPatternMatch("X3.g4", grammar, "s", input, pattern, "X3");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test public void testTokenAndRuleMatch() throws Exception {
|
@Test public void testTokenAndRuleMatch() throws Exception {
|
||||||
|
@ -158,7 +171,7 @@ public class TestParseTreeMatcher extends BaseTest {
|
||||||
|
|
||||||
String input = "x = 99;";
|
String input = "x = 99;";
|
||||||
String pattern = "<ID> = <expr> ;";
|
String pattern = "<ID> = <expr> ;";
|
||||||
checkPatternMatch("X4.g4", grammar, "s", input, pattern, "X4Parser", "X4Lexer");
|
checkPatternMatch("X4.g4", grammar, "s", input, pattern, "X4");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test public void testTokenTextMatch() throws Exception {
|
@Test public void testTokenTextMatch() throws Exception {
|
||||||
|
@ -173,22 +186,22 @@ public class TestParseTreeMatcher extends BaseTest {
|
||||||
String input = "x = 0;";
|
String input = "x = 0;";
|
||||||
String pattern = "<ID> = 1;";
|
String pattern = "<ID> = 1;";
|
||||||
boolean invertMatch = true; // 0!=1
|
boolean invertMatch = true; // 0!=1
|
||||||
checkPatternMatch("X4.g4", grammar, "s", input, pattern, "X4Parser", "X4Lexer", invertMatch);
|
checkPatternMatch("X4.g4", grammar, "s", input, pattern, "X4", invertMatch);
|
||||||
|
|
||||||
input = "x = 0;";
|
input = "x = 0;";
|
||||||
pattern = "<ID> = 0;";
|
pattern = "<ID> = 0;";
|
||||||
invertMatch = false;
|
invertMatch = false;
|
||||||
checkPatternMatch("X4.g4", grammar, "s", input, pattern, "X4Parser", "X4Lexer", invertMatch);
|
checkPatternMatch("X4.g4", grammar, "s", input, pattern, "X4", invertMatch);
|
||||||
|
|
||||||
input = "x = 0;";
|
input = "x = 0;";
|
||||||
pattern = "x = 0;";
|
pattern = "x = 0;";
|
||||||
invertMatch = false;
|
invertMatch = false;
|
||||||
checkPatternMatch("X4.g4", grammar, "s", input, pattern, "X4Parser", "X4Lexer", invertMatch);
|
checkPatternMatch("X4.g4", grammar, "s", input, pattern, "X4", invertMatch);
|
||||||
|
|
||||||
input = "x = 0;";
|
input = "x = 0;";
|
||||||
pattern = "y = 0;";
|
pattern = "y = 0;";
|
||||||
invertMatch = true;
|
invertMatch = true;
|
||||||
checkPatternMatch("X4.g4", grammar, "s", input, pattern, "X4Parser", "X4Lexer", invertMatch);
|
checkPatternMatch("X4.g4", grammar, "s", input, pattern, "X4", invertMatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test public void testAssign() throws Exception {
|
@Test public void testAssign() throws Exception {
|
||||||
|
@ -209,7 +222,7 @@ public class TestParseTreeMatcher extends BaseTest {
|
||||||
|
|
||||||
String input = "x = 99;";
|
String input = "x = 99;";
|
||||||
String pattern = "<ID> = <expr>;";
|
String pattern = "<ID> = <expr>;";
|
||||||
checkPatternMatch("X5.g4", grammar, "s", input, pattern, "X5Parser", "X5Lexer");
|
checkPatternMatch("X5.g4", grammar, "s", input, pattern, "X5");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test public void testLRecursiveExpr() throws Exception {
|
@Test public void testLRecursiveExpr() throws Exception {
|
||||||
|
@ -229,32 +242,31 @@ public class TestParseTreeMatcher extends BaseTest {
|
||||||
|
|
||||||
String input = "3*4*5";
|
String input = "3*4*5";
|
||||||
String pattern = "<expr> * <expr> * <expr>";
|
String pattern = "<expr> * <expr> * <expr>";
|
||||||
checkPatternMatch("X6.g4", grammar, "expr", input, pattern, "X6Parser", "X6Lexer");
|
checkPatternMatch("X6.g4", grammar, "expr", input, pattern, "X6");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void checkPatternMatch(String grammarName, String grammar, String startRule,
|
public void checkPatternMatch(String grammarFileName, String grammar, String startRule,
|
||||||
String input, String pattern,
|
String input, String pattern,
|
||||||
String parserName, String lexerName)
|
String grammarName)
|
||||||
throws Exception
|
throws Exception
|
||||||
{
|
{
|
||||||
checkPatternMatch(grammarName, grammar, startRule, input, pattern, parserName, lexerName, false);
|
checkPatternMatch(grammarFileName, grammar, startRule, input, pattern, grammarName, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void checkPatternMatch(String grammarName, String grammar, String startRule,
|
public void checkPatternMatch(String grammarFileName, String grammar, String startRule,
|
||||||
String input, String pattern,
|
String input, String pattern,
|
||||||
String parserName, String lexerName,
|
String grammarName, boolean invertMatch)
|
||||||
boolean invertMatch)
|
|
||||||
throws Exception
|
throws Exception
|
||||||
{
|
{
|
||||||
|
String parserName = grammarName+"Parser";
|
||||||
|
String lexerName = grammarName+"Lexer";
|
||||||
boolean ok =
|
boolean ok =
|
||||||
rawGenerateAndBuildRecognizer(grammarName, grammar, parserName, lexerName, false);
|
rawGenerateAndBuildRecognizer(grammarFileName, grammar, parserName, lexerName, false);
|
||||||
assertTrue(ok);
|
assertTrue(ok);
|
||||||
|
|
||||||
ParseTree result = execParser(startRule, input, parserName, lexerName);
|
ParseTree result = execParser(startRule, input, parserName, lexerName);
|
||||||
|
|
||||||
ParseTreePatternMatcher p =
|
ParseTreePatternMatcher p = getMatcher(grammarName);
|
||||||
new ParseTreePatternMatcher(loadLexerClassFromTempDir(lexerName),
|
|
||||||
loadParserClassFromTempDir(parserName));
|
|
||||||
boolean matches = p.matches(result, startRule, pattern);
|
boolean matches = p.matches(result, startRule, pattern);
|
||||||
if ( invertMatch ) assertFalse(matches);
|
if ( invertMatch ) assertFalse(matches);
|
||||||
else assertTrue(matches);
|
else assertTrue(matches);
|
||||||
|
|
Loading…
Reference in New Issue