如何用PyParsing实现根据首数字动态获取对应数量输入的语法?
问题
需要使用pyparsing定义动态语法,处理如下格式的输入:
1: a 2: a, b 3: a, b, c
规则要求:每行开头的数字指定后续需要的输入项数量,若输入项数量与数字不匹配则报错。此前仅了解过Forward,不确定是否适用于该场景,询问具体实现方法。
解决方案
不需要使用Forward(Forward主要用于处理递归语法结构,比如嵌套表达式、嵌套列表等),可以通过**解析动作(Parse Action)**实现基于前置数字的数量验证,这是pyparsing处理动态约束的常用方式。
实现步骤
- 定义基础语法组件
先拆分输入的基本元素:数字、标识符、分隔符,以及行的整体结构:
- 数字:匹配纯数字字符串
- 标识符:匹配字母组成的字符串
- 逗号分隔的标识符列表:用
delimited_list快速实现逗号加空格分隔的元素解析 - 行结构:数字 + 冒号加空格 + 标识符列表
- 添加数量验证的解析动作
给行结构绑定解析动作,在解析完成后,提取前置数字和标识符列表,对比两者的数量,不匹配则抛出ParseException。
完整代码示例
import pyparsing as pp # 定义基础语法元素 integer = pp.Word(pp.nums).set_name("integer") identifier = pp.Word(pp.alphas).set_name("identifier") comma_sep_identifiers = pp.delimited_list(identifier, delim=", ") line = integer + pp.Suppress(": ") + comma_sep_identifiers # 解析动作:验证标识符数量与前置数字匹配 def validate_item_count(s, loc, tokens): expected = int(tokens[0]) actual = len(tokens[1]) if actual != expected: raise pp.ParseException(s, loc, f"预期{expected}个输入项,实际得到{actual}个") # 返回结构化结果,方便后续处理 return (expected, tokens[1]) # 为行语法绑定解析动作 line.set_parse_action(validate_item_count) # 测试合法输入 valid_input = """ 1: a 2: a, b 3: a, b, c """ results = line.search_string(valid_input) for res in results: print(f"数字:{res[0]},输入项:{res[1]}") # 测试非法输入(数量不匹配) invalid_input = """ 2: a """ try: line.search_string(invalid_input) except pp.ParseException as e: print(f"解析错误:{e}")
代码说明
pp.Suppress用于忽略冒号加空格这类语法分隔符,避免它们出现在解析结果中delimitted_list自动处理逗号分隔的元素,返回一个列表- 解析动作中通过
tokens参数获取解析到的内容,tokens[0]是前置数字,tokens[1]是标识符列表 - 当数量不匹配时,抛出
ParseException,pyparsing会自动捕获并给出包含位置信息的错误提示
内容的提问来源于stack exchange,提问作者lattitude
相关产品推荐
相关产品推荐

