【问题标题】:Why does `OneOrMore` fails with more than one expression in pyparsing?为什么`OneOrMore`在pyparsing中有多个表达式失败?
【发布时间】:2016-12-07 06:53:52
【问题描述】:

好的,我组装了一个解析器来解析像这样的表达式

abc def ghi LONG|SHORT 12345

----^------ ----^----- --^--
 A: alphas  B: choice  C: num

pyparsing 编写的解析器如下所示:

a = pp.OneOrMore(pp.Word(pp.alphas)).setName("PRT_A")
b = pp.Or(['LONG','SHORT']).setName("PRT_B")
c = pp.Word(pp.nums).setName("PRT_C")
expr = a('A') + b('B') + c('C')

当我向其中输入“某事说 SHORT 13”时:

res = expr.parseString("something said SHORT 13")

我得到错误:

ParseException: 
Expected {"LONG" ^ "SHORT"} (at char 21), (line:1, col:22)
"something said SHORT >!<13"

为什么?我认为OneOrMore 应该将所有单词加起来,直到出现 LONG|SHORT 选择...

【问题讨论】:

  • @user2357112 我已将问题简化为仅包含前瞻问题-我认为,使问题更清晰,更有价值。您介意相应地更新(现在接受的)答案吗(即删除关于Combine 的内容)?
  • 答案已更新,但您还应该更新问题中的错误消息。没有Combine 的版本应该在以后的位置产生错误。

标签: python grammar text-parsing pyparsing


【解决方案1】:

这里的问题是pp.Word(pp.alphas) 包含"LONG""SHORT",导致b 无法匹配。您需要防止它匹配这些关键字,例如带有否定前瞻:

b = pp.Or(['LONG','SHORT']).setName("PRT_B")
a = pp.OneOrMore(~b + pp.Word(pp.alphas)).setName("PRT_A")

或者为OneOrMore 使用stopOn 选项:

b = pp.Or(['LONG','SHORT']).setName("PRT_B")
a = pp.OneOrMore(pp.Word(pp.alphas), stopOn=b).setName("PRT_A")

【讨论】:

  • 重点不是Combine,而是OneOrMore。没有周围的组合也会出现同样的问题。 (也许我应该摆脱该示例的组合...)
  • @halloleo:不,事实证明您有两个错误,即组合错误和第二个错误。如果你取出组合,你会得到一个不同的错误。
  • 不幸的是,ignore() 用于包含可忽略的表达式,就像空白是可忽略的一样——通常是 cmets。但是您对第二个错误的描述已经死了。为了解决这个问题,OneOrMore 有一个 stopOn 选项,用于在看到通常匹配 OneOrMore 表达式的表达式时停止匹配。此外,正如您所说,Combine 也是有问题的 - 也许 Group 更合适。
  • 要遵循您忽略的建议,在这种情况下,请使用否定前瞻:a = ~b + pp.Word(pp.alphas)
  • @PaulMcGuire 我知道问题在于 a 匹配 b。并且“.ignore(b”) 解决方案对我来说很有意义(明天将对其进行测试)。但是使用否定前瞻:a = ~b + pp.Word(pp.alphas) 对我来说没有意义。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-30
  • 1970-01-01
  • 1970-01-01
  • 2023-04-03
相关资源
最近更新 更多