2012-09-28 33 views
3

這爲什麼會失敗?爲什麼使用減號解析字符串會失敗?

data Value = Num Integer 
      | Str String 

let numberOrString = (liftM Num (try int) <|> liftM Str (many1 (noneOf " ")) 
parse (numberOrString >> space) "" "123-4 " 

>> space是必需的。否則解析器將停止後123

預期結果:

parse numberOrString "" "1234" 
-> Num 1234 

parse numberOrString "" "12-34" 
-> Str "12-34" 

結果:

parse numberOrString "" "1234-34 " 
-> Left (line 1, column 5): 
    unexpected "-" 
    expecting digit or space 

回答

4

你不給的int解析器組合的定義,但我們認爲它基本上是預計一個或更多數字,可選地在前面具有「 - 」(但僅在前面!)。現在讓我們通過你的分析器numberOrString

它分析整數字面值,或者失敗的話,一個非空格字符的字符串。在您的示例字符串中,解析器的第一個分支將會成功,因爲它會看到一串數字。它會在「 - 」字符之前停止,因爲這不是一個數字。現在,numberOrString >> space將失敗,因爲在一個數字後,我們期待下一個字符是一個空格,而「 - 」不是。

您基本上已將您的解析器應用於一個字符串兩個整數文字,一個正面和一個負面(或兩個正面文字用「 - 」分隔,取決於您的語法)。這也是爲什麼單獨應用numberOfString解析器僅消耗「1234」的原因,因爲這是它可以解析的最大整數字面值。

編輯︰我猜你想要的是try int失敗,如果有任何非數字字符在大多數字符串中。再次,這實際上取決於您對int的定義,但它可能被定義爲解析器,該解析器可以在至少一個數字的任何字符串上成功,而該字符串不會跟隨字母字符。對於int的常規定義,即使沒有任何中介空格字符,也會在數字串之後跟隨非字母字符(例如「 - 」),因爲這會使兩個整數文字和中綴運算符之間的間隔爲可選。此外,它允許你成功地解析「123)」,而不必寫「123)」。

+0

(字符串是2整數文字的事實是無關緊要的,它與「1234a34」'完全相同的失敗。) – huon

+0

不完全是一個解決方案,但我給出的是一個問題,爲什麼它沒有奏效。這讓我走上了正軌。謝謝! – fho

相關問題