web-dev-qa-db-ja.com

定量的に比較するAST形状

類似のソースコードプログラム(C、C++、Go、または [〜#〜] gcc [〜#〜] でコンパイルされたもの)の抽象構文ツリーの形状を比較するはどうすればよいでしょうか。 ..)?

ソースコードの盗作検出はこのような手法を使用すると思いますが、どのように呼び出されるのかわかりません...

たとえば、ASTを比較するために統合を使用できますが、ブール値の回答しか得られません。数値の「距離」またはある種の数値ベクトル(たとえば、後で機械学習や分類アルゴリズム、またはその他のビッグデータのことを説明するため)を提供するいくつかの手法を探しています。

大量のソースコードセットでのビッグデータや機械学習アプローチへの言及も歓迎します。

(このように広範またはあいまいな質問で申し訳ありません。使用する用語がわかりません)

2つのASTまたはプログラムを単純に比較したくありません。大量のプログラムセット(Debianディストリビューションのソースコードの半分など)を処理し、その中に同様のルーチンを見つけたいと思っています。私はすでに [〜#〜] melt [〜#〜] を使用してGCCの内部表現(Gimple)で作業したいので、それを活用して、いくつかのメトリックを格納します(どのメトリックですか? 循環的複雑度) はおそらく十分ではありません)例えばいくつかのデータベースとそれらを比較して処理します...

補遺: [〜#〜] moss [〜#〜] システムと紙について発見されましたが、構文の形にはまったく関心がないようです。 ツリー編集距離 も調べます。

ほかにも見つかりました(JérémieSalvucciに感謝) Michel Chilowi​​czの博士論文(フランス語、2010年11月)がソースコードの類似点を探す に掲載されました

1つのアプローチは、ソースをXMLにコンパイルしてから、ソースの2つのビットがどれほど異なるかを調べることです。たとえば、Java=世界では、静的分析ツール pmd は、警告するものを探すためのアプローチとしてこれを行います。

_class Example {
 void bar() {
  while (baz)
   buz.doSomething();
 }
}
_

「コンパイル」されて:

_CompilationUnit
 TypeDeclaration
  ClassDeclaration:(package private)
   UnmodifiedClassDeclaration(Example)
    ClassBody
     ClassBodyDeclaration
      MethodDeclaration:(package private)
       ResultType
       MethodDeclarator(bar)
        FormalParameters
       Block
        BlockStatement
         Statement
          WhileStatement
           Expression
            PrimaryExpression
             PrimaryPrefix
              Name:baz
           Statement
            StatementExpression:null
             PrimaryExpression
              PrimaryPrefix
               Name:buz.doSomething
              PrimarySuffix
               Arguments
_

その点は、「このコードとそのコードの違いは、この名前が異なることです」と言ってコードを比較することになります。上記は実際にはxmlであるため、これは、存在する任意の数のxml比較ツールで実行できます。または、数値を求めていた場合、 ツリー編集距離 アルゴリズムを適用できます(関連 SO質問 )。


別のアプローチは、コード形状の「署名」を調べることです。 署名調査 はワードカニンガムによって行われました

alt text

その伝説は少し読みにくいです:

  • _14m_は14のメソッドを意味します
  • _294L_は294行です。
  • _._は空白行ではありません
  • _'_はコメントです
  • _|_(緑)は、1行のifステートメントです。
  • _(.)_(緑)はifブロック内の単一のステートメントです
  • [(.)](茶色)は、ループ内のif内の単一ステートメントです。
  • _{.}_は、単一のステートメントを持つメソッドです。
  • _[.]_(赤)はループ内の単一ステートメントです
  • _([.])_(濃い赤)は、ifブロック内のループ内の単一ステートメントです。

2つのコードセットを比較すると、非常に限られた言語で2つの文字列間の編集距離が調べられます。

6
user40980