另载于 http://www.qingjingjie.com/blogs/2java
这是一个关于抽象语法树(Abstract Syntax Tree, AST)的故事。git
抽象语法树是对程序代码的结构化表示,是对代码进行词法分析、语法分析后获得的产物。编译器要用到它,不少生产力工具也要用它,例如:github
IDE能够自动重构、自动生成一些代码、自动对不规范代码发出警告。这是很强很实惠的功能。 一个大型软件项目经常有几百人合做,几百万行代码。不少代码规范难以百分百落实,不少编程错误潜藏在项目中。这时候咱们会考虑Sonar, FindBug, Checkstyle之类的代码分析工具来帮助咱们扫描出巨量代码中存在的问题。 国内有位老兄就作了个自动生成测试代码的工具。(但不要生成功能代码,咱们要构建良好的抽象和简洁的代码) 我司的系统要进行架构迁移,其中有百万行代码须要修改,用人力来作是很可怕的。我作了个工具来自动完成这件事。
它们利用AST来对大量程序代码作自动化处理,给了咱们莫大的帮助。甚至自动写代码也不是不可能。那么咱们本身能玩一玩AST这种高大上的东西吗?编程
能。Eclipse这个开源的Java IDE就提供了一个库来帮助咱们达到目的,它的名字是JDT(Java Development Tools)。咱们使用它的核心模块JDT Core。设计模式
这个项目历史悠久,功能强力,早期开发者有《设计模式》GoF的做者。架构
它提供了一套关于AST的API,能解析Java代码,生成、分析和操做AST结构。有了它,咱们就不用本身实现高难度的词法分析和语法分析了。框架
(嫌麻烦能够看这个小框架 https://github.com/sorra/exia)
首先准备好库文件——打开你的Eclipse安装目录,在搜索框中搜索如下jar文件(*是通配符):
org.eclipse.jdt.core_*
org.eclipse.core.contenttype_*
org.eclipse.core.jobs_*
org.eclipse.core.resources_*
org.eclipse.core.runtime_*
org.eclipse.equinox.common_*
org.eclipse.equinox.preferences_*
org.eclipse.equinox.registry_*
org.eclipse.osgi_*
org.eclipse.text_*
若是有多个版本,取最新版本。通通copy出来,添加到你的项目中。
源代码包是org.eclipse.jdt.core.source_* 用Eclipse的Attach source功能把它连到第一个jar上,能够阅读源代码。dom
先来溜一段起步代码,把一段Java代码解析成AST。eclipse
import java.util.Map; import org.eclipse.jdt.core.dom.*; import org.eclipse.jdt.JavaCore; ...... public static void main(String[] args) { ASTParser parser = ASTParser.newParser(AST.JLS4); //设置Java语言规范版本 parser.setKind(ASTParser.K_COMPILATION_UNIT); Map<String, String> compilerOptions = JavaCore.getOptions(); compilerOptions.put(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_1_7); //设置Java语言版本 compilerOptions.put(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_1_7); compilerOptions.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_7); parser.setCompilerOptions(compilerOptions); //设置编译选项 char[] src = "class A { void method1(int b){;} }".toCharArray(); parser.setSource(src); CompilationUnit cu = (CompilationUnit) parser.createAST(null); //这个参数是IProgessMonitor,用于GUI的进度显示,咱们不须要,填个null. 返回值是AST的根结点 System.out.println(cu); //把AST直接输出看看啥样 }
AST做为抽象语法树,它就是一棵树,有点像XML的DOM树。
例子中的树大概长这样:ide
CompilationUnit | class | | A method1 | | | void [] {} | | arg ; | | int b
延伸阅读:http://help.eclipse.org/ 点击JDT Plug-in User Guide -> Programmer's Guide -> JDT Core。