我有一个简单的RegexParser,它匹配{key} = {value}多次重复:
object CommandOptionsParser extends RegexParsers {
private val key: Parser[String] = "[^= ]+".r
private val value: Parser[String] = "[^ ]*".r
val pair: Parser[Option[(String, Option[String])]] =
(key ~ ("=".r ~> value).?).? ^^ {
case None => None
case Some(k ~ v) => Some(k.trim -> v.map(_.trim))
}
val pairs: Parser[Map[String, Option[String]]] = phrase(repsep(pair, whiteSpace)) ^^ {
case v =>
Map(v.flatten: _*)
}
def apply(input: String): Map[String, Option[String]] = parseAll(pairs, input) match {
case Success(plan, _) => plan
case x => sys.error(x.toString)
}
}
然而,对于超过1个捕获组而言,值的匹配似乎失败(尽管正则表达式并不限制它)。当我尝试匹配“token = abc again = abc”时,我有以下错误:
[1.11] failure: string matching regex `\z' expected but `a' found
token=abc again=abc'
^
为什么RegexParser有这么奇怪的行为?
答案 0 :(得分:1)
您的意外行为的修复非常简单,只需更改skipWhitespace
:
object CommandOptionsParser extends RegexParsers {
override val skipWhitespace = false
来自RegexParsers
的说明:
解析方法调用方法
skipWhitespace
(默认为true
)如果为真,则在每个解析器之前跳过任何空格 调用。
所以,发生了什么,您的第一个pair
已匹配,然后whiteSpace
被跳过然后,由于repsep
无法找到另一个空白分隔符,它只是假设解析结束了,因此" \ z"预期
另外,我无法帮助,但请注意,对于这样简单的任务,整个Parser方法似乎过于复杂,简单的regexp就足够了。
UPD :您的解析器也可以更简单一些:
val pair: Parser[Option[(String, Option[String])]] =
(key ~ ("=" ~> value).?).? ^^ (_.map {case (k ~ v) => k.trim -> v.map(_.trim)})
val pairs: Parser[Map[String, Option[String]]] = phrase(repsep(pair, whiteSpace)) ^^
{ l => Map(l.flatten: _*)}