1

我对 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 的父级,而不必在最后一个示例中编写它?

4

1 回答 1

1

在 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);
于 2013-10-07T22:53:08.620 回答