使用解析库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_b
是Or
类中的替代方案......
有什么建议怎么办?
你误解了 或者,它应该是:
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_b
和a_and_b
表达式的列表构造 Or)。