2009-04-11 15 views
8

コードを機能コンポーネントに分割する問題がRegexesで発生しました。彼らは壊れたり、彼らが終わるのに時間がかかるかもしれません。この経験から質問が出されます。パーサーはいつ使用しますか?

「パーサーはいつ使用しますか?」

+0

重複しているかどうかは正確にはわかりませんが、次の記事をチェックしてください。* [正規表現には複雑すぎるのはなぜですか?](http:// stackoverflow。com/questions/230517 /あまりにも複雑な正規表現の場合) * [正規表現の代替](http://stackoverflow.com/questions/514313/alternatives-to具体的な例については、 – dirkgently

答えて

9

あなたはパターンを変えることができ、テキスト、の字句やセマンティックな意味で興味を持っているのパーサーを使用する必要があります。ファンクションの意味にかかわらず、文字のパターンに一致するか置換すると、単純にを探しているときに、パーサーは一般的に過剰です。

あなたの場合、テキストの背後にある意味(コードの "機能コンポーネント")に興味があるようですので、パーサーが良い選択です。しかし、パーサーは内部的に正規表現を使うことができるので、相互排他的であると見なされるべきではありません。


"パーサ"は、自動的に複雑にする必要があるわけではありませんが、たとえば、Cコードブロックに興味がある場合は、{と}のネストされたグループを解析するだけです。このパーサーは、2つのトークン( '{'と '}')とそれらの間のテキストブロックにのみ関心があります。

ただし、ネストされたセマンティクスのために単純な正規表現の比較では十分ではありません。次のコードを取る:

void Foo(bool Bar) 
{ 
    if(Bar) 
    { 
     f(); 
    } 
    else 
    { 
     g(); 
    } 
} 

パーサーがfooの全体的な範囲、並びにフー内に含まれる各内側範囲(もし、他のブロックを)理解するであろう。それぞれの '{'トークンに出会うと、その意味を「理解」します。単純な検索では、しかし、テキストの後ろの意味を理解しないと、次はもちろん、我々は正しくありません知っているブロックであると解釈することがあります。

{ 
    if(Bar) 
    { 
     f(); 
    } 
0

あなたの質問は少しあいまいですが、私は私の推測しますあなたの正規表現が複雑になったり、時間がかかりすぎたり、合理的に定義された "言語"を扱えば、パーサが簡単になるという意見があります。

私はあなたが砂の中に行を設定して片側のものは正規表現で行うことができ、反対側ではパーサーが必要だと言うことはできません。状況によって異なります。

1

問題が発生すると直ちにパーサーを使用する必要があります。これは、正規表現が意味するものではなく、単純に解決できないことを意味します。例えば、(釣り合っていない)括弧(反復的に)のマッチングは、そのような問題の1つです。 PCREのようないくつかの味は手書きのパーサで勝てないほど遠くにいるのですが。

2

パーサーには、正規表現よりも魅力的な使用例がいくつかあります。

  • 作業したい表現の種類が、意味的エンティティ(タグ、変数、電話番号など)よりも複雑な場合は常に、パーサーを使用する必要があります。
  • 単にパターンにマッチするのではなく、テキストの意味的意味を知る必要があるときはいつでも。たとえば、電話番号を書くためのすべての可能な方法を照合しようとしている場合、パーサーはおそらく正規表現より優れています。あなたが電話番号に対応する特定のパターンにマッチさせようとしているならば、正規表現はおそらく大丈夫です。
  • 入力が正しく形成されているとは限りません。
  • 構文仕様(C#、XML、C++、Rubyなど)を持つ明確に定義された言語の構造内で完全に作業している場合は、既にパーサーが存在するため、あなたのために。
+0

+1である。 –

+0

@ジョンフェミネラ、私は間違っている可能性がありますが、私は電話番号の例に同意できないと思います。私たちが電話番号を書くさまざまな方法にマッチさせたいと思うならば、それは正規表現(パターンのオプションのリスト付き)として非常にうまく表現できると思います。これは、セマンティクスが必要な場合の非常に良い例ではないかもしれません。 – Parag

+0

@Parag:私は、電話番号が正規表現と一致すると信じていることから来る、幸せな内なる平和をまだ残しておきたいと思います。完全に検証するには電話番号が厄介に複雑です。 –

1

ここでは、スティーブ・イェーゲ:Rich Programmer Foodの礼儀です。

+0

+1個人的なブログ投稿。読んだ後にコンパイラ、再発などの関連するものについて3冊を買った。) –

+0

ありがとう。その場合は、次をご覧ください: http://stackoverflow.com/questions/725372/which-programming-languages-text –

3

ときにパーサを必要とする:

  1. 言語は(あなたが文脈アクションを実行する必要があるときに、より一般的に)あなたはパースツリーを必要とする
  2. wikipedia)定期的ではありません
  3. と、得られる正規表現あまりにもあいまい/複雑すぎる

私の2セント。

+0

私はニットピックを意味するわけではありませんが、ポイント1については、レクサーまたはパーサー? – Parag

2

The Dragon Bookはあなたが正規表現を使用することはできませんかについて小さなセクションを持っています

  • ここで、w彼らは、あなたが「WCW」のような構造と一致しないことができることを意味し、文字列の繰り返しを検出することはできません
  • 固定数の反復または不特定多数の反復しか検出できません。つまり、すでに解析されたトークンを使用して反復回数を決定することはできません。 'n s1 s2 ... sn '
  • "正規表現を使用して、バランスの取れた構造やネストされた構造を記述することはできません[あなたが後でそれを一致させることができるように、すべてのバランスの取れた括弧」1と2については

の文字列の集合]のように、簡単な説明、次のことができないキャプチャサブストリングがあります。あなたが望むなら、パーサを使うよりも。そのような場合に正規表現をどのように使用するのかを考えると、直感的にはできない結論に至ります。 :)

3の場合、文字列リテラルの解析用のK & Rの問題と同じです。文字列リテラルが最初の ""と2番目の ""の間にあるとは言えませんが、エスケープされた引用符(\ ")があるとどうなりますか?

Russelのパラドックスとの関係は、

+0

各議論の前提は何ですか? 1.自分自身についての推論がない2.記憶が限られているのでトークンが有限でなければならない3.すべて - 私はなぜラッセルのパラドックスについて考え始めたのか分からない。その証明を減らすことはできますか? –

+0

私は自分の答えを更新しました。 –

+0

@Asdrei Vajna II "%s @ \\(h \\(el \\)lo \\)@で文字列が\ 1で、部分文字列が\ 2 @" "hello"という単語を含む行。 –

0

パーサーの間に正規表現ができないことがありますが、これは正規表現の中にはありません。 。行うことができます
をたとえば:

スタート:: =(インナー);
インナー:: =スタート| X;

正規表現は、正規表現では、同じ数の開閉括弧があるかどうかを追跡することができないため、これを行うことはできません。そのため、大きなファイルをトークン化して解析しようとすると、パーサーが使用されることが予想されますが、正規表現はファイル内で特別なパターンを見つけることができます。

関連する問題