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

