2

我在下面有一个用 pyparsing 编写的简单解析器:

import pyparsing as pp

Token = pp.Word(pp.alphas)("Token")
Modifier = pp.Word(pp.nums)("Modifier")

Random = pp.Group(pp.Keyword("?") + pp.OneOrMore(Modifier))("Random")
Phrase = pp.Group(Token + pp.OneOrMore(Modifier))("Phrase")

Collection = pp.Group(pp.delimitedList(Phrase ^ Random, ","))("Collection")

tree = Collection.parseString("hello 12 2, ? 1 2, word 4, ? 3 4, testing 5")

然后我尝试这样做:

>>> for name, item in tree[0].items():
        print name, item
Phrase ['testing', '5']
Random ['?', '3', '4']

...但由于某种原因,它只返回树中的最后一个PhraseRandom项目。我怎样才能得到所有这些?

(注意:我也尝试过这样做:

>>> for item in tree[0]:
        print item
['hello', '12', '2']
['?', '1', '2']
['word', '4']
['?', '3', '4']
['testing', '5']

...但如您所见,它不会返回我需要的令牌名称。我也试过做item.name,但那些总是返回空字符串。)

如何遍历 pyparsing 树并按顺序获取每个项目以及分配的名称?

4

1 回答 1

3

ParseResults 可以通过调用获得它们的定义名称getName()

>>> for f in tree[0]: print f.getName(), f.asList()
... 
Phrase ['hello', '12', '2']
Random ['?', '1', '2']
Phrase ['word', '4']
Random ['?', '3', '4']
Phrase ['testing', '5']

您还可以恢复使用setResultsName并将listAllMatches参数设置为 True。在 1.5.6 版本中,expr("name")快捷方式得到了增强,如果名称以 '*' 结尾,则相当于expr.setResultsName("name", listAllMatches=True). 以下是通过设置此标志来更改输出的方式:

>>> Random = pp.Group(pp.Keyword("?") + pp.OneOrMore(Modifier))("Random*")
>>> Phrase = pp.Group(Token + pp.OneOrMore(Modifier))("Phrase*")
>>> Collection = pp.Group(pp.delimitedList(Phrase ^ Random, ","))("Collection")
>>> tree = Collection.parseString("hello 12 2, ? 1 2, word 4, ? 3 4, testing 5")
>>> print tree.dump()
[[['hello', '12', '2'], ['?', '1', '2'], ['word', '4'], ['?', '3', '4'], ['testing', '5']]]
- Collection: [['hello', '12', '2'], ['?', '1', '2'], ['word', '4'], ['?', '3', '4'], ['testing', '5']]
  - Phrase: [['hello', '12', '2'], ['word', '4'], ['testing', '5']]
  - Random: [['?', '1', '2'], ['?', '3', '4']]
于 2012-07-26T18:46:35.223 回答