使用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
相关产品推荐
相关产品推荐

