首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >解析parseaction和lists typerror

解析parseaction和lists typerror
EN

Stack Overflow用户
提问于 2018-08-15 12:08:15
回答 1查看 43关注 0票数 1

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

下面是我的尝试。

代码语言:javascript
复制
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" )转换为list [1,2,3]

然后,MakeCombinedList应该在这个列表中追加一个整数,但是MakeCombinedList接收到的tokens不是单个整数和从MakeIntList创建的整数列表,而是所有整数的列表,如我的注释所示。

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

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-08-16 04:49:54

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

代码语言:javascript
复制
NATURAL = Word(nums).addParseAction(lambda n: int(n[0]))
NATURAL_LIST = delimitedList(NATURAL, combine=True)

您要寻找的功能是Group

代码语言:javascript
复制
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来生成结果标记的子结构。

这里也有一点混乱:

代码语言:javascript
复制
Y = X
Y.addParseAction(MakeY)

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

代码语言:javascript
复制
Y_expr = X
Y_expr.addParseAction(MakeY)

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

代码语言:javascript
复制
Y_expr.runTests("""\
    5 [1,2,3]
    """)

显示:

代码语言:javascript
复制
5 [1,2,3]
[<__main__.Y object at 0x00000241C57B7630>]

因为Y类只使用默认的__repr__行为,所以如果定义自己的内容,可以更好地查看内容:

代码语言:javascript
复制
class Y():
    def __init__(self, ls):
        self.ls = ls
    def __repr__(self):
        return "{}: {}".format(type(self).__name__, vars(self))

现在,runTests显示:

代码语言:javascript
复制
5 [1,2,3]
[Y: {'ls': 5}]

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

代码语言:javascript
复制
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)

只需打印:

代码语言:javascript
复制
5
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51858427

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档