Scala Regex Parser引发了奇怪的错误

时间:2016-04-11 21:55:44

标签: regex scala parsing

我有一个简单的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有这么奇怪的行为?

1 个答案:

答案 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: _*)}