Search code examples
parsinghaskellparsec

How to fail on parse many with parsec?


Apoligies if this is a trivial thing, but I really can't find it out on my own.

PRELIMINARIES

I have a file with many entries like FOO <value>, For Example:

# example.txt
FOO 5
FOO 9

Such a file read as a string would be FOO 5\nFOO 9\n. I tried to parse these with

parseFoo :: ParsecT String u Identity (String, Int)
parseFoo = do
    k <- string "FOO"
    _ <- space
    v <- many1 digit
    return (k, read v)

parseFoos :: ParsecT String u Identity [(String, Int)]
parseFoos = parseFoo `endBy` newline

testFOO :: Either ParseError [(String, Int)]
testFOO = parse parseFoos "" "FOO 5\nFOO 6\n"

This gives me Right [("FOO",5),("FOO",6)] as expected.

MY QUESTION

How to fail parsing on invalid inputs?

For example: parse parseFoos "" "BLAH" returns Right [], but I want the parser to fail.

For example: parse parseFoos "" "FOO 5\nBAR 7\n" returns Right [("FOO", 5)], but I want the parser to fail.


Solution

  • You should match EOF at the end of the parser. Use the provided eof to do it. Without eof the parser will not match the end of file, and will happily parse only part of the input.

    In the do block:

    do
        res <- {- Your parser code here -}
        eof
        return res
    

    Or just use the <* operator: parser <* eof will do.