scala - 解析器测试的意外结果

标签 scala parser-combinators

在以下解析器中:

object Foo extends JavaTokenParsers { 

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

  lazy val expr  = (foo ~ (conjGuard ~> rep(conj ~ noun))) | foo

  def noun      = {println("noun"); word("noun")}
  def conj      = {println("conj"); word("and") }
  def conjGuard = {println("conjGuard"); guard(conj) | f }
  def f         = {println("failure"); (" *".r) ~ failure("bad conj!")}

  def foo = {println("foo"); word("foo")}
}

为什么下面的示例将 conj 打印为最后一个打印输出?它从哪里来?

scala> Foo.parseAll(Foo.expr, "foo and noun")
foo
conjGuard
conj
conj
noun
conj
res71: Foo.ParseResult[java.io.Serializable] = [1.13] parsed: 
        (foo~List((and~noun)))

另外,为什么在这个例子中 foo 不首先打印出来?

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

foo an3 noun
    ^

最佳答案

Why is [it] printing out conj as the last printout?

您使用rep组合器,它将尝试解析 conj ~ noun连续尽可能多次。所以解析完foo and noun后,它将尝试解析 conj再次,conj将会失败,因为没有更多的输入,并且 rep不会失败,只会返回成功的解析。

尝试解析 conj 但失败第二次,它必须要求 conj再次解析器,因此最后一个 conj在输出中。

Also, why isn't foo printing out first in this example?

您使用 def 定义了解析器(而不是 vallazy val )在您使用 println 的任何地方,(正确地)认为否则你只会得到第一个 println ,但你陷入了与 lazy val expr 相同的陷阱:第一个foo , conjGuardconjFoo.expr只会评估一次。

替换lazy val通过def一切都恢复正常。


为了更好地了解发生的情况,您可以使用 log解析器而不是 println :

object Foo2 extends JavaTokenParsers { 

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

  def expr  = (foo ~ (conjGuard ~> rep(conj ~ noun))) | foo

  def noun      = log(word("noun"))("noun")
  def conj      = log(word("and"))("conj")
  def conjGuard = log(guard(conj) | f)("conjGuard")
  def f         = log((" *".r) ~ failure("bad conj!"))("failure")

  def foo = log(word("foo"))("foo")
}

例如:

scala> Foo2.parseAll(Foo2.expr, "foo and noun")
trying foo at scala.util.parsing.input.CharSequenceReader@764688bd
foo --> [1.4] parsed: foo
trying conjGuard at scala.util.parsing.input.CharSequenceReader@765c6526
trying conj at scala.util.parsing.input.CharSequenceReader@765c6526
conj --> [1.8] parsed: and
conjGuard --> [1.4] parsed: and
trying conj at scala.util.parsing.input.CharSequenceReader@765c6526
conj --> [1.8] parsed: and
trying noun at scala.util.parsing.input.CharSequenceReader@3a5c9b85
noun --> [1.13] parsed: noun
trying conj at scala.util.parsing.input.CharSequenceReader@222acbad
conj --> [1.13] failure: string matching regex `\band\b' expected but end of source found

foo and noun
            ^
res1: Foo2.ParseResult[java.io.Serializable] = [1.13] parsed: (foo~List((and~noun)))

关于scala - 解析器测试的意外结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25291916/

相关文章:

class - Scala:基于类型过滤

scala - 解析器组合器语法未产生正确的关联性

Scala 解析器组合器几乎是最后一个

scala - 如何从列表中获取特定项目?

scala - 玩scala框架webservice教程

java - 在 Android 上的 Scala 代码中改造 HTTP 报告 "HTTP method annotation is required"

scala - 比较 RDD 的子集

Scala 解析器组合器,大文件问题

scala - 为什么这组解析器组合器会溢出堆栈?

parsing - 不区分大小写的 Scala 解析器组合器