3

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

如何使用 anASTVisitor来解析我的 AST 以获取所有叶节点?

4

3 回答 3

4

访客模式

如果您还不熟悉特定的设计模式,我建议您先阅读访问者模式。

本质上,它归结为使用双重调度来调用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实现接口,并将其传递给acceptVisitora 的方法Node(通常,但不总是,树的根节点)。


Eclipse 实现

要更全面地了解如何实现您ASTVisitor.

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


叶节点

由于您正在寻找叶节点(定义为没有子节点的 AST 节点),您可以执行以下操作来检索 an 的子节点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];
    }
}

通过调用此方法并传递您检查的每个节点,您可以确定该节点是否没有子节点(length返回数组的值为 0)并将它们添加到Collection您的 a 中ASTVisitor以跟踪它们。

于 2015-12-29T13:55:45.020 回答
1

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

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

希望能帮助到你。

于 2017-08-04T13:30:58.497 回答
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;
    }
}
于 2012-05-14T19:41:48.000 回答