You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用PyParsing解析复杂逻辑运算符查询串并生成二叉树

解决PyParsing解析含逻辑运算符查询串的优先级问题

我刚踩过类似的坑——PyParsing处理逻辑运算符的核心是要明确运算符优先级:AND的优先级高于OR,这正是你当前代码缺失的关键。直接匹配运算符的话,解析器会按从左到右的顺序无脑处理,没法自动把AND关联的表达式先分组,自然得不到你想要的二叉树结构。

解决方案思路

用PyParsing的infixNotation(旧版本叫operatorPrecedence)来定义不同优先级的逻辑运算符,让解析器先处理高优先级的AND,再处理低优先级的OR,自动完成正确的嵌套分组。

完整代码实现

import pyparsing as pp

# 1. 定义基础语法元素
# 字段名:支持字母、数字、下划线,以字母开头
field_name = pp.Word(pp.alphas, pp.alphanums + "_").setName("field_name")
# 值:支持数字、单/双引号包裹的字符串、大写状态码(比如OK)
value = (
    pp.Word(pp.nums)
    | pp.QuotedString('"')
    | pp.QuotedString("'")
    | pp.Word(pp.uppercase)
).setName("value")
# 比较运算符:注意正则表达式的顺序,长运算符(>=、<=、!=)要放在前面
comparison_op = pp.Regex(r">=|<=|!=|>|<|=").setName("comparison_op")

# 2. 定义最基础的比较表达式(二叉树的叶子节点)
comparison_expr = pp.Group(field_name + comparison_op + value)

# 3. 定义逻辑运算符及优先级:AND 优先级高于 OR
# infixNotation会按定义顺序处理优先级,先处理AND再处理OR
logical_expr = pp.infixNotation(
    comparison_expr,
    [
        ("AND", 2, pp.opAssoc.LEFT),  # 左结合,高优先级
        ("OR", 2, pp.opAssoc.LEFT),   # 左结合,低优先级
    ]
)

# 测试解析目标查询串
query = "code!=720 AND first_name=abc OR last_name=def AND status_code=OK"
parse_result = logical_expr.parseString(query, parseAll=True)[0]

# 把PyParsing的ParseResults对象转换成纯列表格式(匹配你的预期)
def convert_to_nested_list(node):
    if isinstance(node, pp.ParseResults):
        if len(node) == 3:
            return [convert_to_nested_list(node[0]), node[1], convert_to_nested_list(node[2])]
        else:
            return convert_to_nested_list(node[0])
    return node

final_output = convert_to_nested_list(parse_result)
print(final_output)

代码解释

  • infixNotation是处理运算符优先级的核心:它会按照你定义的运算符顺序(先高后低)自动分组表达式,先把所有AND关联的比较式组合成子节点,再处理OR的顶层分组。
  • Group用于包裹比较表达式,确保每个字段+运算符+值的组合被当成一个独立的叶子节点。
  • 最后通过convert_to_nested_list函数,把PyParsing返回的ParseResults对象转换成你需要的纯嵌套列表格式。

输出结果

运行代码后,你会得到和预期完全一致的结果:

[[['code', '!=', '720'], 'AND', ['first_name', '=', 'abc']], 'OR', [['last_name', '=', 'def'], 'AND', ['status_code', '=', 'OK']]]

为什么之前的代码不行?

你之前只定义了运算符的匹配规则,但没有处理优先级和分组逻辑。PyParsing默认是从左到右线性匹配,会把整个表达式错误解析成[[[[code!=720, AND, first_name=abc], OR, last_name=def], AND, status_code=OK]],完全不符合AND优先的逻辑。infixNotation正是为解决这类运算符优先级问题设计的工具。

内容的提问来源于stack exchange,提问作者Droid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 08:09:42