python - Pyparsing 使用 Forward 解析递归表达式

标签 python pyparsing

我正在尝试递归地解析一个表达式。我遵循了一些教程,看起来 Forward() 是我需要的类。然而,一些看似简单的事情却给我带来了麻烦。

这是我写的代码

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

我希望它返回 ['1','+','1'] 但它只返回 ['1']

非常感谢您的帮助。

最佳答案

这里有几个问题。按重要性升序排列:

  1. 如果解析后的内容后有额外的文本,parseString 不会引发异常。使用 exp.parseString(input, parseAll=True)
  2. '|'是 MatchFirst,而不是 MatchLongest。由于您的整数是第一个,因此它将首先匹配。然后解析器在“+”上失败了。如果您想要最长的匹配,请使用“^”运算符。
  3. 要点:一旦您转换为“^”(或重新排序表达式以将 exp + exp 放在前面,整数之前),您会发现自己超出了最大递归深度。那是因为此解析器具有 exp 的左递归定义。 .也就是说,解析 exp , 它必须解析 exp ,为此它必须解析 exp等。一般来说,许多已发布的 BNF 使用递归来描述这种重复结构,但 pyparsing 不会为此工作进行必要的先行/回溯。尝试 exp <<= integer + ZeroOrMore('+' + integer) | '(' + exp + ')' - 这个表达式不是左递归的,因为在解析嵌套的 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例子最接近这种风格;自从写了那个,我添加了 infixNotation pyparsing 的方法,这将允许您编写:

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

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

关于python - Pyparsing 使用 Forward 解析递归表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43745793/

相关文章:

python - 在二维空间中计算欧氏距离的最快方法

python - 使用 pyparsing 从字符串中获取所有数字作为列表

python - pyparsing:命名结果?

python - 在 django rest 中自定义序列化器输出

python - 从 numpy 距离数组中提取 N 个最近的对

python - 如何使用 x = A 列,但颜色/色调 = B 列分类变量进行绘图

python - 使用 pyparsing 解析嵌套结构

python - 将现有 pandas 数据框中的一些行复制到新数据框中

python - 如何使用 pyparsing 验证 bool 表达式语法?

python - 为什么 pyparsing 中的有序选择对于我的用例失败?