Java ANTLR输出及其顺序

Java ANTLR输出及其顺序,java,antlr4,Java,Antlr4,我发现ANTLR的输出有一个小问题。 我有一个很小的语法,看起来像这样: test : states; states : '.states' state+; state : stateID=ID { System.out.println("state: " + $stateID.text); | stateID=ID '{' state* '}' { System.out.println("SubState: " + $stateID.text);};

我发现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
    }
}
我要分析的内容如下所示:

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);
//假设在此之前已经完成了词法分析等
ParserRuleContext树=parser.myMainRule();//解析
ParseTreeWalker=新ParseTreeWalker();//预制实用程序类
PrintingGooListener listener=新的PrintingGooListener();//您的自定义子类
走(听众,树);

在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);
//假设在此之前已经完成了词法分析等
ParserRuleContext树=parser.myMainRule();//解析
ParseTreeWalker=新ParseTreeWalker();//预制实用程序类
PrintingGooListener listener=新的PrintingGooListener();//您的自定义子类
走(听众,树);

您不需要创建
ParsetRewalker
的实例。只需使用
ParseTreeWalker.DEFAULT.walk(listener,tree)
您不需要创建
ParseTreeWalker
的实例。只需使用
ParseTreeWalker.DEFAULT.walk(listener,tree)