返回错误的无效解析`rep`内(Returning Error for Invalid Parse

2019-09-27 05:50发布

在下面的DSL,我成功地解析“富”,其次是0个或多个repititions conj ~ noun

object Foo extends JavaTokenParsers { 

  def word(x: String) = s"\\b$x\\b".r

  lazy val expr  = word("foo") ~ rep(conj ~ noun)

  val noun   = word("noun")
  val conj   = word("and") | err("not a conjunction!")

}

信用 :感谢特拉维斯布朗解释为需要word功能在这里 。

测试掉无效的结合时,它看起来不错。

scala> Foo.parseAll(Foo.expr, "foo an3 noun")
res29: Foo.ParseResult[Foo.~[String,List[Foo.~[java.io.Serializable,String]]]] =
[1.5] error: not a conjunction!

foo an3 noun
    ^

但是,另一项测试表明,它不工作- foo and noun应该会成功。

scala> Foo.parseAll(Foo.expr, "foo and noun")
res31: Foo.ParseResult[Foo.~[String,List[Foo.~[java.io.Serializable,String]]]] =
[1.13] error: not a conjunction!

foo and noun
            ^

由于该传入的字符串包含foo and noun ,我不知道其他字符/正在读什么记号。

我已经取代上述errfailure ,但是这是没有好或者:

scala> Foo.parseAll(Foo.expr, "foo a3nd noun")
res32: Foo.ParseResult[Foo.~[String,List[Foo.~[java.io.Serializable,String]]]] =
[1.5] failure: string matching regex `\z' expected but `a' found

foo a3nd noun
    ^

我相信, Parsers#rep介绍了过去failure消息:

def rep[T](p: => Parser[T]): Parser[List[T]] = rep1(p) | success(List())

在此基础上优秀的答案 ,我的理解是, rep1(p)其中P是conj ~ noun )将会失败,导致success(List())因为未能允许后台跟踪)。 但是,我不完全知道为什么success(List())不回来了-失败的消息称: failure: string matching regex '\z' expected but 'a'' found -它预计行尾。

Answer 1:

让我们一步步通过时会发生什么步骤foo and noun被越来越解析:

  • word("foo")被尝试过,它匹配并且消耗foo从输入
  • rep被试,
  • conj被试,
    • word("and")被尝试过,它匹配并且消耗and从输入和
    • 因此第二分支( err )甚至没有进行测试,
  • word("noun")被尝试过,它匹配并且消耗noun从输入
  • rep开始循环:
    • word("and")的尝试,它不匹配,
    • 因此err的审判,由于其本身的定义, 它返回一个错误,在这里结束了解析

你其实不愿意err ,以尽快测试word("and")不匹配,因为它不能匹配了一个很好的理由:我们已经到达EOF。

因此,让我们检测EOF,只有尝试解析连词,如果我们有更多的投入。 让我们写一个解析器,做的是:

def notEOF: Parser[Unit] = Parser { in =>
    if (in.atEnd) Failure("EOF", in) else Success((), in)
  }

接着:

val conj = notEOF ~> (word("and") | " *".r ~> err("not a conjunction!"))

EOF ,这将返回失败,因此rep可以停止循环,并与任何有回报。 否则,它会尝试解析and ,如果没有犯错。 请注意,我用的是" *".r伎俩 ,以确保err总是赢。



文章来源: Returning Error for Invalid Parse inside of `rep`