谈谈Java抽象语法树的构建

相关主题
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
(2) 创建 JavaASTParser 类, VersionASTRequestor 类, DemoASTVisitor 类以及 Client 类,具体代码如下: // JavaASTParser.java public class JavaASTParser {
private static String libraryPath; private VersionASTRequestor astRequestor; private String versionPath;
org.eclipse.core.contenttype_3.4.200.v20130326-1255.jar org.eclipse.core.jobs_3.5.300.v20130429-1813.jar org.eclipse.core.resources_3.8.100.v20130521-2026.jar org.eclipse.core.runtime_3.9.0.v20130326-1255.jar org.eclipse.equinox.common_3.6.200.v20130402-1505.jar org.eclipse.equinox.preferences_3.5.100.v20130422-1538.jar org.eclipse.jdt.core_3.11.1.v20150902-1521.jar org.eclipse.osgi_3.9.0.v20130529-1710.jar
public String[] getAllFiles(String projectVersionPath, String suffix) { ArrayList<String> filesList = new ArrayList<String>(); File file = new File(projectVersionPath); if (file.isDirectory() == true) {
MethodDeclaration
MODIFIERS RETURN_TYPE
NAME
PARAMETERS
Modifier PrimitiveType SimpleName SingleVariableDeclaration
TYPE
NAME
BODY Block STATEMENTS
PrimitiveType SimpleName
为了形象地理解 AST,下面通过一个具体的程序(Circle.java)说明 AST 的结构以及结点的类型。
package a.b.c;
import seu.edu.cn.Shape;
public class Circle {
private final double pi = 3.14;
public double getSqure (double r) {
} }
// VersionASTRequestor.java public class VersionASTRequestor extends FileASTRequestor {
private List<CompilationUnit> correctUnits; public VersionASTRequestor() {
谈谈 Java 抽象语法树的构建
抽象语法树(abstract syntax tree, AST)是程序的一种中间表示形式,是源代码抽象语法结构的树状表 现形式。树上的每个结点都代表一种语法结构。之所以称语法是“抽象”的,是因为这里的语法并不会表 示出真实语法中的每个细节。比如,嵌套括号被隐含在树的结构中,并没有以结点的形式呈现,而类似于 if-than-else 这样的条件语句,可以用两个分支结点表示。本文将谈谈 Java 抽象语法树构建方面有哪些常用 的(解析)工具,重点探讨 JDT 的工作机制和配置方法。
String[] encodings = null; String[] bindingKeys = new String[] {"package", "class", "interface",
"array types", "primitive types", "field" }; parser.createASTs(sourceFilePaths, encodings, bindingKeys, astRequestor, null); }
@SuppressWarnings("unchecked") Map<String, String> complierOptions = JavaCore.getOptions(); parser.setCompilerOptions(complierOptions);
String[] sourceFilePaths = this.getAllFiles(versionPath, ".java");
readFiles(file, suffix, filesList); } int size = filesList.size(); String[] array = filesList.toArray(new String[size]); return array; }
private void readFiles(File file, String suffix, ArrayList<String> filesList) { if (file != null) { if (file.isDirectory()) { File f[] = file.listFiles(); if (f != null) { for (int i = 0; i < f.length; i++) { readFiles(f[i], suffix, filesList); } } } else if (file.getName().endsWith(suffix)) { filesList.add(file.toString()); } }
VariableDeclarationStatement
ReturnStatement
TYPE
FRAGMENTS
PrimitiveType VariavleDeclarationFragment
NAME
INITIALIZER
SimpleName
InfixExpression
图 1. ASTParser 将 Circle 类转化成相应的抽象语法树
初步了解 AST 概念后,下面将介绍如何使用 JDT,即,如何将一个或多个*.java 文件解析成相应的抽 象语法树。
准备工作
(1) 安装 JDK8,Eclipse Mars 版(建议安装新版本,因为新版本中 JDT Core 插件最新,解析能力更强), 并导入下列 jar 包,它们均位于 Eclipse 文件夹 plugins 下,你的版本号可能不同,但前缀名称应该一样:
在插件 JDT Core 的 org.eclipse.jdt.core.dom 包中,含有 AST、ASTParser、ASTNode、ASTVisitor 等类, 通过这些类可以获取、创建、访问和修改抽象语法树。比如,ASTVisitor 类就提供了一系列重载 visit 函数, 用于遍历抽象语法树,以获得 AST 上每个结点信息。
public JavaASTParser(VersionASTRequestor astRequestor, String versionPath) { this.astRequestor = astRequestor; this.versionPath = versionPath; try { File directory = new File(""); JavaASTParser.libraryPath = directory.getAbsolutePath() + File.separator +
当前,将 java 程序转化成抽象语法树的工具较多,比如,JDT (http://www.eclipse.org/jdt/)、ANTLR (http://www.antlr.org/)、RECODER (https://sourceforge.net/projects/recoder/) 以及 JavaCC (http://javacc.org/)等, 其中 RECODER 更新较慢,从 2013 年开始停止发布新版本。在这几款工具中,由于 JDT 工具为开源软件, 在学术界越来越受欢迎。JDT(Java Development Tools)是 Eclipse 中一组 Java 开发工具包,它由 JDT Core、 JDT Debug 以及 JDT UI 插件组成,这 3 个插件均提供了 API 供开发者调用,以支持开发者进一步开发基于 JDT 的其它插件。顾名思义,插件 JDT Core 是 JDT 的核心包,它提供了整个 Eclipse 的核心基础功能,比 如,Eclipse 菜单下的 Refactor 操作,其功能的实现都依赖该核心包。另外,这些插件均以 jar 文件的形式发 布,在下载的 Eclipse 文件夹 plugins 下可以直接获得,如果你想获取,只需要搜索类似于下面的 jar 文件即 可:org.eclipse.jdt.launchingXX.jar, org.eclipse.jdt.uiXX.jar, org.eclipse.jdtXX.jar,这里的 XX 代表每个插件发 布的版本号。
"NeededBindingJARs"; } catch (Exception e) { }
}
public void generateASTs() { ASTParser parser = ASTParser.newParser(AST.JLS8); String[] classpathEntries = this.getAllFiles(libraryPath, ".jar"); String[] sourcePathEntries = { versionPath }; parser.setEnvironment(classpathEntries, sourcePathEntries, null, true); parser.setResolveBindings(true); parser.setBindingsRecovery(true); parser.setStatementsRecovery(true); parser.setKind(ASTParser.K_COMPILATION_UNIT);
PACKAGE
CompilationUnit IMPORTS
TYPES
PackageDeclaration
ImportDeclaration
TypeDeclaration
MODIFIERS
NAME
BODY_DECLARATIONS
Modifier
SimpleName FieldDeclaration
double result = pi*r*r;
return result;
}百度文库
} 图 1 Circle.java 对应的 AST,为清晰起见,图 1 中“粗体”标识的叶子结点并未详细展开。图中的每个 AST 结点均代表程序中相应的程序单元或语法结构。其中,位于最顶层的 CompilationUnit 结点代表源程序 文件(Circle.java);TypeDeclaration 结点代表 Circle 类;FieldDeclaration 结点代表 Circle 类中的属性声明和 初始化语句“private final double pi = 3.14;”;MethodDeclaration 结点表示 getSqure 方法的声明与实现语句; ReturnStatement 结点表示返回语句“return result;”,总之,AST 中的每个结点均代表相应的 Java 语法结构 (有时也称代码实体),在 JDT 中共有 92 种 AST 结点类型,具体可访问 API 文档查看相关信息。
相关文档
最新文档