2012-05-09 33 views
9

ANTLR文法ファイルとJavaソースコードを使用してJavaソースを分析するための完全な実装(githubまたはgooglecode)がありますか?たとえば、変数、メソッドなどの数を数えたいだけです。ANTLRをJavaソースファイルの静的解析に使用する

最近のバージョンのANTLRを使用しています。

+4

私は、ANTLRのWebサイトからJavaパーサー/ ASTビルダーを直接ダウンロードすることができます(したがって、「ANTLRの最近のバージョン」を満たす)。メソッドとフィールドを数えるためのツリークローラの作成は非常に簡単です。 "等"パートは誰もあなたが何を望んでいるかを推測できないことを意味します。標準的な指標ツールではどうしてですか? –

+0

エラーやセキュリティのために静的解析を行うことを検討している場合は、おそらくASTやANTLRが提供するツリー書き換えルール以上のものが必要になります。 [Stratego/XT](http://en.wikipedia.org/wiki/Stratego/XT)と組み合わせてANTLRを使用することをお勧めします。あなたが求めるものの無料公開版を持っている人は誰も知らない。良い質問。あなたがプロの品質のツールがアイラのプロフィールをチェックしたい場合。 –

+1

コンパイルされたバイトコードを見ることで、変数やメソッドを数えるほうがずっと簡単になります。たとえば、ASMバイトコードフレームワークを使用します。 –

答えて

12

私は昼休みにこれに亀裂を入れると思いました。これはあなたの問題を完全に解決するわけではありませんが、始める場所を与えるかもしれません。この例では、すべて同じディレクトリ内で作業していることを前提としています。

  1. GitHubからANTLR sourceをダウンロードしてください。 ANTLRサイトの事前コンパイル済み「完全」JARには、既知のバグが含まれています。 GitHubリポジトリには修正があります。

  2. ANTLRタールボールを抽出します。

    % tar xzf antlr-antlr3-release-3.4-150-g8312471.tar.gz
  3. ANTLR "complete" JARをビルドします。

    % cd antlr-antlr3-8312471 
    % mvn -N install 
    % mvn -Dmaven.test.skip=true 
    % mvn -Dmaven.test.skip=true package assembly:assembly 
    % cd -
  4. Java grammarをダウンロードしてください。他にもあるが、私はこれが動作することを知っている。

  5. 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
  6. Javaソースをコンパイルします。

    % javac -classpath antlr-antlr3-8312471/target/antlr-master-3.4.1-SNAPSHOT-completejar.jar com/habelitz/jsobjectizer/unmarshaller/antlrbridge/generated/*.java
  7. 次のソースファイルMain.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); } }
  8. コンパイル。

    % javac -classpath .:antlr-antlr3-8312471/target/antlr-master-3.4.1-SNAPSHOT-completejar.jar Main.java
  9. カウントするJavaソースのタイプを選択します。例えば、VAR_DECLARATOR,FUNCTION_METHOD_DECLまたはVOID_METHOD_DECLである。

    % cat com/habelitz/jsobjectizer/unmarshaller/antlrbridge/generated/Java.tokens
  10. 最近作成されたMain.javaを含め、どのファイルでも実行できます。

    % java -classpath .:antlr-antlr3-8312471/target/antlr-master-3.4.1-SNAPSHOT-completejar.jar Main VAR_DECLARATOR Main.java 
    6

もちろんこれは、不完全です。詳しく見ると、拡張されたforステートメントのローカル変数がカウントされていないことに気づいたかもしれません。そのためにはVAR_DECLARATORではなくFOR_EACHのタイプを使用する必要があります。

Javaソースの要素をよく理解していなければなりません。また、この特定の文法の定義にどのように一致するかについて、合理的に推測することができます。また、参照のカウントを行うこともできません。宣言は簡単ですが、フィールドの使用をカウントするなど、参照の解決が必要です。p.C.fは、クラスCの静的フィールドfをパッケージp内に参照していますか、またはクラスpの静的フィールドCによって保存されたオブジェクトのインスタンスフィールドfを参照していますか?基本的なパーサーは、Javaのような複雑な言語の参照を解決しません。一般的なケースは非常に困難な場合があるためです。このレベルの制御が必要な場合は、コンパイラ(またはそれに近いもの)を使用する必要があります。 Eclipseコンパイラは一般的な選択です。

また、ANTLR以外のオプションもあります。 JavaCCは別のパーサジェネレータです。 JavaCCをパーサジェネレータとして使用する静的解析ツールPMDでは、指定した種類のカウントに使用できるカスタムルールを記述できます。

+0

構文のインスタンス(例:#変数宣言)を数えるという観点からは、これはうまい答えです。 OPは彼が何をしたいのか不透明です。静的解析は通常、単なる計数をはるかに超えており、通常はシンボルテーブルを必要とし、しばしばフロー解析を必要とします。彼がちょうどカウントする必要がある場合、あなたのソリューションは桃(そう+1)です。もし彼がもっと必要とするなら、これはそれをカットしません。名前解決はJavaのフロー解析だけではありません。 –

+0

@IraBaxter:私の解決策はおそらく部分的であると約束しました。私は彼のニーズが比較的単純ではないという疑いがあります。さらに、ANTLRを使いこなすのは楽しいことでした。 –

+0

antlrの最新バージョンで動作するJava文法は実際には得られていないので、あいまいな質問です。構文は2.0リリースと3.0から大幅に変更されました。オンラインの多くのドキュメントは古いバージョンに合わせて作られていました。それは私を捨てていた。私は主にantlrの構文とアプローチに興味がありました。私の実際の仕事はかなり基本的でした。 –

関連する問題