Module

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

#lookAhead Source

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 Source

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 Source

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 Source

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

Fail if the parser succeeds.

Will never consume input.

#option Source

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

#optional Source

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 Source

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

Match the parser 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 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 (List a)

Parse many phrases until the terminator phrase matches.

#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.

#skipMany Source

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

Skip many instances of a phrase.

#skipMany1 Source

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

Skip at least one instance of a phrase.

#sepBy Source

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

#sepEndBy Source

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

#endBy Source

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

#chainl1 Source

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

#chainr1 Source

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

#alt Source

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

#empty Source

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

#(<|>) Source

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

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