Java ANTLR输出及其顺序
我发现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);};
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)代码>