我试图建立一个验证数学方程的正则表达式。方程本身很简单,我想做一个英语可读的方程,我稍后会返回为真或假。示例如下:
((1 and 2) or 3)
在本例中,我将用true或false交换任何数字。我也会替换,和;",,,,和";or"用"| |";以便使用PHP运行方程。对它的响应最终将是真或假。
一个最终方程的例子是这样的:
(真实,,True) || True)
下面是一些应该被认为是有效的例子。
(1或2或3)
((1 and 2 and 3) or (4 and 5))
所以,我的问题分为两部分。
- 是否可以创建一个正则表达式来验证所有可能的有效方程?对我来说,一个很大的障碍是理解如何验证所有的开场白。也有结束语&;)&;
- 在这种情况下,是否建议使用正则表达式来验证客户端?我已经能够使用AJAX和PHP验证表达式,所以我只是想多了吗?
使用抽运引理可以很容易地证明您想要验证的字符串属于非正则的language
,因此不能使用正则表达式解析。(实际上在证明这一事实的方式,你不能匹配开闭括号或甚至计数它们是使用-正如你在你的问题的第一部分提到的)虽然一些正则表达式引擎可能提供一些额外的功能,可用于解析这(如递归模式),但它不是100%符合正则表达式的正式定义。
您可以考虑自己解析圆括号并使用简单的正则表达式验证其中的表达式,或者您可以使用解析树,类似于编译器所做的。
这可以在php(使用PCRE引擎)中完成。
下面只是一个例子。
您可以注释掉错误检查,然后插入边界构造
围绕正则表达式,使其明确通过/失败。
最大的问题不是递归,而是定义内容边界
条件。我已经为你浓缩好了。这些检查必须
无论你怎么维护它,状态,栈…都是一样的。
(此正则表达式是使用RegexFormat 6构建和测试的)
示例输入:
((( (1 and 2 and 3) or (9) or ( ( 4 and 5)) and 5 ) and 7) )
测试输出:
** Grp 0 - ( pos 0 , len 64 )
((( (1 and 2 and 3) or (9) or ( ( 4 and 5)) and 5 ) and 7) )
** Grp 1 - ( pos 1 , len 62 )
(( (1 and 2 and 3) or (9) or ( ( 4 and 5)) and 5 ) and 7)
** Grp 2 - NULL
** Grp 3 - NULL
** Grp 4 - NULL
正则表达式:所有表单:
不允许填写( )
) (
不允许空表单
Form ) and (
ok
Form ) and 2 and (
ok
Form ( 1 and 2 )
ok
Form ( 1 )
ok
Form ) and 2 )
ok
Form ( 1 and (
ok( whitespace (
或) whitespace )
ok
# (?s)(?:(((?!s*))(?&core)))|s*([()]))(?(DEFINE)(?<core>(?>(?&content)|((?:(?!s*))(?&core)))(?!s*())+)(?<content>(?>(?<=))s*(?:and|or)s*(?=()|(?<=))s*(?:(?:and|or)s+d+)+s*(?:and|or)s*(?=()|(?<=()s*d+(?:(?:s+(?:and|or)s+)?d+)*s*(?=))|(?<=))s*(?:(?:and|or)s+d+)+s*(?=))|(?<=()s*(?:d+s+(?:and|or))+s*(?=()|s+)))
# //////////////////////////////////////////////////////
# // The General Guide to 3-Part Recursive Parsing
# // ----------------------------------------------
# // Part 1. CONTENT
# // Part 2. CORE
# // Part 3. ERRORS
(?s) # Dot-All modifier (used in a previous incarnation)
(?:
# ( # (1), Take off CONTENT (not used here)
# (?&content)
# )
# | # OR
( # Open Paren's
( # (1), parens CORE
(?! s* ) ) # Empty form '( )' not allowed
(?&core)
)
) # Close Paren's
| # OR
s*
( # (2), Unbalanced (delimeter) ERRORS
# - Generally, on a whole parse, these
# are delimiter or content errors
[()]
)
)
# ///////////////////////
# // Subroutines
# // ---------------
(?(DEFINE)
# core
(?<core> # (3)
(?>
(?&content)
|
( # Open Paren's
(?:
(?! s* ) ) # Empty form '( )' not allowed
(?&core)
)
) # Close Paren's
(?! s* ( ) # Empty form ') (' not allowed
)+
)
# content
(?<content> # (4)
(?>
(?<= ) ) # Form ') and ('
s*
(?: and | or )
s*
(?= ( )
|
(?<= ) ) # Form ') and 2 and ('
s*
(?:
(?: and | or )
s+
d+
)+
s*
(?: and | or )
s*
(?= ( )
|
(?<= ( ) # Form '( 1 and 2 )'
s*
d+
(?:
(?:
s+
(?: and | or )
s+
)?
d+
)*
s*
(?= ) )
|
(?<= ) ) # Form ') and 2 )'
s*
(?:
(?: and | or )
s+
d+
)+
s*
(?= ) )
|
(?<= ( ) # Form '( 1 and ('
s*
(?:
d+
s+
(?: and | or )
)+
s*
(?= ( )
|
s+ # Interstitial whitespace
# '( here (' or ') here )'
)
)
)