如何在一般遍历解析树时访问 ANTLR4 中的备用标签?或者,是否有任何方法可以复制 ^
的功能? ANTLR3 的运算符,因为这可以解决问题。
我正在尝试为任何遵循简单方法的 ANTLR4 语法编写一个 AST pretty-print (比如用备用标签命名作品)。我希望能够漂亮地打印出像 3 + 5
这样的术语如 (int_expression (plus (int_literal 3) (int_literal 5)))
,或类似的东西,给定如下语法:
int_expression
: int_expression '+' int_expression # plus
| int_expression '-' int_expression # minus
| raw_int # int_literal
;
raw_int
: Int
;
Int : [0-9]+ ;
我无法有效地命名
plus
和 minus
产生式,因为将它们拉出到自己的产生式中会导致工具提示规则是相互左递归的。如果我不能把它们拉出来,我怎么能给这些作品起名字?注 1:我能够摆脱
+
通过将“好”终端(例如,上面的 Int
)放在特殊产生式(以特殊前缀开头的产生式,例如 raw_
)中,在方法论上进行论证。然后我可以只打印那些父产品名为“raw_
...”的终端,并忽略所有其他终端。这对于摆脱 +
非常有效。 , 同时保持 3
和 5
在输出中。这可以通过 !
来完成。在 ANTLR3 中。注 2:我知道我可以为给定语言的每种产品编写一个专门的 pretty-print 或使用操作,但我想使用 ANTLR4 来解析和生成各种语言的 AST,似乎我应该能够编写这样一个简单 pretty-print 。换句话说,我只关心获得 AST,我宁愿不必为了获得 AST 而用量身定制的 pretty-print 来阻碍每个语法。也许我应该回到ANTLR3?
最佳答案
我建议将 pretty-print 实现为具有嵌套访问者类的监听器实现,以获取各种上下文对象的名称。
private MyParser parser; // you'll have to assign this field
private StringBuilder builder = new StringBuilder();
@Override
public void enterEveryRule(@NotNull ParserRuleContext ctx) {
if (!builder.isEmpty()) {
builder.append(' ');
}
builder.append('(');
}
@Override
public void visitTerminalNode(@NotNull TerminalNode node) {
// TODO: print node text to builder
}
@Override
public void visitErrorNode(@NotNull TerminalNode node) {
// TODO: print node text to builder
}
@Override
public void exitEveryRule(@NotNull ParserRuleContext ctx) {
builder.append(')');
}
protected String getContextName(@NotNull ParserRuleContext ctx) {
return new ContextNameVisitor().visit(ctx);
}
protected class ContextNameVisitor extends MyParserBaseVisitor<String> {
@Override
public String visitChildren() {
return parser.getRuleNames()[ctx.getRuleIndex()];
}
@Override
public String visitPlus(@NotNull PlusContext ctx) {
return "plus";
}
@Override
public String visitMinus(@NotNull MinusContext ctx) {
return "minus";
}
@Override
public String visitInt_literal(@NotNull MinusContext ctx) {
return "int_literal";
}
}
关于pretty-print - 如何在一般遍历解析树时访问 ANTLR4 中的备用标签?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19372959/