Antlrの利点(対して、lex / yacc / bison)[終了]


143

過去には、さまざまなプロジェクト、通常はトランスレータ(EDAアプリにストリーミングされるEDIFのサブセットなど)にlexとyacc(通常はbison)を使用しました。さらに、何十年も前のlex / yacc文法に基づくコードをサポートする必要がありました。私は専門家ではありませんが、ツールの使い方を知っています。

私は過去にさまざまなフォーラムでAntlrについて肯定的なコメントを見てきましたが、何が欠けているのか知りたいです。両方を使用したことがある場合は、Antlrの優れている点と進んだ点を教えてください。私の現在の制約は、C ++ショップで作業することであり、出荷する製品にはJavaが含まれていないため、結果のパーサーはそのルールに従う必要があります。

回答:


145

更新/警告:この回答は古くなっている可能性があります!


主な違いの1つは、ANTLRがLL(*)パーサーを生成するのに対して、YACCとBisonはどちらもLALRであるパー​​サーを生成することです。これは多くのアプリケーションにとって重要な違いであり、最も明白なのは演算子です。

expr ::= expr '+' expr
       | expr '-' expr
       | '(' expr ')'
       | NUM ;

ANTLRは、この文法をそのまま処理することはまったくできません。ANTLR(またはその他のLLパーサージェネレーター)を使用するには、この文法を左再帰的でないものに変換する必要があります。ただし、バイソンはこの形式の文法については問題ありません。'+'と '-'を左結合演算子として宣言する必要がありますが、左再帰では厳密には必要ありません。より良い例はディスパッチでしょう:

expr ::= expr '.' ID '(' actuals ')' ;

actuals ::= actuals ',' expr | expr ;

expractualsルールの両方が左再帰的であることに注意してください。これにより、複数のレジスターの必要性と不要なスピルが回避されるため、コード生成の時期になると、はるかに効率的なASTが生成されます(左寄りのツリーは折りたたむことができますが、右寄りのツリーは折りたたむことができません)。

個人的な好みの点では、LALRの文法は構築とデバッグがはるかに簡単だと思います。欠点は、shift-reduceや(恐ろしい)reduce-reduceなどのやや不可解なエラーに対処する必要があることです。これらは、パーサーの生成時にBisonがキャッチするエラーであるため、エンドユーザーエクスペリエンスには影響しませんが、開発プロセスをもう少し興味深いものにすることができます。ANTLRは、まさにこの理由から、YACC / Bisonよりも使いやすいと一般に考えられています。


2
したがって、Antlrのあなたの知覚における大きな、おそらく単一の利点は、構築フェーズ中にsrやrrなどのエラーが生成されなくなることですか?私は...私はそれを試してみるよ期待していますが、おそらく私が知っていることにこだわってしまいます
ドン・ウェイクフィールド

1
ええ、それだけです。:-)私は、ANTLRがバイソンよりも簡単であるという一般的な意見にもあまり同意しません。そのため、私はあなたの決定に同意します。
Daniel Spiewak、2008年

2
'actuals'ルールには、単純な 'expr'が実際であることを示すために2番目のルールが必要ですか?そうでなければ、素晴らしい説明。
ジョナサンレフラー

8
私は最近見つかった別のコメントには、十年古いものの、合理的な観察になり出力をcompilers.iecc.com/comparch/article/98-11-040 ANTLR / PCCTSは文法の書き込みがより困難にLLいる」、しかし: YaccはLALRです(もちろんご存じのとおり)ことで文法の記述が容易になりますが、生成されたコードは象形文字でもあります。」
Don Wakefield、

72
ANTLRの次のリリースv3.4の左再帰の即時サポートを完了しました。LR式ルールおよびC宣言子ルールのような同様のものを処理します。:)
Terence Parr、

117

YACC / BisonとANTLRの最も重要な違いは、これらのツールが処理できる文法のタイプです。YACC / BisonはLALR文法を処理し、ANTLRはLL文法を処理します。

多くの場合、長い間LALR文法を使用してきた人は、LL文法を使用するのがより難しく、逆もまた同様です。これは、文法やツールが本来より扱いにくいという意味ではありません。どちらのツールが使いやすいかは、主に文法の種類に精通していることになります。

利点に関する限り、LALR文法がLL文法よりも優れている側面もあれば、LL文法がLALR文法よりも優れている側面もあります。

YACC / Bisonは、テーブル駆動のパーサーを生成します。つまり、「処理ロジック」は、パーサーのコードではなく、パーサープログラムのデータに含まれています。見返りは、非常に複雑な言語のパーサーでさえ、コードフットプリントが比較的小さいことです。これは、ハードウェアが非常に限られた1960年代と1970年代に、より重要でした。テーブル駆動のパーサージェネレーターはこの時代にさかのぼり、小さなコードフットプリントが当時の主な要件でした。

ANTLRは再帰下降パーサーを生成します。つまり、文法の各生成規則はパーサーのコード内の関数によって表されるため、「処理ロジック」がパーサーのコードに含まれています。見返りは、パーサーがコードを読むことで何をしているかを理解するのが簡単になることです。また、再帰的降下パーサーは通常、テーブル駆動のパーサーよりも高速です。ただし、非常に複雑な言語の場合、コードフットプリントは大きくなります。これは1960年代と1970年代の問題でした。当時、ハードウェアの制限により、Pascalなどの比較的小さな言語のみがこの方法で実装されていました。

ANTLRで生成されたパーサーは、通常、10.000行以上のコードにあります。手書きの再帰降下パーサーは、多くの場合同じ球場にあります。WirthのOberonコンパイラーは、おそらくコード生成を含めて約4000行のコードを持つ最もコンパクトなコンパイラーですが、Oberonは約40のプロダクションルールしか持たない非常にコンパクトな言語です。

誰かがすでに指摘したように、ANTLRの大きな利点は、ANTLRworksと呼ばれるグラフィカルIDEツールです。それは完全な文法と言語デザインの研究室です。入力時に文法規則を視覚化し、矛盾が見つかった場合は、矛盾の内容と原因をグラフィカルに表示します。左再帰などの競合を自動的にリファクタリングして解決することもできます。競合のない文法が得られたら、ANTLRworksで言語の入力ファイルを解析し、解析ツリーとASTを構築して、IDEでツリーをグラフィカルに表示できます。作業時間を大幅に節約できるため、これは非常に大きな利点です。コーディングを開始する前に、言語設計に概念的なエラーが見つかります。LALR文法のためのそのようなツールを見つけていません。そのようなツールはないようです。

パーサーを生成せずに手動でコーディングしたい人にとっても、ANTLRworksは言語設計/プロトタイピングのための優れたツールです。このようなツールとしては、おそらく最高のものでしょう。残念ながら、LALRパーサーを作成する場合、これは役に立ちません。単にANTLRworksを利用するためにLALRからLLに切り替えることは価値があるかもしれませんが、一部の人にとっては、文法タイプを切り替えることは非常に苦痛な体験になることがあります。つまり、YMMVです。


4
それは、人々がimediately理解になり、異なるメカニズムの後ろの歴史を説明しますので、それのように
zinking

35

ANTLRのいくつかの利点:

  • さまざまな言語でパーサーを出力できます-生成されたパーサーを実行するためにJavaは必要ありません。
  • 素晴らしいGUIにより、文法のデバッグが簡単になります(たとえば、生成されたASTをGUIで確認できます。追加のツールは必要ありません)
  • 生成されたコードは実際には人間が読める形式であり(これはANTLRの目標の1つです)、LLパーサーを生成するという事実はこの点で確かに役立ちます。
  • ((f)lexの正規表現とは対照的に)端末の定義もコンテキストフリーです-たとえば、適切に閉じられた括弧を含む端末の定義を許可します

私の.02 $


9

ANTRLのもう1つの利点は、ANTLRWORKSを使用できることです。ただし、他のジェネレーターにも同様のツールがあるため、これが厳密な利点であるとは言えません。


9
  • BisonとFlexはメモリフットプリントが小さくなりますが、グラフィカルIDEはありません。
  • antlrはより多くのメモリを使用しますが、グラフィカルIDEであるantlrworksがあります。

バイソン/フレックスのメモリ使用量は、通常1 mバイト程度です。それをantlrと比較してください-解析したいファイルのすべてのトークンに対して512バイトのメモリを使用すると仮定します。400万のトークンがあり、32ビットシステムの仮想メモリが不足しています。

解析したいファイルが大きい場合、antlrがメモリ不足になる可能性があるため、構成ファイルのみを解析したい場合は、実行可能な解決策になります。それ以外の場合で、大量のデータを含むファイルを解析する場合は、Bisonを試してください。


7
私は興味がある。トークンごとに512バイトのメモリの消費を説明するドキュメントを参照できますか?その議論を見た覚えはありません。私のGoogleキーワードの選択も、満足感を与えていません...
Don Wakefield

2
パーサーの生成中にパーサージェネレーターのメモリフットプリントについて話しているのか、またはソース言語の入力を解析するときに生成されたパーサーのメモリフットプリントについて話しているのですか?文法に含まれる何百万ものトークンはまったく正気ではないでしょう。もしあなたが真剣にそのような考えを売ろうとしたなら、あなたは精神病院に閉じ込められるべきです。パーサー自体の入力ファイルについては、トークンの数が非常に多い場合がありますが、ほとんどの言語はモジュール化されているため、単一のファイルで入力全体を解析するのではなく、個々のモジュールは小さくなります。
trijezdci
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.