ほとんどすべてのコンパイラは、エラーメッセージとともに行番号を返します。コンパイラの設計の観点から、コンパイラは次のさまざまなフェーズの観点から行番号メッセージをどのように処理するのでしょうか。ありがとう。
- スキャナー
- パーサー
- ASTデータ構造
- コード生成
加えて:
- 実行時環境
- 機械通訳
ほとんどすべてのコンパイラは、エラーメッセージとともに行番号を返します。コンパイラの設計の観点から、コンパイラは次のさまざまなフェーズの観点から行番号メッセージをどのように処理するのでしょうか。ありがとう。
加えて:
クラス割り当て用にかなり単純なコンパイラを実装しました。これはPascalのサブセットでしたが、他にもいくつかの制限がありました。
コンパイラは、ある言語を別の言語に翻訳するツールです。これは、エラーチェックを実行してから、出力コードを生成することによって行われます(可能な場合)。通常、コンパイラのパイプラインは、おおよそ次のものと同等です。
入力コード->字句アナライザー(スキャナー)->構文アナライザー->セマンティックアナライザー->コードジェネレーター->出力コード*
私の言語は単純だったので、たくさんの仮定を立てることができました。たとえば、命令は1行だけになります。私のレクサーは正規表現を使用して、存在してはならない文字をチェックしました。たとえば、「数字、文字、「(」、「、」、「。」などではない文字」など)ファイルを文字列のリストに読み込みました。各文字列は次のとおりです。次の行なので、行をスキャンしてエラーを見つけた場合は、行の番号であるインデックス+1を返します。
たとえば「変数名が文字で始まる場合」をチェックする構文アナライザー(パーサー)では、アルゴリズムは同様でした。
パーサーを拡張したときに、エラーが発生した場合にトークンを返すために、コード内の行にトークンを関連付けました。
最新のコンパイラがこの問題をどのように解決するかはわかりませんが、1つのASTが数行にある可能性があることを念頭に置いて、これもASTと行番号のある種の関連付けであると推測できます(言語によって異なります)。
コード生成を使用すると、コンパイラはコードが(彼らの知る限り)正しいことを認識し、戻りエラーはコードに関するものではなく、コンパイラまたはプロセスに問題があることを認識します(バグ、メモリ不足、書き込みできません場所など)。
ランタイム環境とマシンインタープリターにもJITなどのコンパイラーが含まれている可能性がありますが、エラーメッセージが返されるのは通常、コードではなく、コンパイラーまたはランタイムのバグを示しています。
*これは3パスの非常に単純なモデルであることに注意してください。最近のコンパイラにはもっとたくさんのがあります。
編集:ASTには、行番号とエラーのファイル(ノードごと)を示すフィールドがあることがわかりました。
ほとんどのレクサージェネレーターとパーサージェネレーターは、マッチングエラーが発生したときに呼び出されるエラー報告メソッドを持つコードを生成します。そのメソッドをオーバーライドして、好きなことをすることができます。
前述のように、行と文字番号を、レクサー仕様の識別子または文字列/文字/整数/ブールリテラルに関連付けるのが一般的です。通常、レクサーはyyline()
これを行うためのメソッドを利用可能にします。レクサーに生のトークン(文字列など)の値を返す代わりに、文字列の値、文字、行番号を含むオブジェクトを返すようにします。たとえば、このレクサーの仕様をざっと見てみましょう。
private Symbol symbol(int type) {
return new Symbol(type, yyline, yycolumn);
}
パーサーは解析中にシンボルを受け取り、トークン値とともに位置情報を取得して、それをASTノードにプラグインする必要があります。その情報は、最終的にはシンボルテーブルに組み込まれるはずです。タイプ分析中、各リーフノードには位置情報がバインドされます。かなり良いエラー診断を提供するために必要なのはこれだけです。