Copyright | (c) Edward Kmett 2011-2012 |
---|---|

License | BSD3 |

Maintainer | ekmett@gmail.com |

Stability | experimental |

Portability | non-portable |

Safe Haskell | Safe-Inferred |

Language | Haskell2010 |

Alternative parser combinators.

Originally in `parsers`

package.

## Synopsis

- choice :: Alternative m => [m a] -> m a
- option :: Alternative m => a -> m a -> m a
- optional :: Alternative f => f a -> f (Maybe a)
- skipOptional :: Alternative m => m a -> m ()
- between :: Applicative m => m bra -> m ket -> m a -> m a
- some :: Alternative f => f a -> f [a]
- many :: Alternative f => f a -> f [a]
- sepBy :: Alternative m => m a -> m sep -> m [a]
- sepByNonEmpty :: Alternative m => m a -> m sep -> m (NonEmpty a)
- sepEndByNonEmpty :: Alternative m => m a -> m sep -> m (NonEmpty a)
- sepEndBy :: Alternative m => m a -> m sep -> m [a]
- endByNonEmpty :: Alternative m => m a -> m sep -> m (NonEmpty a)
- endBy :: Alternative m => m a -> m sep -> m [a]
- count :: Applicative m => Int -> m a -> m [a]
- chainl :: Alternative m => m a -> m (a -> a -> a) -> a -> m a
- chainr :: Alternative m => m a -> m (a -> a -> a) -> a -> m a
- chainl1 :: Alternative m => m a -> m (a -> a -> a) -> m a
- chainr1 :: Alternative m => m a -> m (a -> a -> a) -> m a
- manyTill :: Alternative m => m a -> m end -> m [a]
- class Alternative m => Parsing (m :: Type -> Type) where
- try :: m a -> m a
- (<?>) :: m a -> String -> m a
- skipMany :: m a -> m ()
- skipSome :: m a -> m ()
- unexpected :: String -> m a
- eof :: m ()
- notFollowedBy :: Show a => m a -> m ()

# Parsing Combinators

choice :: Alternative m => [m a] -> m a Source #

`choice ps`

tries to apply the parsers in the list `ps`

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

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

`option x p`

tries to apply parser `p`

. If `p`

fails without
consuming input, it returns the value `x`

, otherwise the value
returned by `p`

.

priority = option 0 (digitToInt <$> digit)

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

One or none.

It is useful for modelling any computation that is allowed to fail.

#### Examples

Using the `Alternative`

instance of Control.Monad.Except, the following functions:

`>>>`

`import Control.Monad.Except`

`>>>`

`canFail = throwError "it failed" :: Except String Int`

`>>>`

`final = return 42 :: Except String Int`

Can be combined by allowing the first function to fail:

`>>>`

Left "it failed"`runExcept $ canFail *> final`

`>>>`

Right 42`runExcept $ optional canFail *> final`

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

`skipOptional p`

tries to apply parser `p`

. It will parse `p`

or nothing.
It only fails if `p`

fails after consuming input. It discards the result
of `p`

. (Plays the role of parsec's optional, which conflicts with Applicative's optional)

between :: Applicative m => m bra -> m ket -> m a -> m a Source #

`between open close p`

parses `open`

, followed by `p`

and `close`

.
Returns the value returned by `p`

.

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

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

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

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

`sepBy p sep`

parses *zero* or more occurrences of `p`

, separated
by `sep`

. Returns a list of values returned by `p`

.

commaSep p = p `sepBy` (symbol ",")

sepByNonEmpty :: Alternative m => m a -> m sep -> m (NonEmpty a) Source #

`sepByNonEmpty p sep`

parses *one* or more occurrences of `p`

, separated
by `sep`

. Returns a non-empty list of values returned by `p`

.

sepEndByNonEmpty :: Alternative m => m a -> m sep -> m (NonEmpty a) Source #

`sepEndByNonEmpty p sep`

parses *one* or more occurrences of `p`

,
separated and optionally ended by `sep`

. Returns a non-empty list of values
returned by `p`

.

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

`sepEndBy p sep`

parses *zero* or more occurrences of `p`

,
separated and optionally ended by `sep`

, ie. haskell style
statements. Returns a list of values returned by `p`

.

haskellStatements = haskellStatement `sepEndBy` semi

endByNonEmpty :: Alternative m => m a -> m sep -> m (NonEmpty a) Source #

`endByNonEmpty p sep`

parses *one* or more occurrences of `p`

, separated
and ended by `sep`

. Returns a non-empty list of values returned by `p`

.

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

`endBy p sep`

parses *zero* or more occurrences of `p`

, separated
and ended by `sep`

. Returns a list of values returned by `p`

.

cStatements = cStatement `endBy` semi

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

`count n p`

parses `n`

occurrences of `p`

. If `n`

is smaller or
equal to zero, the parser equals to `return []`

. Returns a list of
`n`

values returned by `p`

.

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

`chainl p op x`

parses *zero* or more occurrences of `p`

,
separated by `op`

. Returns a value obtained by a *left* associative
application of all functions returned by `op`

to the values returned
by `p`

. If there are zero occurrences of `p`

, the value `x`

is
returned.

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

`chainr p op x`

parses *zero* or more occurrences of `p`

,
separated by `op`

Returns a value obtained by a *right* associative
application of all functions returned by `op`

to the values returned
by `p`

. If there are no occurrences of `p`

, the value `x`

is
returned.

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

`chainl1 p op x`

parses *one* or more occurrences of `p`

,
separated by `op`

Returns a value obtained by a *left* associative
application of all functions returned by `op`

to the values returned
by `p`

. . This parser can for example be used to eliminate left
recursion which typically occurs in expression grammars.

expr = term `chainl1` addop term = factor `chainl1` mulop factor = parens expr <|> integer mulop = (*) <$ symbol "*" <|> div <$ symbol "/" addop = (+) <$ symbol "+" <|> (-) <$ symbol "-"

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

`chainr1 p op x`

parses *one* or more occurrences of `p`

,
separated by `op`

Returns a value obtained by a *right* associative
application of all functions returned by `op`

to the values returned
by `p`

.

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

`manyTill p end`

applies parser `p`

*zero* or more times until
parser `end`

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

.
This parser can be used to scan comments:

simpleComment = do{ string "<!--" ; manyTill anyChar (try (string "-->")) }

Note the overlapping parsers `anyChar`

and `string "-->"`

, and
therefore the use of the `try`

combinator.

# Parsing Class

class Alternative m => Parsing (m :: Type -> Type) where Source #

Additional functionality needed to describe parsers independent of input type.

Take a parser that may consume input, and on failure, go back to where we started and fail as if we didn't consume input.

(<?>) :: m a -> String -> m a infixr 0 Source #

Give a parser a name

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

A version of many that discards its input. Specialized because it can often be implemented more cheaply.

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

`skipSome p`

applies the parser `p`

*one* or more times, skipping
its result. (aka skipMany1 in parsec)

unexpected :: String -> m a Source #

Used to emit an error on an unexpected token

This parser only succeeds at the end of the input. This is not a
primitive parser but it is defined using `notFollowedBy`

.

eof = notFollowedBy anyChar <?> "end of input"

notFollowedBy :: Show a => m a -> m () Source #

`notFollowedBy p`

only succeeds when parser `p`

fails. This parser
does not consume any input. This parser can be used to implement the
'longest match' rule. For example, when recognizing keywords (for
example `let`

), we want to make sure that a keyword is not followed
by a legal identifier character, in which case the keyword is
actually an identifier (for example `lets`

). We can program this
behaviour as follows:

keywordLet = try $ string "let" <* notFollowedBy alphaNum