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

基于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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 00:20:05