2009-04-24 5 views
4

最初に文字に一致する可能性のあるすべての文字のセットを、文字列の中のある特定のインスタンスjava.util.regex.Patternで計算したいと考えています。より正式には、特定の正規表現に相当するDFAを仮定すると、すべての発信トランジションのセットが開始状態から必要です。正規表現パターンにマッチした最初の文字セットを判別できますか?

例:

{ 'a', 'b', 'c', 'd', ' ', '\n', '\r', '\t' } 

任意のアイデア:

Pattern p = Pattern.compile("[abc]def|daniel|chris|\\s+"); 
Set<Character> first = getFirstSet(p); 

セットfirstには、次の要素が含まれている必要がありますか?私は自分自身でDFAを構築し、そのような状態を決定することができることをよく承知していますが、そのような面倒を避けたいと思います(読んでください:私にはそれほど価値がありません)。私のホスト言語は実際にはScalaなので、Scalaの中核となるすべてのライブラリにアクセスすることができます(これは価値があります)。

答えて

4

私はあなたが正規表現を解析し、そのような最初のセットを構築して、左から右の方法で解析された正規表現で動作する再帰関数を定義できると思います。

いくつかのものは単純です:

  • 順序:最初の(R1R2)=最初の(R1)+()最初(R2)最初の(R1における '' 場合は、他の空のセット)
  • 交替:最初の最初|(R1、R2)=最初の(R1)+(R2)
  • 反復:最初の(R *)=最初の(R)+ [
  • 文字 ':最初の(C)= C
  • Characterclasses:最初([c1-cn])=セット(c1、c2、...、cn) ...

正規表現の方言が知っているすべてのプリミティブと特別なフラグにこれを拡張してください。

+0

ええ、私はそれについて考えました。これは、自分でDFAのフロントエンドを構築することと事実上同じです。たぶん私はこれになるならこれをやるだろうが、私はむしろ簡単な解決策を見つけるだろう。 –

+0

私は、(言語標準の固定文法に従って)それを構文解析するよりもはるかに簡単ではないか、かなり明白な再帰をいくつか見ていますが、おそらくそれは私のコンパイラ構築の脳です。 – Tetha

+0

よく解析してから再帰的な探索あまりにも悪いですが、私はちょうど最初のセットを取得するためにJavaの正規表現のセマンティクスを複製することについて幸せではないです。 –

1

あなたはrecursivly括弧を囲むの...

  • ストリップを、それを解決し、recursivlyを呼び出すことができます。
  • トップレベルの選択肢で分割し、各部分を繰り返し呼び出します。
  • 何の選択肢がない場合
    • 出力最初なしオプションシンボルに左アップから始まるすべてのシンボル。
    • 文字グループがある場合は、すべてのシンボルを出力します。

は、おそらくこのアイデアにエラーがたくさんありますが、これは私がしようとするだろうものです。アサーション、グループ名、他の何千ものを取り除かなければなりません。そして、[^ 0-9]のような反転文字クラスを見つけたら、たくさんの文字を出力する必要があります。

だから私はそれが本当に複雑な問題だと思います。

+0

私は否定のクラスについては考えていませんでした。 JavaがUTF-8を使用していることを考慮すると、FIRSTセットのサイズは数十万になる可能性があります。おお!たぶん私は正規表現が何にもマッチして、それを最適化されないままにしておくと仮定します。 –

+0

私はちょうど表現を書き直すことを考えました - 入力式の最初のシンボルにマッチする式を作ることができたら、いくつかの単一のシンボル文字列と派生した式が一致するかどうかをテストします。しかし、すべての文字を取得するには、文字セット全体をループする必要があります。これは、Unicodeの多くの作業です。そして私はそのような派生表現を得る方法を考えることができません。たぶん、正規表現の実装をハッキングし、リフレクションを介して内部の状態を調べます。 –

+0

しかし、これはおそらく正規表現の実装を書くことに終わるでしょう。だから私は(良い)アイディアから外れている。 –

関連する問題