我试图理解antlr 4中的parse树匹配,所以我有以下Java代码:
package sampleCodes;
public class fruits {
public static void main(String[] args){
int a = 10;
System.out.println(a);
}
}
我正在使用antlr 4来创建此代码的解析树。现在,我想使用树模式匹配函数来查找" int a = 10;"。github上有一个文档:https://github.com/antlr/antlr4/blob/master/master/doc/tree-matching.md,用示例解释了这一点(类似的(:
ParseTree t = ...; // assume t is a statement
ParseTreePattern p = parser.compileParseTreePattern("<ID> = <expr>;", MyParser.RULE_statement);
ParseTreeMatch m = p.match(t);
if ( m.succeeded() ) {...}
通过阅读此文档和其他一些资源,我了解的是:
ParseTreePattern p = parser.compileParseTreePattern("<ID> = <expr>;", MyParser.RULE_statement);
要通过第二个参数的规则必须能够正确解析作为第一个参数所提供的模式。现在,我使用的语法是此处给出的Java:https://github.com/antlr/grammars-v4/tree/master/java
javalexer.g4, javaparser.g4
我无法从上面的github文档中获取有关如何构建图案字符串及其相应规则的太多信息。因此,我尝试了很少的组合来获得比赛,但是它们似乎都没有起作用。例如:
ParseTreePattern p = parser.compileParseTreePattern("<variableDeclaratorId> = <variableInitializer>", parser.RULE_variableDeclarator);
ParseTreeMatch m = p.match(tree);
System.out.println(m);
这给出了:
匹配失败;找到0标签
我知道我当然在弦模式中做错了什么。任何人都可以帮助我解释此模式匹配功能,并说出在这种情况下应该使用的正确论点。另外,提供指向一些有用资源的链接,我可以在其中了解更多有关此的链接并从事复杂模式。(我在Antlr4参考中找不到(
此代码的解析树的一部分
我认为在组合XPath和树模式匹配时要描述您想要的。
也许是这样的东西:
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.pattern.ParseTreeMatch;
import org.antlr.v4.runtime.tree.pattern.ParseTreePattern;
import java.util.List;
public class Main {
public static void main(String[] args) {
String source = "package sampleCodes;n" +
"n" +
"public class fruits {n" +
"n" +
" static { int q = 42; }n" +
"n" +
" public static void main(String[] args){n" +
" int a = 10;n" +
" System.out.println(a);n" +
" }n" +
"}n";
JavaLexer lexer = new JavaLexer(CharStreams.fromString(source));
JavaParser parser = new JavaParser(new CommonTokenStream(lexer));
ParseTree tree = parser.compilationUnit();
ParseTreePattern p = parser.compileParseTreePattern("<IDENTIFIER> = <expression>", JavaParser.RULE_variableDeclarator);
List<ParseTreeMatch> matches = p.findAll(tree, "//variableDeclarator");
for (ParseTreeMatch match : matches) {
System.out.println("nMATCH:");
System.out.printf(" - IDENTIFIER: %sn", match.get("IDENTIFIER").getText());
System.out.printf(" - expression: %sn", match.get("expression").getText());
}
}
}
导致以下输出:
MATCH:
- IDENTIFIER: q
- expression: 42
MATCH:
- IDENTIFIER: a
- expression: 10
关于您使用的语法,字符串模式正确。
match()
找不到任何东西的原因是,您可能会将整棵树传递给它(即带有Rule compilationUnit
的树(也许您希望它可以搜索整个树,而match()
仅尝试将模式与给定的ParseTree
对象匹配。match()
不会尝试在给定ParseTree
的子树中找到给定的模式。为了使其工作,您首先需要找到VariableDeclaratorContext
的所有节点(通过覆盖BaseListener
中的enterVariableDeclarator()
方法(,然后尝试匹配它们每个模式。例如
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.ParseTreeWalker;
import org.antlr.v4.runtime.tree.pattern.ParseTreeMatch;
import org.antlr.v4.runtime.tree.pattern.ParseTreePattern;
public class Main {
public static void main(String[] args) {
String javaCode = "public class Main {n" +
" public static void main() {n" +
" int i =0;n" +
" }n" +
"}";
JavaGLexer javaGLexer = new JavaGLexer(CharStreams.fromString(javaCode));
CommonTokenStream tokens = new CommonTokenStream(javaGLexer);
JavaGParser javaGParser = new JavaGParser(tokens);
ParseTree tree = javaGParser.compilationUnit();
ParseTreePattern p = javaGParser.compileParseTreePattern("<variableDeclaratorId> = <variableInitializer>", javaGParser.RULE_variableDeclarator);
ParseTreeWalker walker = new ParseTreeWalker();
IDListener idListener = new IDListener();
walker.walk(idListener, tree);
ParseTreeMatch match;
for (JavaGParser.VariableDeclaratorContext ctx: idListener.getVarCTXs())
{
match = p.match(ctx);
if (match.succeeded()) {
System.out.println("Match n" + " - IDENTIFIER: " +
match.get("variableDeclaratorId").getText() +
"n - INITIALIZER: " + match.get("variableInitializer").getText());
}
}
}
}
IDListener
扩展了JavaGBaseListener
并覆盖enterVariableDeclarator()
,并将variableDeclator
节点放在列表中,可以由getVarCTXs()
。
输出是:
匹配 - 标识符:我 - 初始化器:0