我正在尝试构建一个验证数学方程式的正则表达式。方程式本身非常简单,我希望制作一个英文可读的方程式,以后我将返回真或假。一个例子就是这样。
((1和2)或3)
在这个例子中,我将用true或false替换任何数字。我也将用“&&”替换“和”和“或”与“||”为了使用PHP运行方程式。对此的回应最终将为真或假。
示例最终等式看起来像这样:
((true&& true)|| true)
以下是一些应被视为有效的例子。
(1或2或3)
((1和2和3)或(4和5))
所以,我的问题分为两部分。
答案 0 :(得分:2)
使用pumping lemma可以很容易地证明您要验证的字符串属于不常规的language
,因此无法使用正则表达式进行解析。 (实际上是以证明这一点的方式使用你无法匹配开括号或右括号的事实或者使用它们 - 正如你在问题的第一部分中提到的那样)虽然一些正则表达式引擎可能提供一些可用于解析的附加功能这(就像递归模式一样)但它并不是100%符合正则表达式的正式定义。
您可以考虑自己解析括号并使用简单的正则表达式验证其中的表达式,或者您可以使用parse tree,类似于编译器所做的。
答案 1 :(得分:1)
这可以在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
正则表达式:
5/29所有表格:
不允许使用空格式( )
不允许使用空表单) (
表格) and (
确定
表格) and 2 and (
确定
表格( 1 and 2 )
确定
表格( 1 )
确定
表格) and 2 )
确定
表格( 1 and (
确定
表格( whitespace (
或) whitespace )
确定
# (?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 )'
)
)
)