pass a lexer and a parser to the tree pattern match or instead of the classes.

This commit is contained in:
Terence Parr 2013-11-21 09:32:45 -08:00
parent 599896cf1b
commit e68757717f
3 changed files with 42 additions and 59 deletions

View File

@ -62,8 +62,6 @@ public abstract class Recognizer<Symbol, ATNInterpreter extends ATNSimulator> {
/** If this recognizer was generated, it will have a serialized ATN
* 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
* created the interpreter from it.
*/

View File

@ -31,7 +31,6 @@
package org.antlr.v4.runtime.tree.pattern;
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.Lexer;
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.ParserRuleContext;
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.ATNDeserializationOptions;
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.StringReader;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@ -86,13 +83,9 @@ public class ParseTreePatternMatcher {
public ParseTreePatternMatcher() { }
public ParseTreePatternMatcher(Class<? extends Lexer> lexerClass,
Class<? extends Parser> parserClass)
{
this.lexerClass = lexerClass;
this.parserClass = parserClass;
lazyInit();
public ParseTreePatternMatcher(Lexer lexer, Parser parser) {
this.lexer = lexer;
this.parser = parser;
String sATN = parser.getSerializedATN();
ATNDeserializationOptions deserializationOptions = new ATNDeserializationOptions();
deserializationOptions.setGenerateRuleBypassTransitions(true);
@ -106,25 +99,6 @@ public class ParseTreePatternMatcher {
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) {
ParseTreePattern p = compile(patternRuleName, pattern);
ParseTreeMatch m = matches_(tree, p.patternTree, p);
@ -243,7 +217,6 @@ public class ParseTreePatternMatcher {
}
public List<? extends Token> tokenize(String pattern) {
lazyInit();
// make maps for quick look up
Map<String, Integer> tokenNameToType = toMap(parser.getTokenNames(), 0);
Map<String, Integer> ruleNameToIndex = toMap(parser.getRuleNames(), 0);

View File

@ -1,11 +1,16 @@
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.TokenStream;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.pattern.ParseTreePattern;
import org.antlr.v4.runtime.tree.pattern.ParseTreePatternMatcher;
import org.junit.Test;
import java.lang.reflect.Constructor;
import java.util.List;
import static org.junit.Assert.assertEquals;
@ -81,9 +86,7 @@ public class TestParseTreeMatcher extends BaseTest {
rawGenerateAndBuildRecognizer("X1.g4", grammar, "X1Parser", "X1Lexer", false);
assertTrue(ok);
ParseTreePatternMatcher p =
new ParseTreePatternMatcher(loadLexerClassFromTempDir("X1Lexer"),
loadParserClassFromTempDir("X1Parser"));
ParseTreePatternMatcher p = getMatcher("X1");
List<? extends Token> tokens = p.tokenize("<ID> = <expr> ;");
String results = tokens.toString();
@ -104,9 +107,7 @@ public class TestParseTreeMatcher extends BaseTest {
rawGenerateAndBuildRecognizer("X2.g4", grammar, "X2Parser", "X2Lexer", false);
assertTrue(ok);
ParseTreePatternMatcher p =
new ParseTreePatternMatcher(loadLexerClassFromTempDir("X2Lexer"),
loadParserClassFromTempDir("X2Parser"));
ParseTreePatternMatcher p = getMatcher("X2");
ParseTreePattern t = p.compile("s", "<ID> = <expr> ;");
String results = t.patternTree.toStringTree(p.getParser());
@ -125,9 +126,7 @@ public class TestParseTreeMatcher extends BaseTest {
rawGenerateAndBuildRecognizer("X2.g4", grammar, "X2Parser", "X2Lexer", false);
assertTrue(ok);
ParseTreePatternMatcher p =
new ParseTreePatternMatcher(loadLexerClassFromTempDir("X2Lexer"),
loadParserClassFromTempDir("X2Parser"));
ParseTreePatternMatcher p = getMatcher("X2");
ParseTreePattern t = p.compile("s", "<ID> = <ID> ;");
String results = t.patternTree.toStringTree(p.getParser());
@ -135,6 +134,20 @@ public class TestParseTreeMatcher extends BaseTest {
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 {
String grammar =
"grammar X3;\n" +
@ -144,7 +157,7 @@ public class TestParseTreeMatcher extends BaseTest {
String input = "x ;";
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 {
@ -158,7 +171,7 @@ public class TestParseTreeMatcher extends BaseTest {
String input = "x = 99;";
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 {
@ -173,22 +186,22 @@ public class TestParseTreeMatcher extends BaseTest {
String input = "x = 0;";
String pattern = "<ID> = 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;";
pattern = "<ID> = 0;";
invertMatch = false;
checkPatternMatch("X4.g4", grammar, "s", input, pattern, "X4Parser", "X4Lexer", invertMatch);
checkPatternMatch("X4.g4", grammar, "s", input, pattern, "X4", invertMatch);
input = "x = 0;";
pattern = "x = 0;";
invertMatch = false;
checkPatternMatch("X4.g4", grammar, "s", input, pattern, "X4Parser", "X4Lexer", invertMatch);
checkPatternMatch("X4.g4", grammar, "s", input, pattern, "X4", invertMatch);
input = "x = 0;";
pattern = "y = 0;";
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 {
@ -209,7 +222,7 @@ public class TestParseTreeMatcher extends BaseTest {
String input = "x = 99;";
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 {
@ -229,32 +242,31 @@ public class TestParseTreeMatcher extends BaseTest {
String input = "3*4*5";
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 parserName, String lexerName)
String grammarName)
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 parserName, String lexerName,
boolean invertMatch)
String grammarName, boolean invertMatch)
throws Exception
{
String parserName = grammarName+"Parser";
String lexerName = grammarName+"Lexer";
boolean ok =
rawGenerateAndBuildRecognizer(grammarName, grammar, parserName, lexerName, false);
rawGenerateAndBuildRecognizer(grammarFileName, grammar, parserName, lexerName, false);
assertTrue(ok);
ParseTree result = execParser(startRule, input, parserName, lexerName);
ParseTreePatternMatcher p =
new ParseTreePatternMatcher(loadLexerClassFromTempDir(lexerName),
loadParserClassFromTempDir(parserName));
ParseTreePatternMatcher p = getMatcher(grammarName);
boolean matches = p.matches(result, startRule, pattern);
if ( invertMatch ) assertFalse(matches);
else assertTrue(matches);