我在ANTLR的输出中遇到了一个小问题。我有一个非常小的语法,看起来像这样:
test : states;
states : '.states' state+;
state : stateID=ID {
System.out.println("state: " + $stateID.text);
| stateID=ID '{' state* '}' {
System.out.println("SubState: " + $stateID.text);};
我想解析的内容如下所示:
a{
b
c{
d
}
}
好吧,问题是,我将得到的第一个令牌是"b",然后是"d",然后是"c"。但我的目的是将其解析为我的数据结构,我需要了解他们的父母。我所知道的是,c是d的父级,但是b呢?如果我将示例重写为以下形式:
a{
c{
d
}
b
}
一切都很好。那么有没有办法知道谁是 b 的父级,而不必在上一个例子中编写它?
在 ANTLR 4 中,不再建议使用语法操作。解析器可能会以意外的顺序访问和测试不同的规则和替代项,因此除非您要添加错误处理代码,否则最好让进程正常运行,然后检查结果。
因此,您让解析器创建其树,然后编写一个自定义侦听器,该侦听器将在每一步发出您的println
调用。例如,假设您正在使用名为 Foo
的语法,以便 和 ANTLR 自动生成一个FooBaseListener
类。
所以首先你要做一些类似的东西:
public class PrintingFooListener extends FooBaseListener {
@Override
public void enterState(FooParser.StateContext ctx)
{
// It is possible to get all sorts of token/subrule/text
// information from the ctx input, especially if you labeled
// the parser/lexer rules.
System.out.println("I entered State");
}
}
然后使用 ParseTreeWalker
实用程序类在访客拖曳的情况下浏览解析树:
// Assume lexing, etc. already done before this point
ParserRuleContext<Token> tree = parser.myMainRule(); // Do parse
ParseTreeWalker walker = new ParseTreeWalker(); // Premade utility class
PrintingFooListener listener = new PrintingFooListener(); // Your customized subclass
walker.walk(listener, tree);