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



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

123 456
-^- -^-
[A]  B

其中 A 部分和B部分都只包含数字,而 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类中的替代方案......

有什么建议怎么办?

你误解了 或者,它应该是:

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式的。

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

最新更新