gpt4 book ai didi

python - 使用 dump() 和 asXML() 函数时 pyparsing 不同的结果

转载 作者:太空宇宙 更新时间:2023-11-04 03:43:33 28 4
gpt4 key购买 nike

我在使用 pyparsing 解析结果时遇到问题。我有一个语法来解析一个表达式。在语法中的每个规则中都有 setResultName() 函数,因此我可以轻松地操作解析结果。但是当使用 dump() 函数查看结果的组织方式时,它不会显示所有解析的结果。但是,当使用 asXML() 函数时,所有结果都在那里并且按照我想要的方式构建。

语法如下:

# Rule for any alphanumeric word
identifier = Word(alphas, alphas + nums)

# Rule for "e" in floating point numbers
e = CaselessLiteral('E')

# Rule for booleans
boolean = (Keyword('True')
| Keyword('False')
).setParseAction(lambda tokens: bool(tokens[0])).setResultsName("boolean")

# Rule for integer numbers
integer = Word(nums).setParseAction(lambda tokens: int(tokens[0]))

# Rule for factor operator
factor_operator = (Literal('*')
| Literal('/')
| Literal('%')
).setResultsName("operator")

# Rule for term operator
term_operator = (Literal('+')
| Literal('-')
).setResultsName("operator")

# Rule for double numbers
double = Combine(integer +
Optional(Literal('.') + Optional(integer)) +
Optional(e + Optional(term_operator) + integer)
).setParseAction(lambda tokens: float(tokens[0])).setResultsName("double")

# Forwarding expression rule
expression = Forward()

# Rule define type of factor
factor = Group((
Literal('(').suppress() +
expression.setResultsName("expression") +
Literal(')').suppress())
| double
| boolean
).setResultsName("factor")

# Rule for factors
factors = Group(ZeroOrMore(factor_operator + factor)).setResultsName("factors")

# Rule for term
term = Forward()
term << Group(factor + delimitedList(factors)).setResultsName("term")

# Rule for terms
terms = Group(ZeroOrMore(term_operator + term)).setResultsName("terms")

# Rule for expression
expression << Group(Optional(term_operator) + term + delimitedList(terms)
).setResultsName("expression")

return expression

这是我要解析的表达式:

"(2 * 3) + 20 / 5 - 1"

这里是 dump() 的输出:

[[[[[[[2.0], ['*', [3.0]]], []]], []], ['+', [[20.0], ['/', [5.0]]], '-', [[1.0], []]]]]
- expression: [[[[[[2.0], ['*', [3.0]]], []]], []], ['+', [[20.0], ['/', [5.0]]], '-', [[1.0], []]]]
- term: [[[[[2.0], ['*', [3.0]]], []]], []]
- factor: [[[[2.0], ['*', [3.0]]], []]]
- expression: [[[2.0], ['*', [3.0]]], []]
- term: [[2.0], ['*', [3.0]]]
- factor: [2.0]
- double: 2.0
- factors: ['*', [3.0]]
- factor: [3.0]
- double: 3.0
- operator: *
- terms: []
- factors: []
- terms: ['+', [[20.0], ['/', [5.0]]], '-', [[1.0], []]]
- operator: -
- term: [[1.0], []]
- factor: [1.0]
- double: 1.0
- factors: []

以及 asXML() 的输出:

<expression>
<expression>
<term>
<factor>
<double>2.0</double>
</factor>
<factors>
<operator>*</operator>
<factor>
<double>3.0</double>
</factor>
</factors>
</term>
<terms>
<operator>-</operator>
<term>
<factor>
<double>20.0</double>
</factor>
<factors>
<operator>/</operator>
<factor>
<double>5.0</double>
</factor>
</factors>
</term>
<operator>+</operator>
<term>
<factor>
<double>1.0</double>
</factor>
<factors>
</factors>
</term>
</terms>
</expression>
</expression>

问题出在带括号的嵌套表达式之后的术语标签上。在 xml 中,它显示其中的所有术语(即“+”、“20.0/5.0”、“-”、“1.0”),这应该是一个运算符和术语列表。使用 dump() 函数时,它仅显示最后一个运算符和术语(即“-”、“1.0”)。谁能帮我理解这个?有什么我想念的吗?抱歉,我没有说清楚。

最佳答案

如果 dump()asXML() 之间存在差异,我更可能将其视为 asXML() 中的错误>。该方法被迫对需要的内容进行相当多的“猜测”,在某些情况下我很容易看出它猜错了。

pyparsing 的默认行为是将所有已解析的标记作为一个简单的字符串列表返回。无论解析器是如何构建的,它都会这样做。这是为了

(A + B + C).parseString

AA = A + B
(AA + C).parseString

and

DD = B + C
(A + DD).parseString

所有返回相同的东西。

让我们看一个简单的语法,名字/年龄对的倍数:

test = "Bob 10 Sue 12 Henry 7"

这是我们的解析器:

name = Word(alphas)
integer = Word(nums)

parser = OneOrMore(name + integer)

# or you can use the new multiplication syntax
parser = (name + integer) * (1,)

使用给定的示例文本和上述解析器,这将是:

['Bob', '10', 'Sue', '12', 'Henry', '7']

现在这并不难走完,一次阅读两个项目。但是,如果有额外的可选字段,那么事情就会变得更加棘手。因此,告诉 pyparsing 每个人的姓名和年龄应该分组在一起要容易得多。

parser = OneOrMore(Group(name + integer))

现在我们得到了每个人的子列表,并且无需猜测是否可能有其他选项。

[['Bob', '10'], ['Sue', '12'], ['Henry', '7']]

如果您将结果名称添加到原始未分组的解析器,我们会看到这一点(我使用的是"new"可调用语法,而不是冗长且令人分心的“setResultsName”调用格式):

parser = OneOrMore(name("name") + integer("age"))
result = parser.parseString(test)

了解我们现在对未分组结果的了解,如果我们要求 result.name,我们应该得到哪个名称?

如果您遇到多个表达式共享相同结果名称的情况,那么您有 3 个选项:

  • 只保留最后一个被解析(默认,这就是你所看到的)

  • 使用 Group 类添加分组,以便将多个共享结果分成不同的子结构

  • listAllItems=True 参数添加到 setResultsName()

    parser = (OneOrMore(name.setResultsName("name", listAllItems=True)
    + integer.setResultsName("age", listAllItems=True)))

    或者如果使用缩写的可调用格式,请在结果名称的末尾添加“*”:

    parser = OneOrMore(name("name*") + integer("age*"))

现在 result.name 将为您提供列表中所有已解析的名称,result.age 将为您提供相应的年龄。但对于这样的数据,我更愿意看到数据被解析成组。

parser = OneOrMore(Group(name("name") + integer("age")))

如果您希望 asXML() 使用标签“person”来标记每个组,然后将该名称添加到组中,并使用尾随的“*”来捕获所有组。

parser = OneOrMore(Group(name("name") + integer("age"))("person*")

(这已经是一个冗长的答案,所以我省略了这些测试的 dump() 和 asXML() 输出 - 留作 OP 和 future 读者的练习。)

关于python - 使用 dump() 和 asXML() 函数时 pyparsing 不同的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24982455/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com