正如 Russell Borogove 所说,在同一解析级别上,命名结果必须是唯一的。你不能有一个“行”包含两个或多个相同类型的命名元素(例如两个“文本”或两个“乳胶”),因为它们都将使用底层字典中的相同键。listAllMatches
关于最新 PyParsing 中的解决方案,我将遵从 Paul McGuire 的意见,正如他所写的那样:)
您还可以通过将解析操作附加到“latex_h”或“reg_text”来解决此问题,但是如果“latex_h”元素需要任何兄弟“reg_text”元素的知识,这将无济于事。在这种情况下,您可能需要进一步分解语法,或使用基于树的方法进行解析(从最低元素到根,通过解析操作和/或遍历结果列表) ,而不是基于字典的方法。
重要的是要注意解析树并没有留下“狗”。它被正确解析,只是解析结果没有分配给字典。您可以像这样访问解析的值:sol.line[0]
至于为什么'latex'和'cat'出现在'line'之外,你需要把OneOrMore定义放在一个Group()中。
这是一个示例,它在解析reg_text
元素时(而不是在解析任何父元素时)对元素应用解析操作grammar
。它不能解决您遇到的“命名结果”问题,但是如果没有关于您尝试使用解析器实现的内容的上下文,我无法提出解决方案。
from pyparsing import *
latex_h = QuotedString("$")('latex')
reg_text = Word(alphas)('text')
grammar = Group(OneOrMore( latex_h | reg_text ))('line')
def parse_reg_text(s, loc, toks):
if toks.text == 'dog':
return "atomic " + toks.text
else:
return "ninja " + toks.text
reg_text.setParseAction(parse_reg_text)
sol = grammar.parseString('''dog $x^2$ cat $y^3$''')
print sol.dump()
这给出了以下输出:
[['atomic dog', 'x^2', 'ninja cat', 'y^3']]
- line: ['atomic dog', 'x^2', 'ninja cat', 'y^3']
- latex: y^3
- text: ninja cat