2

我一直在让 scala 组合器解析器(特别是通过 JavaTokenParsers 的 RegexParsers)在整数和浮点数之间做出决定时遇到问题。我必须在这里遗漏一些非常基本的东西,因为我似乎无法在任何地方找到任何提及这个特定问题的内容。我已经在有问题的解析器代码中包含了一个规范(当然,减去了)。

@RunWith(classOf[JUnitRunner])
class SandboxSpec extends FlatSpec with ShouldMatchersForJUnit {

  sealed trait PropertyValue

  case class IntValue(value: Int) extends PropertyValue
  case class RealValue(value: Float) extends PropertyValue

  class Parser extends JavaTokenParsers {
    def propertyLiteral : Parser[PropertyValue] = intValue | realValue

    def realValue  = floatingPointNumber ^^ {
      s => RealValue(s.toFloat)
    }

    def intValue  = wholeNumber ^^ {
      s => IntValue(s.toInt)
    }
  }

  "A java token parser" should "parse a float" in {
    val p = new Parser()

    val result = p.parseAll(p.propertyLiteral, "5.4") match {
      case p.Success(x, _) => x
      case p.NoSuccess(msg, _) => fail(msg)
    }

    result should be(RealValue(5.4f))

  }
}

这失败并显示以下错误消息:

string matching regex `\z' expected but `.' found

一个想法是,基于这个线程,我<~ not(not('.'))在整数之后放置了一个,但这似乎并没有解决问题。

4

1 回答 1

3

你快到了 - 你唯一需要改变的not(not('.'))not('.')。为什么?

问题是intValue总是消耗点之前的部分。如果您现在编写x ~ '.',请检查是否有一个点,并将其与点之前的部分一起使用。但是你想在没有点的时候消费,所以你必须写x ~ not('.').

当你写作时,x ~ not(not('.'))你有一个双重否定,这与没有否定是相同的。这里唯一的区别是这种双重否定允许您查找下一个输入而不使用它。这是因为在失败时输入不会被消耗以允许以下解析器再次解析它。对于双重失败,您既不会消耗任何东西,也不会实现已经提到的查找。

于 2012-12-18T00:21:54.557 回答