プログラミング言語用のパーサーを構築するとき、私が稼いだものと、どちらを選んで失ったものですか?
プログラミング言語用のパーサーを構築するとき、私が稼いだものと、どちらを選んで失ったものですか?
回答:
LL解析とLR解析をいくつかの基準で比較します。
複雑
ここでLLが勝ちます。LLパーサーを簡単に手書きできます。実際、これは一般的に行われます。MicrosoftC#コンパイラは手書きの再帰降下パーサーです(ソースはこちら、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を対比したサイトへのリンクです。下部近くのセクションを探します。
ここでは、違いに関する会話を見つけることができます。そこに表明された意見を批判的に見ることは悪い考えではありませんが、そこでは少し聖なる戦争が起こっています。