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

1 回答 1

4

您没有给出int解析器组合器的定义,但让我们假设它本质上需要一个或多个数字,可选地在前面加上一个“-”(但只在前面!)。现在让我们来看看你的numberOrString解析器。

它解析一个整数文字,或者解析一个非空格字符的字符串。在您的示例字符串上,解析器的第一个分支将成功,因为它会看到一串数字。它将在“-”字符之前停止,因为那不是数字。现在,numberOrString >> space将失败,因为在数字之后,我们期望下一个字符是空格,而“-”不是。

您实际上已将解析器应用于由两个整数文字组成的字符串,一个正数和一个负数(或两个由“-”分隔的正数,具体取决于您的语法)。这也是numberOfString单独应用解析器只消耗“1234”的原因,因为这是它可以解析的最大整数字面量。

编辑:我猜你想要的是try int如果在一个主要是数字的字符串中有任何非数字字符,那么你想要失败。同样,这实际上取决于您对 的定义int,但它可能被定义为解析器,该解析器可以成功处理任何至少一位数字且后面没有字母字符的字符串。的通常定义int将在后跟非字母数字字符的数字字符串上成功,例如“-”,即使没有任何中间空格字符,因为这使得两个整数文字和中缀运算符之间的空格是可选的。此外,它还允许您成功解析“123)”,而无需编写“123 )”。

于 2012-09-28T15:46:23.410 回答