このようなタイプのエラーは、タイプチェック中または入力の解析中に生成されますか?どのタイプでエラーに対処する必要がありますか?
4 に答える
私の見方では、これはセマンティックエラーです。これは、以前にバインドしていない識別子を使用している場合でも、言語が正常に解析されるためです。つまり、構文解析では、プログラムの整形式性のみがチェックされます。セマンティック分析は、プログラムが有効な意味を持っていることを実際にチェックします。たとえば、バインディング、スコーピング、タイピングなどです。@pstが言ったように、解析中にスコープチェックを行うことができますが、これは実装の詳細です。AFAIKの古いコンパイラは、時間とスペースを節約するためにこれを行っていましたが、今日、パフォーマンスやメモリに厳しい制約がない場合、このようなアプローチには疑問があります。
プログラムは言語文法に準拠しているため、構文的に正しいです。言語文法には、「識別子を宣言する必要があります」のようなステートメントは含まれていません。実際、そうする方法はありません。これらの線に沿って2レベルの文法を構築する試みは、Algol-68プロジェクトでは見事に失敗しました。私の知る限り、それは試みられていません。
それぞれの意味は、もしあれば、意味論的な問題です。Frank deRemerは、このような問題を「静的セマンティクス」と呼びました。
私の意見では、これは厳密には構文エラーではなく、セマンティックエラーでもありません。静的に型付けされ、コンパイルされた言語(CやC ++など)にこれを実装する場合、チェックをパーサーに入れず(パーサーはこの間違いを実際にチェックできないため)、コードジェネレーターにチェックを入れます(抽象構文ツリーをウォークし、それをアセンブリコードに変換するコンパイラの部分)。したがって、私の意見では、これは構文エラーとセマンティックエラーの間にあります。これは構文関連のエラーであり、コードに対してセマンティック分析を実行することによってのみ確認できます。
ただし、ASTが直接実行される(バイトコードへのコンパイルなしで、JITなしで)プリミティブスクリプト言語を検討する場合、ASTをウォークし、宣言されていない変数を見つけるのは、エバリュエーター/エグゼキューター関数自体です-この場合、ランタイムエラー。違いは、言語がスクリプトまたはコンパイルされたものである場合、プログラムライフサイクル(コンパイル時間とランタイム)のさまざまな部分にある「AST_walk()」ルーチンの間にあります。
識別子を宣言する必要のある言語(および多くの言語)の場合、宣言されていない識別子を持つプログラムは形式が正しくないため、宣言が欠落していることは明らかに構文エラーです。
これに対処する通常の方法は、シンボルに関する情報をシンボルテーブルに組み込んで、解析でこの情報を使用できるようにすることです。
識別子の種類が解析にどのように影響するかの例を次に示します。
C / C ++
古典的なケース:
(a)-b;
に応じてa
、それはキャストまたは減算のいずれかです。
#include <stdio.h>
#if TYPEDEF
typedef double a;
#else
double a = 3.0;
#endif
int main() {
int b = 3;
printf("%g\n", (a)-b);
return 0;
}
したがって、a
まったく宣言されていない場合、コンパイラはプログラムを構文的に不正な形式として拒否する必要があります(これは、まさに標準で使用されている単語です)。
XML
これは簡単です:
<block>Hello, world</blob>
これは不正な形式のXMLですが、CFGでは検出できません。(それでも、すべてのXMLパーサーは不正な形式として正しく拒否します。)HTML / SGMLの場合、明確に定義された状況で終了タグが省略される可能性がありますが、解析は複雑ですが、それでも決定論的です。繰り返しになりますが、タグの正確な宣言によって有効な入力の解析が決定され、宣言に応じて異なる解析を行う入力を簡単に思い付くことができます。
英語
OK、プログラミング言語ではありません。他にもプログラミング言語の例がたくさんありますが、これが他の直感を引き起こす可能性があると思いました。
文法的に正しい2つの文を考えてみましょう。
The sheep is in the meadow.
The sheep are in the meadow.
さて、どうですか:
The cow is in the meadow.
(*) The cow are in the meadow.
2番目の文は、あいまいですが(名詞または動詞が間違っていますか?)、理解できますが、文法的に正しくありません。しかし、それ(および他の同様の例)を知るためには、それsheep
がマークされていない複数形を持っていることを知る必要があります。確かに、多くの動物はマークされていない複数形を持っているので、私は次のすべてを文法的に認識しています。
The caribou are in the meadow.
The antelope are in the meadow.
The buffalo are in the meadow.
しかし、絶対にそうではありません:
(*) The mouse are in the meadow.
(*) The bird are in the meadow.
等
構文アナライザーは文脈自由文法パーサーを使用するため、構文分析は文脈自由文法の構文解析に制限されるという一般的な誤解があるようです。これは単に真実ではありません。
C(およびファミリ)の場合、構文アナライザはシンボルテーブルを使用して解析を支援します。XMLの場合はタグスタックを使用し、一般化SGML(HTMLを含む)の場合はタグ宣言も使用します。したがって、全体として考えられる構文アナライザーは、分析の一部にすぎないCFGよりも強力です。
特定のプログラムが構文解析に合格したという事実は、それが意味的に正しいことを意味するものではありません。たとえば、構文アナライザーa
は、正しく解析するために型であるかどうかを知る必要がありますが、型で(a)-b
ある場合はキャストが実際に可能であるかどうかを知る必要はありません。変数の場合は減算されます。これらの検証は、解析ツリーが構築された後の型分析中に発生する可能性がありますが、それでもコンパイル時のエラーです。a
a
b
a