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]+至少匹配一个数字,但如果需要也可以匹配几十个。

作为参考,您的 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 回答