2012-12-17 61 views
2

我一直有一個問題,得到了整數和浮點數之間的scala combinator分析器(特別是通過JavaTokenParsers的RegexParsers)。我必須在這裏錯過一些非常基本的東西,因爲我無法在任何地方發現這個特定問題。我已經包含了一個有問題的解析器代碼的規範(當然不包括)。使用Scala組合器分析器來區分整數和浮點數

@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 

一個想法,根據本thread,我放在<~ not(not('.'))的wholeNumber之後,但這似乎並沒有解決問題。

回答

3

你幾乎在那裏 - 你需要改變的唯一東西是not(not('.'))not('.')。爲什麼?

問題是intValue總是消耗點之前的部分。如果您現在編寫x ~ '.',則檢查一個點是否跟隨並與點之前的部分一起使用。但是,當一個點不跟隨時,你想消費,因此你必須寫x ~ not('.')

當你寫x ~ not(not('.'))你有一個雙重否定,這是相同的沒有否定。這裏唯一的區別是這樣的雙重否定允許你查找下一個輸入而不消耗它。這是因爲在失敗時,爲了讓下面的解析器再次解析它,不會消耗輸入。如果發生雙重故障,您不會消耗任何東西,但會實現已經提到的查找。

+0

我知道這是簡單的事情,它只是通過我......謝謝! –