Parsing ANTLR解析树修改

Parsing ANTLR解析树修改,parsing,tree,antlr,grammar,Parsing,Tree,Antlr,Grammar,我正在使用ANTLR4为我的语法创建一个解析树,我要做的是修改树中的某些节点。这将包括删除某些节点和插入新节点。这背后的目的是优化我正在编写的语言。我还没有找到解决这个问题的办法。最好的方法是什么?虽然目前没有真正的支持或工具用于树重写,但很有可能做到这一点。甚至没有那么痛苦 ParseTreeListener或您的MyBaseListener可以与ParseTreeWalker一起使用,以遍历您的解析树 从这里,您可以使用ParserRuleContext.removeLastChild()删

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

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

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

从这里,您可以使用
ParserRuleContext.removeLastChild()
删除节点,但是在执行此操作时,您必须注意
parsertrewalker.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);
}

我使用此方法编写了一个transpiler,它将同步内部语言编译成异步javascript。这非常痛苦。

另一种方法是编写一个
ParseTreeVisitor
,将树转换回字符串。(在某些情况下,这可能很简单,因为您只调用
TerminalNode.getText()
并在
aggregateResult(…)
中连接)

然后将修改添加到此访问者,以便生成的字符串表示包含您试图实现的修改

然后解析字符串,得到一个包含所需修改的解析树


这在某些方面确实有点骇人听闻,因为需要对字符串进行两次解析。另一方面,解决方案不依赖于antlr实现细节。

我需要类似的东西来实现简单的转换。最后,我使用了一个
ParseTreeWalker
和一个自定义的
…BaseListener
,在这里我重写了
enter…
方法。在这个方法中,
ParserRuleContext.children
是可用的,可以进行操作

class MyListener extends ...BaseListener {
    @Override
    public void enter...(...Context ctx) {
        super.enter...(ctx);
        ctx.children.add(...);
    }
}

new ParseTreeWalker().walk(new MyListener(), parseTree);

不,抱歉,没办法。你在说什么样的优化?另请参见:我希望修改树,更具体地说是终端节点及其值,例如,如果我有一个表达式2+4,我想用一个值为6的节点替换它。这不是一个很大的优化,但是如果有它就好了。不,没有办法替换解析树中的节点/子树。也许以后:好的,谢谢你的时间。
class MyListener extends ...BaseListener {
    @Override
    public void enter...(...Context ctx) {
        super.enter...(ctx);
        ctx.children.add(...);
    }
}

new ParseTreeWalker().walk(new MyListener(), parseTree);