I have written a parser in Haskell's parsec library for a lisp-like language, and I would like to improve its error messages, but I am stuck in the following situation:
p :: Parser Integer
p = do
try (string "number")
space
integer
parens :: Parser a -> Parser a
parens p = do
char '('
v <- p
char ')'
return v
finalParser p = p <|> (parens finalParser)
So the parser p
behaves quite nicely error-wise, it does not commit and consume input until it sees the keyword "number". Once it successfully parsed the keyword, it will not restore its input on failure. If this parser is combined with other parsers using the <|>
operator, and it parses the keyword, it will show the error message of p
and not try the next parser.
Already parens p
does not have this property anymore.
I would like to write a function parens
as above that consumes only input, if the parser p
consumes input.
Here are a few examples of the behavior, I am trying to achieve. finalParser should parse:
- "(((number 5)))", "number 5", "(number 5)" all should parse to the integer 5, and consume everything,
- "(5)" should consume nothing (not even the parenthesis) and fail
- "(number abc)", "number cde" should fail and consume input.