【问题标题】:Scala PackratParsers: backtracking seems not to workScala PackratParsers:回溯似乎不起作用
【发布时间】:2014-07-28 02:35:00
【问题描述】:

以下 scala 代码无法按预期工作:

import scala.util.parsing.combinator.PackratParsers
import scala.util.parsing.combinator.syntactical.StandardTokenParsers
import scala.util.parsing.combinator.lexical.StdLexical

object Minimal extends StandardTokenParsers with PackratParsers {
  override val lexical = new StdLexical

  lexical.delimiters += ("<", "(", ")")

  lazy val expression: PackratParser[Any] = (
  numericLit
  | numericLit ~ "<" ~ numericLit
  )

  def parseAll[T](p: PackratParser[T], in: String): ParseResult[T] =
    phrase(p)(new PackratReader(new lexical.Scanner(in)))

  def main(args: Array[String]) = println(parseAll(expression, "2 < 4"))
}

我收到错误消息:

[1.3] failure: end of input expected

2 < 4
  ^

但是,如果我将“表达式”的定义更改为

  lazy val expression: PackratParser[Any] = (
    numericLit ~ "<" ~ numericLit
  | numericLit
  )

问题消失了。

问题似乎在于,对于“表达式”的原始定义代码,应用了仅包含“numericLit”的第一条规则,因此解析器确实希望输入在之后立即结束。我不明白为什么解析器一注意到输入确实没有结束就不会回溯; scala PackratParsers 应该是回溯,我还确保按照另一个问题的答案中的建议将“def”替换为“lazy val”。

【问题讨论】:

    标签: scala backtracking parser-combinators


    【解决方案1】:

    您看到此行为的原因是交替运算符(竖线)旨在接受其第一个成功的备选方案。在您的情况下,numericLit 成功,因此替代方案从不考虑其他替代方案。

    使用这种语法规范,如果一个替代方案可以匹配另一个替代方案的前缀,您必须小心。如您所见,较长的替代项应放在替代项中的较早位置,否则永远不会成功。

    如果您希望较短的替代项仅在其后没有更多输入时才匹配,那么您可以尝试使用 not 组合器来表达该额外条件。但是,如果打算在其他构造中使用expression,这种方法会导致问题。

    【讨论】:

    【解决方案2】:

    它与packrat解析器无关。

    您需要知道的是,在PEG 中,选择运算符选择第一个匹配项,在您的情况下为numericLit

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-29
      相关资源
      最近更新 更多