一言で言えば
問題の迅速な解決策は、ドキュメントのすべての可能な始まりを認識するREGEXまたはFSA(有限状態オートマトン)を定義することであるようです(実際にはドキュメントに対応しない偽陽性は許可されます)。その後、入力で非常に高速に実行して、ドキュメントがエラーなしで開始できる次の場所を特定できます。ドキュメントの開始位置が誤っている場合がありますが、パーサーによって認識され、破棄されます。
したがって、Finite State Automatonがあなたが探していたパーサー名かもしれません。:)
問題
特に語彙に多くの解釈がある場合、実際の問題を理解することは常に困難です。単語解析フォレストは、いくつかの解析ツリーを持つあいまいな文のコンテキストフリー(CF)解析のために作られました(afaik)。文章のラティスの構文解析、または他のタイプの文法に多少一般化できます。したがって、Earley、GLR、Marpa、および派生パーサー(他にも多くあります)に関するすべての回答は、この場合は関係ありませんでした。
しかし、それは明らかにあなたが考えていることではありません。明確なドキュメントのシーケンスである一意の文字列を解析し、ドキュメントの構文がどのように定義されているかを実際に言っていないため、それぞれ、または何らかの構造化表現の解析ツリーを取得したい正式な言語の観点。あなたが持っているのは、ドキュメントの先頭で開始されたときに解析ジョブを実行するアルゴリズムとテーブルです。だからそれ。
実際の問題は、ドキュメントのストリームに、ドキュメントを分離するかなりのゴミが含まれていることです。そして、あなたの困難は、このゴミを十分に速くスキャンすることであるように思われます。現在の手法は、最初から開始し、最初の文字からスキャンを試行し、ドキュメント全体がスキャンされるまで、失敗するたびに次の文字での再起動にスキップします。次に、スキャンしたばかりのドキュメントの後の最初の文字から繰り返すことを繰り返します。
それは、@ amonが彼の答えの第2部で提案した解決策でもあります。
パーサーのコードがドキュメントの先頭で非常に効率的に開始されるように最適化される可能性は低いため、これは非常に高速なソリューションではない場合があります(テストする方法はありません)。通常の使用では、これは一度だけ行われるため、最適化の観点からはホットスポットではありません。したがって、このソリューションでのあなたの適度な幸福は驚くことではありません。
したがって、本当に必要なのは、大量のゴミで始まるドキュメントの先頭をすばやく見つけることができるアルゴリズムです。そして、あなたは幸運です。そのようなアルゴリズムは存在します。そして、私はあなたがそれを知っていると確信しています:それは正規表現の検索と呼ばれます。
シンプルなソリューション
あなたがしなければならないことは、ドキュメントの仕様を分析して、これらのドキュメントがどのように始まるかを見つけることです。構文仕様がどのように正式に編成されているのかわからないので、その方法を正確に説明することはできません。おそらくそれらはすべて、有限のリストからの単語で始まり、おそらくいくつかの句読点や数字と混ざっています。それはあなたが確認するためのものです。
あなたがしなければならないのは、ドキュメントの最初の数文字を認識することができる有限状態オートマトン(FSA)、または同等にほとんどのプログラマーに対して正規表現(REGEX)を定義することです。大きい(時間がかかるため)これは、ドキュメントの仕様から比較的簡単に行うことができ、おそらくドキュメントの仕様を読み取るプログラムで自動的に実行できます。
正規表現を作成したら、次のように入力ストリームで実行して、最初の(または次の)ドキュメントの先頭にすばやく移動できます。
私が想定しています
- docstart
すべての文書の先頭にマッチする正規表現である
- search(regex, stream)
検索という機能であるstream
ストリングのため一致していることregex
。返されると、ストリームは最初に一致するサブストリングの先頭から始まるサフィックスサブストリームに縮小されるか、空のストリームに一致が検出されません。
- parse(stream)
ストリームの最初(ドキュメントの残り)からドキュメントの解析を試み、解析ツリーを任意の形式で返すか、失敗します。戻ると、解析されたドキュメントの終わりの直後の位置から始まるサフィックスサブストリームにストリームが縮小されます。解析が失敗した場合、例外を呼び出します。
forest = empty_forest
search(docstart, stream)
while stream is not empty:
try:
forest = forest + parse(stream)
except
remove first character from stream
search(docstart, stream)
次の検索で同じ一致が再び検出されないように、最初の文字を削除する必要があることに注意してください。
もちろん、ストリームの短縮はイメージです。ストリームのインデックスにすぎない場合があります。
最後の注意点は、すべての始まりを認識している限り、正規表現はあまり正確である必要はないということです。文書の先頭にできない文字列(誤検知)をときどき認識する場合、唯一のペナルティは、パーサーへの1回の無駄な呼び出しのコストです。
したがって、有用な場合は、正規表現の簡素化に役立つ可能性があります。
より高速なソリューションの可能性について
上記のソリューションは、ほとんどの場合、かなりうまく機能するはずです。ただし、大量のゴミとテラバイトのファイルを処理する必要がある場合は、より高速に実行される他のアルゴリズムがある可能性があります。
このアイデアは、ボイヤー・ムーアの文字列検索アルゴリズムに由来しています。このアルゴリズムは、文字列の構造分析を使用してほとんどのストリームの読み取りをスキップし、フラグメントを見ずにジャンプするため、単一のストリングのストリームを非常に高速に検索できます。これは、単一の文字列に対する最速の検索アルゴリズムです。
難点は、単一の文字列ではなく、検索正規表現への適応が非常にデリケートであり、検討している正規表現の機能によってはうまく機能しない可能性があることです。これは、解析するドキュメントの構文に依存する可能性があります。しかし、私が見つけた文書を注意深く読む時間がないので、これについて私をあまり信用しないでください。
私はあなたにウェブ上で見つけた1つまたは2つのポインタを残していますが、これは明らかに査読された研究論文であるものを含みますが、これはよりパフォーマンスの問題がある場合にのみ考慮されるより推測的で、おそらく研究的であるとみなすべきです。そして、おそらくそれを行うシェルフプログラムはありません。