11

我正在尝试用 parsec 解析一些文本:

data Cmd = LoginCmd String
         | JoinCmd String
         | LeaveCmd String
    deriving (Show)

singleparam :: Parser Cmd
singleparam = do
    cmd <- choice [string "leave", string "login", string "join"]
    spaces
    nick <- many1 anyChar
    eof
    return $ LoginCmd nick

我期待choice尝试匹配“leave”,如果失败,则尝试“login”等。但它只尝试匹配“leave”,如果失败,则会出错。

ghci> parseTest singleparam (pack "login asdf")
parse error at (line 1, column 1):
unexpected "o"
expecting "leave"
ghci> parseTest singleparam (pack "leave asdf")
LoginCmd "asdf"

我究竟做错了什么?

4

1 回答 1

16

Parsec 不会像这样自动回溯(为了提高效率)。规则是一旦一个分支接受一个令牌,那么替代分支就会被修剪。解决方案是使用等添加显式try (string "leave")回溯try (string "login")

在您的示例中,“l”字符是将 Parsec 提交到第一个“离开”分支并放弃“登录”和“加入”的下一个分支的标记。

更多细节在真实世界 Haskell (书,在线)上 parsec

于 2012-04-02T12:34:36.323 回答