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

使用pyparsing递归解析带参数和关键字参数的函数调用表达式

解决pyparsing递归深度错误的函数解析器问题

原代码核心问题分析

  • 递归定义逻辑错误:body <<= body | ... 将body作为第一个匹配选项,导致解析器会无限递归尝试匹配自身,直接触发递归深度超限错误。pyparsing的Forward递归定义必须把非递归项放在前面,避免优先自引用。
  • 引用错误:ppc.identifier 应为 pp.pyparsing_common.identifier,原代码未正确调用pyparsing的内置标识符解析器。
  • 冗余空匹配:pp.empty 允许空元素,会导致参数列表出现无效空项,不符合语法要求。
  • 参数结构混淆:未清晰区分位置参数(单个值/函数调用)和关键字参数(key=value),导致解析逻辑混乱。

修正后的代码

import pyparsing as pp

# 定义基础符号
LP, RP = map(pp.Suppress, "()")
EQ = pp.Suppress("=")

# 原子类型解析
ident = pp.pyparsing_common.identifier("ident")
number = pp.pyparsing_common.number
string = pp.QuotedString('"') | pp.QuotedString("'")
date = pp.Combine(pp.Word(pp.nums, exact=4) + "-" + pp.Word(pp.nums, exact=2) + "-" + pp.Word(pp.nums, exact=2))("date")
literal = date | number | string

# 递归表达式定义
expr = pp.Forward()

# 关键字参数结构:key=expr
kwarg = pp.Group(ident + EQ + expr)("kwarg")
# 函数参数:支持位置参数(expr)或关键字参数(kwarg)
func_arg = expr | kwarg
# 函数调用结构:IDENT(ARG_LIST)
func_call = pp.Group(ident + LP + pp.Optional(pp.delimitedList(func_arg)) + RP)("func_call")

# 表达式可以是字面量或嵌套函数调用(非递归项优先匹配)
expr <<= literal | func_call

# 顶层解析目标:完整的函数调用表达式
top_level_expr = func_call

关键修正说明

  1. 调整递归顺序:将非递归的literal放在expr匹配选项的最前面,递归的func_call后置,避免解析器陷入无限递归。
  2. 明确参数结构:拆分出kwarg和func_arg,清晰区分位置参数与关键字参数的语法,符合目标表达式规则。
  3. 修复引用错误:修正标识符解析器的调用路径,确保使用pyparsing内置的标识符规则。
  4. 移除冗余空匹配:确保参数列表中的每个元素都是有效的位置参数或关键字参数,避免无效空项。
  5. 分层逻辑构建:从原子字面量到复杂函数调用,逐层构建解析规则,逻辑更清晰易维护。

测试示例

# 测试嵌套函数+混合参数的解析
test_str = "calc_sum(100, '2024-06-01', multiply(x=50, y=add(20, 30)))"
result = top_level_expr.parseString(test_str)
print(result.dump())

输出会展示结构化的解析结果,验证嵌套函数、位置参数、关键字参数的解析正确性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 16:35:10