为什么这会失败?
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
答案 0 :(得分:4)
您没有给出int
解析器组合器的定义,但我们假设它基本上需要一个或多个数字,前面可选地带有“ - ”(但只在前面!)。现在让我们来看看你的numberOrString
解析器。
它解析一个整数文字,或者说是一个非空格字符串。在您的示例字符串上,解析器的第一个分支将成功,因为它会看到一串数字。它将在“ - ”字符前停止,因为这不是数字。现在,numberOrString >> space
将失败,因为在一个数字之后,我们期望下一个字符是一个空格,“ - ”不是。
您基本上将解析器应用于两个整数文字字符串,一个正面和一个负面(或两个正面文字用“ - ”分隔,具体取决于您的语法)。这也是为什么单独应用numberOfString
解析器只消耗“1234”的原因,因为这是它可以解析的最大整数文字。
编辑:我猜你想要的是try int
失败,如果大多数数字字符串中有任何非数字字符。同样,这实际上取决于您对int
的定义,但它可能被定义为一个解析器,它在至少一个未跟随字母字符的数字的任何字符串上成功。 int
的通常定义将在数字字符串后面跟随非字母数字字符(例如“ - ”)成功,即使没有任何插入空格字符,因为这使得两个整数字面值和中缀运算符之间的空格可选。此外,它允许您成功解析“123)”,而无需编写“123)”。