0

私が尋ねたこのSOの質問で説明されている次の条件を満たす必要がある数式の正規表現が必要でした。

この表現でうまくいきました

しかし今は、以前の条件に加えて、開き括弧と閉じ括弧のサポートを追加する必要があります。私の正規表現がこれらのパターンの表現を検証するように

例えば。*6+(7-9)または/6.25*(7-9.2)または+6または*6/(7.5-9)

既存の正規表現に変更を加えようとしましたが、達成できませんでした。また、単一の括弧が数式に存在する可能性があるため、有効ではない*6+(7-9これらのパターンも受け入れます。*6+7-9)

リンクはRegExrです。助けてください。

4

2 に答える 2

5

@Bibhu、数式は任意にネストできるため、それらを検証するには実際のパーサーが必要です。正規表現は機能しません。正規表現は、任意の深さの再帰的な入れ子を処理できるほど強力ではありません。

ネストを最大レベルに制限すると、式を検証できる(非常に大きくて醜い)正規表現を作成できます。しかし基本的に、正規表現はこの仕事には不適切なツールです。

すでに使用方法を知っているパーサー ジェネレーターがある場合は、それが数式のパーサーを作成する最も簡単な方法です。そうでない場合でも、単純なトップダウンの再帰降下パーサーを手動で作成するのは非常に簡単です。

于 2012-07-04T06:30:45.700 に答える
0

賞金を提供しているかどうか疑問に思っています。

正規表現での単純な再帰は、たまたまスタック可能な成功/失敗を返す gosub です。

以下は、指定した単純な演算子と単純な構文規則に対して Perl 独自の解析アルゴリズムを渡す Perl ルーチンです。ニーズが非常に単純であるため、単一の正規表現で実行されます。

派手に見えますが、「()」という単純なバランスの取れたテキストに解決されます。Dot Net
はこれができるようです。置換 (つまり (?&var) ) を実行するだけ
で、Dot Net が必要とするバランスの取れたグループ化を実行するのは非常に簡単なはずです... 即時検証。

ネスティングは問題ではないため、これを投稿しています。問題は、構文解析は単純に
見えますが、細部に問題があるということです。

^
(?:
     ^ (?&sign)? (?&number)
  |
     (?&operator) 
     (?<! ^ (?:\/|\*) )
     (?<! ^ [*]{2} )
     (?&sign)? (?&number)
  |
     (?: (?&operator)
         (?<! ^ (?:\/|\*) )
         (?<! ^ [*]{2} )
         (?<! [(] (?:\/|\*) )
         (?<! [(] [*]{2} )
         (?&sign)?
       |
         (?<= [(] )
       |
         ^ (?&sign)?
     )

     (?<term>
        \(
           (?:
                (?>  (?&sign)?
                     (?&number)
                     (?: (?&operator) (?&sign)? (?&number) )*
                )
             |
                (?>
                    (?: (?<= [(] ) | (?&operator) )
                    (?<! [(] (?:\/|\*) )
                    (?<! [(] [*]{2} )
                    (?&sign)?
                    (?&term)
                )
           )*
        \)
        (?! [(] )
        (?> (?&operator) (?&sign)? (?&number) )*
     )
)*
$

(?(DEFINE)
  (?<number>    \d+(?:\.\d+)?   )
  (?<sign>      [+-]            )
  (?<operator>
        (?:  [*]{2}
          |  [\/*]
          |  (?<pm>[-+]) (?! \k<pm>) )
         )
  )

出力

passed  ''
passed  '(6**-2**3)'
passed  '6-+2'
passed  '-(-(8*((2)/3)))'
passed  '-((8*((2)/3)))'
passed  '-((8*((2**4)/3)))'
passed  '-((8*((2**4)/3)))**((-1)*(8*((2**4/99)/3)))'
passed  '-((8*((2**4)/3)))**((-1)*(8*((2**-4/99)/3)))'
passed  '-((8*((2**4)/3)))**-((-1)*(8*((2**-4/99)/3)))'
passed  '((8*((2)/3)))'
passed  '((8*((2)/3)))'
passed  '+((8*((-2)/-3)))'
passed  '8-6*2'
passed  '-8-6*2'
passed  '((8*((2-(8*(8+6)/2))/3))-7*2/234)+8/2*1'
passed  '-(8*(8+6)/2)'
passed  '(9*9/9)'
passed  '(9*(9)/9*(9*(9)/9)*1)'
passed  '(9*(9)/9*(9*(9)/9))*(9*(9)/9*(9*(9)/9))'

failed  '(6--2)'
failed  '-(/(8*((2)/3)))'
failed  '-((8*((2(6))/3)))'
failed  '+((8*((+2)/--3)))'
failed  '+((8*((+2)/--3+)))'
failed  '+((8*((*2)/--3)))'
failed  '+((8*((*2)/-3)))'
failed  '-((8*((-2)/+-3)))'
failed  '+8/2(1)'
failed  '-(8)*(8/('
failed  '-(8)*(8/()'
failed  '*(9*9/9)'
failed  '*(9*(9)/9*(9*(9)/9))*(9*(9)/9*(9*(9)/9))'
failed  '/(9*(9)/9*(9*(9)/9))*(9*(9)/9*(9*(9)/9))'
于 2012-08-13T00:45:31.850 に答える