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

如何用pyparsing处理含函数调用的中缀表达式解析?

让PyParsing同时支持普通表达式与带函数调用的表达式解析

要解决这个问题,核心是扩展原有的operand定义,使其能识别函数调用语法,同时保留对普通标识符的支持。函数调用本身属于表达式的原子部分,优先级高于四则运算等操作,所以不需要调整原有运算符优先级配置。

修改步骤说明:

  • 用pp.Forward()定义递归表达式引用,因为函数参数可以是任意表达式(包括嵌套函数调用)。
  • 重新定义operand,包含两种情况:普通标识符,以及函数调用(标识符 + 括号包裹的逗号分隔参数列表)。
  • 函数调用的参数列表支持多个表达式,允许空参数列表(如f())。

完整代码示例:

import pyparsing as pp

# 定义递归表达式的forward引用,用于解析函数参数
expression = pp.Forward()

# 普通标识符:由字母数字组成
identifier = pp.Word(pp.alphanums)

# 函数调用语法:标识符 + ( 可选的逗号分隔表达式列表 )
function_call = identifier + pp.Group(pp.Suppress('(') + pp.Optional(pp.delimitedList(expression)) + pp.Suppress(')'))

# 扩展operand:支持普通标识符或函数调用
operand = identifier | function_call

# 运算符定义保持不变
boolean_operator = pp.one_of(['||', '&&'])
comparison_operator = pp.one_of(['<', '<=', '>', '>=', '==', '!='])

# 用扩展后的operand构建infix表达式
infix_pattern = pp.infix_notation(
    operand,
    [
        ('^', 2, pp.OpAssoc.LEFT),
        ('*', 2, pp.OpAssoc.LEFT),
        ('/', 2, pp.OpAssoc.LEFT),
        ('+', 2, pp.OpAssoc.LEFT),
        ('-', 2, pp.OpAssoc.LEFT),
        (comparison_operator, 2, pp.OpAssoc.LEFT),
        (boolean_operator, 2, pp.OpAssoc.LEFT),
    ]
)

# 完成递归表达式的定义
expression << infix_pattern

# 测试原有普通表达式
print("测试普通表达式:(a + b) * c")
print(infix_pattern.parse_string('(a + b) * c'))
# 输出:[[['a', '+', 'b'], '*', 'c']]

# 测试带函数调用的表达式
print("\n测试带函数调用的表达式:a(b) == c(d)")
print(infix_pattern.parse_string('a(b) == c(d)'))
# 输出:[['a', ['b'], '==', 'c', ['d']]]

# 测试嵌套函数调用
print("\n测试嵌套函数调用:f(g(a + b), c*d) > 5")
print(infix_pattern.parse_string('f(g(a + b), c*d) > 5'))
# 输出:[['f', [['g', [['a', '+', 'b']]], ['c', '*', 'd']], '>', '5']]

原代码失效原因:

原代码中的operand仅定义为pp.Word(pp.alphanums),只会匹配连续的字母数字字符,遇到(就会停止解析。输入a(b)时,只会识别出'a',后续的(b)被当作无关内容丢弃,导致表达式解析不完整。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 19:25:17