私はウィキペディアで両方を読んでいて、LR(0)パーサーは存在しますが、LL(0)パーサーのようなものはないことに気づきました。
私が読んだことから、LL(k)/ LR(k)のkは、パーサーが見ることができる文字数を意味することを理解していますbeyond現在作業中の現在の文字。
だから私の質問は、LR(0)が存在するのに、なぜLL(0)パーサーのようなものがないのですか?
違いは、LR(k)とLL(k)のkの意味と関係があります。
LL(k)では、パーサーは、左端の派生をトレースするトップダウンの左から右への解析に関する情報を維持します。パーサーは、現在の非終端記号を繰り返し確認し、入力ストリームの次のkトークンを調べて、使用するプロダクションを決定することで機能します。その結果、LL(0)パーサーがある場合、パーサーは、現在の非終端記号のみに基づいて、使用するプロダクションを予測する必要があります。これは、各非終端記号に関連付けられた生成が1つしかない場合にのみ可能です。つまり、文法は、文字列を1つだけ生成するか、まったく生成しません(ループに入る)。したがって、数学的に明確に定義されていますが、LL(0)解析は実際には使用されません。
LR(k)では、パーサーはボトムアップで機能します。現在の「状態」とともにシンボルのスタックを維持し、shiftを実行するかどうかを継続的に決定します(別のシンボルを上にプッシュします)スタック)またはreduce(スタックからいくつかのシンボルをポップし、逆にプロダクションを適用します)。 LL(k)パーサーとLR(k)パーサーの主な違いの1つは、LR(k)パーサーが実行するアクションを決定する方法です。 LR(k)パーサーでは、先読みの次のkトークンと、パーサーの現在の状態の両方に基づいて、次に何をするかの決定が行われます。結果として、 LR(0)パーサーは、先読みトークンが表示されない場合でも、実行するアクションについてある程度インテリジェントな決定を行うことができます。これは、パーサーの現在の状態が、プロダクション内のどこにパーサーが何であるかに関する膨大な量の情報をエンコードできるためです。現実的には、入力の次のトークンとして表示されることを期待できます(パーサーがそれらのトークンを直接見ることができない場合でも)。
つまり、LL(0)は非常に弱いです。これは、パーサーが純粋に現在の非終端記号に基づいて決定を行う必要があるためです。つまり、使用されるプロダクションに基づいて、さまざまなアクションの1つを実行できません。 LR(0)パーサーは、その選択が内部状態に基づいているため、かなり強力です。内部状態は通常、パーサーが次に何をすべきかについて情報に基づいた決定を行うのに十分詳細です。
LR(0)が適度に強力であるのに対し、LL(0)が弱いもう1つの理由があります。 LL(0)パーサーでは、パーサーはどのプロダクションを実行するかを即座に決定する必要があります。つまり、パーサーはプロダクションを完全に盲目的に推測する必要があります。 LR(0)パーサーでは、パーサーは、削減する時期であると判断する前に、複数のシンボルをシフトできます。その結果、パーサーは、先読みなしで、文字列の構造を理解するのに十分な入力トークンを確認するまで、使用する削減についての決定を延期することができます。これは、LL(k)文法が自動的にLR(k)になるというより一般的な事実の特殊なケースです。
お役に立てれば!