使用 pyparsing 分析时如何使两个语法等效部分的第一部分可选

How to make the first part of two syntactical equivalent parts optional when analysing with pyparsing

使用解析库 pyparsing 我想分析这样的结构:

123 456

-^- -^-
[A]  B

其中 AB 部分仅包含数字,A 部分是可选的。这里有一些例子,解析器如何将字符串分解成它们的部分:

123 456 ==> A="123", B="456"
456     ==> A="",    B="456"
123     ==> A="",    B="123"
1 123   ==> A="1",   B="123"

编写解析器的本机方法如下所示:

a = pp.Optional(pp.Word(pp.nums)).setName("PART_A")
b = pp.Word(pp.nums).setName("PART_B")
expr = a('A')  + b('B')

此解析器适用于 "123 456" 按预期返回 {'A': '123', 'B': '456'}。但是它在 "456" 上失败了:

ParseException:
Expected PART_B (at char 3), (line:1, col:4)
"456>!<"

这是可以理解的,因为可选部分 A 已经消耗了应该匹配部分 B 的文本,即使 A 是可选的...我的想法是设置一个 stopOn= 选项,但它需要停止在与要匹配的表达式相同类型的表达式上...

更新: 我的第二个想法是将 Optional 结构重写为 Or 结构:

a = pp.Word(pp.nums).setName("PART_A")('A')
b = pp.Word(pp.nums).setName("PART_B")('B')
just_b = b
a_and_b = a + b
expr = pp.Or(just_b, a_and_b)

但是,对于 "123 456" 形式的文本,这现在失败了 - 尽管 a_and_bOr class 中的替代...

有什么建议吗?

你误解了或者,应该是:

expr = pp.Or([just_b, a_and_b])

按照您构建它的方式,Or 仅使用 just_b 构建,a_and_b 作为布尔参数传递 savelist

请考虑使用运算符重载来构造 And、Or、MatchFirst 和 Each 表达式。

integer = pp.Word(pp.nums)

a = integer("A")
b = integer("B")

expr = a + b | b

显式风格看起来就是这样,嗯,Java-ish。

要回答标题中的问题,您几乎已经解决了这个问题:请务必尝试匹配完整的 a_and_b 表达式,方法是将其放在 MatchFirst 中(如我的示例代码所做的那样) ,或通过使用 Or 表达式(使用“^”运算符,或通过使用 just_ba_and_b 表达式的列表构造 Or)。