0

C ++で記述された私のプログラムでは、それぞれがC関数の宣言を含む文字列のセットを取得し、それらに対していくつかの操作を実行する必要があります。

操作の1つは、ある関数が別の関数と等しいかどうかを比較することです。そのためには、関数のセマンティクスに影響を与えないコメントと中間の空白を削除してから、文字列の比較を行う予定です。ただし、関数によって生成される出力を変更するために削除すると、文字列内に空白を保持したいと思います。

文字列文字を繰り返し、引用符(")が検出されるたびに「文字列モード」に入り、エスケープされた引用符を認識するコードを記述できますが、これを行うためのより良い方法があるかどうか疑問に思います。本格的なCパーサーを使用し、関数文字列に対して実行し、すべてのコメントと余分な空白を無視してから、ASTを再び文字列に変換するというアイデアがあります。しかし、いくつかのCパーサーを見回すと、ほとんどが私のソースコードと統合するための雌犬であるように感じます(私がそうである場合は間違っていることを証明してください)。おそらく、私はyacc何かを使用して、既存のC文法を使用し、パーサーを自分で実装しようとすることができます...

それで、これを行うための最良の方法に関するアイデアはありますか?

編集:

私が書いているプログラムは、抽象的なモデルを取り、それをCコードに変換します。モデルはグラフで構成され、ノードにはCコードのセグメントが含まれる場合と含まれない場合があります(より正確には、実行が完全に決定論的である必要があり(つまり、グローバル状態がない)、メモリ操作が許可されないC関数定義)。プログラムはグラフ上でパターンマッチングを実行し、これらのパターンに準拠する特定のノードをマージおよび分割します。ただし、これらの操作は、ノードが同じ機能を示す場合(つまり、C関数の定義が同じ場合)にのみ実行できます。この「それらが同じであることの確認」は、C関数宣言を含む文字列を単に比較することによって行われます。それらが文字ごとに同一である場合、それらは等しいです。

モデルの生成方法の性質上、コメントと余分な空白が削除される場合、これは非常に合理的な比較方法ですこれが異なる可能性がある唯一の要因であるためです。これは私が直面している問題です-最小限の実装作業でこれを行うにはどうすればよいですか?

4

3 に答える 3

4

ある関数が別の関数と等しいかどうかを比較するとはどういう意味ですか?適切に正確な意味で、その問題は決定不可能であることが知られています!

あなたはあなたのプログラムが実際に何をしているのかを教えてくれませんでした。すべての実際のCプログラムを正しく解析することは簡単ではありません(C言語の構文とセマンティクスはそれほど単純ではないためです!)。

既存のツールやライブラリを使用して支援することを検討しましたか?LLVM Clangは可能性であり、プラグインを介してGCCを拡張するか、 MELTでコード化された拡張機能を使用することでさらに優れたものになります。

しかし、私たちはあなたの本当の目標を理解せずにあなたをもっと助けることはできません。そして、Cコードの解析は、おそらくあなたが想像するよりも複雑です。

于 2011-11-06T10:27:43.980 に答える
0

おそらく、解析したい C 関数は、私たちが推測しているほど一般的ではありません (テキスト形式であり、実際のコンパイラによって解析されるものでもあります)。

あなたは逆のことを考えるかもしれません:

小さなドメイン固有言語(構文は C よりも構文解析がはるかに簡単になる可能性があります) を定義し、C コードを解析する代わりに別の方法でそれを行うことは理にかなっています: ユーザーは DSL を使用し、ツールは C を生成します。 DSL からのコード(後の段階で通常の C コンパイラによってコンパイルされる) 。

あなたの DSL は実際には、C 関数に変換されるより多くの手続き部分と混合された抽象モデルの記述である可能性があります。関心のある C 関数は非常に特殊であるため、それらを生成する DSL は小さい可能性があります。

(ANTLR、YACC、Bison などの多くのパーサー ジェネレーターは、同様のアイデアに基づいて構築されていると考えてください)。

私は実際にMELTでかなり似たようなことをしました(特に私のDSL2011 論文を読んでください)。C に変換された DSL を設計するための便利なトリックが見つかるかもしれません。

于 2011-11-06T19:53:37.823 に答える