python - Pyparsing 解析操作并列出类型错误

标签 python pyparsing

对于小语言,我想解析 "X [Y,Z,V]" 形式的表达式,其中 X, YZV 是自然数。

以下是我的尝试。

from pyparsing import *

class Y():
    def __init__(self, ls):
        self.ls = ls

def MakeCombinedList(tokens):
    print(len(tokens)) # prints 4
    print(tokens)      # [5, 1, 2, 3]
    clist = tokens[1]
    clist.append(tokens[0]) # 'int' attribute object has no attribute 'append'
    return clist

def MakeIntList(tokens):
    nlist = tokens[0].split(",")
    ilist = []
    for n in nlist:
        ilist.append(int(n))
    return ilist

def MakeY(tokens):
    Yobj = Y(tokens[0])
    return Yobj

LEFT_BRACK = Suppress(Literal("["))
RIGHT_BRACK = Suppress(Literal("]"))

NATURAL = Word(nums).addParseAction(lambda n: int(n[0]))
NATURAL_LIST = delimitedList(NATURAL, combine = True)
NATURAL_VEC = LEFT_BRACK + NATURAL_LIST +  RIGHT_BRACK
NATURAL_VEC.addParseAction(MakeIntList)

X = NATURAL + NATURAL_VEC
X.addParseAction(MakeCombinedList)

Y = X
Y.addParseAction(MakeY)


print(Y.parseString("5 [1,2,3]").ls)

MakeIntList 应该将诸如 "1,2,3" 之类的字符串转换为列表 [1,2,3] .

MakeCombinedList 然后应该将一个整数附加到该列表中,但是 MakeCombinedList 收到的 token 不是单个整数和整数从 MakeIntList 创建的列表,而是所有整数的列表,如我的评论所示。

如何使 MakeCombinedList 内的 tokens[1] 成为调用 MakeIntList 的结果?

最佳答案

这两行代码相互矛盾,因为您使用第一行将单独的数字字符串解析为整数,然后第二行将它们组合回逗号分隔的字符串。

NATURAL = Word(nums).addParseAction(lambda n: int(n[0]))
NATURAL_LIST = delimitedList(NATURAL, combine=True)

您正在寻找的功能是群组:

NATURAL = Word(nums).addParseAction(lambda n: int(n[0]))
NATURAL_LIST = Group(delimitedList(NATURAL))
NATURAL_VEC = LEFT_BRACK + NATURAL_LIST +  RIGHT_BRACK
# no MakeIntList parse action required

现在,您不必创建一个新字符串,然后在解析操作中重新解析它,而是使用 Group 告诉 pyparsing 创建结果标记的子结构。

这里还存在一些困惑:

Y = X
Y.addParseAction(MakeY)

这会将 Y 从顶部定义的类重新定义为 pyparsing 表达式,并且在尝试访问其 ls 属性时,您会得到一些奇怪的回溯。

Y_expr = X
Y_expr.addParseAction(MakeY)

我编写了 runTests 方法,以便更轻松地进行简单的表达式测试和打印,而不必处理 Py2/Py3 打印差异:

Y_expr.runTests("""\
    5 [1,2,3]
    """)

演出:

5 [1,2,3]
[<__main__.Y object at 0x00000241C57B7630>]

由于您的 Y 类仅使用默认的 __repr__ 行为,因此如果您定义自己的行为,您可以更好地看到内容:

class Y():
    def __init__(self, ls):
        self.ls = ls
    def __repr__(self):
        return "{}: {}".format(type(self).__name__, vars(self))

现在 runTests 显示:

5 [1,2,3]
[Y: {'ls': 5}]

如果 Y 类的目的只是为您提供解析字段的属性名称,请考虑使用结果名称:

X = NATURAL('ls') + NATURAL_VEC

Y_expr = X
#~ Y_expr.addParseAction(MakeY)

# what you had written originally    
print(Y_expr.parseString("5 [1,2,3]").ls)

只会打印:

5

关于python - Pyparsing 解析操作并列出类型错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51858427/

相关文章:

python - Pyparsing中的关键字匹配 : non-greedy slurping of tokens

python - 无法使用 pyparsing 正确解析此文件

python - pyparsing - 定义关键字 - 比较文字、单词、关键字和组合

从终端窗口快速生成自定义合成音调序列的 Python 方法

python - 当链接将重定向到另一个时如何通过 urllib 获取内容?

python - 任务完成时间比预期要长得多

python - 使用 popen 和专用的 TTY Python 运行交互式 Bash

java - 如何从文本文件集合中提取某些值

python - Python 中多个类的混淆矩阵

python - 你能解释一下为什么我有这个吗?