C
言語標準で定義されている言語には、プリプロセッサが含まれています。以下は、構文的に正しい C プログラムです。
#define START int main(
#define MIDDLE ){
START int argc, char** argv MIDDLE return 0; }
文法自体があいまいであり、言語。その CFG は興味深く、さらに便利ですが、C ではありません。
実際、標準のプロダクションでは、構文的に正しいソース ファイルとは何かを説明しようとさえしていません。彼らは次のように説明しています。
ソースファイルの字句構造 (前処理後の有効なトークンの字句構造とともに)。
個々のプリプロセッサ ディレクティブの文法
後処理言語の文法のスーパーセット。 と の他の用途を区別する他のメカニズム、および と の他の用途を区別するメカニズムに依存してtypedef-name
いidentifier
ます。constant-expression
conditional-expression
ポイント3の問題は「構文」ではなく「意味」であると主張する人がたくさんいます。ただし、C の性質 (およびその従兄弟である C++ の性質はさらにそうです) は、プログラムの解析から「セマンティクス」を解きほぐすことが不可能であることです。たとえば、次は構文的に正しい C プログラムです。
#define base 7
#if base * 2 < 10
&one ?= two*}}
#endif
int main(void){ return 0; }
したがって、「CFG によって定義された C 言語の構文である」ということを本当に意味するのであれば、答えはノーでなければなりません。「C 言語でのプログラムの翻訳の中間生成物である文字列を表す言語の構文を定義する CFG はありますか」という意味であれば、答えはイエスである可能性があります。 aconstant-expression
と aが何であるかを正確にする必要性は、typedef-name
他の言語にはない方法で、構文を必然的に文脈依存にする必要があります。