41

Haskell と Parsec は初めてです。第 16 章 Using Parsec of Real World Haskell を読んだ後、疑問が頭に浮かびました: なぜ、いつ Parsec が Yacc/Bison/Antlr のような他のパーサー ジェネレーターよりも優れているのか?

私の理解では、Parsec はパーサーを書く優れた DSL を作成し、Haskell はそれを非常に簡単かつ表現力豊かにします。しかし、構文解析は、複数のターゲット言語に出力する独自の言語に値する標準/人気のあるテクノロジーです。では、Bison/Antlr から Haskell コードを生成する代わりに、いつ Parsec を使用するのでしょうか?

この質問は、テクノロジーを少し超えて、業界の慣行の領域にまで及ぶ可能性があります。パーサーをゼロから作成する場合、Bison/Antlr などと比較して、Haskell/Parsec を選択する利点は何ですか?

ところで:私の質問はこれと非常に似ていますが、満足のいく回答が得られませんでした。

4

3 に答える 3

55

リストしたツールの主な違いの 1 つは、ANTLR、Bison、およびその仲間がパーサージェネレーターであるのに対し、Parsec はパーサーコンビネーターライブラリであることです。

パーサー ジェネレーターは、文法の記述を読み取り、パーサーを吐き出します。通常、既存の文法を新しい文法に結合することはできません。また、生成された既存の 2 つのパーサーを新しいパーサーに結合することもできません。

パーサー コンビネーター OTOH は、既存のパーサーを新しいパーサーに結合するだけです。通常、パーサー コンビネーター ライブラリには、空の文字列または単一の文字を解析できるいくつかの単純な組み込みパーサーが付属しており、1 つ以上のパーサーを取得して新しいパーサーを返す一連のコンビネーターが付属しています。 、元のパーサーのシーケンスを解析する (たとえば、パーサーとパーサーを組み合わせてパーサーを形成できますd) odo元のパーサーの代替 (たとえば、0パーサーと1パーサーからパーサーへ0|1)、または元のパーサーを複数回解析します (反復)。

これが意味することは、たとえば、Java 用の既存のパーサーと HTML 用の既存のパーサーを取り、それらを JSP 用のパーサーに結合できるということです。

ほとんどのパーサー ジェネレーターはこれをサポートしていないか、限られた方法でしかサポートしていません。パーサーコンビネーター OTOHはこれのみをサポートし、他には何もサポートしません。

于 2011-02-20T14:03:55.310 に答える
9

この質問と、質問にリンクされている質問を確認することをお勧めします。

最も使いやすい Haskell 構文解析テクノロジはどれですか? またその理由は?

Haskell では、競合は Parsec (および他のパーサー コンビネーター) とパーサー ジェネレーター Happy の間で行われます。作業する LR 文法が既にある場合は Happy を選択します。パーサー コンビネーターは LL 形式の文法を使用し、LR から LL への変換には多少の労力がかかり、コンビネーター パーサーは通常かなり遅くなります。文法がない場合は、Parsec を使用します。Parsec は Happy よりも柔軟 (強力) で、Happy と Alex でコードを生成するよりも「Haskell で」作業する方が楽しいです。解析に Happy を使用する場合、ほとんどの場合、字句解析に Alex を使用する必要があります。

業界の慣習として、Parsec を取得するためだけに Haskell を使用することを決定するのは奇妙です。構文解析に関しては、現在の言語のほとんどに少なくともパーサー ジェネレーターがあり、おそらく Parsec や PEG システムのポートのような、より柔軟なものがあります。

リンクされた質問に対する Ira Baxter の回答は、パーサーが翻訳者を作成するためのヒマラヤ山脈の足場に到達するだけであることにスポットライトを当てていましたが、翻訳者の一部であることはパーサーの用途の 1 つにすぎないため、まだ多くのドメインが存在します。 ANTLR、Happy、Parsec などのかなり最小限のシステムで十分です。

于 2011-02-20T09:18:03.393 に答える
6

スティーブンの答えに続いて、パーサーコンビネーターに固執したい場合、Parsecの最も一般的な代替手段の1つは attoparsec だと思います。主な違いは、attoparsec がより速度に偏って書かれており、それに応じてトレードオフを行うことです。たとえば、Parsec は、解析が失敗した場合に有用なエラー メッセージを返そうとするために何らかの簿記を行いますが、attoparsec は同じ程度には行いません。また、attoparsec は 1 つの入力ストリーム/トークン型に特化しているのに対し、Parsec は入力型から抽象化するため、String、ByteString、Text などの型のストリームを問題なく解析できると思います。

于 2011-02-20T10:12:02.817 に答える