私は過去にさまざまなプロジェクト、通常は翻訳者(EDAアプリにストリーミングされるEDIFのサブセットなど)にLexとyacc(より一般的にはbison)を使用しました。さらに、数十年前のLex/yacc文法に基づいたコードをサポートする必要がありました。私は専門家ではありませんが、ツールの使い方を知っています。
私は過去にさまざまなフォーラムでAntlrについて肯定的なコメントを見てきましたが、何が欠けているのか興味があります。したがって、両方を使用した場合は、Antlrの改善点または改善点を教えてください。私の現在の制約は、C++ショップで働いていることです。出荷する製品にはJavaが含まれないため、結果のパーサーはそのルールに従う必要があります。
大きな違いの1つは、ANTLRがLL(*)パーサーを生成するのに対して、YACCとBisonはどちらもLALRであるパーサーを生成することです。これは多くのアプリケーションにとって重要な違いであり、最も明白な演算子は次のとおりです。
expr ::= expr '+' expr
| expr '-' expr
| '(' expr ')'
| NUM ;
ANTLRは、この文法をそのままではまったく処理できません。 ANTLR(またはその他のLLパーサージェネレーター)を使用するには、この文法を左再帰ではないものに変換する必要があります。ただし、Bisonはこの形式の文法には問題ありません。 「+」と「-」を左結合演算子として宣言する必要がありますが、左再帰には厳密には必要ありません。より良い例はディスパッチです:
expr ::= expr '.' ID '(' actuals ')' ;
actuals ::= actuals ',' expr | expr ;
expr
ルールとactuals
ルールの両方が左再帰的であることに注意してください。これにより、複数のレジスタと不要なスピルの必要性を回避するため、コード生成の時間になると、はるかに効率的なASTが生成されます)。
個人的な好みの観点から、LALR文法は構築とデバッグがはるかに簡単だと思います。欠点は、shift-reduceや(恐ろしい)reduce-reduceのようなやや不可解なエラーに対処する必要があることです。これらはパーソンを生成するときにBisonがキャッチするエラーであるため、エンドユーザーエクスペリエンスには影響しませんが、開発プロセスを少し面白くすることができます。 ANTLRは一般的に、まさにこの理由からYACC/Bisonよりも使いやすいと考えられています。
YACC/BisonとANTLRの最も大きな違いは、これらのツールが処理できる文法の種類です。 YACC/BisonはLALR文法を処理し、ANTLRはLL文法を処理します。
多くの場合、長い間LALR文法を扱ってきた人は、LL文法を扱うのがより難しく、逆もまた同様です。それは、文法やツールが本質的に扱いにくいことを意味するものではありません。どのツールが使いやすいと思うかは、ほとんどが文法の種類に精通していることになります。
利点に関しては、LALR文法がLL文法よりも有利な側面があり、LL文法がLALR文法よりも有利な側面があります。
YACC/Bisonは、テーブル駆動のパーサーを生成します。つまり、「処理ロジック」は、パーサーのコードではなく、パーサープログラムのデータに含まれます。メリットは、非常に複雑な言語のパーサーでさえ、コードのフットプリントが比較的小さいことです。これは、ハードウェアが非常に限られていた1960年代と1970年代に、より重要でした。テーブル駆動のパーサージェネレーターはこの時代に遡り、小さなコードフットプリントが当時の主な要件でした。
ANTLRは、再帰降下パーサーを生成します。これは、構文の各生成規則がパーサーのコードの関数によって表されるため、「処理ロジック」がパーサーのコードに含まれることを意味します。利点は、コードを読むことでパーサーが何をしているのかを理解しやすくなることです。また、再帰降下パーサーは通常、テーブル駆動型パーサーよりも高速です。ただし、非常に複雑な言語の場合、コードのフットプリントは大きくなります。これは1960年代と1970年代の問題でした。当時、ハードウェアの制限により、たとえばPascalなどの比較的小さな言語のみがこの方法で実装されていました。
ANTLRで生成されたパーサーは通常、1万行以上のコードの近くにあります。手書きの再帰パーサーは、多くの場合同じ場所にあります。 WirthのOberonコンパイラはおそらくコード生成を含む約4000行のコードを備えた最もコンパクトなコンパイラですが、Oberonは約40のプロダクションルールしか持たない非常にコンパクトな言語です。
誰かがすでに指摘したように、ANTLRの大きなプラスは、ANTLRworksと呼ばれるグラフィカルなIDEツールです。完全な文法および言語設計ラボです。入力時に文法規則を視覚化し、コンフリクトが見つかった場合、コンフリクトの内容とその原因をグラフィカルに表示します。左再帰などのコンフリクトを自動的にリファクタリングして解決することもできます。あなたの言語と解析ツリーを構築し、ASTあなたのために、IDEでツリーをグラフィカルに表示します。これは多くの時間の作業を節約できるため、非常に大きな利点です。コーディングを開始する前の言語設計で!LALR文法用のそのようなツールは見つかりませんでしたが、そのようなツールはないようです。
パーサーを生成するのではなく、それらを手動でコーディングしたい人にとっても、ANTLRworksは言語設計/プロトタイプ作成のための優れたツールです。おそらくこのような最高のツールが利用可能です。残念ながら、LALRパーサーを構築したい場合、それは役に立ちません。単純にANTLRworksを利用するためにLALRからLLに切り替えることは価値があるかもしれませんが、一部の人にとっては、文法タイプの切り替えは非常に苦痛な経験になる可能性があります。つまり、YMMV。
ANTLRのいくつかの利点:
私の.02 $
ANTRLのもう1つの利点は、 [〜#〜] antlrworks [〜#〜] を使用できることです。ただし、他のジェネレーターにも同様のツールがあるため、これが厳密な利点であるとは言えません。同様に。
Bison/Flexのメモリ使用量は通常、1メガバイト程度です。 antlrとは対照的です-解析するファイル内のすべてのトークンに512バイトのメモリを使用すると仮定します。 400万のトークンがあり、32ビットシステムで仮想メモリが不足しています。
解析するファイルが大きい場合、antlrがメモリ不足になる可能性があるため、構成ファイルを解析するだけの場合は実行可能なソリューションになります。それ以外の場合、大量のデータを含むファイルを解析する場合は、Bisonを試してください。