文法のあるファイルからC++でパーサーを作成する最良の方法は何ですか?
6 に答える
それは文法に大きく依存します。私は再帰下降パーサーが好きです。これは通常、手書きで書かれています(ただし、文法の説明から生成することは可能です)。
パーサジェネレータを使用する場合は、ByaccとAntlrの2つの適切な選択肢があります。yaccと(合理的に)互換性のあるものが必要な場合は、Byaccが(はるかに)最良の選択です。yaccと互換性のあるものを使用することを好む既存のコードも経験もない状態で最初から始めている場合は、Antlrがほぼ間違いなく最善の策です。
言及されているので、バイソンについても少しお話します。私はそれがそうである疫病のようにバイソンを避けたいと思います。「1つを捨てる計画を立てる」というブルックスのアドバイスはここに当てはまります。Robert Corbett(Byaccの作者)は、パーサジェネレータでの最初の試みとしてBisonを作成しました。残念ながら、彼はそれを捨てるのではなく、GNUに渡しました。技術的な卓越性を打ち負かすマーケティングの典型的なケースでは、バイソンは広く使用されています(そして、よく知らない人にも推奨されています)が、バイソンは比較的あいまいなままです。
編集:私はそれをするのが嫌いですが、それも言及されているので、Boost.spiritについてもコメントします。これはテンプレートメタプログラミングの最もクールな例かもしれませんが、それを真剣に使用しようとしないことをお勧めするいくつかの問題があります。
- コンパイル時間は非常に長くなる可能性があります。10分が一般的であり、より大きな/より複雑な文法はさらに長くかかる可能性があります(コンパイラがクラッシュしないと仮定した場合)。
- 間違いを犯した場合、解読が事実上不可能な非常に長いエラーメッセージが生成される可能性があります。テンプレートを多用するコードからのエラーメッセージはとにかく悪いことで有名であり、Spiritは他の何よりもシステムにストレスを与えます。
私を信じてください:あなたがスピリットのようなものを書くことができるという事実は、印象的なものと素晴らしいものの境界にあります-しかし、私が扱っていた文法が(そして常に残る)と確信した場合にのみ、それを使用します非常に小さくてシンプルです。
Lex と Yaccを見たことがありますか? リンクされたドキュメントのセクション 5 から引用するには:
C++ パーサーを作成する私の好みの方法は、Lex に単純な C ファイルを生成させ、YACC に C++ コードを生成させることです。次にアプリケーションをリンクすると、関数が extern "C" であることを伝えない限り、C++ コードはデフォルトで C 関数を見つけることができないため、いくつかの問題が発生する可能性があります。
私はバイソンを使用しましたが、私のレベルにぴったりの例を見つけました。それを使って簡単な計算機を作成することができました、もちろんそれははるかに多くのことをすることができます。
電卓は、たとえば1 + 2 * 3を取り、構文木を構築しました。ただし、ドキュメントにはツリーの構築方法が記載されていなかったため、作業に少し時間がかかりました。
もう一度行く場合は、「antlr」が見栄えがよく、十分にサポートされているので調べます。
マーティン。
パーサーを作成する最良の方法は、lex と yacc を使用することです。