python 使用Forward解析递归表达式

hc2pp10m  于 2023-02-11  发布在  Python
关注(0)|答案(2)|浏览(171)

我正在尝试递归解析一个表达式。我看了一些教程,看起来Forward()是我需要的类。然而,一些看似简单的东西却给我带来了麻烦。
这是我写的代码

from pyparsing import *
exp = Forward()
integer = Word(nums)
exp << (integer | (exp + '+' + exp))
input = "1+1"
print exp.parseString(input)

我希望它返回['1','+','1'],但它只返回['1']
非常感谢帮助。

mpgws1up

mpgws1up1#

你现在有几个问题。按重要性升序排列:
1.如果在解析的内容之后有额外的文本,parseString将不会引发异常。
1.“|“”是MatchFirst,而不是MatchLongest。由于您的整数是第一个,因此将首先匹配该整数。然后,分析器将自动在“+”上失败。如果希望匹配最长时间,请使用“^”运算符。
1.大人物:转换为“^”后(或者重新排序表达式,把exp + exp放在整数前面),你会发现自己放大了最大递归深度,这是因为这个解析器有exp的左递归定义,也就是说,要解析一个exp,它必须解析一个exp,它必须解析一个exp,等等。许多已发布的BNF使用递归来描述这种重复的结构,但是pyparser并不做必要的前视/后视。尝试exp <<= integer + ZeroOrMore('+' + integer) | '(' + exp + ')'-这个表达式是 not left-recursive,因为在解析嵌套的exp之前,您必须越过一个左括号。
编辑:对不起,我之前的建议有点太快了,下面是正确的递归表达式解析方法:

from pyparsing import *

exp = Forward()
LPAR, RPAR = map(Suppress, "()")
integer = Word(nums)
term = integer | Group(LPAR + exp + RPAR)
exp << term + ZeroOrMore('+' + term)

input = "(1+1) + 1"
print(exp.parseString(input))

印刷品

[['1', '+', '1'], '+', '1']

如果你跟踪代码,你会看到递归:exp使用term定义,term使用exp定义。fourFn.py示例最接近这种样式;在写了这篇文章之后,我在pyparser中添加了infixNotation方法,它允许您编写:

exp = infixNotation(integer, [
                    ('+', 2, opAssoc.LEFT),
                    ])

infixNotation在内部负责递归定义,隐式定义'(' + exp + ')'表达式,并使实现具有运算优先级的运算符系统变得容易。

rdrgkggo

rdrgkggo2#

我最近遇到了这个问题,现在PyParsing 3.0.0b2以上支持左递归,但需要显式启用,|操作符的操作数顺序需要调整如下。

from pyparsing import ParserElement, Forward, Word, nums

ParserElement.enable_left_recursion()
exp = Forward()
integer = Word(nums)
exp << ((exp + '+' + exp) | integer)
input = "1+1"
print(exp.parseString(input))

这将输出以下内容。

['1', '+', '1']

相关问题