foundation-0.0.30: Alternative prelude with batteries and no dependencies

License | BSD-style
Maintainer | Haskell Foundation
Stability | experimental
Portability | portable
Safe Haskell | None
Language | Haskell2010

Foundation.Parser

Contents

- Result
- Parser source
- combinator

Description

The current implementation is mainly, if not copy/pasted, inspired from `memory`'s Parser.

Foundation Parser makes use of the Foundation's `Collection` and `Sequential` classes to allow you to define generic parsers over any `Sequential` of inpu.

This way you can easily implements parsers over `LString`, `String`.

    flip parseOnly "my.email@address.com" $ do
       EmailAddress
         <$> (takeWhile ((/=) '@' <*  element '@')
         <*> takeAll

Synopsis

- data Parser input result
- parse :: ParserSource input => Parser input a -> input -> Result input a
- parseFeed :: (ParserSource input, Monad m) => m (Chunk input) -> Parser input a -> input -> m (Result input a)
- parseOnly :: (ParserSource input, Monoid (Chunk input)) => Parser input a -> input -> Either (ParseError input) a
- data Result input result
  - = ParseFailed (ParseError input)
  - | ParseOk (Chunk input) result
  - | ParseMore (Chunk input -> Result input result)
- data ParseError input
  - = NotEnough (CountOf (Element input))
  - | NotEnoughParseOnly
  - | ExpectedElement (Element input) (Element input)
  - | Expected (Chunk input) (Chunk input)
  - | Satisfy (Maybe String)
- reportError :: ParseError input -> Parser input a
- class (Sequential input, IndexedCollection input) => ParserSource input where
  - type Chunk input
  - nullChunk :: input -> Chunk input -> Bool
  - appendChunk :: input -> Chunk input -> input
  - subChunk :: input -> Offset (Element input) -> CountOf (Element input) -> Chunk input
  - spanChunk :: input -> Offset (Element input) -> (Element input -> Bool) -> (Chunk input, Offset (Element input))
- peek :: ParserSource input => Parser input (Maybe (Element input))
- element :: (ParserSource input, Eq (Element input), Element input ~ Element (Chunk input)) => Element input -> Parser input ()
- anyElement :: ParserSource input => Parser input (Element input)
- elements :: (ParserSource input, Sequential (Chunk input), Element (Chunk input) ~ Element input, Eq (Chunk input)) => Chunk input -> Parser input ()
- string :: String -> Parser String ()
- satisfy :: ParserSource input => Maybe String -> (Element input -> Bool) -> Parser input (Element input)
- satisfy_ :: ParserSource input => (Element input -> Bool) -> Parser input (Element input)
- take :: (ParserSource input, Sequential (Chunk input), Element input ~ Element (Chunk input)) => CountOf (Element (Chunk input)) -> Parser input (Chunk input)
- takeWhile :: (ParserSource input, Sequential (Chunk input)) => (Element input -> Bool) -> Parser input (Chunk input)
- takeAll :: (ParserSource input, Sequential (Chunk input)) => Parser input (Chunk input)
- skip :: ParserSource input => CountOf (Element input) -> Parser input ()
- skipWhile :: (ParserSource input, Sequential (Chunk input)) => (Element input -> Bool) -> Parser input ()
- skipAll :: (ParserSource input, Collection (Chunk input)) => Parser input ()
- (<|>) :: 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)
- repeat :: ParserSource input => Condition -> Parser input a -> Parser input [a]
- data Condition
  - = Between !And
  - | Exactly !Word
- data And = And !Word !Word

# Documentation

data Parser input result #

Foundation's `Parser` monad.

Its implementation is based on the parser in `memory`.

#### Instances

Instances details

ParserSource input => Alternative (Parser input) # |
Instance details Defined in Foundation.Parser Methods empty :: Parser input a # (<|>) :: Parser input a -> Parser input a -> Parser input a # some :: Parser input a -> Parser input [a] # many :: Parser input a -> Parser input [a] #
ParserSource input => Applicative (Parser input) # |
Instance details Defined in Foundation.Parser Methods pure :: a -> Parser input a # (<*>) :: Parser input (a -> b) -> Parser input a -> Parser input b # liftA2 :: (a -> b -> c) -> Parser input a -> Parser input b -> Parser input c # (*>) :: Parser input a -> Parser input b -> Parser input b # (<*) :: Parser input a -> Parser input b -> Parser input a #
Functor (Parser input) # |
Instance details Defined in Foundation.Parser Methods fmap :: (a -> b) -> Parser input a -> Parser input b # (<$) :: a -> Parser input b -> Parser input a #
ParserSource input => Monad (Parser input) # |
Instance details Defined in Foundation.Parser Methods (>>=) :: Parser input a -> (a -> Parser input b) -> Parser input b # (>>) :: Parser input a -> Parser input b -> Parser input b # return :: a -> Parser input a #
ParserSource input => MonadPlus (Parser input) # |
Instance details Defined in Foundation.Parser Methods mzero :: Parser input a # mplus :: Parser input a -> Parser input a -> Parser input a #

parse :: ParserSource input => Parser input a -> input -> Result input a #

Run a Parser on a ByteString and return a `Result`

parseFeed :: (ParserSource input, Monad m) => m (Chunk input) -> Parser input a -> input -> m (Result input a) #

Run a parser on an @initial input.

If the Parser need more data than available, the @feeder function is automatically called and fed to the More continuation.

parseOnly :: (ParserSource input, Monoid (Chunk input)) => Parser input a -> input -> Either (ParseError input) a #

parse only the given input

The left-over `Element input` will be ignored, if the parser call for more data it will be continuously fed with `Nothing` (up to 256 iterations).

# Result

data Result input result #

result of executing the `parser` over the given `input`

Constructors

ParseFailed (ParseError input) | the parser failed with the given `ParserError`
ParseOk (Chunk input) result | the parser complete successfuly with the remaining `Chunk`
ParseMore (Chunk input -> Result input result) | the parser needs more input, pass an empty `Chunk` or `mempty` to tell the parser you don't have anymore inputs.

#### Instances

Instances details

Functor (Result input) # |
Instance details Defined in Foundation.Parser Methods fmap :: (a -> b) -> Result input a -> Result input b # (<$) :: a -> Result input b -> Result input a #
(Show k, Show input) => Show (Result input k) # |
Instance details Defined in Foundation.Parser Methods showsPrec :: Int -> Result input k -> ShowS # show :: Result input k -> String # showList :: [Result input k] -> ShowS #

data ParseError input #

common parser error definition

Constructors

NotEnough (CountOf (Element input)) | meaning the parser was short of `CountOf` `Element` of `input`.
NotEnoughParseOnly | The parser needed more data, only when using `parseOnly`
ExpectedElement (Element input) (Element input) | when using `element`
Expected (Chunk input) (Chunk input) | when using `elements` or `string`
Satisfy (Maybe String) | the `satisfy` or `satisfy_` function failed,

#### Instances

Instances details

(Typeable input, Show input) => Exception (ParseError input) # |
Instance details Defined in Foundation.Parser Methods toException :: ParseError input -> SomeException # fromException :: SomeException -> Maybe (ParseError input) # displayException :: ParseError input -> String # backtraceDesired :: ParseError input -> Bool #
Show (ParseError String) # |
Instance details Defined in Foundation.Parser Methods showsPrec :: Int -> ParseError String -> ShowS # show :: ParseError String -> String # showList :: [ParseError String] -> ShowS #
Show input => Show (ParseError input) # |
Instance details Defined in Foundation.Parser Methods showsPrec :: Int -> ParseError input -> ShowS # show :: ParseError input -> String # showList :: [ParseError input] -> ShowS #

reportError :: ParseError input -> Parser input a #

helper function to report error when writing parsers

This way we can provide more detailed error when building custom parsers and still avoid to use the naughty _fail_.

    myParser :: Parser input Int
    myParser = reportError $ Satisfy (Just "this function is not implemented...")

# Parser source

class (Sequential input, IndexedCollection input) => ParserSource input where #

Associated Types

type Chunk input #

Methods

nullChunk :: input -> Chunk input -> Bool #

appendChunk :: input -> Chunk input -> input #

subChunk :: input -> Offset (Element input) -> CountOf (Element input) -> Chunk input #

spanChunk :: input -> Offset (Element input) -> (Element input -> Bool) -> (Chunk input, Offset (Element input)) #

#### Instances

Instances details

ParserSource String # |
Instance details Defined in Foundation.Parser Associated Types
type Chunk String |
Instance details Defined in Foundation.Parser type Chunk String = String
Methods nullChunk :: String -> Chunk String -> Bool # appendChunk :: String -> Chunk String -> String # subChunk :: String -> Offset (Element String) -> CountOf (Element String) -> Chunk String # spanChunk :: String -> Offset (Element String) -> (Element String -> Bool) -> (Chunk String, Offset (Element String)) #
ParserSource [a] # |
Instance details Defined in Foundation.Parser Associated Types
type Chunk [a] |
Instance details Defined in Foundation.Parser type Chunk [a] = [a]
Methods nullChunk :: [a] -> Chunk [a] -> Bool # appendChunk :: [a] -> Chunk [a] -> [a] # subChunk :: [a] -> Offset (Element [a]) -> CountOf (Element [a]) -> Chunk [a] # spanChunk :: [a] -> Offset (Element [a]) -> (Element [a] -> Bool) -> (Chunk [a], Offset (Element [a])) #

# combinator

peek :: ParserSource input => Parser input (Maybe (Element input)) #

peek the first element from the input source without consuming it

Returns `Nothing` if there is no more input to parse.

element :: (ParserSource input, Eq (Element input), Element input ~ Element (Chunk input)) => Element input -> Parser input () #

anyElement :: ParserSource input => Parser input (Element input) #

Get the next `Element input` from the parser

elements :: (ParserSource input, Sequential (Chunk input), Element (Chunk input) ~ Element input, Eq (Chunk input)) => Chunk input -> Parser input () #

string :: String -> Parser String () #

satisfy :: ParserSource input => Maybe String -> (Element input -> Bool) -> Parser input (Element input) #

take one element if satisfy the given predicate

satisfy_ :: ParserSource input => (Element input -> Bool) -> Parser input (Element input) #

take one element if satisfy the given predicate

take :: (ParserSource input, Sequential (Chunk input), Element input ~ Element (Chunk input)) => CountOf (Element (Chunk input)) -> Parser input (Chunk input) #

takeWhile :: (ParserSource input, Sequential (Chunk input)) => (Element input -> Bool) -> Parser input (Chunk input) #

takeAll :: (ParserSource input, Sequential (Chunk input)) => Parser input (Chunk input) #

Take the remaining elements from the current position in the stream

skip :: ParserSource input => CountOf (Element input) -> Parser input () #

skipWhile :: (ParserSource input, Sequential (Chunk input)) => (Element input -> Bool) -> Parser input () #

skipAll :: (ParserSource input, Collection (Chunk input)) => Parser input () #

consume every chunk of the stream

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

An associative binary operation

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

Zero or more.

#### Examples

Expand

    >>> many (putStr "la")
    lalalalalalalalala... * goes on forever *

    >>> many Nothing
    Just []

    >>> take 5 <$> many (Just 1)
    * hangs forever *

Note that this function can be used with Parsers based on Applicatives. In that case `many parser` will attempt to parse `parser` zero or more times until it fails.

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

One or more.

#### Examples

Expand

    >>> some (putStr "la")
    lalalalalalalalala... * goes on forever *

    >>> some Nothing
    nothing

    >>> take 5 <$> some (Just 1)
    * hangs forever *

Note that this function can be used with Parsers based on Applicatives. In that case `some parser` will attempt to parse `parser` one or more times until it fails.

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

One or none.

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

#### Examples

Expand

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:

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

    >>> runExcept $ optional canFail *> final
    Right 42

repeat :: ParserSource input => Condition -> Parser input a -> Parser input [a] #

repeat the given parser a given amount of time

Unlike `some` or `many`, this operation will bring more precision on how many times you wish a parser to be sequenced.

## Repeat `Exactly` a number of time

    repeat (Exactly 6) (takeWhile ((/=) ',') <* element ',')

## Repeat `Between` lower ``And`` upper times

    repeat (Between $ 1 `And` 10) (takeWhile ((/=) ',') <* element ',')

data Condition #

Constructors

Between !And |
Exactly !Word |

#### Instances

Instances details

Show Condition # |
Instance details Defined in Foundation.Parser Methods showsPrec :: Int -> Condition -> ShowS # show :: Condition -> String # showList :: [Condition] -> ShowS #
Eq Condition # |
Instance details Defined in Foundation.Parser Methods (==) :: Condition -> Condition -> Bool # (/=) :: Condition -> Condition -> Bool #

data And #

Constructors

And !Word !Word |

#### Instances

Instances details

Show And # |
Instance details Defined in Foundation.Parser Methods showsPrec :: Int -> And -> ShowS # show :: And -> String # showList :: [And] -> ShowS #
Eq And # |
Instance details Defined in Foundation.Parser Methods (==) :: And -> And -> Bool # (/=) :: And -> And -> Bool #