0

この BNF 文法の preg_match 関数を書きたいと思います。

EXP ::= EXP + TERM | EXP - TERM | TERM

TERM ::= TERM * FACTOR | TERM / FACTOR | FACTOR

FACTOR ::= ( EXP ) | DIGIT

DIGIT ::= 0 | 1 | 2 | 3 

3 を超える文字や数字を許可したくありません。文字列は $ 記号で終了する必要があります。これらのパターンを試しましたが、うまくいきません。私は自分が犯した間違いを理解していません。

$pattern  = "|[0-3\+\-()*/]+\\$$|";

$pattern  = "|[^A-Za-z][0-3\+\-()*/]+\\$$|";

編集:

これも試した

$pattern = "|^[0-3+-()*/]+\$$|";

しかし、これは12 +1$ を許可し、3 を超える数字は許可したくありません。

誰かがこれを手伝ってくれませんか?

ありがとうございました。

4

1 に答える 1

1

式を検証しようとしている場合は、許可された文字のみが含まれていることを確認するだけでなく、それ以上のことを行う必要があります。数字は?それらは[0-3]+少なくとも 1 桁に一致するため存在しますが、必要に応じて数十桁にも一致する可能性があります。

参考までに、BNF が説明する言語は規則的ではありません。純粋な正規表現では何もできません。(たとえば、括弧のレベル数を追跡できる必要があります...そして有限状態オートマトン(REなど)は数えられません。)

幸いなことに、PCRE は単なる正規表現ではありません。:) 少なくとも PHP では、ネストされた括弧などを一致させるために絶対に必要な再帰を許可します。

$pattern = ':^(([0-3]|\((?1)\))([+*/-](?1))?)\$$:';

(?1)最初のサブパターンへの再帰的な参照です -- 実際のパターンであり、一致したテキストではありません。パターン自体をそこに貼り付けるようなものですが、切り取りと貼り付けを無限に行うのは大変です。:P この場合、それは を指し([0-3]|\((?1)\))([+*/-](?1))?ます。

それ以外は、単純化された文法を使用しています(操作の順序を除いて、とにかく正規表現でこれを実際に解析することはできません)。

DIGIT  : [0-3]  
OPER   : [+*/-]
LPAREN : '('
RPAREN : ')'

EXP     : (DIGIT | LPAREN EXP RPAREN ) (OPER EXP)?
PATTERN : EXP '$'

(?1)実際のパターンでは、EXP にほぼ正確に対応しています。

于 2013-05-17T22:47:41.437 に答える