我想验证一个字符串,它包含一个像
这样的表达式isFun && ( isHelpful || isUseful )
这些表达式可以包含操作数,二元运算符和一元运算符:
my $unary_operator = qr/(?:\+|\-|!|not)/;
my $binary_operator = qr/(?:<|>|<=|>=|==|\!\=|<=>|\~\~|\&|\||\^|\&\&|\|\||lt|gt|le|ge|and|or|xor|eq|ne|cmp)/i;
my $operand = qr/[a-z0-9_]+/i;
它们与你从perl的条件模式中所知道的类似(例如在if语句中)。括号必须是平衡的,一元运算符只能连续使用一次。
我想找到一个perl兼容的正则表达式,它确保有一个有效的逻辑/数学表达式,其中只使用给定的运算符,操作数与$operand
给出的正则表达式匹配。通过递归,这在perl中是可能的。该声明采用中缀表示法。
我目前的解决方案是解析树并执行一些迭代,但我想将此算法压缩为单个正则表达式。
对于我的第一次尝试(我仍然排除了所有详细的操作数),我使用了
my $re =
qr{
( # 1
( # 2 operands ...
$operand
)
|
( # 3 unary operators with recursion for operand
(?:$unary_operator(?!\s*$unary_operator)\s*(?1))
)
|
( # 4 balance brackets
\(
\s*(?1)\s*
\)
)
|
( # 5 binary operators with recursion for each operand
(?1)\s*$binary_operator\s*(?1)
)
)
}x;
...最终以无限递归结束。我认为递归可能是在括号5中使用第一个(?1)引起的。
有人在那里有一个有效的解决方案吗?
答案 0 :(得分:0)
以下内容适用于验证表达式:
use strict;
use warnings;
my $unary_operator = qr/(?:\+|\-|!|not)/;
my $binary_operator = qr/(?:<|>|<=|>=|==|\!\=|<=>|\~\~|\&|\||\^|\&\&|\|\||lt|gt|le|ge|and|or|xor|eq|ne|cmp)/i;
my $operand = qr/[a-z0-9_]+/i;
my $re =
qr{^
( # 1
\s*
(?> (?:$unary_operator \s*)* )
(?:
\b$operand\b
|
\( (?1) \)
)
(?:
\s*
$binary_operator
\s*
(?1)
)*
\s*
)
$}x;
while (<DATA>) {
chomp;
my ($expr, $status) = split "#", $_, 2;
if ($expr =~ $re) {
print "good $_\n";
} else {
print "bad $_\n";
}
}
__DATA__
isFun # Good
isFun && isHelpful # Good
isFun && isHelpful || isUseful # Good
isFun && ( isHelpful || isUseful ) # Good
isFun && ( isHelpful || (isUseful) ) # Good
isFun && ( isHelpful || (isUseful ) # Fail - Missing )
not (isFun && (isHelpful || (isBad && isDangerous))) # Good
isGenuine!isReal # Fail
!isGenuine isReal # Fail
输出:
good isFun # Good
good isFun && isHelpful # Good
good isFun && isHelpful || isUseful # Good
good isFun && ( isHelpful || isUseful ) # Good
good isFun && ( isHelpful || (isUseful) ) # Good
bad isFun && ( isHelpful || (isUseful ) # Fail - Missing )
good not (isFun && (isHelpful || (isBad && isDangerous))) # Good
bad isGenuine!isReal # Fail
bad !isGenuine isReal # Fail