您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

在以二叉树方式进行pyparsing中解析复杂的逻辑表达式

在以二叉树方式进行pyparsing中解析复杂的逻辑表达式

注意:operatorPrecedence不推荐使用pyparsing方法,而推荐使用method name infixNotation

尝试更改:

expr = pp.operatorPrecedence(clause,[ 
                            ("OR", 2, pp.opAssoc.LEFT, ), 
                            ("AND", 2, pp.opAssoc.LEFT, ),])

至:

expr = pp.operatorPrecedence(condition,[ 
                            ("OR", 2, pp.opAssoc.LEFT, ), 
                            ("AND", 2, pp.opAssoc.LEFT, ),])

operatorPrecedence的第一个参数是要与运算符一起使用的原始操作数-无需在圆括号中包含您的complexExpr- operatorPrecedence会为您完成此操作。由于操作数实际上是另一个更深层次的比较,因此您可以考虑更改:

condition = (expr + operator + expr)

至:

condition = pp.Group(expr + operator + expr)

因此,operatorPrecedence的输出更易于处理。有了这些更改,解析x > 7 AND x < 8 OR x = 4将给出:

[[['x', '>', '7'], 'AND', [['x', '<', '8'], 'OR', ['x', '=', '4']]]]

识别OR的较高优先级并首先对其进行分组。(您确定要使用AND和OR优先顺序吗?我认为传统顺序是相反的,如此Wikipedia条目所示。)

我想您也在问为什么pyparsing和operatorPrecedence不以嵌套二进制对的形式返回结果,也就是说,您希望解析“ A,B和C”将返回:

[['A', 'and', 'B'] 'and', 'C']

但是您得到的是:

['A', 'and', 'B', 'and', 'C']

这是因为operatorPrecedence使用重复而不是递归来解析相同优先级下的重复操作。请参阅与您的问题非常相似的问题,其答案包括解析动作,可将您的重复解析树转换为更传统的二进制解析树。您还可以在pyparsing Wiki页面上找到使用operatorPrecedence实现的示例布尔表达式解析器

:澄清一下,这是我建议您将解析器减少为:

import pyparsing as pp

operator = pp.Regex(">=|<=|!=|>|<|=").setName("operator")
number = pp.Regex(r"[+-]?\d+(:?\.\d*)?(:?[eE][+-]?\d+)?")
identifier = pp.Word(pp.alphas, pp.alphanums + "_")
comparison_term = identifier | number 
condition = pp.Group(comparison_term + operator + comparison_term)

expr = pp.operatorPrecedence(condition,[
                            ("AND", 2, pp.opAssoc.LEFT, ),
                            ("OR", 2, pp.opAssoc.LEFT, ),
                            ])

print expr.parseString("x > 7 AND x < 8 OR x = 4")

如果您还想添加对NOT的支持,那么它将类似于:

expr = pp.operatorPrecedence(condition,[
                            ("NOT", 1, pp.opAssoc.RIGHT, ),
                            ("AND", 2, pp.opAssoc.LEFT, ),
                            ("OR", 2, pp.opAssoc.LEFT, ),
                            ])

在某个时候,您可能想comparison_term使用更完整的算术表达式来扩展的定义,并用其自己的operatorPrecedence定义来定义。我建议这样做,而不是创建一个庞然大物的opPrec定义,因为您已经提到了性能上的一些缺点opPrec。如果仍然遇到性能问题,请查看ParserElement.enablePackrat

其他 2022/1/1 18:34:40 有487人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶