在下面的Parser中:
object Foo extends JavaTokenParsers {
def word(x: String) = s"\\b$x\\b".r
lazy val expr = aSentence | something
lazy val aSentence = noun ~ verb ~ obj
lazy val noun = word("noun")
lazy val verb = word("verb") | err("not a verb!")
lazy val obj = word("object")
lazy val something = word("FOO")
}
它会解析noun verb object
。
scala> Foo.parseAll(Foo.expr, "noun verb object")
res1: Foo.ParseResult[java.io.Serializable] = [1.17] parsed: ((noun~verb)~object)
但是,在输入有效的noun
但无效的verb
时,为什么err("not a verb!")
会使用该特定错误消息返回Error?< / p>
scala> Foo.parseAll(Foo.expr, "noun vedsfasdf")
res2: Foo.ParseResult[java.io.Serializable] =
[1.6] failure: string matching regex `\bverb\b' expected but `v' found
noun vedsfasdf
^
信用:感谢Travis Brown解释了对word
函数here的需求。
此question似乎相似,但我不确定如何使用err
函数处理~
。
答案 0 :(得分:3)
这是您可能会问的另一个问题:为什么它没有抱怨它期待“&#34; FOO&#34;但得到了&#34;名词&#34;?毕竟,如果它无法解析aSentence
,那么它将尝试something
。
当你想到它时,罪魁祸首应该是显而易见的:源代码中有两个Failure
结果并选择一个? |
(又名append
)。
Parser
上的此方法会将输入提供给两个解析器,然后在append
上调用ParseResult
。该方法在该级别是抽象的,并以Success
,Failure
和Error
以不同方式定义。
在Success
和Error
上,它始终采用this
(即左侧的解析器)。但是,在Failure
上,它还有其他功能:
case class Failure(override val msg: String, override val next: Input) extends NoSuccess(msg, next) {
/** The toString method of a Failure yields an error message. */
override def toString = "["+next.pos+"] failure: "+msg+"\n\n"+next.pos.longString
def append[U >: Nothing](a: => ParseResult[U]): ParseResult[U] = { val alt = a; alt match {
case Success(_, _) => alt
case ns: NoSuccess => if (alt.next.pos < next.pos) this else alt
}}
}
或者,换句话说,如果双方都失败了,那么它将占据阅读大部分输入的一方(这就是为什么它不会抱怨丢失FOO
),但是如果两者都读取了相同的数量,它将优先于第二次失败。
我确实不知道它是否应该检查正确方面是否为Error
,如果是,则返回该值。毕竟,如果左侧是Error
,它总是返回。这看起来很可疑,但也许它应该是那样的。但我离题了。
回到问题,似乎它应该与err
一起消失,因为它们都消耗了相同数量的输入,对吧?嗯......这就是事情:正则表达式解析器首先跳过whiteSpace,但正则表达式文字和文字字符串。它不适用于所有其他方法,包括err
。
这意味着err
的输入位于空白处,而单词的输入位于单词处,因此,输入位于输入处。试试这个:
lazy val verb = word("verb") | " *".r ~ err("not a verb!")
可以说err
应该被RegexParsers
覆盖以做正确的事(tm)。由于Scala Parser Combinators现在是一个单独的项目,我建议您打开一个问题并使用Pull Request实施更改。它会对某些解析器产生更改错误消息的影响(嗯,这就是改变它的全部目的:)。