我想为这个BNF语法编写一个preg_match函数。
EXP ::= EXP + TERM | EXP - TERM | TERM
TERM ::= TERM * FACTOR | TERM / FACTOR | FACTOR
FACTOR ::= ( EXP ) | DIGIT
DIGIT ::= 0 | 1 | 2 | 3
我不想允许任何字母和任何数字> 3并且字符串应该以$ sign结尾。我已经尝试过这些模式,但它不起作用。我不明白我犯了什么错误。
$pattern = "|[0-3\+\-()*/]+\\$$|";
$pattern = "|[^A-Za-z][0-3\+\-()*/]+\\$$|";
编辑:
也试过这个
$ pattern =“| ^ [0-3 + - ()* /] + \ $$ |”;
但这允许 12 + 1 $并且我不想允许任何数字> 3.
有人可以帮帮我吗?
谢谢。
答案 0 :(得分: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。