gpt4 book ai didi

pretty-print - 如何使用 ANTLR4 漂亮地打印作品和行号?

转载 作者:行者123 更新时间:2023-12-04 04:15:11 25 4
gpt4 key购买 nike

我正在尝试编写一段代码,该代码将采用 ANTLR4 解析器并使用它为类似于 grun ( misc.TestRig ) 上的 -tree 选项给出的输入生成 AST。但是,我还希望输出包含所有行号/偏移量信息。

例如,而不是打印

(add (int 5) '+' (int 6))

我想得到
(add (int 5 [line 3, offset 6:7]) '+' (int 6 [line 3, offset 8:9]) [line 3, offset 5:10])

或者类似的东西。

ANTLR4 还没有大量的访问者示例,但我很确定我可以通过复制 toStringTree 的默认实现来完成大部分工作。 (由 grun 使用)。但是,我没有看到有关行号或偏移量的任何信息。

我希望能够写出这样的 super 简单的代码:
String visit(ParseTree t) {
return "(" + t.productionName + t.visitChildren() + t.lineNumber + ")";
}

但似乎没有这么简单。我猜我应该能够从解析器中获取行号信息,但我还没有想出如何做到这一点。如何在遍历中获取此行号/偏移量信息?

为了填写下面解决方案中的几个空白,我使用了:
List<String> ruleNames = Arrays.asList(parser.getRuleNames());
parser.setBuildParseTree(true);
ParserRuleContext prc = parser.program();
ParseTree tree = prc;

获取 treeruleNames . program是我的语法中顶级产品的名称。

最佳答案

Trees.toStringTree方法可以使用 ParseTreeListener 来实现.以下监听器产生与 Trees.toStringTree 完全相同的输出.

public class TreePrinterListener implements ParseTreeListener {
private final List<String> ruleNames;
private final StringBuilder builder = new StringBuilder();

public TreePrinterListener(Parser parser) {
this.ruleNames = Arrays.asList(parser.getRuleNames());
}

public TreePrinterListener(List<String> ruleNames) {
this.ruleNames = ruleNames;
}

@Override
public void visitTerminal(TerminalNode node) {
if (builder.length() > 0) {
builder.append(' ');
}

builder.append(Utils.escapeWhitespace(Trees.getNodeText(node, ruleNames), false));
}

@Override
public void visitErrorNode(ErrorNode node) {
if (builder.length() > 0) {
builder.append(' ');
}

builder.append(Utils.escapeWhitespace(Trees.getNodeText(node, ruleNames), false));
}

@Override
public void enterEveryRule(ParserRuleContext ctx) {
if (builder.length() > 0) {
builder.append(' ');
}

if (ctx.getChildCount() > 0) {
builder.append('(');
}

int ruleIndex = ctx.getRuleIndex();
String ruleName;
if (ruleIndex >= 0 && ruleIndex < ruleNames.size()) {
ruleName = ruleNames.get(ruleIndex);
}
else {
ruleName = Integer.toString(ruleIndex);
}

builder.append(ruleName);
}

@Override
public void exitEveryRule(ParserRuleContext ctx) {
if (ctx.getChildCount() > 0) {
builder.append(')');
}
}

@Override
public String toString() {
return builder.toString();
}
}

该类可以按如下方式使用:

List<String> ruleNames = ...;
ParseTree tree = ...;

TreePrinterListener listener = new TreePrinterListener(ruleNames);
ParseTreeWalker.DEFAULT.walk(listener, tree);
String formatted = listener.toString();

可以通过更新 exitEveryRule 来修改该类以在输出中生成信息。方法:

@Override
public void exitEveryRule(ParserRuleContext ctx) {
if (ctx.getChildCount() > 0) {
Token positionToken = ctx.getStart();
if (positionToken != null) {
builder.append(" [line ");
builder.append(positionToken.getLine());
builder.append(", offset ");
builder.append(positionToken.getStartIndex());
builder.append(':');
builder.append(positionToken.getStopIndex());
builder.append("])");
}
else {
builder.append(')');
}
}
}

关于pretty-print - 如何使用 ANTLR4 漂亮地打印作品和行号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19350705/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com