在以下解析器中:
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
定义了解析器(而不是 val
或 lazy val
)在您使用 println
的任何地方,(正确地)认为否则你只会得到第一个 println
,但你陷入了与 lazy val expr
相同的陷阱:第一个foo
, conjGuard
和conj
在Foo.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/