機能するアルゴリズムについて説明します。実行時間はそれほど悪くないはずです。これもかなり事前計算できます。
私はと仮定します(それはおそらく簡単にそのような場合に適応するのですが)非終端記号が含まれていない、あなたが知らないことのx、yのかの派生。また、派生に使用されないプロダクション(たとえばA → Aなど)が文法に含まれていないと仮定します。aバツyaA → A
主な問題は、実際に解析することですあなたが続くことができるか知っているので、あなたがで終わる状態の種類を知りたいと、。これは、xを知らないほど簡単ではありません。aaバツ
Earleyのアルゴリズムの適応を使用します。最初にそのアルゴリズムを理解する必要があります。初期化と完了の手順が異なることを除いて、アルゴリズムはほぼ同じように機能します。
初期化のために、我々はすべての発生のためにアーリー項目に私たちの最初のセットをシード1(の最初の文字、あなたの文法のいずれかの生産で)。このアイテムのバックポインターを-1、無効な値に設定します。これは、修正された補完において重要です。基本的に、-1は「この制作がどこから始まったのかわかりません」を意味します。a1a
次に、このような初期のEarleyアイテムすべてに対して、Earleyアルゴリズムを個別に実行します。解析が互いに干渉する可能性があるため、これらすべてを同時に実行することはできません。ここでバックトラックするよりも速い方法は簡単にはわかりません。
完了ステップでは、-1のバックポインタを処理するように変更するだけです。出所が分からない作品を完成させたので困っています。ただし、PennelloとDeRemerによってL A L R (1 )先読みセットを計算するために使用される方法L A L R (1 )は私たちを救ってくれます。ここで必要なのは、まさにL A L R (1 )先読みセットです。これらの先読みセットのすべての項目は、文法内で対応する位置にあります。これは、完成した生産の可能な継続に対応します。L A L R (1 )
残念ながら、ここでもう一度バックトラックする以外に選択肢はありません。先読みセットのすべての位置について、この位置で完了ステップを実行し、そこから解析を続行します。これは、解析ごとに個別に行います。文法が場合、先読みによって、どの位置に移動する必要があるかが一意に決定されるため、バックトラックする必要はありません。L A L R (1 )
上記のアルゴリズムをを1文字超え続行します。この追加の仮想文字を「任意の文字」と見なします。これにより、探している「フォロー」セットがすぐに得られます-スキャナーフェーズがこの最終的なものを見つけるといつでもセットすると、この文字を回答セットに追加できます。a
編集:私は、バックトラックによって導入されたオーバーヘッドのほとんどを取り除く方法を見つけたと思います。これらの識別子のプレフィックスを使用する必要があるため、すべてのEarleyアイテムに文字列である識別子のセットを関連付けます。初期化時に、すべての初期アイテムをEarleyセットに追加し、一意の識別子をすべてのセットに関連付けます。
スキャナーと予測ステップで、識別子は新しいアイテムに引き継がれます。同じEarleyセット内で、識別子のみが異なるEarleyアイテムは、識別子をマージすることでマージされます。識別子を使用してこれらの新しいアイテムに対してスキャナーと予測の手順を実行できることに注意してください。この手順をすべての識別子に対して個別に実行する必要はありません。
L A L R (1 )
基本的に、これらの識別子を使用してバックトラッキングを行うため、スキャナーと予測ステップで二重の作業を行わないようにします。