賞金を提供しているかどうか疑問に思っています。
正規表現での単純な再帰は、たまたまスタック可能な成功/失敗を返す 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))'