{-# LANGUAGE PatternSynonyms #-}
{-|
Module      : Parsley.Applicative
Description : The @Applicative@ combinators
License     : BSD-3-Clause
Maintainer  : Jamie Willis
Stability   : stable

This modules contains all of the @Applicative@ combinators that would normally be found in
@Data.Functor@ or @Control.Applicative@. However, since Parsley makes use of staging, the signatures
of these combinators do not correctly match the signatures of those in base Haskell.

@since 0.1.0.0
-}
module Parsley.Applicative (
    pure, (<*>), (*>), (<*),
    fmap, (<$>), void, (<$), ($>), (<&>), constp,
    unit, (<~>), (<~), (~>),
    liftA2, liftA3,
    (<:>), (<**>),
    sequence, traverse, repeat,
    between,
    (>>)
  ) where

import Prelude hiding           (pure, (<*>), (*>), (<*), (>>), (<$>), fmap, (<$), traverse, sequence, repeat)
import Parsley.Defunctionalized (Defunc(CONS, CONST, ID, EMPTY), pattern FLIP_H, pattern UNIT)
import Parsley.Internal         (makeQ, Parser)
import Parsley.ParserOps        (ParserOps, pure)

import qualified Parsley.Internal as Internal ((<*>), (*>), (<*))

-- Applicative Operations
{-|
Sequential application of one parser's result to another's. The parsers must both succeed, one after
the other to combine their results. If either parser fails then the combinator will fail.

@since 0.1.0.0
-}
infixl 4 <*>
(<*>) :: Parser (a -> b) -> Parser a -> Parser b
<*> :: Parser (a -> b) -> Parser a -> Parser b
(<*>) = Parser (a -> b) -> Parser a -> Parser b
forall a b. Parser (a -> b) -> Parser a -> Parser b
(Internal.<*>)

{-|
Sequence two parsers, keeping the result of the second and discarding the result of the first.

@since 0.1.0.0
-}
infixl 4 <*
(<*) :: Parser a -> Parser b -> Parser a
<* :: Parser a -> Parser b -> Parser a
(<*) = Parser a -> Parser b -> Parser a
forall a b. Parser a -> Parser b -> Parser a
(Internal.<*)

{-|
Sequence two parsers, keeping the result of the first and discarding the result of the second.

@since 0.1.0.0
-}
infixl 4 *>
(*>) :: Parser a -> Parser b -> Parser b
*> :: Parser a -> Parser b -> Parser b
(*>) = Parser a -> Parser b -> Parser b
forall a b. Parser a -> Parser b -> Parser b
(Internal.*>)

-- Functor Operations
{-|
Maps a function over the result of a parser.

@since 0.1.0.0
-}
fmap :: ParserOps rep => rep (a -> b) -> Parser a -> Parser b
fmap :: rep (a -> b) -> Parser a -> Parser b
fmap rep (a -> b)
f = (rep (a -> b) -> Parser (a -> b)
forall (rep :: Type -> Type) a. ParserOps rep => rep a -> Parser a
pure rep (a -> b)
f Parser (a -> b) -> Parser a -> Parser b
forall a b. Parser (a -> b) -> Parser a -> Parser b
<*>)

{-|
Alias of `fmap`.

@since 0.1.0.0
-}
infixl 4 <$>
(<$>) :: ParserOps rep => rep (a -> b) -> Parser a -> Parser b
<$> :: rep (a -> b) -> Parser a -> Parser b
(<$>) = rep (a -> b) -> Parser a -> Parser b
forall (rep :: Type -> Type) a b.
ParserOps rep =>
rep (a -> b) -> Parser a -> Parser b
fmap

{-|
This combinator \"forgets\" the result of a parser, and replaces it with @()@.

@since 0.1.0.0
-}
void :: Parser a -> Parser ()
void :: Parser a -> Parser ()
void Parser a
p = Parser a
p Parser a -> Defunc () -> Parser ()
forall (rep :: Type -> Type) a b.
ParserOps rep =>
Parser a -> rep b -> Parser b
$> Defunc ()
UNIT

{-|
This combinator \"forgets\" the result of a parser, and replaces it the given value.

@since 0.1.0.0
-}
infixl 4 <$
(<$) :: ParserOps rep => rep b -> Parser a -> Parser b
rep b
x <$ :: rep b -> Parser a -> Parser b
<$ Parser a
p = Parser a
p Parser a -> Parser b -> Parser b
forall a b. Parser a -> Parser b -> Parser b
*> rep b -> Parser b
forall (rep :: Type -> Type) a. ParserOps rep => rep a -> Parser a
pure rep b
x

{-|
This combinator \"forgets\" the result of a parser, and replaces it the given value.

@since 0.1.0.0
-}
infixl 4 $>
($>) :: ParserOps rep => Parser a -> rep b -> Parser b
$> :: Parser a -> rep b -> Parser b
($>) = (rep b -> Parser a -> Parser b) -> Parser a -> rep b -> Parser b
forall a b c. (a -> b -> c) -> b -> a -> c
flip rep b -> Parser a -> Parser b
forall (rep :: Type -> Type) b a.
ParserOps rep =>
rep b -> Parser a -> Parser b
(<$)

{-|
Maps a function over the result of a parser.

@since 0.1.0.0
-}
infixl 4 <&>
(<&>) :: ParserOps rep => Parser a -> rep (a -> b) -> Parser b
<&> :: Parser a -> rep (a -> b) -> Parser b
(<&>) = (rep (a -> b) -> Parser a -> Parser b)
-> Parser a -> rep (a -> b) -> Parser b
forall a b c. (a -> b -> c) -> b -> a -> c
flip rep (a -> b) -> Parser a -> Parser b
forall (rep :: Type -> Type) a b.
ParserOps rep =>
rep (a -> b) -> Parser a -> Parser b
fmap

-- | @since 0.1.0.0
constp :: Parser a -> Parser (b -> a)
constp :: Parser a -> Parser (b -> a)
constp = (Defunc (a -> b -> a)
forall a1 b. Defunc (a1 -> b -> a1)
CONST Defunc (a -> b -> a) -> Parser a -> Parser (b -> a)
forall (rep :: Type -> Type) a b.
ParserOps rep =>
rep (a -> b) -> Parser a -> Parser b
<$>)

-- Alias Operations
{-|
Alias of @(`*>`)@

@since 0.1.0.0
-}
infixl 1 >>
(>>) :: Parser a -> Parser b -> Parser b
>> :: Parser a -> Parser b -> Parser b
(>>) = Parser a -> Parser b -> Parser b
forall a b. Parser a -> Parser b -> Parser b
(*>)

-- Monoidal Operations
{-|
This parser always returns @()@ without consuming input.

@since 0.1.0.0
-}
unit :: Parser ()
unit :: Parser ()
unit = Defunc () -> Parser ()
forall (rep :: Type -> Type) a. ParserOps rep => rep a -> Parser a
pure Defunc ()
UNIT

{-|
Sequential zipping of one parser's result with another's. The parsers must both succeed, one after
the other to pair their results. If either parser fails then the combinator will fail.

@since 0.1.0.0
-}
infixl 4 <~>
(<~>) :: Parser a -> Parser b -> Parser (a, b)
<~> :: Parser a -> Parser b -> Parser (a, b)
(<~>) = Defunc (a -> b -> (a, b)) -> Parser a -> Parser b -> Parser (a, b)
forall (rep :: Type -> Type) a b c.
ParserOps rep =>
rep (a -> b -> c) -> Parser a -> Parser b -> Parser c
liftA2 ((a -> b -> (a, b))
-> Code (a -> b -> (a, b)) -> Defunc (a -> b -> (a, b))
forall (q :: Type -> Type) a. Quapplicative q => a -> Code a -> q a
makeQ (,) [||(,)||])

{-|
Alias of @(`<*`)@

@since 0.1.0.0
-}
infixl 4 <~
(<~) :: Parser a -> Parser b -> Parser a
<~ :: Parser a -> Parser b -> Parser a
(<~) = Parser a -> Parser b -> Parser a
forall a b. Parser a -> Parser b -> Parser a
(<*)

{-|
Alias of @(`*>`)@

@since 0.1.0.0
-}
infixl 4 ~>
(~>) :: Parser a -> Parser b -> Parser b
~> :: Parser a -> Parser b -> Parser b
(~>) = Parser a -> Parser b -> Parser b
forall a b. Parser a -> Parser b -> Parser b
(*>)

-- Lift Operations
{-|
Sequential combination of two parsers results. The results are combined using the given function.

@since 0.1.0.0
-}
liftA2 :: ParserOps rep => rep (a -> b -> c) -> Parser a -> Parser b -> Parser c
liftA2 :: rep (a -> b -> c) -> Parser a -> Parser b -> Parser c
liftA2 rep (a -> b -> c)
f Parser a
p Parser b
q = rep (a -> b -> c)
f rep (a -> b -> c) -> Parser a -> Parser (b -> c)
forall (rep :: Type -> Type) a b.
ParserOps rep =>
rep (a -> b) -> Parser a -> Parser b
<$> Parser a
p Parser (b -> c) -> Parser b -> Parser c
forall a b. Parser (a -> b) -> Parser a -> Parser b
<*> Parser b
q

{-|
Sequential combination of three parsers results. The results are combined using the given function.

@since 0.1.0.0
-}
liftA3 :: ParserOps rep => rep (a -> b -> c -> d) -> Parser a -> Parser b -> Parser c -> Parser d
liftA3 :: rep (a -> b -> c -> d)
-> Parser a -> Parser b -> Parser c -> Parser d
liftA3 rep (a -> b -> c -> d)
f Parser a
p Parser b
q Parser c
r = rep (a -> b -> c -> d)
f rep (a -> b -> c -> d) -> Parser a -> Parser (b -> c -> d)
forall (rep :: Type -> Type) a b.
ParserOps rep =>
rep (a -> b) -> Parser a -> Parser b
<$> Parser a
p Parser (b -> c -> d) -> Parser b -> Parser (c -> d)
forall a b. Parser (a -> b) -> Parser a -> Parser b
<*> Parser b
q Parser (c -> d) -> Parser c -> Parser d
forall a b. Parser (a -> b) -> Parser a -> Parser b
<*> Parser c
r

{-|
Sequential consing of one parser's result with another's. The parsers must both succeed, one after
the other to combine their results. If either parser fails then the combinator will fail.

@since 0.1.0.0
-}
infixl 4 <:>
(<:>) :: Parser a -> Parser [a] -> Parser [a]
<:> :: Parser a -> Parser [a] -> Parser [a]
(<:>) = Defunc (a -> [a] -> [a]) -> Parser a -> Parser [a] -> Parser [a]
forall (rep :: Type -> Type) a b c.
ParserOps rep =>
rep (a -> b -> c) -> Parser a -> Parser b -> Parser c
liftA2 Defunc (a -> [a] -> [a])
forall a1. Defunc (a1 -> [a1] -> [a1])
CONS

{-|
A variant of @(`<*>`)@ with the arguments reversed.

@since 0.1.0.0
-}
infixl 4 <**>
(<**>) :: Parser a -> Parser (a -> b) -> Parser b
<**> :: Parser a -> Parser (a -> b) -> Parser b
(<**>) = Defunc (a -> (a -> b) -> b)
-> Parser a -> Parser (a -> b) -> Parser b
forall (rep :: Type -> Type) a b c.
ParserOps rep =>
rep (a -> b -> c) -> Parser a -> Parser b -> Parser c
liftA2 (Defunc ((a -> b) -> a -> b) -> Defunc (a -> (a -> b) -> b)
forall y x a b c.
((x -> y) ~ ((a -> b -> c) -> b -> a -> c)) =>
Defunc x -> Defunc y
FLIP_H Defunc ((a -> b) -> a -> b)
forall a1. Defunc (a1 -> a1)
ID)

-- Auxillary functions
{-|
Given a list of parsers, `sequence` will parse each in turn and collect all their results into a
list. All the parsers in the list must succeed.

@since 0.1.0.0
-}
sequence :: [Parser a] -> Parser [a]
sequence :: [Parser a] -> Parser [a]
sequence = (Parser a -> Parser [a] -> Parser [a])
-> Parser [a] -> [Parser a] -> Parser [a]
forall (t :: Type -> Type) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Parser a -> Parser [a] -> Parser [a]
forall a. Parser a -> Parser [a] -> Parser [a]
(<:>) (Defunc [a] -> Parser [a]
forall (rep :: Type -> Type) a. ParserOps rep => rep a -> Parser a
pure Defunc [a]
forall a1. Defunc [a1]
EMPTY)

{-|
Like `sequence`, but the parsers to sequence are generated from seed values using a given generator
function.

@since 0.1.0.0
-}
traverse :: (a -> Parser b) -> [a] -> Parser [b]
traverse :: (a -> Parser b) -> [a] -> Parser [b]
traverse a -> Parser b
f = [Parser b] -> Parser [b]
forall a. [Parser a] -> Parser [a]
sequence ([Parser b] -> Parser [b])
-> ([a] -> [Parser b]) -> [a] -> Parser [b]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> Parser b) -> [a] -> [Parser b]
forall a b. (a -> b) -> [a] -> [b]
map a -> Parser b
f

{-|
The combinator @repeat n p@ will attempt to parse @p@ exactly @n@ times. That is not to say that
the parser must fail on the @n+1@th try, but there must be @n@ successes for the combinator to
succeed. All the results generated from @p@ will be collected into a list.

@since 0.1.0.0
-}
repeat :: Int -> Parser a -> Parser [a]
repeat :: Int -> Parser a -> Parser [a]
repeat Int
n = [Parser a] -> Parser [a]
forall a. [Parser a] -> Parser [a]
sequence ([Parser a] -> Parser [a])
-> (Parser a -> [Parser a]) -> Parser a -> Parser [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Parser a -> [Parser a]
forall a. Int -> a -> [a]
replicate Int
n

{-|
The combinator @between open close p@ will first parse @open@ then @p@ and then @close@, yielding
the result given by @p@.

@since 0.1.0.0
-}
between :: Parser o -> Parser c -> Parser a -> Parser a
between :: Parser o -> Parser c -> Parser a -> Parser a
between Parser o
open Parser c
close Parser a
p = Parser o
open Parser o -> Parser a -> Parser a
forall a b. Parser a -> Parser b -> Parser b
*> Parser a
p Parser a -> Parser c -> Parser a
forall a b. Parser a -> Parser b -> Parser a
<* Parser c
close