The parser
try p behaves like the parser
p,
except that it backtracks the parser state when
p fails
(either consuming input or not).
This combinator is used whenever arbitrary look ahead is needed. Since
it pretends that it hasn't consumed any input when
p fails,
the (
<|>) combinator will try its second alternative even
if the first parser failed while consuming input.
For example, here is a parser that is supposed to parse the word “let”
or the word “lexical”:
>>> parseTest (string "let" <|> string "lexical") "lexical"
1:1:
unexpected "lex"
expecting "let"
What happens here? The first parser consumes “le” and fails (because
it doesn't see a “t”). The second parser, however, isn't tried, since
the first parser has already consumed some input!
try fixes
this behavior and allows backtracking to work:
>>> parseTest (try (string "let") <|> string "lexical") "lexical"
"lexical"
try also improves error messages in case of overlapping
alternatives, because Megaparsec's hint system can be used:
>>> parseTest (try (string "let") <|> string "lexical") "le"
1:1:
unexpected "le"
expecting "let" or "lexical"
Note that as of Megaparsec 4.4.0,
string backtracks
automatically (see
tokens), so it does not need
try.
However, the examples above demonstrate the idea behind
try so
well that it was decided to keep them. You still need to use
try when your alternatives are complex, composite parsers.