[Haskell-cafe] Parsec - Custom Fail

mwinter at brocku.ca mwinter at brocku.ca
Tue May 5 11:02:15 EDT 2009


I am using parsec to parse a small programming language. The language is typed and
I need to do some type checking, too. I have decided to do the parsing and type checking
simultaneously in the my parsec parser. This approach avoids to keep source code positions
in the data type in order to produce suitable error messages during type checking. Anyhow,
because type errors are usually detected after parsing some code I need produce error
messages with an earlier source position. Unfortunately, there is no function that produces 
an error taking a position as parameter. 

I tried the following:

myFail :: SourcePos -> String -> GenParser tok st a
myFail pos msg = setPosition pos >> fail msg

This is already a workaround because I am modifying the position in the parser just to
produce an error message. But even worse, it does not work. If I use this function as in:

test :: Either ParseError ()
test = runParser (char '(' >> myFail (newPos "" 100 100) "Test") () "" "("

the position of the error is still the original position (line 1, column 2). As far as I can tell
setPosition does not take effect until another symbol is read. This could be achieved by
simply using anyToken if we are not at the end of the input (as in the example above). I
came up with the following:

myFail :: SourcePos -> String -> GenParser Char st a
myFail pos msg = do {
                     State toks _ st <- getParserState;
                     setParserState $ State ('d':toks) pos st;
                     fail msg

This code works but it is not nice at all. The function myFail is not longer polymorphic in
the type of tokens since we need an element of this data type in order to add it temporarily
to the input ('d' above).

My guess is that one has to enforce strictness at some point in order to work with the first
approach, but I was not successful. Any ideas?


More information about the Haskell-Cafe mailing list