haskellattoparsec

Incomplete input using endOfInput parser


Consider the string "(=x250) toto e", and the function:

charToText :: Char -> Text
charToText c = pack [c]

The string is successfully parsed by:

mconcat <$> manyTill (charToText <$> anyChar) (char 'e')

with the expected result "(=x250) toto ".

However, the parser:

mconcat <$> manyTill (charToText <$> anyChar) endOfInput

returns Partial _.

Why is it so ? I thought endOfInput would succeed at the end of the string and stop manyTill (as in the first example).


Solution

  • To get a complete answer, you'll need to provide a fully self-contained example that generates the Result: incomplete input error message, but your Attoparsec parser is working correctly. You can see similar behavior with a much simpler example:

    λ> parse (char 'e') "e"
    Done "" 'e'
    λ> parse endOfInput ""
    Partial _
    

    Attoparsec parsers by design allow incremental supply of additional input. When they are run on some (potentially partial) input, they return a Done result if the parser unconditionally succeeds on the supplied input. They return a Partial result if more input is needed to decide if the parser succeeds.

    For my example above, char 'e' always successfully parses the partial input "e", no matter what additional input you might decide to supply, hence the result is a Done.

    However, endOfInput might succeed on the partial input "", but only if no additional input is going to be supplied. If there is additional input, endOfInput will fail. Because of this, a Partial result is returned.

    It's the same for your example. The success of your second parser depends on whether or not additional input is supplied. If there's no additional input, the parser is Done, but if there is additional input, the parser has more to do.

    You will either need to arrange to run your parser with parseOnly:

    λ> parseOnly (manyTill anyChar endOfInput) "foo"
    Right "foo"
    

    or you will feed your parse result an empty bytestring which will indicate that no further input is available:

    λ> parse (manyTill anyChar endOfInput) "foo"
    Partial _
    λ> feed (parse (manyTill anyChar endOfInput) "foo") ""
    Done "" "foo"