解析布尔运算包括带正则表达式的括号?

时间:2010-01-22 15:25:50

标签: javascript python regex

是否有一个正则表达式可以解析表示简单布尔算术的字符串(在Python和/或Javascript中,不需要是相同的表达式)?例如,我想解析这个字符串:

a and (b and c) and d or e and (f or g)

假设:
*括号不嵌套
*术语a,b,...,z不是子表达式

结果捕获应首先按括号分组,然后再使用相同或更简单的正则表达式进行解析。

我已经成功编写了一个天真的正则表达式来解析没有括号的布尔运算。

有什么想法吗?

3 个答案:

答案 0 :(得分:2)

通常你会使用例如recursive descent parser来执行此任务,但你可以使用正则表达式获取所有部分(标记):

x = 'a and (b and c) and d or e and (f or g)'
import re

matches = re.findall(r'\(.*?\)|\w+', x)
print ','.join(matches)

运营商通常有不同的precedence。首先评估括号,然后是and表达式,最后是or表达式,在优先级相同的情况下按从左到右的顺序。你说你想首先返回括号匹配,但实际上你通常会做的是使用部分构建一个表达式树并递归地计算它。

答案 1 :(得分:1)

假设没有嵌套将其简化为可以使用正则表达式的级别。匹配的正则表达式(假设和/或仅可以轻松扩展):

>>> expr = 'a and (b and c) and d or e and (f or g)'
>>> regex = re.compile('\((\w+)\s+(and|or)\s+(\w)\)|(\w+)')
>>> results = regex.findall(expr)
>>> results = [i[:3] if i[0] else i[3] for i in results]
>>> results
['a', 'and', ('b', 'and', 'c'), 'and', 'd', 'or', 'e', 'and', ('f', 'or', 'g')]

现在你将带括号的部分作为3个字符串(操作数 - 操作符 - 操作数)的元组,并将字符串的其余部分作为每个标记的字符串(操作符或操作数)。

您可以浏览列表,评估每个带括号的表达式,并将其替换为结果。完成后,您可以再次浏览它并从左到右或根据您设置的某些优先级规则进行评估(例如,在您用完AND之前继续评估AND,然后开始评估OR)。

答案 2 :(得分:1)

pyparsing wiki上的Examples page包含一个示例SimpleBool.py,它将解析和计算表达式,例如:

test = ["p and not q",
        "not not p",
        "not(p and q)",
        "q or not p and r",
        "q or not (p and r)",
        "p or q or r",
        "p or q or r and False",
        ]

(嗯,没有任何嵌套parens的例子,但这些也支持。)

使用以下代码完整定义实际解析器:

boolOperand = Word(alphas,max=1) | oneOf("True False")
boolExpr = operatorPrecedence( boolOperand,
    [
    ("not", 1, opAssoc.RIGHT, BoolNot),
    ("and", 2, opAssoc.LEFT,  BoolAnd),
    ("or",  2, opAssoc.LEFT,  BoolOr),
    ])

示例的其余部分给出了BoolNot,BoolOr和BoolAnd的实现。 operatorPrecedence构造定义了操作序列,它们的arity和associativity,以及可选的用解析元素构造的类。 operatorPrecedence然后负责定义语法,包括在嵌套括号内的boolExpr的递归定义。生成的结构类似于使用给定BoolXxx类的嵌套AST。这些类反过来定义eval方法,以便可以使用以下代码解析和评估表达式:

p = True
q = False
r = True
for t in test:
    res = boolExpr.parseString(t)[0]
    print t,'\n', res, '=', bool(res),'\n'

pyparsing本身是一个有点冗长的模块,但它是一个单一的源文件,所以它的安装空间非常小。麻省理工学院许可证允许非商业和商业用途。