Javascript 用正则表达式解析包含括号的布尔算术?

Javascript 用正则表达式解析包含括号的布尔算术?,javascript,python,regex,Javascript,Python,Regex,是否有一个正则表达式可以解析表示简单布尔运算的字符串(在Python和/或Javascript中,不需要是同一个表达式)?例如,我想分析这个字符串: a and (b and c) and d or e and (f or g) 假设: *括号不嵌套 *术语a、b、…、z不是子表达式 结果捕获应该首先按括号分组,然后用相同或更简单的正则表达式再次解析 我已经成功地编写了一个简单的正则表达式,用于解析没有括号的布尔算术 有什么想法吗?通常您会使用例如a来完成此任务,但您可以使用正则表达式获取所有

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

a and (b and c) and d or e and (f or g)
假设:
*括号不嵌套
*术语a、b、…、z不是子表达式

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

我已经成功地编写了一个简单的正则表达式,用于解析没有括号的布尔算术


有什么想法吗?

通常您会使用例如a来完成此任务,但您可以使用正则表达式获取所有部分(令牌):

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)

运营商通常有不同的选择。首先计算括号,然后计算
表达式,最后计算
表达式,如果优先级相同,则按从左到右的顺序计算。您说要首先返回括号匹配项,但实际上您通常会使用这些部分构建一个表达式树并递归地求值。

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

现在,括号中的部分作为3个字符串(操作数运算符operand)的元组,其余部分作为每个标记(运算符或操作数)的字符串

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

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",
        ]
(嗯,没有任何带有嵌套参数的示例,但也支持这些示例。)

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

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),
    ])
p = True
q = False
r = True
for t in test:
    res = boolExpr.parseString(t)[0]
    print t,'\n', res, '=', bool(res),'\n'
该示例的其余部分给出了BoolNot、BoolOr和BoolAnd的实现。OperatorRecessence构造定义了操作序列、它们的算术性和关联性,还可以选择使用解析的元素构造一个类。OperatorRecessence然后负责定义语法,包括嵌套括号内boolExpr的递归定义。结果结构类似于使用给定BoolXxx类的嵌套AST。这些类依次定义
eval
方法,以便使用以下代码解析和计算表达式:

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),
    ])
p = True
q = False
r = True
for t in test:
    res = boolExpr.parseString(t)[0]
    print t,'\n', res, '=', bool(res),'\n'

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

您到底想做什么?我有一个定制的客户端JS实现,它生成这样一个布尔算术表达式(其中a、b、c…实际上是字段查找,供以后在Django ORM过滤器中使用),然后将其发布到服务器并用Python解析。我希望这是有意义的。所以你想解析这个表达式以便以后对其求值,对吗?不确定“求值”是什么意思。在这一点上,我并不太关心实际的术语,因为我已经有了一个很好的实现来识别a,b,…,z中的标记。注意,如果括号进行嵌套,您需要采取一种完全不同的方法,因为正则表达式不能处理计数(即嵌套任何东西)标记,您指出的方法是正确的“正确”的解决方案涉及一个表达式树,但鉴于括号从未嵌套在我的实现中,我认为一个正则表达式在这里就足够了。谢谢,Paul,这看起来很简单,我会看一看的!