私たちのCフロントエンドは、プリプロセッサ要素を含むコードを解析できます。これはかなりの程度まで実行でき、それでも使用可能なASTを構築できます。(はい、解析ツリーには正確なファイル/行/列番号情報があります)。
ほとんどのコードを処理できるようにするいくつかの制限があります。これらのいくつかのケースでは、処理できません。多くの場合、同等のコードを提供するソースファイルへの小さな簡単な変更で問題が解決します。
規則と制限の大まかなセットは次のとおりです。
- #includesと#definesは、宣言またはステートメントが発生する可能性がある場所であればどこでも発生する可能性がありますが、ステートメントの途中では発生しません。これらが問題を引き起こすことはめったにありません。
- マクロ呼び出しは、関数呼び出しが式で発生する場合に発生する可能性があります。または、ステートメントの代わりにセミコロンなしで表示される可能性があります。整形式でないチャンクにまたがるマクロ呼び出しは適切に処理されません(誰もが驚いていますか?)。後者は時折発生しますが、まれではなく、手動で修正する必要があります。OPの「j(v、oid)*」の例には問題がありますが、これはコードでは非常にまれです。
- #if ... #endifは、主要な言語の概念(非終端記号)(定数、式、ステートメント、宣言、関数)またはそのようなエンティティのシーケンス、または特定の整形式ではないが一般的に発生するイディオム(ifなど)をラップする必要があります。 (exp){。条件文の各アームには、他のアームと同じ種類の構文構造が含まれている必要があります。#悪い種類のコメントとして使用されるランダムなテキストを折り返すと問題が発生しますが、実際のコメントを作成することでソースで簡単に修正できます。これらの条件が満たされない場合は、多くの場合、#if #elsif #else #endいくつかのトークンを移動して、元のソースコードを変更する必要があります。
私たちの経験では、これらの問題を回避するために、数時間で50,000行のコードベースを修正できます。それは面倒に思えますが(そしてそれはそうです)、代替手段はソースコードをまったく解析できないことです。これは面倒よりもはるかに悪いことです。
また、単なるパーサー以上のものが必要です。解析ツリーの取得に成功した後に何が起こるかを知るには、 「解析後の生活」を参照してください。宣言が埋め込まれているプリプロセッサコンテキストで宣言が記録されるシンボルテーブルを構築するためにいくつかの追加作業を行い、型チェックにプリプロセッサ条件を含めることができるようにしました。