基于Python pyparsing解析非规范遗留花括号文件格式
用pyparsing解析遗留花括号格式文件的实现方案
一、核心语法定义思路
针对这种括号内换行无意义、外部换行分隔语句的格式,核心是用pyparsing的嵌套结构处理括号,同时区分内外换行的作用:
1. 基础元素定义
- 字符串字面量:匹配带双引号的字符串,支持内部转义(按需扩展)
- 标识符与符号:匹配变量名、命名空间、运算符等非括号/逗号/换行的内容
- 括号匹配规则:分别定义
[]、{}、()的嵌套结构,内部元素用逗号或换行作为分隔符
2. 语法规则代码实现
from pyparsing import ( Word, alphanums, Literal, quotedString, Forward, Group, ZeroOrMore, OneOrMore, Suppress, LineEnd, Optional ) # 定义基础元素 identifier = Word(alphanums + "_::") string_lit = quotedString token = identifier | string_lit | Word("=+-*/") # 定义括号结构:用Forward实现递归嵌套 bracket_expr = Forward() # 括号内部元素:逗号或换行分隔,兼容末尾逗号 bracket_content = ZeroOrMore( bracket_expr | token + Optional(Suppress("," | LineEnd())) ) # 分别定义三种括号,标记类型名 square_bracket = Group(Literal("[").suppress() + bracket_content + Literal("]").suppress()).setName("[]") curly_bracket = Group(Literal("{").suppress() + bracket_content + Literal("}").suppress()).setName("{}") round_bracket = Group(Literal("(").suppress() + bracket_content + Literal(")").suppress()).setName("()") # 递归引用括号表达式 bracket_expr << (square_bracket | curly_bracket | round_bracket) # 语句定义:由token和括号表达式组成,外部换行分隔语句 statement = OneOrMore(token | bracket_expr) # 顶层语法:多个语句,允许空行分隔 top_level = ZeroOrMore(Group(statement) + Suppress(Optional(LineEnd())))
二、解析结果转换为目标AST结构
自定义Brace类封装节点,遍历pyparsing解析结果进行转换:
1. 定义Brace类
class Brace: def __init__(self, type_, children): self.type = type_ self.children = children def __repr__(self): return f"Brace('{self.type}', {repr(self.children)})"
2. 转换函数实现
def parse_to_ast(parsed_result): ast = [] # 遍历每个顶层语句(对应换行分隔的节点) for stmt in parsed_result: stmt_children = [] for elem in stmt: # 处理括号节点 if hasattr(elem, 'getName'): bracket_type = elem.getName() bracket_children = [ parse_bracket(e) if hasattr(e, 'getName') else str(e) for e in elem if e != '' ] stmt_children.append(Brace(bracket_type, bracket_children)) else: # 普通token直接加入 stmt_children.append(str(elem)) # 每个语句对应一个换行类型的Brace节点 ast.append(Brace('\n', stmt_children)) return ast def parse_bracket(bracket_group): bracket_type = bracket_group.getName() children = [] for elem in bracket_group: if hasattr(elem, 'getName'): children.append(parse_bracket(elem)) else: children.append(str(elem)) return Brace(bracket_type, children)
3. 使用示例
# 测试示例文本 sample_text = """Variable = [1, 2] Variable2 = { Variable, "Literal", } Variable[1] = Variable2 Namespace::Function(argument, {"string literal", 100}) """ # 解析并转换为AST parsed = top_level.parseString(sample_text) ast = parse_to_ast(parsed) # 打印AST for node in ast: print(node)
输出结果将与目标结构一致,每个换行分隔的语句对应Brace('\n', ...)节点,括号内容对应带类型的Brace节点,其余为字符串token。
三、关键细节说明
- 换行处理:顶层语句用
LineEnd()分隔,括号内部将换行视为逗号等价分隔符,实现内外换行的不同语义 - 递归嵌套:通过
Forward()实现括号的多层嵌套解析 - 末尾逗号兼容:用
Optional(Suppress("," | LineEnd()))处理格式中允许的末尾逗号
内容的提问来源于stack exchange,提问作者user66554
相关产品推荐
相关产品推荐

