Java AST遍历

时间:2015-02-21 10:27:53

标签: java antlr traversal abstract-syntax-tree

所以,我目前正在使用ANTLR和Java进行DSL实现。到目前为止,我已经基于ANTLR语法创建了自己的AST层次结构。为什么?因为不幸的是,ANTLR v4不支持output = AST。

无论如何,层次结构可以简化如下:

Expressions
-> BinaryExpressions(Expressions, Expressions)
    -> Multiplication(Expression, Expression)
    -> Addition(Expression, Expression)
    -> Greater_Equal(Expression, Expression)
    -> Less_Equal(Expression, Expression)

然后列表继续。无论如何,鉴于此,我到目前为止生成了一个组织良好的层次结构。所以例如3 +(2 * 3)会产生类似的东西:

Addition(Integer(3), Multiplication(Integer(2), Integer(3))

其中对象的类是添加的。

无论如何,鉴于此,我如何遍历这个层次结构?上面的例子只是对整体复杂性的快速概述,但是我如何通过使用递归函数迭代这个?因为,例如,定义(ASTNode节点:someNode)不起作用,因为ASTNode的对象(顶级类 - 所有类的母亲)不能被迭代。

谢谢!

1 个答案:

答案 0 :(得分:1)

这取决于你想要做什么,真的。

例如,如果要评估刚刚解析的公式,可以通过定义接口为每个AST节点赋予eval()方法:

public interface Evaluable {
    Something eval();
}

此时,您可以为所有节点定义操作,例如:

public class Integer implements Evaluable {
    @Override
    public Something eval() {
        return value;
    }

    private final Something value;
}

然后:

public class Multiplication implements Evaluable {
    @Override
    public Something eval() {
        return left.eval().product(right.eval());
    }

    private final Expression left;
    private final Expression right;
}

等等。

此时,您在根节点上调用.eval(),将以递归方式传播呼叫,并将结果传播回顶部。

这只是一个快速的解决方案。更精细(和复杂)的依赖于双间接模式,其中eval方法传递Evaluator,它为每种类型定义了一个重载的eval方法并封装了操作,从而将它们与AST节点。