2

int と float を決定する 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

このスレッドに基づいて考えた 1 つ、wholeNumber の後に a を配置しまし<~ not(not('.'))たが、これで問題が解決したようには見えませんでした。

4

1 に答える 1

3

あなたはほとんどそこにいます - あなたが変更する必要があるのnot(not('.'))not('.'). なんで?

問題は、intValue常にドットの前の部分を消費することです。今書くx ~ '.'と、ドットが続くかどうかを確認し、ドットの前の部分と一緒に消費します。しかし、ドットが続かないときに消費したいので、 と書く必要がありますx ~ not('.')

あなたが書くときx ~ not(not('.'))、否定なしと同じ二重否定があります。ここでの唯一の違いは、このような二重否定により、次の入力を消費せずにルックアップできることです。これは、失敗した場合、次のパーサーが再度解析できるようにするために、入力が消費されないためです。二重の失敗では、何も消費しませんが、前述のルックアップを達成します。

于 2012-12-18T00:21:54.557 に答える