Choosing Haskell Text.Parsec.Combinator does not cancel

I am trying to parse text with a 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 

I expect choice try to match "leave", and if that fails, try "login", etc. But he is only trying to match the "leave", and if he fails, he gives an error.

 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" 

What am I doing wrong?

+8
haskell parsec
source share
1 answer

Parsec does not automatically backtrack on this (for efficiency). The rule is that after the branch accepts the token, alternative branches are truncated. The solution is to add explicit backtracking with try (string "leave") and try (string "login") , etc.

In your example, the symbol "l" is the token that passes Parsec to the first branch "leave" and leaves the following branches "login" and "join".

More details in the real world of Haskell (book, online) in parse .

+14
source share

All Articles