背景情報(5月スキップ):文法を設計する必要があるユニで設定されたタスクに取り組んでいます提供されているDSLの場合。文法はBNFまたはEBNFでなければなりません。他にも、文法の語彙ルールと構文解析ルールについて評価されています。たとえば、ルールが言語サブセットに適しているかどうか、これらのルールがどれほど包括的であるか、ルールがどれほど明確であるかなどです。
私が理解していないのは、これらのルールがBNFで定義された文法でカバーされているかどうかです(これは私たちにとって新しいトピックです)。
質問:BNFまたはEBNFのいずれかで定義されている特定の言語の文法に、の規則が含まれていますか/語彙分析および/または解析? (またはこれらは他の場所で指定する必要がありますか?)
また、何が字句規則と考えられますか?そして、何が解析ルールと考えられますか?
はい、BNF文法には字句解析と構文解析に必要なすべてのルールが含まれています。 2つの違いは少しあいまいです。 [〜#〜] ebnf [〜#〜] のlexicalルールの良い例は次のようになります:
number = [ "-" ], digit, { digit } ;
digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
通常、レクサーは比較的単純なコードを使用して実装できます。次のスペースの文字列を検索し、結果がオプションの「-」で始まり、その後に少なくとも1桁が含まれ、その後にのみ桁が含まれるかどうかを確認できます。レクサーはほとんどの場合別のステップでしたが、最近はパーサーと一緒にまとめられています。したがって、あいまいさ。
parserルールは、次の加算式のように、number
非終端を使用して何かを大きくします。
add = number, "+", number
同じファイルで混同されていても、教授は「レクサー」ルールと「パーサー」ルールの明確な違いを見たいと思うでしょう。たとえば、これを行わない:
add = {"0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" }, "+",
{"0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" }
エラーが発生しやすいだけでなく、読み取りや実装が困難です。
字句解析の文法は通常、正規表現を使用して指定されます(特に大学タイプのプロジェクトの場合)。 通常の言語を受け入れます。
パーサーは通常、コンテキストフリー言語を受け入れます。これはBNFを介して指定できます。
パーサーとスキャナー(または字句アナライザー)の違いはやや不自然ですが、パーサーの作成が簡単になります。
あなたの質問への答えは確かにあります。解析ルールと字句解析ルールの両方を、EBNF(実際には、BNFのよりコンパクトな形式です)を使用して指定できます。ただし、プロダクション品質のコンパイラでは、答えの次の部分は異なります。
ほとんどの言語には、文脈に依存しない文法があり、先読みとバックトラッキングに関する一連のルールに準拠しています。最も一般的な文法はLL(1)とLR(1)です。 LR(1)は通常YACCなどのパーサージェネレーターを意味しますが、LL(1)文法は、多くの場合、手作業でコーディングされた単純な再帰降下文法を許可します。文法のこの部分は、トークン(端末)まで続きますが、それより低くはありません。
シンボルは通常、演算子文法などのさらに単純な文法を使用して個別に定義されます。 [ここで説明するよりも適切な定義については、これらの用語を調べることができます。]これらのシンボルを読み取るレクサーは、通常、コンパイラーのパフォーマンスの大部分に関与するため、私の経験では、常に手動でコーディングされています。 Lexは不格好(Cのみ)で、正規表現が遅すぎます。
重要なのは、構文解析ルールがパーサーに必要なテクノロジーを駆動し、字句化ルールが字句解析プログラムに対応することを理解することです。それらの間の明確な違いは、それらがトークン(端末)の使用に適用されるか、それらの構築に適用されるかです。
これはあなたの学問の進歩を助けることはできませんが、おもちゃのプロジェクトを超えて行く場合は重要です。