4

C宣言や関数定義のリストを部分的に解析したいと思います。

つまり、それぞれが1つの宣言または関数定義を含むサブストリングに分割したいと思います。

次に、各宣言は(個別に)別のモジュールに渡されます(完全なCパーサーが含まれてますが、直接呼び出すことはできません)。

もちろん、プログラムに別の完全なCパーサーを含めることでこれを行うことができますが、これは避けたいと思います。

私がこれまでに直面したトリッキーなケースは'}'、宣言/定義を終了するかどうかの問題を含みます。たとえば

int main(int ac, char **av) {return 0;}

...'}'はターミネーターですが、

typedef struct foo {int bar;} *pfoo;

そうではない。次のような病理学的なコードも存在する可能性があります。

struct {int bar;} *getFooPtr(...) { /* code... */ }

ノート

  • 私の関数がそれを見る前に、Cコードがすでに完全に前処理されていると仮定してください。(実際にはそうではありませんが、回避策があります。)
  • 私のパーサーはおそらくLPegを使用してLuaに実装されます
4

3 に答える 3

1

私の知る限り、次の解決策は宣言に対してのみ機能します(つまり、関数定義はこのセクションから除外する必要があります。そうでない場合は、セミコロンを追加すると回避策になる可能性があります:)

  1. 現在の位置にいるキャラクターを調べます
  2. の場合;、宣言の終わりが見つかりました。
  3. "またはの場合'は、一致する引用符にジャンプし、必要に応じてエスケープシーケンスをスキップします。
  4. (、またはの場合は、一致する、、[または{にジャンプします(必要に応じて、ネストされた角かっこと文字列を再帰的にスキップします))]}
  5. それ以外の場合は、次の入力文字に進み、手順1に進みます。

これが不十分であることが判明した場合は、clangパーサーに切り替えます。

于 2012-11-26T21:06:17.043 に答える
1

関数定義を処理するために回答のステートマシンを拡張するには、次の手順を追加します。

  1. fun/var状態を「不明」に設定します
  2. 現在の位置にいるキャラクターを調べます
  3. の場合;、宣言の終わりが見つかりましたが、関数定義ではありません(ただし、関数宣言である可能性があります)。
  4. "またはの場合'は、一致する引用符にジャンプし、必要に応じてエスケープシーケンスをスキップします。
  5. (、またはの場合は、一致する、、[または{にジャンプします(必要に応じて、ネストされた角かっこと文字列を再帰的にスキップします))]}
  6. fun /var状態が'function'で、スキップしただけの場合{.. }、宣言の終わりとその関数定義が見つかりました
  7. fun /var状態が'unknown'で、スキップした場合は(.. )、fun/var状態を'function'に設定します。
  8. 現在の文字がまたはの場合は=,fun/var状態を「not-function」に設定します。
  9. 次の入力文字に進み、2に戻ります。

もちろん、これは後処理されたコードでのみ機能します。まだ展開されていないさまざまな奇妙なことを行うマクロがある場合、すべての賭けは無効になります。

于 2012-11-26T21:20:14.773 に答える
0

最善の策は、宣言に関連するC文法の部分を抽出し、そのパーサーまたはその短縮バージョンを作成することです。同様に、関数本体の文法も同様の方法で省略して、スキップできるようにする必要があります。

これにより、宣言に対して比較的信頼できるパーサーが生成される可能性があります。

信頼できるC文法を手に入れることができない可能性が高いのは残念です。ANSI規格にあるものは、コンパイラが実際に使用するものではありません。すべてのベンダーは、コンパイラーに優れた機能と複雑な機能を追加しています(たとえば、MS Cのdeclspecsなど)。

プリプロセッサが実行されたという仮定は興味深いものです。プリプロセッサ構成はどこで入手しますか?(たとえば、コンパイラコマンドラインは、パス、プラグマ設定などを定義します)?各開発環境はプリプロセッサの条件を設定するさまざまな方法を定義しているため、これは見た目よりも困難です。

時折発生するエラーを受け入れる場合は、重要なクライアントのコードでミスを犯す頻度を法として、ヒューリスティックが有効な候補になります。これは、プリプロセッサの問題を完全に回避して、未処理のコードを処理できることも意味します。

于 2012-11-26T22:00:09.147 に答える