3

给定以下最小的工作示例:

from pyparsing import *
latex_h  = QuotedString("$")('latex')
reg_text = Word(alphas)('text')
grammar  = OneOrMore( latex_h | reg_text )('line')

sol = grammar.parseString('''dog $x^2$ cat''')
print sol.dump()

我希望输出看起来像:

['dog', 'x^2', 'cat']
- line: ['dog', 'x^2', 'cat']
  - text: dog
  - latex: x^2
  - text: cat

但我得到了:

['dog', 'x^2', 'cat']
- latex: x^2
- line: ['dog', 'x^2', 'cat']
  - latex: x^2
  - text: cat
- text: cat

我不明白为什么在解析树中dog被遗忘了?另外,为什么text, latex 外边有两个元素line

4

1 回答 1

3

正如 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
于 2012-11-06T03:03:42.540 回答