私はこれまで、さまざまなプロジェクト、通常はトランスレータ(EDA アプリにストリーミングされる EDIF のサブセットなど)で lex と yacc(通常は bison)を使用してきました。さらに、数十年前に遡る lex/yacc 文法に基づくコードをサポートする必要がありました。そのため、私は専門家ではありませんが、ツールの使い方は知っています。
これまでさまざまなフォーラムで Antlr に関する肯定的なコメントを見てきましたが、私が見逃している点が何なのか気になっています。両方を使用したことがある方は、Antlr のどちらが優れているか、またはより先進的であるかを教えてください。現在の制約は、私が C++ ショップで働いており、出荷する製品に Java が含まれないため、結果として得られるパーサーはそのルールに従う必要があるということです。
ベストアンサー1
更新/警告: この回答は古くなっている可能性があります。
大きな違いの 1 つは、ANTLR は LL(*) パーサーを生成するのに対し、YACC と Bison はどちらも LALR パーサーを生成することです。これは多くのアプリケーションにとって重要な違いであり、最も顕著なのは演算子です。
expr ::= expr '+' expr
| expr '-' expr
| '(' expr ')'
| NUM ;
ANTLR は、この文法をそのままではまったく処理できません。ANTLR (または他の LL パーサー ジェネレーター) を使用するには、この文法を左再帰でないものに変換する必要があります。ただし、Bison はこの形式の文法で問題ありません。'+' と '-' を左結合演算子として宣言する必要がありますが、左再帰では厳密には必須ではありません。よりよい例は、dispatch です。
expr ::= expr '.' ID '(' actuals ')' ;
actuals ::= actuals ',' expr | expr ;
expr
と の規則は両方ともactuals
左再帰的であることに注目してください。これにより、複数のレジスタと不要なスピル (左傾斜ツリーは折りたたむことができますが、右傾斜ツリーは折りたたむことができません) の必要性が回避されるため、コード生成時にはるかに効率的な AST が生成されます。
個人的な好みとしては、LALR 文法の方が構築やデバッグがはるかに簡単だと思います。欠点は、shift-reduce や (恐ろしい) Reduce-reduce などのやや不可解なエラーに対処しなければならないことです。これらは、パーサーを生成するときに Bison がキャッチするエラーなので、エンドユーザーのエクスペリエンスには影響しませんが、開発プロセスを少し面白くすることができます。ANTLR は、まさにこの理由から、YACC/Bison よりも使いやすいと一般に考えられています。