在Parser Combinators中理解`not`

时间:2014-09-01 16:23:14

标签: scala parser-combinators

我写了下面的Parser,目的是fail - 在空白处:

import scala.util.parsing.combinator._

object Foo extends JavaTokenParsers { 
  val wsTest = not(whiteSpace) // uses whitespace inherited from `RegexParsers`
}

为什么解析一堆空白成功?

scala> Foo.parseAll(Foo.wsTest, "          ")
res5: Foo.ParseResult[Unit] = [1.11] parsed: ()

scala> res5.successful
res6: Boolean = true

project查看Parsers#not,我希望我的上述测试可以Failure

  /** Wrap a parser so that its failures and errors become success and
   *  vice versa -- it never consumes any input.
   */
  def not[T](p: => Parser[T]): Parser[Unit] = Parser { in =>
    p(in) match {
      case Success(_, _)  => Failure("Expected failure", in)
      case _              => Success((), in)
    }
  }

1 个答案:

答案 0 :(得分:4)

JavaTokenParsers扩展了RegexParsers,RegexParsers有:

 protected val whiteSpace = """\s+""".r

 def skipWhitespace = whiteSpace.toString.length > 0

 implicit def regex(r: Regex): Parser[String] = new Parser[String] {
    ... 
    val start = handleWhiteSpace(source, offset)
    ...
 }

 protected def handleWhiteSpace(source: java.lang.CharSequence, offset: Int): Int =
   if (skipWhitespace)
     (whiteSpace findPrefixMatchOf (source.subSequence(offset, source.length))) match {
       case Some(matched) => offset + matched.end
       case None => offset
     }
   else
     offset

所以它会跳过空格(你可以通过覆盖def skipWhitespace = false来覆盖它)

因此解析器" "等于""

空白试图匹配""但它失败了(""" \ s +"""需要至少一个空格)而将其转换为成功