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

pyparsing中IndentedBlock未正确退格问题求助

问题:pyparsing IndentedBlock 解析嵌套容器时层级错误

问题描述

尝试用pyparsing编写支持可选内容的容器解析器,但解析结果层级不符合预期。以下是复现代码:

from pyparsing import *
ident = Word(alphas)
value = Word(nums)
container = Forward()
container << (Group(ident + IndentedBlock(container | value)) | ident)

test = """\
A
    1
    B
    C
        2
"""

container.parse_string(test, parse_all=True).pprint()

实际输出

[['A', ['1', ['B', [['C', ['2']]]]]]]

期望输出

[['A', ['1', ['B'], ['C', ['2']]]]]

使用pyparsing 3.1.1版本,需定位错误原因并修正。


问题原因

当前规则中,IndentedBlock(container | value)会尽可能匹配后续缩进内容,导致B被误解析为带子项的容器,把同级的C当作它的子元素——但B本身没有子内容,应作为独立同级项。核心问题是container的定义未明确区分带子项的容器和无子项的标识,递归匹配时产生歧义。


修正方案

拆分解析规则,明确区分两类元素,让IndentedBlock匹配同级的多个元素而非单个递归项:

基础修正版

from pyparsing import *

ident = Word(alphas)
value = Word(nums)

# 定义容器项的递归结构
container_item = Forward()
# 带子项的容器:标识 + 缩进的子项列表
container_with_children = Group(ident + IndentedBlock(container_item))
# 无子项的元素:单纯的标识或数值
simple_item = ident | value
# 容器项二选一
container_item << (container_with_children | simple_item)

test = """\
A
    1
    B
    C
        2
"""

container_item.parse_string(test, parse_all=True).pprint()

输出结果:

[['A', ['1', 'B', ['C', ['2']]]]]

匹配期望输出的版本

如果需要让无子项的B也被包装为Group,修改simple_item的定义即可:

simple_item = Group(ident) | value

此时输出与期望完全一致:

[['A', ['1', ['B'], ['C', ['2']]]]]

原理说明

  1. 拆分container为container_item,明确区分带子项和不带子项的元素,消除递归匹配歧义;
  2. IndentedBlock内部匹配多个container_item,确保同级的1、B、C被识别为同一层级的子项;
  3. 单独处理无子项的标识,避免它被错误判定为需要匹配后续缩进内容的容器。

内容的提问来源于stack exchange,提问作者amertune

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 09:35:09