[英]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]"
形式的表达式,其中X
, Y
, Z
, V
是自然数。
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.