プログラミング言語にパーサーを構築するとき、私が稼いだものと、どちらかを選択しなくなったものは何ですか?
LLとLRの構文解析を、いくつかの基準で比較します。
複雑さ
LLがここで勝ちます。 LLパーサーは簡単に手書きできます。実際、これは一般的に行われています。MicrosoftC#コンパイラは手書きの再帰降下パーサーです(ソース here 、Patrick Kristiansenのコメントを探してください-ブログ投稿も非常に興味深いものです)。
LR解析では、テキストを解析するのに、かなり直感に反する方法を使用します。それは機能しますが、それがどのように機能するかについて頭を抱えるのに少し時間がかかりました。したがって、このようなパーサーを手動で作成するのは困難です。多かれ少なかれ、LRパーサージェネレーターを実装することになります。
一般性
LRがここで勝ちます:すべてのLL言語はLR言語ですが、LL言語よりも多くのLR言語があります(LLパーサーで解析できる場合、言語はLL言語であり、解析できる場合、言語はLR言語です。 LRパーサー)。
LLは、ほぼすべてのプログラミング言語を実装するときにが気になる迷惑な点をいくつか持っています。概要については こちら を参照してください。
LR言語ではない明確な言語がありますが、それらは非常にまれです。そのような言語に出会うことはほとんどありません。ただし、LALRにはいくつかの問題があります。
LALRは、多かれ少なかれ、LRパーサーがテーブルを小さくするためのハックです。 LRパーサーのテーブルは、通常、非常に大きくなる可能性があります。 LALRパーサーは、小さなテーブルと引き換えにすべてのLR言語を解析する機能を放棄します。ほとんどのLRパーサーは実際にLALRを使用します(ただし、秘密裏にではありませんが、通常、実装するものを正確に見つけることができます)。
LALRは、shift-reduceとreduce-reduceの競合について不平を言う可能性があります。これはテーブルハックが原因です。ほとんどのエントリが空であるため機能しますが、エントリが空でない場合は競合が発生します。これらの種類のエラーは自然なものではなく、理解するのが困難であり、修正は通常かなり奇妙です。
コンパイラエラーとエラー回復
LLがここで勝ちます。 LL解析では、特に手書きのパーサーでは、通常、有用なコンパイラエラーが発生するのは非常に簡単です。あなたは次に何を期待しているのかを知っているので、それが現れない場合は、通常、何がうまくいかず、最も敏感なエラーが何であるかを知っています。
また、LL解析では、エラー回復がはるかに簡単です。入力が正しく解析されない場合は、少し前にスキップして、残りの入力が正しく解析されるかどうかを確認できます。たとえば、一部のプログラミングステートメントの形式が正しくない場合、先にスキップして次のステートメントを解析できるため、複数のエラーをキャッチできます。
LRパーサーを使用すると、これははるかに困難になります。文法を拡張して、誤った入力を受け入れ、問題が発生した領域にエラーを出力するようにできますが、通常、これはかなり困難です。非LR(または非LALR)文法で終わる可能性も高くなります。
速度
速度は、入力を解析する方法(LLまたはLR)の実際の問題ではなく、結果のコードの品質とテーブルの使用(LLとLRの両方にテーブルを使用できます)の問題です。したがって、LLとLRはこの点で同等です。
リンク
ここ は、LLとLRを対比するサイトへのリンクです。下部近くのセクションを探します。
ここ 違いについての会話を見つけることができます。そこで批判的な意見を批判的に見ることは悪い考えではありません。 聖なる戦争 が少し続いています。
詳細については、 here と here はパーサーに関する私自身の2つの投稿ですが、厳密にはLLとLRの対比に関するものではありません。