Parsing.Combinators
- Package
- purescript-parsing
- Repository
- purescript-contrib/purescript-parsing
A “parser combinator” is a function which takes some parsers as arguments and returns a new parser.
Combinators in other packages
Many variations of well-known monadic and applicative combinators used for parsing are defined in other PureScript packages. We list some of them here.
If you use a combinator from some other package for parsing, keep in mind
this surprising truth about the parsing package:
All other combinators used with this package will be stack-safe,
but usually the combinators with a MonadRec
constraint will run faster.
So you should prefer MonadRec
versions of combinators, but for reasons
of speed, not stack-safety.
Data.Array
Expect better parsing speed from the List
-based combinators in this
module than from Array
-based combinators.
Data.List
The many
and many1
combinators in this package
are redeclarations of
the manyRec
and someRec
combinators in Data.List.
Data.List.Lazy
Combinators in this package
the replicateA and replicateM combinators are re-exported from
this module. replicateA n p
or replicateM n p
will repeat parser p
exactly n
times. The replicateA
combinator can
produce either an Array
or a List
.
#try Source
try :: forall m s a. ParserT s m a -> ParserT s m a
If the parser fails then backtrack the input stream to the unconsumed state.
One use for this combinator is to ensure that the right parser of an alternative will always be tried when the left parser fails.
>>> runParser "ac" ((char 'a' *> char 'b') <|> (char 'a' *> char 'c'))
Left (ParseError "Expected 'b'" (Position { line: 1, column: 2 }))
>>> runParser "ac" (try (char 'a' *> char 'b') <|> (char 'a' *> char 'c'))
Right 'c'
#tryRethrow Source
tryRethrow :: forall m s a. ParserT s m a -> ParserT s m a
If the parser fails then backtrack the input stream to the unconsumed state.
Like try
, but will reposition the error to the try
point.
>>> runParser "ac" (try (char 'a' *> char 'b'))
Left (ParseError "Expected 'b'" (Position { index: 1, line: 1, column: 2 }))
>>> runParser "ac" (tryRethrow (char 'a' *> char 'b'))
Left (ParseError "Expected 'b'" (Position { index: 0, line: 1, column: 1 }))
#notFollowedBy Source
notFollowedBy :: forall s a m. ParserT s m a -> ParserT s m Unit
Fail if the parser succeeds.
Will never consume input.
#optionMaybe Source
optionMaybe :: forall m s a. ParserT s m a -> ParserT s m (Maybe a)
pure Nothing
in the case where a parser fails without consuming input.
#many1 Source
many1 :: forall m s a. ParserT s m a -> ParserT s m (NonEmptyList a)
Match one or more times.
#manyTill_ Source
manyTill_ :: forall s a m e. ParserT s m a -> ParserT s m e -> ParserT s m (Tuple (List a) e)
Parse many phrases until the terminator phrase matches. Returns the list of phrases and the terminator phrase.
Non-greedy repetition
Use the manyTill_ combinator
to do non-greedy repetition of a pattern p
, like we would in Regex
by writing p*?
.
To repeat pattern p
non-greedily, write
manyTill_ p q
where q
is the entire rest of the parser.
For example, this parse fails because many
repeats the pattern letter
greedily.
runParser "aab" do
a <- many letter
b <- char 'b'
pure (Tuple a b)
(ParseError "Expected 'b'" (Position { line: 1, column: 4 }))
To repeat pattern letter
non-greedily, use manyTill_
.
runParser "aab" do
Tuple a b <- manyTill_ letter do
char 'b'
pure (Tuple a b)
(Tuple ('a' : 'a' : Nil) 'b')
#many1Till Source
many1Till :: forall s a m e. ParserT s m a -> ParserT s m e -> ParserT s m (NonEmptyList a)
Parse at least one phrase until the terminator phrase matches.
#many1Till_ Source
many1Till_ :: forall s a m e. ParserT s m a -> ParserT s m e -> ParserT s m (Tuple (NonEmptyList a) e)
Parse many phrases until the terminator phrase matches, requiring at least one match. Returns the list of phrases and the terminator phrase.
#manyIndex Source
manyIndex :: forall s m a. Int -> Int -> (Int -> ParserT s m a) -> ParserT s m (Tuple Int (List a))
Parse the phrase as many times as possible, at least N times, but no more than M times. If the phrase can’t parse as least N times then the whole parser fails. If the phrase parses successfully M times then stop. The current phrase index, starting at 0, is passed to the phrase.
Returns the list of parse results and the number of results.
manyIndex n n (\_ -> p)
is equivalent to replicateA n p
.
#sepBy1 Source
sepBy1 :: forall m s a sep. ParserT s m a -> ParserT s m sep -> ParserT s m (NonEmptyList a)
Parse phrases delimited by a separator, requiring at least one match.
#sepEndBy1 Source
sepEndBy1 :: forall m s a sep. ParserT s m a -> ParserT s m sep -> ParserT s m (NonEmptyList a)
Parse phrases delimited and optionally terminated by a separator, requiring at least one match.
#endBy1 Source
endBy1 :: forall m s a sep. ParserT s m a -> ParserT s m sep -> ParserT s m (NonEmptyList a)
Parse phrases delimited and terminated by a separator, requiring at least one match.
#chainl Source
chainl :: forall m s a. ParserT s m a -> ParserT s m (a -> a -> a) -> a -> ParserT s m a
chainl p f
parses one or more occurrences of p
, separated by operator f
.
Returns a value
obtained by a left-associative application of the functions returned by
f
to the values returned by p
. This combinator can be used to
eliminate left-recursion in expression grammars.
For example:
chainl digit (string "+" $> add) 0
#chainr Source
chainr :: forall m s a. ParserT s m a -> ParserT s m (a -> a -> a) -> a -> ParserT s m a
chainr p f
parses one or more occurrences of p
, separated by operator f
.
Returns a value
obtained by a right-associative application of the functions returned by
f
to the values returned by p
. This combinator can be used to
eliminate right-recursion in expression grammars.
For example:
chainr digit (string "+" $> add) 0
#advance Source
advance :: forall s m a. ParserT s m a -> ParserT s m a
If the parser succeeds without advancing the input stream position, then force the parser to fail.
This combinator can be used to prevent infinite parser repetition.
Does not depend on or effect the consumed
flag which indicates whether
we are committed to this parsing branch.
#withErrorMessage Source
withErrorMessage :: forall m s a. ParserT s m a -> String -> ParserT s m a
Provide an error message in the case of failure.
#(<?>) Source
Operator alias for Parsing.Combinators.withErrorMessage (left-associative / precedence 4)
#withLazyErrorMessage Source
withLazyErrorMessage :: forall m s a. ParserT s m a -> (Unit -> String) -> ParserT s m a
Provide an error message in the case of failure, but lazily. This is handy in cases where constructing the error message is expensive, so it's preferable to defer it until an error actually happens.
parseBang :: Parser Char
parseBang = char '!' <~?> \_ -> "Expected a bang"
#(<~?>) Source
Operator alias for Parsing.Combinators.withLazyErrorMessage (left-associative / precedence 4)
#asErrorMessage Source
asErrorMessage :: forall m s a. String -> ParserT s m a -> ParserT s m a
Flipped (<?>)
.
#(<??>) Source
Operator alias for Parsing.Combinators.asErrorMessage (right-associative / precedence 3)
Re-exports from Control.Plus
Re-exports from Data.List.Lazy
#replicateM Source
replicateM :: forall m a. Monad m => Int -> m a -> m (List a)
Perform a monadic action n
times collecting all of the results.
Re-exports from Data.Unfoldable
#replicateA Source
replicateA :: forall m f a. Applicative m => Unfoldable f => Traversable f => Int -> m a -> m (f a)
Perform an Applicative action n
times, and accumulate all the results.
> replicateA 5 (randomInt 1 10) :: Effect (Array Int)
[1,3,2,7,5]
Re-exports from Data.Unfoldable1
#replicate1A Source
replicate1A :: forall m f a. Apply m => Unfoldable1 f => Traversable1 f => Int -> m a -> m (f a)
Perform an Apply
action n
times (at least once, so values n
less
than 1 will be treated as 1), and accumulate the results.
> replicate1A 2 (randomInt 1 10) :: Effect (NEL.NonEmptyList Int)
(NonEmptyList (NonEmpty 8 (2 : Nil)))
> replicate1A 0 (randomInt 1 10) :: Effect (NEL.NonEmptyList Int)
(NonEmptyList (NonEmpty 4 Nil))