python 列表(嵌套)解析器在 pyparsing 中会是什么样子?

What would a python list (nested) parser look like in pyparsing?

提问人:Sergej Herbert 提问时间:12/28/2022 更新时间:12/29/2022 访问量:65

问:

我想了解如何使用 pyparsing 来解析嵌套的 Python 列表之类的东西。 这是一个需要理解pyparsing的问题。由于示例列表可能看起来像 JSON 或 Python 本身而规避该问题的解决方案不应阻止使用 pyparsing。

因此,在人们开始向我抛出 json 和 literal_eval 之前,让我们考虑一个字符串和结果,如下所示:

Input:
{1,2,3,{4,5}}
Expected Output (Python list):
[1,2,3,[4,5]]

我目前有这段代码,但输出没有解析嵌套列表

import pyparsing


print(
    pyparsing.delimited_list(
        pyparsing.Word(pyparsing.nums) | pyparsing.nested_expr("{", "}")
    )
    .parse_string("{1,2,3,{4,5}}")
    .as_list()
)
# [['1,2,3,', ['4,5']]]

这里已经有几乎相同的问题,但这个问题通过使用 json 解析来规避: Python 使用 Pyparsing 解析逗号分隔的嵌套括号

Python 递归 pyparsing

评论


答:

3赞 Xiddoc 12/28/2022 #1

您需要使用正向引用,因为您的逻辑是递归的。不可能使用以前未定义过的内容,因此该对象允许您这样做:Forward

expr = pyparsing.Forward()
expr <<= pyparsing.delimited_list(
    pyparsing.Word(pyparsing.nums) | pyparsing.nested_expr("{", "}", expr)
)

print(expr.parse_string("{1,2,3,{4,5}}").as_list())
# [['1', '2', '3', ['4', '5']]]

这个答案还有另一个关于如何使用它们的好例子。

评论

0赞 Sergej Herbert 12/28/2022
看起来不错。但是你知道为什么这个输入会失败吗?"{{1},2,3,{4,5}}"
0赞 Sergej Herbert 12/29/2022 #2

多亏了 Xiddoc 的答案,我能够稍微调整答案,以便在表达式以列表开头时也有效(不知道为什么带有 nested_expr 的解决方案不起作用)

import pyparsing as pp


expr = pp.Forward()
group_start, group_end = map(pp.Suppress, r"{}")

number = pp.Word(pp.nums).setParseAction(lambda s, l, t: int(t[0]))
nested_list = pp.Group(group_start + expr[...] + group_end)
expr <<= pp.delimited_list(number | nested_list)

print(expr.parse_string(r"{{1},2,3,{4,5}}", parse_all=True).as_list()[0])
# [[1],2,3,[4,5]]