現代の言語はまだパーサージェネレーターを使用していますか?


38

これが出てきたとき、私はここウィキペディア gccコンパイラスイートについて調査していました:

GCCはBisonで生成されたLALRパーサーの使用を開始しましたが、徐々に手書きの再帰パーサーに切り替えました。2004年のC ++、および2006年のCおよびObjective-Cの場合。現在、すべてのフロントエンドは手書きの再帰下降パーサーを使用しています。

最後の文で(そしてウィキペディアを信頼する限り)私は間違いなく「C(gcc)、C ++(g ++)、Objective-C、Objective-C ++、Fortran(gfortran)、Java(gcj)、 Ada(GNAT)、Go(gccgo)、Pascal(gpc)、... Mercury、Modula-2、Modula-3、PL / I、D(gdc)、およびVHDL(ghdl)」はすべてフロントエンドであり、パーサージェネレーターを長く使用します。つまり、それらはすべて手書きのパーサーを使用します。

私の質問は、このプラクティスはどこにでもあるのですか?特に、[Python、Swift、Ruby、Java、Scala、ML、Haskell]のxの「xの標準/公式実装には手書きパーサーがありますか」に対する正確な答えを探していますか?(実際、他の言語に関する情報もここで歓迎されています。)掘り下げた後、私は自分でこれを見つけることができると確信しています。しかし、これはコミュニティによって簡単に答えられると確信しています。ありがとう!


3
データポイント:CPythonには、自家製のLALRパーサージェネレーター(pgen)があります。残りについては知りません。

8
データポイント:Ghc(haskell)は、OCamlと同様に、LALRパーサージェネレーター(ハッピー)を使用します。
トワンヴァンラーホーフェン14

1
あるべき「...現代の高性能コンパイラを実行してください」ないか機械生成されたパーサーを使用しないかというコンパイラである一方、言語は、仕様ではない実装であるため、または類似。
dmckee 14

@dmckee、はい、あなたは正しいです。ただし、名前の付け方は長くなり始めていますが、あまり重要ではありません。あなたが私より創造的であれば、それを自由に編集してください!
eatonphil 14

MLについて:MLtonはMLに固有のパーサージェネレーターを使用しますが、SML / NJについても90%確信しています。その「手書き」を検討する場合としない場合があります。
パトリックコリンズ14

回答:


34

私の知る限り、GCCは特に手書きパーサーを使用して、構文エラー診断を改善しています(つまり、構文エラーに関する人間に意味のあるメッセージを提供しています)。

構文解析理論(およびそれから派生する構文解析ジェネレーター)は、主に正しい入力句を認識して解析することに関するものです。しかし、コンパイラーには、誤った入力に対して意味のあるエラーメッセージを表示すること(および構文エラー後の残りの入力を意味のある形で解析できること)が期待されます。

また、古いレガシー言語(C11やC ++ 11など)(最新のリビジョンが3年前であっても概念的には古い)は、まったくコンテキストフリーではありません。パーサージェネレーター(つまり、バイソンまたはメンヒル)の文法でその文脈依存性に対処することは、退屈なほど困難です。


2
同意します。解析エラーからの回復(最初のエラーで解析を停止したくない場合、古いBorland Pascalの場合)と高品質のエラーメッセージ(人間が望むような解決のためのヒントや提案を含む)の作成は両方とも本質的にコンテキストです-敏感な、ヒューリスティックなタスク。それらは、ストックパーサージェネレーターの出力の上でややできますが、それはスローです。
ジョナサンユニス14

2
Dealing with that context sensitiveness in grammars for parser generators is boringly difficult。また、これらのツールはコンテキストフリーのパーサーを生成するため、多かれ少なかれ不可能です。このようなツールを使用している場合、すべての状況依存制約が存在するかどうかを確認する正しい場所は、解析ツリーを生成したです。
dtech

7

パーサージェネレーターとパーサーエンジンは非常に一般的です。一般性の利点は、物事の全体的なスキームにおいて、正確なパーサーを迅速に構築して機能させることが簡単であることです。

パーサーエンジン自体は、その一般性のためにパフォーマンスの面で苦しんでいます。手書きコードは、テーブル駆動のパーサーエンジンよりも常に大幅に高速になります。

パーサージェネレーター/エンジンが困難な2番目の領域は、すべての実際のプログラミング言語がコンテキスト依存であり、多くの場合非常に微妙な点です。LR言語はコンテキストに依存しません。つまり、構文で適切に伝えることが不可能な、位置と環境に関する多くの微妙な点があります。属性付きグラマーは、「使用前に宣言する」などの基本的な言語規則に対処しようとします。この文脈依存性を手書きコードに配線するのは簡単です。


15
パフォーマンスの主張の引用をお願いします?テーブル駆動はパフォーマンスを大幅に最適化することができ、ジェネレーターは非常に効率的ですが、実質的に手動で実装されることのないアルゴリズムにアクセスできます(テーブルやマジックナンバーの不可解な混乱のため)。

2
第2の領域について:多くの多くの主要な本当のプログラミング言語は、(あなたはすべてのセットを参照する必要があると思い適用されるいかなる意味においても敏感な文脈ではありません有効である、型チェックや、後のプログラムは決して何手書きまたは生成されたパーサーは解析しようとします)。手書きパーサーの方が柔軟性が高く、これは一部の言語では役立ちますが、ほとんどの場合、エラー回復とレポート、増分などの領域で役立ちます。パーサージェネレーターは、認識力のため(使用するかどうか)そのような文法を書きたいのは別の話です)。-1

解析中にシンボルテーブル情報を使用する場合、コンテキスト依存と呼ぶこともできます。属性付き文法は完全に文脈依存ではありませんが、完全に文脈依存ではないと思います。エラーリカバリとレポートに関する他のポイントは十分に考慮されています。
BobDalgleish 14

1
CおよびC ++では、解析中にシンボルテーブル情報が必要です(または、式ステートメントと変数宣言などを区別しない、はるかに具体性の低い解析ツリーを受け入れます)。しかし、私はそれらを考えていませんでした。Java、Lisp、JavaScript、Ruby、Python、Go、Rust、Scala、Swift、Haskellなどの言語(おそらくC#やMLもありますか?)とにかく欲しい。それらの多くには、実際にはLL(1)文法、またはLALR文法さえあります。

1
すべての実際の言語の引用は文脈依存ですか?
psr 14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.