Search code examples
parsinghaskellparsec

<|> in Parsec - why do these examples behave differently?


I think I'm misunderstanding <|> in parsec - I have an input stream that contains either a bunch of as in one representation or a bunch of as in another representation. I would expect the following to functions to be equivalent (given that the input is the form I said, and I have verified that it is):

foo = do
    ...
    a1s <- many $ try $ a1
    a2s <- many $ try $ a2
    return $ a1s ++ a2s

versus

foo = do
    ...
    as <- (many $ try $ a1) <|> (many $ try $ a2)
    return as

What could be going wrong? The first function works on my input, the second function fails, saying unexpected a2, expecting a1.


Solution

  • When you give a sequence of a2 to the latter parser, the first many matches and returns an empty list, so it doesn't try to match against the second many.

    You can use many1 instead.

    foo = do
        ...
        as <- many1 a1 <|> many a2
        return as
    

    In this case, the many1 fails when you give a sequence of a2, and the many matches against the input.