如何在java中使用访问者的AST

时间:2012-04-26 10:31:07

标签: java abstract-syntax-tree

我使用org.eclipse.jdt.core.dom生成某些给定Java源代码的AST。 生成AST后,我有根节点。

如何使用ASTVisitor以便我可以解析我的AST以获取所有叶节点?

3 个答案:

答案 0 :(得分:2)

访客模式

如果您还不熟悉特定的设计模式,我建议您先从Visitor Pattern开始阅读。

基本上,它归结为使用double dispatch在Visitor类上调用适当的方法,将访问对象作为参数传递。通常,它以与以下(YMMV)类似的方式实现:

public interface Node {
    void acceptVisitor(Visitor v);

    Collection<Node> getChildren();
}

// Incomplete implementation, for demonstration only
public class SubNode implements Node {

    @Override
    public void acceptVisitor(Visitor v) {
        if(v.preVisit(this)) {
            v.visit(this);
            v.postVisit(this);
        }
        getChildren().forEach(child -> child.accept(v));
    }
}

public interface Visitor {
    boolean preVisit(Node node);

    void visit(Node node);

    void visit(SubNode node);

    void postVisit(Node node);
}

然后实现Visitor接口,并将其传递到acceptVisitor的{​​{1}}方法(通常但不总是树的根节点)。

Eclipse实施

要更全面地了解如何实施Node,您可以查看this tutorial

在您的特定情况下,您需要扩展org.eclipse.jdt.core.dom.ASTVisitor类,覆盖您关注的org.eclipse.jdt.core.dom.ASTNode实现的ASTVisitor方法。然后将此visit的实例传递给AST根节点的accept方法。

叶节点

由于您正在寻找叶节点(定义为没有子节点的AST节点),您可以执行the following之类的操作来检索ASTVisitor的子节点:

ASTNode

通过调用此方法并传递您检查的每个节点,您可以确定该节点是否没有子节点(返回的数组的public Object[] getChildren(ASTNode node) { List list= node.structuralPropertiesForType(); for (int i= 0; i < list.size(); i++) { StructuralPropertyDescriptor curr= (StructuralPropertyDescriptor) list.get(i); Object child= node.getStructuralProperty(curr); if (child instanceof List) { return ((List) child).toArray(); } else if (child instanceof ASTNode) { return new Object[] { child }; } return new Object[0]; } } 将为0)并将其添加到您的lengthCollection要跟踪它们。

答案 1 :(得分:1)

这可能不是正确的方法,但这可以获取所有叶节点。

1)维护两组节点,让我们说S1S2
2)遍历所有节点并将每个节点添加到S1 3)如果node.getParent() != null,则将node.getParent()添加到S2
4)这意味着S1跟踪所有节点,而S2具有所有内部节点。叶子节点是S1 - S2

希望它有所帮助。

答案 2 :(得分:0)

一个例子是:

package de.vogella.jdt.astsimple.handler;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.MethodDeclaration;

public class MethodVisitor extends ASTVisitor {
  List<MethodDeclaration> methods = new ArrayList<MethodDeclaration>();
    @Override
    public boolean visit(MethodDeclaration node) {
      methods.add(node);
      return super.visit(node);
    }

    public List<MethodDeclaration> getMethods() {
      return methods;
    }
}