gpt4 book ai didi

parsing - ANTLR 解析树修改

转载 作者:行者123 更新时间:2023-12-02 09:17:51 25 4
gpt4 key购买 nike

我正在使用 ANTLR4 为我的语法创建一个解析树,我想要做的是修改树中的某些节点。这将包括删除某些节点并插入新节点。其背后的目的是优化我正在编写的语言。我还没有找到解决这个问题的方法。解决这个问题的最佳方法是什么?

最佳答案

虽然目前还没有用于树重写的真正支持或工具,但这是很有可能做到的。甚至没有那么痛苦。

ParseTreeListener 或您的 MyBaseListener 可以与 ParseTreeWalker 一起使用来遍历您的解析树。

从这里,您可以使用ParserRuleContext.removeLastChild()删除节点,但是在执行此操作时,您必须注意ParseTreeWalker.walk:

public void walk(ParseTreeListener listener, ParseTree t) {
if ( t instanceof ErrorNode) {
listener.visitErrorNode((ErrorNode)t);
return;
}
else if ( t instanceof TerminalNode) {
listener.visitTerminal((TerminalNode)t);
return;
}
RuleNode r = (RuleNode)t;
enterRule(listener, r);
int n = r.getChildCount();
for (int i = 0; i<n; i++) {
walk(listener, r.getChild(i));
}
exitRule(listener, r);
}

如果步行者访问了这些节点的父节点,则您必须用某些东西替换删除的节点,我通常选择空的ParseRuleContext对象(这是因为上面方法中 n 的缓存值)。这可以防止 ParseTreeWalker 抛出 NPE。

添加节点时,请确保将 ParseRuleContext 上的可变父级设置为新父级。此外,由于上述方法中已缓存 n,因此一个好的策略是在您点击之前检测需要更改的位置。希望您的更改在 walk 中进行,因此 ParseTreeWalker 将在同一次遍历中遍历它们(否则您可能需要多次遍历...)

您的伪代码应如下所示:

public void enterRewriteTarget(@NotNull MyParser.RewriteTargetContext ctx){
if(shouldRewrite(ctx)){
ArrayList<ParseTree> nodesReplaced = replaceNodes(ctx);
addChildTo(ctx, createNewParentFor(nodesReplaced));
}
}

我使用这种方法编写了一个转译器,将同步内部语言编译为异步 javascript。实在是太痛苦了。

关于parsing - ANTLR 解析树修改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23487619/

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