スコープをスキャンすることから始めます。ファイルを処理する際に、左中括弧 { と右中括弧 } を数えて、現在のスコープを把握する必要があります。また、ファイルをスキャンするときに // と /* ... */ を解析する必要があります。 、そのため、何かが実際のコードではなくコメントに含まれていることを知ることができます。#if もありますが、これらを解釈する方法を知るには、コードをコンパイルする必要があります。
次に、スコープの開き中かっこの直前のテキストを解析して、それらが何であるかを判断する必要があります。関数は、グローバル スコープ、クラス スコープ、または名前空間スコープにある可能性があるため、名前空間とクラスを解析して、対象のスコープのタイプを識別できる必要があります。通常は、かなり単純な構文解析で問題を解決できます (ほとんどのプログラマーは同様のスタイルを使用します。たとえば、「class Fred」とその開き中括弧の間に空白行を入れることは一般的ではありません。しかし、「class Fred {」と書く場合があります。 'template class __DECLSPEC MYWEIRDMACRO Fred {' のように、余分なジャンクを行に追加する可能性もあります。ただし、非常に単純な「行には、両側に空白がある「クラス」という単語が含まれていますか?ほとんどの場合に機能するヒューリスティック。
OK、名前空間とクラスの内部にいることがわかり、新しいオープン スコープが見つかりました。メソッドですか?
メソッドの主な識別機能は次のとおりです。
- リターンタイプ。これは任意の文字列であり、多くのトークン ("__DLLEXPORT const unsigned myInt32typedef * &") である可能性があります。プロジェクト全体をコンパイルしない限り、チャンスはありません。
- 関数名。単一のトークン (ただし、"operator=" などに注意してください)
- ゼロ個以上のパラメーターまたは「空」を含む括弧のペア。これが一番の手がかりです。
- 関数宣言には、多くのスコープの前にある特定の予約語 (enum、class、struct など) は含まれません。また、つまずいてはならない予約語 (template、const など) を使用する場合があります。
したがって、空白行または ; で終わる行を検索できます。前のステートメント/スコープの終わりを示す { または }。次に、そのポイントとスコープの左中括弧の間のすべてのテキストを取得します。次に、トークンのリストを抽出し、パラメーター リストのブラケットとの一致を試みます。トークンが予約語 (enum、struct、class など) でないことを確認します。
これにより、メソッドがあるという「合理的な信頼度」が得られます。かなり高い精度を得るために多くの解析は必要ありません。「パーサー」を混乱させるすべての特殊なケースを見つけるのに多くの時間を費やすことができますが、合理的に一貫性のあるコードベース (つまり、自社のコードのみ) で作業している場合は、おそらくすべてのパーサーを特定できるでしょう。メソッドをコードに簡単に組み込むことができます。