Pyparsing - 递归返回意外结果

时间:2014-08-13 03:18:43

标签: python python-2.7 text-processing pyparsing

我正在努力解决基本的递归pyparsing问题。第一个问题是为什么要添加一个额外的元组层,第二个问题是它为什么不拆分list_pattern元素。

def parse_tree_to_dict(data):

    import pyparsing as pp

    _printables = list(pp.printables) + [" "]
    _printables = "".join([x for x in _printables if x not in ["|", "}", "{"]])

    word_pattern = pp.Word(_printables)
    list_pattern = pp.delimitedList(pp.OneOrMore(word_pattern), "|")

    itemlist = pp.dictOf(list_pattern, pp.nestedExpr("{", "}"))
    items = itemlist.parseString(data)

    # print(items.dump())
    print(items.asDict())
    return items.asDict()


if __name__ == "__main__":

    s = "a1{a3|b3}"
    data = parse_tree_to_dict(s)

当你运行它时,你得到这个:

{'a1': (['a3|b3'], {})}

所以元组来自哪里,以及为什么list_pattern没有分开 - 我至少会有预期

{'a1': ['a3', 'b3']}

当我们添加更复杂的结构时,递归组件似乎正在工作,但是会出现相同的基本问题。

    s = "a1{b2{a3|b3}c2{d3|e3}e2{a4}}b1{a6|b7}"
    data = parse_tree_to_dict(s)

这将导致

{'a1': (['b2', (['a3|b3'], {}), 'c2', (['d3|e3'], {}), 'e2', (['a4'], {})], {}), 'b1': (['a6|b7'], {})}

任何人都可以帮助我吗?谢谢你的期待......

1 个答案:

答案 0 :(得分:1)

你有几个踩在一起的表情。您可以尝试为dict值定义list_pattern,但是在定义dictOf时,可以使用list_pattern作为键,使用通用nestedExpr作为值。 nestedExpr不会对' |'做任何特别的事情。分隔符,它只是在' {' '}'嵌套字符并为其提供可打印字词的列表。因为' a3 | b3'没有空格,nestedExpr只是将它作为一个单词返回。

在我看来,你的dict是由一个单词组成的键组成,后跟一个可能嵌套的子句。这是实现这一目标的第一步(我不认为这将完全为您提供嵌套的dict输出,但它是一个开始):

list_pattern = pp.Forward()
LBR,RBR = map(pp.Suppress,"{}")
list_pattern << pp.delimitedList(pp.OneOrMore(word_pattern|pp.Group(LBR+list_pattern+RBR)), "|")

itemlist = pp.dictOf(word_pattern, list_pattern)

这将解析您的数据,并为您提供&#39; a3&#39;的值列表。和&#39; b3&#39;。

{'a1': (['a3', 'b3'], {})}

你问题的第二部分是&#34;那个元组来自哪里?&#34;好吧, 没有元组,你看到的是pyparsing的ParseResults类型的完整repr输出。由于ParseResults提供了解析标记列表和命名结果的双重接口,因此它的repr是标记的元组和结果名称的字典。

如果我们尝试按键访问第一项的值,您可以更清楚地看到这一点:

print data.keys()[0]
print data[data.keys()[0]]  # or print data['a1']

打印

a1
['a3', 'b3']

您始终可以使用asList()将ParseResults折叠到实际列表。

另外,查看Word类的新构造函数参数excludeChars。使用printables 中的所有字符(除外)可以更容易地定义Word,以便排除少数字。