使用ANTLR对Java源文件进行静态分析
是否有人拥有使用ANTLR语法文件和Java源代码分析Java源代码的完整实现(可能是github或googlecode)。例如,我希望能够简单地计算变量、方法等的数量使用ANTLR对Java源文件进行静态分析,java,antlr,Java,Antlr,是否有人拥有使用ANTLR语法文件和Java源代码分析Java源代码的完整实现(可能是github或googlecode)。例如,我希望能够简单地计算变量、方法等的数量 还使用了最新版本的ANTLR。我想我应该在午餐休息时尝试一下。这可能不能完全解决你的问题,但它可能会给你一个开始的地方。本例假设您在同一目录中执行所有操作 从GitHub下载。来自ANTLR站点的预编译的“complete”JAR包含一个已知的bug。GitHub回购协议已经解决了这个问题 取出ANTLR焦油球 % tar xz
还使用了最新版本的ANTLR。我想我应该在午餐休息时尝试一下。这可能不能完全解决你的问题,但它可能会给你一个开始的地方。本例假设您在同一目录中执行所有操作
% tar xzf antlr-antlr3-release-3.4-150-g8312471.tar.gz
% mkdir com/habelitz/jsobjectizer/unmarshaller/antlrbridge/generated
% mv *.g com/habelitz/jsobjectizer/unmarshaller/antlrbridge/generated
% java -classpath antlr-antlr3-8312471/target/antlr-master-3.4.1-SNAPSHOT-completejar.jar org.antlr.Tool -o com/habelitz/jsobjectizer/unmarshaller/antlrbridge/generated Java.g
% javac -classpath antlr-antlr3-8312471/target/antlr-master-3.4.1-SNAPSHOT-completejar.jar com/habelitz/jsobjectizer/unmarshaller/antlrbridge/generated/*.java
% mkdir com/habelitz/jsobjectizer/unmarshaller/antlrbridge/generated
% mv *.g com/habelitz/jsobjectizer/unmarshaller/antlrbridge/generated
% java -classpath antlr-antlr3-8312471/target/antlr-master-3.4.1-SNAPSHOT-completejar.jar org.antlr.Tool -o com/habelitz/jsobjectizer/unmarshaller/antlrbridge/generated Java.g
% javac -classpath antlr-antlr3-8312471/target/antlr-master-3.4.1-SNAPSHOT-completejar.jar com/habelitz/jsobjectizer/unmarshaller/antlrbridge/generated/*.java
import java.io.IOException;
import java.util.List;
import org.antlr.runtime.*;
import org.antlr.runtime.tree.*;
import com.habelitz.jsobjectizer.unmarshaller.antlrbridge.generated.*;
public class Main {
public static void main(String... args) throws NoSuchFieldException, IllegalAccessException, IOException, RecognitionException {
JavaLexer lexer = new JavaLexer(new ANTLRFileStream(args[1], "UTF-8"));
JavaParser parser = new JavaParser(new CommonTokenStream(lexer));
CommonTree tree = (CommonTree)(parser.javaSource().getTree());
int type = ((Integer)(JavaParser.class.getDeclaredField(args[0]).get(null))).intValue();
System.out.println(count(tree, type));
}
private static int count(CommonTree tree, int type) {
int count = 0;
List children = tree.getChildren();
if (children != null) {
for (Object child : children) {
count += count((CommonTree)(child), type);
}
}
return ((tree.getType() != type) ? count : count + 1);
}
}
% java -classpath .:antlr-antlr3-8312471/target/antlr-master-3.4.1-SNAPSHOT-completejar.jar Main VAR_DECLARATOR Main.java
6
VAR\u声明符
,函数\u方法\u DECL
,或VOID\u方法\u DECL
% cat com/habelitz/jsobjectizer/unmarshaller/antlrbridge/generated/Java.tokens
import java.io.IOException;
import java.util.List;
import org.antlr.runtime.*;
import org.antlr.runtime.tree.*;
import com.habelitz.jsobjectizer.unmarshaller.antlrbridge.generated.*;
public class Main {
public static void main(String... args) throws NoSuchFieldException, IllegalAccessException, IOException, RecognitionException {
JavaLexer lexer = new JavaLexer(new ANTLRFileStream(args[1], "UTF-8"));
JavaParser parser = new JavaParser(new CommonTokenStream(lexer));
CommonTree tree = (CommonTree)(parser.javaSource().getTree());
int type = ((Integer)(JavaParser.class.getDeclaredField(args[0]).get(null))).intValue();
System.out.println(count(tree, type));
}
private static int count(CommonTree tree, int type) {
int count = 0;
List children = tree.getChildren();
if (children != null) {
for (Object child : children) {
count += count((CommonTree)(child), type);
}
}
return ((tree.getType() != type) ? count : count + 1);
}
}
% java -classpath .:antlr-antlr3-8312471/target/antlr-master-3.4.1-SNAPSHOT-completejar.jar Main VAR_DECLARATOR Main.java
6
for
语句的局部变量没有被计算在内。为此,您需要为每个使用类型,而不是VAR\u声明符
您需要对Java源代码的元素有很好的理解,并且能够合理地猜测这些元素如何与这个特定语法的定义相匹配。您也将无法进行引用计数。声明很容易,但计算字段的使用,例如,需要引用解析。p.C.f
是指包p
中类C
的静态字段f
,还是指由类p
的静态字段C
存储的对象的实例字段f
?基本解析器不会解析像Java这样复杂的语言的引用,因为一般情况下可能非常困难。如果您想要这种级别的控制,您需要使用编译器(或更接近它的东西)。Eclipse编译器是一种流行的选择
我还应该提到,除了ANTLR,您还有其他选择。JavaCC是另一个解析器生成器。静态分析工具PMD使用JavaCC作为解析器生成器,允许您编写自定义规则,用于指定的计数类型。我假设您可以直接从ANTLR网站下载Java解析器/AST生成器(因此满足“ANTLR的最新版本”)。编写一个树爬虫来计算方法和字段是相当容易的。“等”部分意味着没有人能猜出你还想要什么;为什么一个标准的度量工具不能做到呢?如果您正在考虑对错误或安全性进行静态分析,那么您可能需要的不仅仅是ANTLR提供的AST和树重写规则。您可能希望结合使用ANTLR。我不知道有谁有一个免费的公众版本的你所寻求的。好问题。如果你想要专业质量工具,请查看Ira的个人资料。通过查看编译后的字节码(例如使用ASM字节码框架),计算变量和方法会容易得多。@JörnHorstmann:检查字节码得到的计数可能与检查源代码得到的计数不同。内联编译时常量、桥接方法等将导致不同的数字。无论嵌套类型的变量/方法等是否计入封闭类型的总数,事情都变得更加复杂。为什么不将其作为起点呢?它不使用ANTLR,而是使用javacc。顺便说一句,它可能已经生成了您正在寻找的所有度量。从简单计算语法实例(例如#变量声明)的角度来看,这是一个很好的答案。OP对于他想做的其他事情是不透明的;静态分析通常不仅仅是计数,通常需要一个符号表,并且通常需要流分析。如果他只需要数数,你的解决方案就是桃子(so+1);如果他需要更多,这不会解决问题,Java的名称解析更不用说流分析了。@IraBaxter:同意我的解决方案可能只是部分解决方案。我怀疑他的需求相对来说并不复杂,再加上重新使用ANTLR很有趣。这是一个模糊的问题,因为我从来没有用Java语法来处理ANTLR的最新版本。语法与2.0版和3.0版相比发生了很大变化。很多在线文档都是针对旧版本的。它把我甩了。我主要对antlr的语法和方法感兴趣。我的实际任务相当基本。谢谢,我终于重新审视了这一点。我有很多编译错误,试图从源代码构建antlr。我最终只构建了我需要的模块(antlr complete,等等)。作为构建的一部分,我还必须关闭gpg。除此之外,语法也如预期的那样起作用。