Reputation: 263
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:
Upvotes: 3
Views: 100
Reputation: 33569
I would like to write a function
parens
as above that consumes only input, if theparser p
consumes input.
Rather than that, consider factoring your syntax so you don't even need to backtrack after consuming a parenthesis.
Instead of trying to make this work:
parens p1 <|> parens p2
why not write this instead:
parens (p1 <|> p2)
?
Upvotes: 1