[Haskell-cafe] Parsec - Custom Fail
Daniel Fischer
daniel.is.fischer at web.de
Tue May 5 13:42:37 EDT 2009
Am Dienstag 05 Mai 2009 17:38:35 schrieb mwinter at brocku.ca:
> Thanks, but I want a nice solution not another, even more complicated,
> workaround.
I'm afraid you're out of luck there.
Parsec carries a ParseError around even for successful parses (where it's a SourcePos and
and empty list of messages).
When binding two parsers, if the second doesn't consume any input, for the overall result
it calls mergeErrorReply, which calls mergeError from Text.ParserCombinators.Parsec.Error:
mergeError :: ParseError -> ParseError -> ParseError
mergeError (ParseError pos msgs1) (ParseError _ msgs2)
= ParseError pos (msgs1 ++ msgs2)
So that doesn't look at the position of the second error :(
You could change the sources of parsec, the least intrusive would probably be to modify
mergeError:
mergeError :: ParseError -> ParseError -> ParseError
mergeError (ParseError _ []) pe2 = pe2
mergeError (ParseError pos msgs1) (ParseError _ msgs2)
= ParseError pos (msgs1 ++ msgs2)
or you could employ an ugly workaround like
setPosAndFail :: tok -> SourcePos -> String -> GenParser tok st a
setPosAndFail dummy pos msg = do
setPosition pos
inp <- getInput
setInput (dummy:inp)
tokenPrim (const "") (\p _ _ -> p) Just
fail msg
myFail :: SourcePos -> String -> GenParser Char st a
myFail = setPosAndFail 'a'
to pretend you actually consumed some input.
It works:
*TestWorkAround> test
Left (line 100, column 100):
Test
but isn't pretty.
More information about the Haskell-Cafe
mailing list