简体   繁体   English

Pyparsing解析并列出typerror

[英]Pyparsing parseaction and lists typerror

For a small language I want to parse expressions of the form "X [Y,Z,V]" where X , Y , Z , V are natural numbers. 对于一种小语言,我想解析"X [Y,Z,V]"形式的表达式,其中XYZV是自然数。

Below is my attempt. 以下是我的尝试。

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 is supposed to transform a string such as "1,2,3" into the list [1,2,3] . MakeIntList应该将诸如"1,2,3"类的字符串转换为列表[1,2,3]

MakeCombinedList is then supposed to append an integer to this list, but the tokens received by MakeCombinedList are not the single integer and the integer list created from MakeIntList , but a list of all the integers, as indicated by my comment. 然后,应该将MakeCombinedList追加到此列表中,但MakeCombinedList接收到的tokens不是单个整数和从MakeIntList创建的整数列表,而是所有整数的列表,如我的注释所示。

How can I make tokens[1] inside MakeCombinedList be the result of calling MakeIntList ? 我怎样才能使MakeCombinedList内的tokens[1]成为调用MakeIntList的结果?

These two lines are working against each other, since you use the first to parse separate numeric strings into ints, and then the second just combines them back into a comma-separated string. 这两行是相互冲突的,因为您使用第一行将单独的数字字符串解析为int,然后使用第二行将它们重新组合成一个逗号分隔的字符串。

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

The feature you are looking for is Group : 您要查找的功能是Group

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

Now instead of creating a new string and then re-parsing it in a parse action, you use Group to tell pyparsing to make a sub-structure of the resulting tokens. 现在,您无需使用解析操作来创建新的字符串,而是使用Group告诉pyparsing生成结果标记的子结构,而不是创建新的字符串,然后在解析操作中对其进行重新解析。

There is also a little confusion going on here: 这里还有些混乱:

Y = X
Y.addParseAction(MakeY)

This will redefine Y from the class defined at the top to a pyparsing expression, and you get some weird traceback when trying to accessing its ls attribute. 这会将Y从顶部定义的类重新定义为pyparsing表达式,并且在尝试访问其ls属性时会得到一些奇怪的回溯。

Y_expr = X
Y_expr.addParseAction(MakeY)

I wrote the runTests method to make it easier to do simple expression testing and printing, without having to deal with Py2/Py3 print differences: 我编写了runTests方法,以使其更容易进行简单的表达式测试和打印,而不必处理Py2 / Py3的打印差异:

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

Shows: 显示:

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

Since your Y class just uses the default __repr__ behavior, you can see the contents better if you define your own: 由于您的Y类仅使用默认的__repr__行为,因此,如果您定义自己的类,则可以更好地查看内容:

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

Now runTests shows: 现在,runTests显示:

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

If the purpose of the Y class is to just give you attribute names for your parsed fields, consider using results names instead: 如果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)

Will just print: 只会打印:

5

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM