pyparsing:使用简单算术的嵌套表达式

时间:2019-01-16 01:25:14

标签: python-3.x math pyparsing

我正在使用pyparsing解析由分隔列表形成但包含一些基本算术(例如,只是乘法)的嵌套表达式。 一个示例表达式可能如下所示:

(A, B, 2 * C, 3 * ( D, E, 2 * F, 3 *(G, H)), I )

输出应展开算术运算:

( A, B, C, C, D, E, F, F, G, H, G, H, G, H, D, E, F, F, G, H, G, H, G, H, D, E, F, F, G, H, G, H, G, H, I )

有人可以提示我如何解决该问题吗?

我开始如下:由于只存在运算乘法,所以我决定在有些奇怪的列表中使用'*'字符作为分隔符:

import pyparsing as pp

oddDelim = pp.Or([',', '*'])
weirdList = pp.Optional(',').suppress() + \
            pp.delimitedList(pp.Or([pp.alphas, pp.pyparsing_common.number]), delim = oddDelim, combine = False) + \
            pp.Optional('*').suppress()
nestedTest = pp.nestedExpr(content = weirdList)

使用此nestedTest表达式,我得到一个合理的结果:

[['A', 'B', 2, 'C', 3, ['D', 'E', 2, 'F', 3, ['G', 'H']], 'I']]

但是我不知道应该如何解析标记以便正确展开算术运算。

理想情况下,我不是想在FOR循环中按顺序遍历令牌,而是希望从最高的嵌套程度开始逐步展开算法,然后逐步下降。但是我不知道怎么...

nestedExpr是要走的路吗?还是应该更改方法并使用Forward或infixNotation?我对pyparsing非常陌生,如果对此有一些提示/想法,将不胜感激。

非常感谢您的帮助!

干杯, 波城

1 个答案:

答案 0 :(得分:1)

如果您想使用Forward()来滚动我们自己的递归语法,则最好开始 为您的语法编写BNF。这将帮助您直接考虑 问题空间,然后再担心编码。

以下是您发布的内容的粗略BNF:

list_expr ::= '(' list_item [',' list_item]* ')'
list_item ::= term | mult_term | list_expr
mult_term ::= integer '*' list_item
term      ::= A-Z

也就是说,括号中的每个列表都有一个逗号分隔的列表 项,并且每个项可以是单个字符项,乘法表达式 一个整数,一个“ *”和一个项目,或者另一个括号中的嵌套列表。

要将其转换为pyparsing,请自下而上定义每个表达式。对于 实例,使用新的Char类(一个单字符)定义一个术语 来自一串允许的字符):

term = pp.Char("ABCDEFGHI... etc.")

您需要将Forward用于list_item,因为它将需要以下表达式: 尚未定义,因此Forward()为您提供了一个占位符。那当你有 术语,mult_term和list_expr定义,使用“ << =”“插入”定义 放入现有的占位符,如下所示:

list_item <<= term | mult_term | list_expr

由于您询问了infixNotation,因此我也将讨论这种方法。 使用infixNotation时,请查看您的输入并确定构成什么 分组,运算符和操作数。

这里的分组很容易,它是使用()进行的, 这是非常标准的,默认情况下,infixNotation会将其视为此类。

下一步确​​定最低级别 操作数是。您有两种类型的操作数:整数和单字母 字符。

两个运算符分别为“ *”和“。”。

由于您只要求提出建议,所以我会停在那里,让您解决/奋斗 自行完成下一步。