This module includes everything you need to get started writing a parser.
If you are new to Megaparsec and don't know where to begin, take a look
at the tutorial https://markkarpov.com/tutorial/megaparsec.html.
In addition to the Text.Megaparsec module, which exports and re-exports
almost everything that you may need, we advise importing
Text.Megaparsec.Char if you plan to work with a stream of Char tokens,
or Text.Megaparsec.Byte if you intend to parse binary data.
It is common to start working with the library by defining a type synonym
like this:
type Parser = Parsec Void Text
^ ^
| |
Custom error component Input stream type
Then you can write type signatures like Parser Int—for a parser that
returns an Int, for example.
Similarly (since it's known to cause confusion), you should use the
ParseErrorBundle type parametrized like this:
ParseErrorBundle Text Void
^ ^
| |
Input stream type Custom error component (the same you used in Parser)
Megaparsec uses some type-level machinery to provide flexibility without
compromising on type safety. Thus, type signatures are sometimes necessary
to avoid ambiguous types. If you're seeing an error message that reads
like “Type variable e0 is ambiguous …”, you need to give an explicit
signature to your parser to resolve the ambiguity. It's a good idea to
provide type signatures for all top-level definitions.
Note that we re-export monadic combinators from
Control.Monad.Combinators because these are more efficient than
Applicative-based ones (†). Thus many and some may clash with the
functions from Control.Applicative. You need to hide those functions like
this:
import Control.Applicative hiding (many, some)
† As of Megaparsec 9.7.0 many and
some are as efficient as their monadic
counterparts.
Also note that you can import Control.Monad.Combinators.NonEmpty if you
wish that combinators like some return NonEmpty lists. The module
lives in the parser-combinators package (you need at least version
0.4.0).
This module is intended to be imported qualified:
import qualified Control.Monad.Combinators.NonEmpty as NE
manyTill p end applies parser pzero or more times until parser
end succeeds. Returns the list of values returned by p. Note that
end result is consumed and lost. Use manyTill_ if you wish to keep
it.
manyTill_ p end applies parser pzero or more times until
parser end succeeds. Returns the list of values returned by p and the
end result. Use manyTill if you have no need in the result of the
end.
someTill p end works similarly to manyTill p end, but p
should succeed at least once. Note that end result is consumed and
lost. Use someTill_ if you wish to keep it.
parseMaybe p input runs the parser p on input and returns the
result inside Just on success and Nothing on failure. This function
also parses eof, so if the parser doesn't consume all of its input, it
will fail.
The function is supposed to be useful for lightweight parsing, where
error messages (and thus file names) are not important and the entire
input should be consumed. For example, it can be used for parsing a single
number according to a specification of its format.
runParser p file input runs parser p on the input stream of
tokens input, obtained from source file. The file is only used in
error messages and may be the empty string. Returns either a
ParseErrorBundle (Left) or a value of type a (Right).
parseFromFile p file = runParser p file <$> readFile file
The function is similar to runParser, with the difference that it
accepts and returns the parser state. This allows us, e.g., to specify an
arbitrary textual position at the beginning of parsing. This is the most
general way to run a parser over the Identity monad.
runParserT p file input runs parser p on the input list of tokens
input, obtained from source file. The file is only used in error
messages and may be the empty string. Returns a computation in the
underlying monad m that returns either a ParseErrorBundle (Left) or
a value of type a (Right).
Type class describing monads that implement the full set of primitive
parsers.
Note that the following primitives are “fast” and should be taken
advantage of as much as possible if your aim is a fast parser: tokens,
takeWhileP, takeWhile1P, and takeP.
The parser label name p behaves as parser p, but whenever the
parser p fails without consuming any input, it replaces names of
“expected” tokens with the name name.
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 lookahead is needed. Since
it pretends that it hasn't consumed any input when p fails, the
(A.<|>) 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”:
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:
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.
If p in lookAhead p succeeds (either consuming input or not),
the whole parser behaves as if p succeeded without consuming anything
(the parser state is not updated either). If p fails, lookAhead has
no effect, i.e. it will fail consuming input if p fails consuming
input. Combine with try if this is undesirable.
notFollowedBy p only succeeds when the parser p fails. This
parser never consumes any input and never modifies parser state. It
can be used to implement the “longest match” rule.
withRecovery r p allows us to continue parsing even if the parser
p fails. In this case r is called with the actual ParseError as
its argument. Typical usage is to return a value signifying failure to
parse this particular object and to consume some part of the input up
to the point where the next object starts.
Note that if r fails, the original error message is reported as if
withRecovery had not been used. In no way can the recovering parser r
influence error messages.
observing p allows us to “observe” failure of the p parser,
should it happen, without actually ending parsing, but instead getting
the ParseError in Left. On success, the parsed value is returned in
Right as usual. Note that this primitive just allows you to observe
parse errors as they happen; it does not backtrack or change how the
p parser works in any way.
The parser token test expected accepts tokens for which the
matching function test returns Just results. If Nothing is
returned, the expected set is used to report the items that were
expected.
For example, the satisfy parser is implemented as:
satisfy f = token testToken Set.empty
where
testToken x = if f x then Just x else Nothing
Note: the type signature of this primitive was changed in version
7.0.0.
The parser tokens test chk parses a chunk of input chk and
returns it. The supplied predicate test is used to check equality of
given and parsed chunks after a candidate chunk of correct length is
fetched from the stream.
Note that beginning with Megaparsec 4.4.0, this is an auto-backtracking
primitive, which means that if it fails, it never consumes any input.
This is done to make its consumption model match how error messages for
this primitive are reported (which becomes important as the user gets
more control with primitives like withRecovery):
This means, in particular, that it's no longer necessary to use try
with tokens-based parsers, such as string and
string'. This feature does not affect
performance in any way.
Parse zero or more tokens for which the supplied predicate holds.
Try to use this as much as possible because for many streams this
combinator is much faster than parsers built with
many and satisfy.
takeWhileP (Just "foo") f = many (satisfy f <?> "foo")
takeWhileP Nothing f = many (satisfy f)
The combinator never fails, although it may parse the empty chunk.
Similar to takeWhileP, but fails if it can't parse at least one
token. Try to use this as much as possible because for many streams
this combinator is much faster than parsers built with
some and satisfy.
takeWhile1P (Just "foo") f = some (satisfy f <?> "foo")
takeWhile1P Nothing f = some (satisfy f)
Note that the combinator either succeeds or fails without consuming any
input, so try is not necessary with it.
Extract the specified number of tokens from the input stream and
return them packed as a chunk of the stream. If there are not enough
tokens in the stream, a parse error will be signaled. It's guaranteed
that if the parser succeeds, the requested number of tokens will be
returned.
The parser is roughly equivalent to:
takeP (Just "foo") n = count n (anySingle <?> "foo")
takeP Nothing n = count n anySingle
Note that if the combinator fails due to an insufficient number of
tokens in the input stream, it backtracks automatically. No try is
necessary with takeP.
The most general function to fail and end parsing is parseError. The
others are built on top of it. This section also includes functions
starting with the register prefix, which allow users to register
“delayed” ParseErrors.
Specify how to process ParseErrors that happen inside of this
wrapper. This applies to both normal and delayed ParseErrors.
As a side effect of the implementation, the inner computation will start
with an empty collection of delayed errors, and they will be updated and
“restored” on the way out of region.
Register a ParseError for later reporting. This action does not end
parsing and has no effect except for adding the given ParseError to the
collection of “delayed” ParseErrors which will be taken into
consideration at the end of parsing. Only if this collection is empty will
the parser succeed. This is the main way to report several parse errors
at once.
Performance note: when you need to parse a single token, it is often
a good idea to use satisfy with the right predicate function instead of
creating a complex parser using the combinators.
oneOf ts succeeds if the current token is in the supplied
collection of tokens ts. Returns the parsed token. Note that this
parser cannot automatically generate the “expected” component of error
message, so usually you should label it manually with label or (<?>).
As the dual of oneOf, noneOf ts succeeds if the current token is
not in the supplied list of tokens ts. Returns the parsed character.
Note that this parser cannot automatically generate the “expected”
component of error message, so usually you should label it manually with
label or (<?>).
Return both the result of a parse and the chunk of input that was
consumed during parsing. This relies on the change of the stateOffset
value to evaluate how many tokens were consumed. If you mess with it
manually in the argument parser, prepare for trouble.
Return the current source position. This function is not cheap, so do
not call it, e.g., on matching of every token—that's a bad idea. Still,
you can use it to get a SourcePos to attach to things that you parse.
The function works under the assumption that we move in the input stream
only forwards and never backwards, which is always true unless the user
abuses the library.