PyParsing解析Solidity方法签名时出现无限递归错误求助
Solidity函数签名解析的递归深度超限问题
问题描述
我编写了用于解析Solidity函数方法签名的PyParsing语法,代码如下:
from pyparsing import Word, alphas, alphanums, oneOf, Group, Forward, ZeroOrMore, Optional, delimitedList solidity_type = Forward() primitive = oneOf("address uint uint8 uint16 uint32 uint64 uint128 uint256 int int8 int16 int32 int64 int128 int256 bool bytes bytes1 bytes4 bytes32") array = solidity_type + "[]" tuple_type = "(" + delimitedList(solidity_type) + ")" solidity_type <<= (primitive | array | tuple_type) function_name = Word(alphas, alphanums + "_") arguments = Optional(delimitedList(solidity_type)) function_signature = function_name + "(" + arguments + ")" sig = "diamondCut((address,uint8,bytes4[])[],address,bytes)" parsed_sig = function_signature.parseString(sig) print(parsed_sig.dump())
运行时触发{RecursionError}maximum recursion depth exceeded错误,测试array.parseString("(bytes4)[]")也会出现同样问题。尝试过用Group包裹表达式、调整选项顺序、将array设为独立Forward,都无法解决,需要修改代码解析目标签名。
解决方法
递归超限的原因是array和tuple_type都直接依赖solidity_type,而solidity_type又包含这两者,导致解析器在尝试匹配时陷入无限递归。解决思路是调整语法定义的优先级,让解析器优先匹配最底层的类型,再逐步向上匹配复合类型,同时用Group明确结构避免歧义:
from pyparsing import Word, alphas, alphanums, oneOf, Group, Forward, Optional, delimitedList solidity_type = Forward() # 先定义最基础的原始类型 primitive = oneOf("address uint uint8 uint16 uint32 uint64 uint128 uint256 int int8 int16 int32 int64 int128 int256 bool bytes bytes1 bytes4 bytes32") # 定义元组:用Group包裹,确保内部结构被正确识别 tuple_type = Group("(" + delimitedList(solidity_type) + ")") # 定义数组:优先匹配原始类型或元组后再匹配数组后缀,避免递归循环 array = Group((primitive | tuple_type) + "[]") # 最后把所有类型选项按优先级加入solidity_type solidity_type <<= (primitive | tuple_type | array) function_name = Word(alphas, alphanums + "_") arguments = Optional(delimitedList(Group(solidity_type))) function_signature = Group(function_name + "(" + arguments + ")") sig = "diamondCut((address,uint8,bytes4[])[],address,bytes)" parsed_sig = function_signature.parseString(sig) print(parsed_sig.dump())
关键修改点
- 调整类型匹配顺序:让解析器先匹配
primitive,再匹配tuple_type,最后匹配array,避免一开始就进入复合类型的递归匹配 - 用Group包裹复合类型:明确元组和数组的结构,让解析结果更清晰,同时帮助解析器识别完整的复合类型单元
- 数组定义优化:数组不再直接依赖
solidity_type,而是基于已匹配的primitive或tuple_type,打破无限递归的循环
运行修改后的代码,就能成功解析目标签名,输出的结构化结果也能清晰展示函数名和每个参数的类型结构。
内容的提问来源于stack exchange,提问作者aram10
相关产品推荐
相关产品推荐

