Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do I get "unexpected end of input" when my parser is explicitly looking for it?

Tags:

haskell

parsec

import Control.Applicative hiding (many)
import Text.Parsec
import Text.Parsec.String

lexeme :: Parser a -> Parser a
lexeme p = many (oneOf " \n\r") *> p

identifier :: Parser String
identifier = lexeme $ many1 $ oneOf (['a'..'z'] ++ ['A'..'Z'])

operator :: String -> Parser String
operator = lexeme . string

field :: Parser (String, String)
field = (,) <$> identifier <* operator ":" <*> identifier <* operator ";"

fields :: Parser [(String, String)]
fields = many (try field) <* eof

testInput :: String
testInput = unlines
    [ "    FCheckErrors         : Boolean            ;"
    , "    FAcl                 : TStrings           ;"
    ]

main :: IO ()
main = parseTest fields testInput

When runn this yields:

parse error at (line 3, column 1): unexpected end of input

When I remove the explicit eof matching there is no such parse error:

fields = many (try field)

I also tried try field `manyTill` eof, but that will result in the same behavior as the original code.

I want to make sure the parser consumes the whole input, how can I do that?

like image 285
Jens Mühlenhoff Avatar asked Mar 15 '23 23:03

Jens Mühlenhoff


1 Answers

The problem is that there is a newline before eof (inserted by unlines).

So eof must be run through lexeme.

fields = many (try field) <* lexeme eof

Otherwise Parsec is trying to run the fields parser on the newline.

like image 186
Jens Mühlenhoff Avatar answered Apr 09 '23 16:04

Jens Mühlenhoff