ANTLR4解析树简化

ANTLR4解析树简化,antlr,antlr4,Antlr,Antlr4,有没有办法让ANTLR4自动删除生成的解析树中的冗余节点 更具体地说,我一直在试验GLSL的语法,由于自动处理运算符优先级所需的规则转发,解析树中的“表达式”的线性序列很长 大多数生成的树节点只是“转发到下一个优先级级别”,因此不提供任何有用的语法信息-您只需要每个序列中的最后一个表达式节点(即规则转发停止的点),或者它成为具有多个子节点的实际树节点的点(即,在源代码中遇到实际表达式) 我希望有一种简单的方法来消除伪中间表达式节点——这种类型的结构在任何具有运算符优先级的语法中都必须是常见的 语

有没有办法让ANTLR4自动删除生成的解析树中的冗余节点

更具体地说,我一直在试验GLSL的语法,由于自动处理运算符优先级所需的规则转发,解析树中的“表达式”的线性序列很长

大多数生成的树节点只是“转发到下一个优先级级别”,因此不提供任何有用的语法信息-您只需要每个序列中的最后一个表达式节点(即规则转发停止的点),或者它成为具有多个子节点的实际树节点的点(即,在源代码中遇到实际表达式)

我希望有一种简单的方法来消除伪中间表达式节点——这种类型的结构在任何具有运算符优先级的语法中都必须是常见的

语法的基本结构是从该语言的Khronos规范中相当直接的克隆:


ANTLR v4能够从处理不同优先级的单个递归规则生成代码,如果您使用这样的语法(例如基本数学):

ANTLRv3无法做到这一点,基本上要求您为每个优先级编写一条规则。因此,我建议您重写语法以避免这些样板规则

然后,我认为您混淆了。AST就像解析树的简化版本,只保留您需要的内容。例如,使用上面的
expr
规则,AST不会包含任何括号节点,因为优先级在树本身中编码,您通常不需要知道是什么她在给定表达式中的某个部分是否加了括号


您的程序应该从解析树构建AST,然后再从解析树开始。不要直接处理解析树,即使乍一看很方便,因为工具会为您生成它们。这很快就会变得很麻烦。构建您自己的树结构(AST),为手头的任务量身定制。

使用访问者实现按顺序访问每个节点。通过在访问节点时向父节点添加节点来构建自己的树。在访问节点时决定是否将其添加到新树中。例如:

public T visitExpression(@NotNull AcParser.ExpressionContext ctx) {
        // Expressionable parent = getParent(Expressionable.class, ctx);
        // Class<? extends AcExpression> expClass = AcExpression.class;
        AcExpression obj = null;
        String text = ctx.getText();

        //do something with text or children
        for (int i=0; i<ctx.getChildCount(); i++){
            printnl(ctx.getChild(i).getText()+"/");
        }

        return visitChildren(ctx);
    }
public T visitExpression(@NotNull AcParser.ExpressionContext ctx){
//Expressionable parent=getParent(Expressionable.class,ctx);

//ClassI正在编写一个源代码到源代码的转换器,即旨在删除未使用的变量、未使用的函数等。在可能的情况下,我希望保留源代码格式,因此不想过于抽象,但我同意这种看法。另外,感谢对单递归规则的更新-我认为这将很好地解决问题。(我仍在试图理解ANTLR4中的变化-与3完全不同…。@Isogen74是的,它与v3非常不同,这是为了更好的IMHO。无论如何,如果你正在构建一个源代码到源代码的转换器,你完全正确的做法是不要太抽象。你需要解析树来完成这些事情。这里有一个想法给你(我已成功使用):构建一个AST,并在每个AST节点中保留对相关解析树节点的引用。通过这种方式,您可以从两者中获得最佳效果。您可以拥有一个抽象语法树,同时仍然能够将节点与输入中的单个字符相关联。感谢您的帮助-将魅力作为一种技术发挥作用。感谢-结合Lucas的建议(不要偷懒,做一个适当的AST),这看起来是一条路要走。
public T visitExpression(@NotNull AcParser.ExpressionContext ctx) {
        // Expressionable parent = getParent(Expressionable.class, ctx);
        // Class<? extends AcExpression> expClass = AcExpression.class;
        AcExpression obj = null;
        String text = ctx.getText();

        //do something with text or children
        for (int i=0; i<ctx.getChildCount(); i++){
            printnl(ctx.getChild(i).getText()+"/");
        }

        return visitChildren(ctx);
    }