Copyright | © 2017–present Mark Karpov |
---|---|

License | BSD 3 clause |

Maintainer | Mark Karpov <markkarpov92@gmail.com> |

Stability | experimental |

Portability | portable |

Safe Haskell | Safe-Inferred |

Language | Haskell2010 |

The module provides parser combinators defined for instances of
`Applicative`

and `Alternative`

. It also re-exports functions that are
commonly used in parsing from Control.Applicative with additional
parsing-related comments added.

Due to the nature of the `Applicative`

and `Alternative`

abstractions,
they are prone to memory leaks and not as efficient as their monadic
counterparts. Although all the combinators we provide in this module are
perfectly expressible in terms of `Applicative`

and `Alternative`

, please
prefer Control.Monad.Combinators instead when possible.

If you wish that the combinators that cannot return empty lists return
values of the `NonEmpty`

data type, use the
Control.Applicative.Combinators.NonEmpty module.

### A note on backtracking

Certain parsing libraries, such as Megaparsec, do not backtrack every
branch of parsing automatically for the sake of performance and better
error messages. They typically backtrack only “atomic” parsers, e.g.
those that match a token or several tokens in a row. To backtrack an
arbitrary complex parser/branch, a special combinator should be used,
typically called `try`

. Combinators in this module are defined in terms
`Applicative`

and `Alternative`

operations. Being quite abstract, they
cannot know anything about inner workings of any concrete parsing
library, and so they cannot use `try`

.

The essential feature of the `Alternative`

type class is the `(`

operator that allows to express choice. In libraries that do not
backtrack everything automatically, the choice operator and everything
that is build on top of it require the parser on the left hand side to
backtrack in order for the alternative branch of parsing to be tried.
Thus it is the responsibility of the programmer to wrap more complex,
composite parsers in `<|>`

)`try`

to achieve correct behavior.

## Synopsis

- (<|>) :: Alternative f => f a -> f a -> f a
- many :: Alternative f => f a -> f [a]
- some :: Alternative f => f a -> f [a]
- optional :: Alternative f => f a -> f (Maybe a)
- empty :: Alternative f => f a
- between :: Applicative m => m open -> m close -> m a -> m a
- choice :: (Foldable f, Alternative m) => f (m a) -> m a
- count :: Applicative m => Int -> m a -> m [a]
- count' :: Alternative m => Int -> Int -> m a -> m [a]
- eitherP :: Alternative m => m a -> m b -> m (Either a b)
- endBy :: Alternative m => m a -> m sep -> m [a]
- endBy1 :: Alternative m => m a -> m sep -> m [a]
- manyTill :: Alternative m => m a -> m end -> m [a]
- manyTill_ :: Alternative m => m a -> m end -> m ([a], end)
- someTill :: Alternative m => m a -> m end -> m [a]
- someTill_ :: Alternative m => m a -> m end -> m ([a], end)
- option :: Alternative m => a -> m a -> m a
- sepBy :: Alternative m => m a -> m sep -> m [a]
- sepBy1 :: Alternative m => m a -> m sep -> m [a]
- sepEndBy :: Alternative m => m a -> m sep -> m [a]
- sepEndBy1 :: Alternative m => m a -> m sep -> m [a]
- skipMany :: Alternative m => m a -> m ()
- skipSome :: Alternative m => m a -> m ()
- skipCount :: Applicative m => Int -> m a -> m ()
- skipManyTill :: Alternative m => m a -> m end -> m end
- skipSomeTill :: Alternative m => m a -> m end -> m end

# Re-exports from Control.Applicative

(<|>) :: Alternative f => f a -> f a -> f a infixl 3 #

An associative binary operation

This combinator implements choice. The parser `p `

first applies
`<|>`

q`p`

. If it succeeds, the value of `p`

is returned. If `p`

fails, parser
`q`

is tried.

many :: Alternative f => f a -> f [a] #

Zero or more.

applies the parser `many`

p`p`

*zero* or more times and returns a list
of the values returned by `p`

.

identifier = (:) <$> letter <*> many (alphaNumChar <|> char '_')

some :: Alternative f => f a -> f [a] #

One or more.

applies the parser `some`

p`p`

*one* or more times and returns a list
of the values returned by `p`

.

word = some letter

optional :: Alternative f => f a -> f (Maybe a) #

One or none.

tries to apply the parser `optional`

p`p`

. It will parse `p`

or
`Nothing`

. It only fails if `p`

fails after consuming input. On success
result of `p`

is returned inside of `Just`

, on failure `Nothing`

is
returned.

See also: `option`

.

empty :: Alternative f => f a #

The identity of `<|>`

This parser fails unconditionally without providing any information about the cause of the failure.

*Since: 0.4.0*

# Original combinators

between :: Applicative m => m open -> m close -> m a -> m a Source #

parses `between`

open close p`open`

, followed by `p`

and `close`

.
Returns the value returned by `p`

.

braces = between (symbol "{") (symbol "}")

choice :: (Foldable f, Alternative m) => f (m a) -> m a Source #

tries to apply the parsers in the list `choice`

ps`ps`

in order,
until one of them succeeds. Returns the value of the succeeding parser.

choice = asum

count :: Applicative m => Int -> m a -> m [a] Source #

eitherP :: Alternative m => m a -> m b -> m (Either a b) Source #

Combine two alternatives.

eitherP a b = (Left <$> a) <|> (Right <$> b)

endBy :: Alternative m => m a -> m sep -> m [a] Source #

parses `endBy`

p sep*zero* or more occurrences of `p`

, separated and
ended by `sep`

. Returns a list of values returned by `p`

.

cStatements = cStatement `endBy` semicolon

endBy1 :: Alternative m => m a -> m sep -> m [a] Source #

parses `endBy1`

p sep*one* or more occurrences of `p`

, separated and
ended by `sep`

. Returns a list of values returned by `p`

.

manyTill :: Alternative m => m a -> m end -> m [a] Source #

applies parser `manyTill`

p end`p`

*zero* or more times until parser
`end`

succeeds. Returns the list of values returned by `p`

. `end`

result
is consumed and lost. Use `manyTill_`

if you wish to keep it.

See also: `skipMany`

, `skipManyTill`

.

manyTill_ :: Alternative m => m a -> m end -> m ([a], end) Source #

applies parser `manyTill_`

p end`p`

*zero* 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`

.

See also: `skipMany`

, `skipManyTill`

.

*Since: 1.2.0*

someTill :: Alternative m => m a -> m end -> m [a] Source #

works similarly to `someTill`

p end

, but `manyTill`

p end`p`

should succeed at least once. `end`

result is consumed and lost. Use
`someTill_`

if you wish to keep it.

someTill p end = liftA2 (:) p (manyTill p end)

See also: `skipSome`

, `skipSomeTill`

.

someTill_ :: Alternative m => m a -> m end -> m ([a], end) Source #

works similarly to `someTill_`

p end

, but `manyTill_`

p end`p`

should succeed at least once. Use `someTill`

if you have no need in the
result of the `end`

.

See also: `skipSome`

, `skipSomeTill`

.

*Since: 1.2.0*

option :: Alternative m => a -> m a -> m a Source #

sepBy :: Alternative m => m a -> m sep -> m [a] Source #

parses `sepBy`

p sep*zero* or more occurrences of `p`

, separated by
`sep`

. Returns a list of values returned by `p`

.

commaSep p = p `sepBy` comma

sepBy1 :: Alternative m => m a -> m sep -> m [a] Source #

parses `sepBy1`

p sep*one* or more occurrences of `p`

, separated by
`sep`

. Returns a list of values returned by `p`

.

sepEndBy :: Alternative m => m a -> m sep -> m [a] Source #

parses `sepEndBy`

p sep*zero* or more occurrences of `p`

, separated
and optionally ended by `sep`

. Returns a list of values returned by `p`

.

sepEndBy1 :: Alternative m => m a -> m sep -> m [a] Source #

parses `sepEndBy1`

p sep*one* or more occurrences of `p`

, separated
and optionally ended by `sep`

. Returns a list of values returned by `p`

.

skipMany :: Alternative m => m a -> m () Source #

applies the parser `skipMany`

p`p`

*zero* or more times, skipping
its result.

See also: `manyTill`

, `skipManyTill`

.

skipSome :: Alternative m => m a -> m () Source #

applies the parser `skipSome`

p`p`

*one* or more times, skipping its
result.

See also: `someTill`

, `skipSomeTill`

.

skipCount :: Applicative m => Int -> m a -> m () Source #

skipManyTill :: Alternative m => m a -> m end -> m end Source #

applies the parser `skipManyTill`

p end`p`

*zero* or more times
skipping results until parser `end`

succeeds. Result parsed by `end`

is
then returned.

skipSomeTill :: Alternative m => m a -> m end -> m end Source #

applies the parser `skipSomeTill`

p end`p`

*one* or more times
skipping results until parser `end`

succeeds. Result parsed by `end`

is
then returned.