使用 pyparsing 分析时如何使两个语法等效部分的第一部分可选
How to make the first part of two syntactical equivalent parts optional when analysing with 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_b
是 Or
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_b
和 a_and_b
表达式的列表构造 Or)。
使用解析库 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
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_b
和 a_and_b
表达式的列表构造 Or)。