Module

Parsing.Combinators

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

The many and many1 combinators in the Parsing.Combinators.Array module are faster.

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

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

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 }))

#lookAhead

lookAhead :: forall s a m. ParserT s m a -> ParserT s m a

Parse a phrase, without modifying the consumed state or stream position.

#choice

choice :: forall f m s a. Foldable f => f (ParserT s m a) -> ParserT s m a

Parse one of a set of alternatives.

#between

between :: forall m s a open close. ParserT s m open -> ParserT s m close -> ParserT s m a -> ParserT s m a

Wrap a parser with opening and closing markers.

For example:

parens = between (string "(") (string ")")

#notFollowedBy

notFollowedBy :: forall s a m. ParserT s m a -> ParserT s m Unit

Fail if the parser succeeds.

Will never consume input.

#option

option :: forall m s a. a -> ParserT s m a -> ParserT s m a

Provide a default result in the case where a parser fails without consuming input.

#optionMaybe

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.

#optional

optional :: forall m s a. ParserT s m a -> ParserT s m Unit

Optionally parse something, failing quietly.

To optionally parse p and never fail: optional (try p).

#many

many :: forall s m a. ParserT s m a -> ParserT s m (List a)

Match the phrase p as many times as possible.

If p never consumes input when it fails then many p will always succeed, but may return an empty list.

#many1

many1 :: forall m s a. ParserT s m a -> ParserT s m (NonEmptyList a)

Match the phrase p as many times as possible, at least once.

#manyTill

manyTill :: forall s a m e. ParserT s m a -> ParserT s m e -> ParserT s m (List a)

Parse many phrases until the terminator phrase matches.

#manyTill_

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

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_

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

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.

#skipMany

skipMany :: forall s a m. ParserT s m a -> ParserT s m Unit

Skip many instances of a phrase.

#skipMany1

skipMany1 :: forall s a m. ParserT s m a -> ParserT s m Unit

Skip at least one instance of a phrase.

#sepBy

sepBy :: forall m s a sep. ParserT s m a -> ParserT s m sep -> ParserT s m (List a)

Parse phrases delimited by a separator.

For example:

digit `sepBy` string ","

#sepBy1

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.

#sepEndBy

sepEndBy :: forall m s a sep. ParserT s m a -> ParserT s m sep -> ParserT s m (List a)

Parse phrases delimited and optionally terminated by a separator.

#sepEndBy1

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.

#endBy

endBy :: forall m s a sep. ParserT s m a -> ParserT s m sep -> ParserT s m (List a)

Parse phrases delimited and terminated by a separator.

#endBy1

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

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

#chainl1

chainl1 :: forall m s a. ParserT s m a -> ParserT s m (a -> a -> a) -> ParserT s m a

chainl requiring at least one match.

#chainr

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

#chainr1

chainr1 :: forall m s a. ParserT s m a -> ParserT s m (a -> a -> a) -> ParserT s m a

chainr requiring at least one match.

#advance

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

withErrorMessage :: forall m s a. ParserT s m a -> String -> ParserT s m a

Provide an error message in the case of failure.

#(<?>)

Operator alias for Parsing.Combinators.withErrorMessage (left-associative / precedence 4)

#withLazyErrorMessage

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 '!' <~?> \_ -> "a bang"

#(<~?>)

Operator alias for Parsing.Combinators.withLazyErrorMessage (left-associative / precedence 4)

#asErrorMessage

asErrorMessage :: forall m s a. String -> ParserT s m a -> ParserT s m a

Flipped (<?>).

#(<??>)

Operator alias for Parsing.Combinators.asErrorMessage (right-associative / precedence 3)

Re-exports from Control.Plus

#alt

alt :: forall f a. Alt f => f a -> f a -> f a

#empty

empty :: forall f a. Plus f => f a

#(<|>)

Operator alias for Control.Alt.alt (right-associative / precedence 3)

Re-exports from Data.List.Lazy

#replicateM

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

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

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))

Modules