代码之家  ›  专栏  ›  技术社区  ›  nikola

分析布尔运算,包括括号和regex?

  •  5
  • nikola  · 技术社区  · 15 年前

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

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

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

    结果捕获应该首先用括号分组,然后用相同或更简单的regex再次解析。

    我已经成功地编写了一个简单的regex来解析没有括号的布尔运算。

    有什么想法吗?

    3 回复  |  直到 12 年前
        1
  •  2
  •   Mark Byers    15 年前

    通常您会使用例如a recursive descent parser 对于此任务,但可以使用regex获取所有部分(标记):

    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 表达式,在优先级相等的情况下从左到右排列。你说你想先返回括号匹配项,但实际上你通常要做的是使用部分构建一个表达式树并递归地计算。

        2
  •  1
  •   Max Shawabkeh    15 年前

    假设没有嵌套,将其简化到可以使用regex的级别。匹配的regex(假设和/或仅此,可以轻松扩展):

    >>> 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个字符串(操作数运算符操作数)的元组,其余字符串作为每个标记(操作数或操作数)的字符串。

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

        3
  •  1
  •   PaulMcG    15 年前

    这个 Examples page 在pyparsing wiki上包含一个示例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和关联性,还可以选择用解析的元素构造一个类。然后,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本身是一个有点长的模块,但它是一个单一的源文件,因此它的安装占用空间非常小。麻省理工学院许可证允许非商业和商业使用。