module Parsley.Internal.Core.Primitives (
    Parser,
    Reg,
    module Parsley.Internal.Core.Primitives
  ) where

import Prelude hiding                      (pure)
import Parsley.Internal.Core.CombinatorAST (Combinator(..), ScopeRegister(..), Reg(..), Parser(..))
import Parsley.Internal.Core.Defunc        (Defunc(BLACK))
import Parsley.Internal.Common.Indexed     (Fix(In), (:+:)(..))
import Parsley.Internal.Common.Utils       (WQ)

{-|
This typeclass is used to allow abstraction of the representation of user-level functions.
See the instances for information on what these representations are. This may be required
as a constraint on custom built combinators that make use of one of the minimal required methods
of this class.

@since 0.1.0.0
-}
class ParserOps rep where
  {-|
  Lift a value into the parser world without consuming input or having any other effect.

  @since 0.1.0.0
  -}
  pure :: rep a -> Parser a

  {-|
  Attempts to read a single character matching the provided predicate. If it succeeds, the
  character will be returned and consumed, otherwise the parser will fail having consumed no input.

  @since 0.1.0.0
  -}
  satisfy :: rep (Char -> Bool) -- ^ The predicate that a character must satisfy to be parsed
          -> Parser Char        -- ^ A parser that matches a single character matching the predicate

  {-|
  @conditional fqs p def@ first parses @p@, then it will try each of the predicates in @fqs@ in turn
  until one of them returns @True@. The corresponding parser for the first predicate that succeeded
  is then executes, or if none of the predicates succeeded then the @def@ parser is executed.

  @since 0.1.0.0
  -}
  conditional :: [(rep (a -> Bool), Parser b)] -- ^ A list of predicates and their outcomes
              -> Parser a                      -- ^ A parser whose result is used to choose an outcome
              -> Parser b                      -- ^ A parser who will be executed if no predicates succeed
              -> Parser b

{-|
This is the default representation used for user-level functions and values: plain old code.

@since 0.1.0.0
-}
instance ParserOps WQ where
  pure :: WQ a -> Parser a
pure = Defunc a -> Parser a
forall (rep :: Type -> Type) a. ParserOps rep => rep a -> Parser a
pure (Defunc a -> Parser a) -> (WQ a -> Defunc a) -> WQ a -> Parser a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. WQ a -> Defunc a
forall a. WQ a -> Defunc a
BLACK
  satisfy :: WQ (Char -> Bool) -> Parser Char
satisfy = Defunc (Char -> Bool) -> Parser Char
forall (rep :: Type -> Type).
ParserOps rep =>
rep (Char -> Bool) -> Parser Char
satisfy (Defunc (Char -> Bool) -> Parser Char)
-> (WQ (Char -> Bool) -> Defunc (Char -> Bool))
-> WQ (Char -> Bool)
-> Parser Char
forall b c a. (b -> c) -> (a -> b) -> a -> c
. WQ (Char -> Bool) -> Defunc (Char -> Bool)
forall a. WQ a -> Defunc a
BLACK
  conditional :: [(WQ (a -> Bool), Parser b)] -> Parser a -> Parser b -> Parser b
conditional = [(Defunc (a -> Bool), Parser b)]
-> Parser a -> Parser b -> Parser b
forall (rep :: Type -> Type) a b.
ParserOps rep =>
[(rep (a -> Bool), Parser b)] -> Parser a -> Parser b -> Parser b
conditional ([(Defunc (a -> Bool), Parser b)]
 -> Parser a -> Parser b -> Parser b)
-> ([(WQ (a -> Bool), Parser b)]
    -> [(Defunc (a -> Bool), Parser b)])
-> [(WQ (a -> Bool), Parser b)]
-> Parser a
-> Parser b
-> Parser b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((WQ (a -> Bool), Parser b) -> (Defunc (a -> Bool), Parser b))
-> [(WQ (a -> Bool), Parser b)] -> [(Defunc (a -> Bool), Parser b)]
forall a b. (a -> b) -> [a] -> [b]
map (\(WQ (a -> Bool)
f, Parser b
t) -> (WQ (a -> Bool) -> Defunc (a -> Bool)
forall a. WQ a -> Defunc a
BLACK WQ (a -> Bool)
f, Parser b
t))

{-|
This is used to allow defunctionalised versions of many standard Haskell functions to be used
directly as an argument to relevant combinators.

@since 0.1.0.0
-}
instance {-# INCOHERENT #-} x ~ Defunc => ParserOps x where
  pure :: x a -> Parser a
pure = x a -> Parser a
forall a. Defunc a -> Parser a
_pure
  satisfy :: x (Char -> Bool) -> Parser Char
satisfy = x (Char -> Bool) -> Parser Char
Defunc (Char -> Bool) -> Parser Char
_satisfy
  conditional :: [(x (a -> Bool), Parser b)] -> Parser a -> Parser b -> Parser b
conditional = [(x (a -> Bool), Parser b)] -> Parser a -> Parser b -> Parser b
forall a b.
[(Defunc (a -> Bool), Parser b)]
-> Parser a -> Parser b -> Parser b
_conditional

-- Core smart constructors
{-# INLINE _pure #-}
_pure :: Defunc a -> Parser a
_pure :: Defunc a -> Parser a
_pure = Fix (Combinator :+: ScopeRegister) a -> Parser a
forall a. Fix (Combinator :+: ScopeRegister) a -> Parser a
Parser (Fix (Combinator :+: ScopeRegister) a -> Parser a)
-> (Defunc a -> Fix (Combinator :+: ScopeRegister) a)
-> Defunc a
-> Parser a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (:+:)
  Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) a
-> Fix (Combinator :+: ScopeRegister) a
forall k (f :: (k -> Type) -> k -> Type) (a :: k).
f (Fix f) a -> Fix f a
In ((:+:)
   Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) a
 -> Fix (Combinator :+: ScopeRegister) a)
-> (Defunc a
    -> (:+:)
         Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) a)
-> Defunc a
-> Fix (Combinator :+: ScopeRegister) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Combinator (Fix (Combinator :+: ScopeRegister)) a
-> (:+:)
     Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) a
forall k k (f :: k -> k -> Type) (k :: k) (a :: k)
       (g :: k -> k -> Type).
f k a -> (:+:) f g k a
L (Combinator (Fix (Combinator :+: ScopeRegister)) a
 -> (:+:)
      Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) a)
-> (Defunc a -> Combinator (Fix (Combinator :+: ScopeRegister)) a)
-> Defunc a
-> (:+:)
     Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Defunc a -> Combinator (Fix (Combinator :+: ScopeRegister)) a
forall a (k :: Type -> Type). Defunc a -> Combinator k a
Pure

{-|
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 Fix (Combinator :+: ScopeRegister) (a -> b)
p <*> :: Parser (a -> b) -> Parser a -> Parser b
<*> Parser Fix (Combinator :+: ScopeRegister) a
q = Fix (Combinator :+: ScopeRegister) b -> Parser b
forall a. Fix (Combinator :+: ScopeRegister) a -> Parser a
Parser ((:+:)
  Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) b
-> Fix (Combinator :+: ScopeRegister) b
forall k (f :: (k -> Type) -> k -> Type) (a :: k).
f (Fix f) a -> Fix f a
In (Combinator (Fix (Combinator :+: ScopeRegister)) b
-> (:+:)
     Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) b
forall k k (f :: k -> k -> Type) (k :: k) (a :: k)
       (g :: k -> k -> Type).
f k a -> (:+:) f g k a
L (Fix (Combinator :+: ScopeRegister) (a -> b)
p Fix (Combinator :+: ScopeRegister) (a -> b)
-> Fix (Combinator :+: ScopeRegister) a
-> Combinator (Fix (Combinator :+: ScopeRegister)) b
forall (k :: Type -> Type) a b. k (a -> b) -> k a -> Combinator k b
:<*>: Fix (Combinator :+: ScopeRegister) a
q)))

{-|
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 Fix (Combinator :+: ScopeRegister) a
p <* :: Parser a -> Parser b -> Parser a
<* Parser Fix (Combinator :+: ScopeRegister) b
q = Fix (Combinator :+: ScopeRegister) a -> Parser a
forall a. Fix (Combinator :+: ScopeRegister) a -> Parser a
Parser ((:+:)
  Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) a
-> Fix (Combinator :+: ScopeRegister) a
forall k (f :: (k -> Type) -> k -> Type) (a :: k).
f (Fix f) a -> Fix f a
In (Combinator (Fix (Combinator :+: ScopeRegister)) a
-> (:+:)
     Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) a
forall k k (f :: k -> k -> Type) (k :: k) (a :: k)
       (g :: k -> k -> Type).
f k a -> (:+:) f g k a
L (Fix (Combinator :+: ScopeRegister) a
p Fix (Combinator :+: ScopeRegister) a
-> Fix (Combinator :+: ScopeRegister) b
-> Combinator (Fix (Combinator :+: ScopeRegister)) a
forall (k :: Type -> Type) a b. k a -> k b -> Combinator k a
:<*: Fix (Combinator :+: ScopeRegister) b
q)))

{-|
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 Fix (Combinator :+: ScopeRegister) a
p *> :: Parser a -> Parser b -> Parser b
*> Parser Fix (Combinator :+: ScopeRegister) b
q = Fix (Combinator :+: ScopeRegister) b -> Parser b
forall a. Fix (Combinator :+: ScopeRegister) a -> Parser a
Parser ((:+:)
  Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) b
-> Fix (Combinator :+: ScopeRegister) b
forall k (f :: (k -> Type) -> k -> Type) (a :: k).
f (Fix f) a -> Fix f a
In (Combinator (Fix (Combinator :+: ScopeRegister)) b
-> (:+:)
     Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) b
forall k k (f :: k -> k -> Type) (k :: k) (a :: k)
       (g :: k -> k -> Type).
f k a -> (:+:) f g k a
L (Fix (Combinator :+: ScopeRegister) a
p Fix (Combinator :+: ScopeRegister) a
-> Fix (Combinator :+: ScopeRegister) b
-> Combinator (Fix (Combinator :+: ScopeRegister)) b
forall (k :: Type -> Type) a b. k a -> k b -> Combinator k b
:*>: Fix (Combinator :+: ScopeRegister) b
q)))

{-|
This combinator always fails.

@since 0.1.0.0
-}
empty :: Parser a
empty :: Parser a
empty = Fix (Combinator :+: ScopeRegister) a -> Parser a
forall a. Fix (Combinator :+: ScopeRegister) a -> Parser a
Parser ((:+:)
  Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) a
-> Fix (Combinator :+: ScopeRegister) a
forall k (f :: (k -> Type) -> k -> Type) (a :: k).
f (Fix f) a -> Fix f a
In (Combinator (Fix (Combinator :+: ScopeRegister)) a
-> (:+:)
     Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) a
forall k k (f :: k -> k -> Type) (k :: k) (a :: k)
       (g :: k -> k -> Type).
f k a -> (:+:) f g k a
L Combinator (Fix (Combinator :+: ScopeRegister)) a
forall (k :: Type -> Type) a. Combinator k a
Empty))

{-|
This combinator implements branching within a parser. It is left-biased, so that if the first branch
succeeds, the second will not be attempted. In accordance with @parsec@ semantics, if the first
branch failed having consumed input the second branch cannot be taken. (see `try`)

@since 0.1.0.0
-}
infixr 3 <|>
(<|>) :: Parser a -> Parser a -> Parser a
Parser Fix (Combinator :+: ScopeRegister) a
p <|> :: Parser a -> Parser a -> Parser a
<|> Parser Fix (Combinator :+: ScopeRegister) a
q = Fix (Combinator :+: ScopeRegister) a -> Parser a
forall a. Fix (Combinator :+: ScopeRegister) a -> Parser a
Parser ((:+:)
  Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) a
-> Fix (Combinator :+: ScopeRegister) a
forall k (f :: (k -> Type) -> k -> Type) (a :: k).
f (Fix f) a -> Fix f a
In (Combinator (Fix (Combinator :+: ScopeRegister)) a
-> (:+:)
     Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) a
forall k k (f :: k -> k -> Type) (k :: k) (a :: k)
       (g :: k -> k -> Type).
f k a -> (:+:) f g k a
L (Fix (Combinator :+: ScopeRegister) a
p Fix (Combinator :+: ScopeRegister) a
-> Fix (Combinator :+: ScopeRegister) a
-> Combinator (Fix (Combinator :+: ScopeRegister)) a
forall (k :: Type -> Type) a. k a -> k a -> Combinator k a
:<|>: Fix (Combinator :+: ScopeRegister) a
q)))

{-# INLINE _satisfy #-}
_satisfy :: Defunc (Char -> Bool) -> Parser Char
_satisfy :: Defunc (Char -> Bool) -> Parser Char
_satisfy = Fix (Combinator :+: ScopeRegister) Char -> Parser Char
forall a. Fix (Combinator :+: ScopeRegister) a -> Parser a
Parser (Fix (Combinator :+: ScopeRegister) Char -> Parser Char)
-> (Defunc (Char -> Bool)
    -> Fix (Combinator :+: ScopeRegister) Char)
-> Defunc (Char -> Bool)
-> Parser Char
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (:+:)
  Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) Char
-> Fix (Combinator :+: ScopeRegister) Char
forall k (f :: (k -> Type) -> k -> Type) (a :: k).
f (Fix f) a -> Fix f a
In ((:+:)
   Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) Char
 -> Fix (Combinator :+: ScopeRegister) Char)
-> (Defunc (Char -> Bool)
    -> (:+:)
         Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) Char)
-> Defunc (Char -> Bool)
-> Fix (Combinator :+: ScopeRegister) Char
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Combinator (Fix (Combinator :+: ScopeRegister)) Char
-> (:+:)
     Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) Char
forall k k (f :: k -> k -> Type) (k :: k) (a :: k)
       (g :: k -> k -> Type).
f k a -> (:+:) f g k a
L (Combinator (Fix (Combinator :+: ScopeRegister)) Char
 -> (:+:)
      Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) Char)
-> (Defunc (Char -> Bool)
    -> Combinator (Fix (Combinator :+: ScopeRegister)) Char)
-> Defunc (Char -> Bool)
-> (:+:)
     Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) Char
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Defunc (Char -> Bool)
-> Combinator (Fix (Combinator :+: ScopeRegister)) Char
forall (k :: Type -> Type).
Defunc (Char -> Bool) -> Combinator k Char
Satisfy

{-|
This combinator will attempt to parse a given parser. If it succeeds, the result is returned without
having consumed any input. If it fails, however, any consumed input remains consumed.

@since 0.1.0.0
-}
lookAhead :: Parser a -> Parser a
lookAhead :: Parser a -> Parser a
lookAhead = Fix (Combinator :+: ScopeRegister) a -> Parser a
forall a. Fix (Combinator :+: ScopeRegister) a -> Parser a
Parser (Fix (Combinator :+: ScopeRegister) a -> Parser a)
-> (Parser a -> Fix (Combinator :+: ScopeRegister) a)
-> Parser a
-> Parser a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (:+:)
  Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) a
-> Fix (Combinator :+: ScopeRegister) a
forall k (f :: (k -> Type) -> k -> Type) (a :: k).
f (Fix f) a -> Fix f a
In ((:+:)
   Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) a
 -> Fix (Combinator :+: ScopeRegister) a)
-> (Parser a
    -> (:+:)
         Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) a)
-> Parser a
-> Fix (Combinator :+: ScopeRegister) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Combinator (Fix (Combinator :+: ScopeRegister)) a
-> (:+:)
     Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) a
forall k k (f :: k -> k -> Type) (k :: k) (a :: k)
       (g :: k -> k -> Type).
f k a -> (:+:) f g k a
L (Combinator (Fix (Combinator :+: ScopeRegister)) a
 -> (:+:)
      Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) a)
-> (Parser a -> Combinator (Fix (Combinator :+: ScopeRegister)) a)
-> Parser a
-> (:+:)
     Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Fix (Combinator :+: ScopeRegister) a
-> Combinator (Fix (Combinator :+: ScopeRegister)) a
forall (k :: Type -> Type) a. k a -> Combinator k a
LookAhead (Fix (Combinator :+: ScopeRegister) a
 -> Combinator (Fix (Combinator :+: ScopeRegister)) a)
-> (Parser a -> Fix (Combinator :+: ScopeRegister) a)
-> Parser a
-> Combinator (Fix (Combinator :+: ScopeRegister)) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Parser a -> Fix (Combinator :+: ScopeRegister) a
forall a. Parser a -> Fix (Combinator :+: ScopeRegister) a
unParser

{-|
This combinator will ensure that a given parser fails. If the parser does fail, a @()@ is returned
and no input is consumed. If the parser succeeded, then this combinator will fail, however it will
not consume any input.

@since 0.1.0.0
-}
notFollowedBy :: Parser a -> Parser ()
notFollowedBy :: Parser a -> Parser ()
notFollowedBy = Fix (Combinator :+: ScopeRegister) () -> Parser ()
forall a. Fix (Combinator :+: ScopeRegister) a -> Parser a
Parser (Fix (Combinator :+: ScopeRegister) () -> Parser ())
-> (Parser a -> Fix (Combinator :+: ScopeRegister) ())
-> Parser a
-> Parser ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (:+:)
  Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) ()
-> Fix (Combinator :+: ScopeRegister) ()
forall k (f :: (k -> Type) -> k -> Type) (a :: k).
f (Fix f) a -> Fix f a
In ((:+:)
   Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) ()
 -> Fix (Combinator :+: ScopeRegister) ())
-> (Parser a
    -> (:+:)
         Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) ())
-> Parser a
-> Fix (Combinator :+: ScopeRegister) ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Combinator (Fix (Combinator :+: ScopeRegister)) ()
-> (:+:)
     Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) ()
forall k k (f :: k -> k -> Type) (k :: k) (a :: k)
       (g :: k -> k -> Type).
f k a -> (:+:) f g k a
L (Combinator (Fix (Combinator :+: ScopeRegister)) ()
 -> (:+:)
      Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) ())
-> (Parser a -> Combinator (Fix (Combinator :+: ScopeRegister)) ())
-> Parser a
-> (:+:)
     Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Fix (Combinator :+: ScopeRegister) a
-> Combinator (Fix (Combinator :+: ScopeRegister)) ()
forall (k :: Type -> Type) a. k a -> Combinator k ()
NotFollowedBy (Fix (Combinator :+: ScopeRegister) a
 -> Combinator (Fix (Combinator :+: ScopeRegister)) ())
-> (Parser a -> Fix (Combinator :+: ScopeRegister) a)
-> Parser a
-> Combinator (Fix (Combinator :+: ScopeRegister)) ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Parser a -> Fix (Combinator :+: ScopeRegister) a
forall a. Parser a -> Fix (Combinator :+: ScopeRegister) a
unParser

{-|
This combinator allows a parser to backtrack on failure, which is to say that it will
not have consumed any input if it were to fail. This is important since @parsec@ semantics demand
that the second branch of @(`<|>`)@ can only be taken if the first did not consume input on failure.

Excessive use of `try` will reduce the efficiency of the parser and effect the generated error
messages. It should only be used in one of two circumstances:

* When two branches of a parser share a common leading prefix (in which case, it is often better
  to try and factor this out).
* When a parser needs to be executed atomically (for example, tokens).

@since 0.1.0.0
-}
try :: Parser a -> Parser a
try :: Parser a -> Parser a
try = Fix (Combinator :+: ScopeRegister) a -> Parser a
forall a. Fix (Combinator :+: ScopeRegister) a -> Parser a
Parser (Fix (Combinator :+: ScopeRegister) a -> Parser a)
-> (Parser a -> Fix (Combinator :+: ScopeRegister) a)
-> Parser a
-> Parser a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (:+:)
  Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) a
-> Fix (Combinator :+: ScopeRegister) a
forall k (f :: (k -> Type) -> k -> Type) (a :: k).
f (Fix f) a -> Fix f a
In ((:+:)
   Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) a
 -> Fix (Combinator :+: ScopeRegister) a)
-> (Parser a
    -> (:+:)
         Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) a)
-> Parser a
-> Fix (Combinator :+: ScopeRegister) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Combinator (Fix (Combinator :+: ScopeRegister)) a
-> (:+:)
     Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) a
forall k k (f :: k -> k -> Type) (k :: k) (a :: k)
       (g :: k -> k -> Type).
f k a -> (:+:) f g k a
L (Combinator (Fix (Combinator :+: ScopeRegister)) a
 -> (:+:)
      Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) a)
-> (Parser a -> Combinator (Fix (Combinator :+: ScopeRegister)) a)
-> Parser a
-> (:+:)
     Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Fix (Combinator :+: ScopeRegister) a
-> Combinator (Fix (Combinator :+: ScopeRegister)) a
forall (k :: Type -> Type) a. k a -> Combinator k a
Try (Fix (Combinator :+: ScopeRegister) a
 -> Combinator (Fix (Combinator :+: ScopeRegister)) a)
-> (Parser a -> Fix (Combinator :+: ScopeRegister) a)
-> Parser a
-> Combinator (Fix (Combinator :+: ScopeRegister)) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Parser a -> Fix (Combinator :+: ScopeRegister) a
forall a. Parser a -> Fix (Combinator :+: ScopeRegister) a
unParser

{-# INLINE _conditional #-}
_conditional :: [(Defunc (a -> Bool), Parser b)] -> Parser a -> Parser b -> Parser b
_conditional :: [(Defunc (a -> Bool), Parser b)]
-> Parser a -> Parser b -> Parser b
_conditional [(Defunc (a -> Bool), Parser b)]
cs (Parser Fix (Combinator :+: ScopeRegister) a
p) (Parser Fix (Combinator :+: ScopeRegister) b
def) =
  let ([Defunc (a -> Bool)]
fs, [Parser b]
qs) = [(Defunc (a -> Bool), Parser b)]
-> ([Defunc (a -> Bool)], [Parser b])
forall a b. [(a, b)] -> ([a], [b])
unzip [(Defunc (a -> Bool), Parser b)]
cs
  in Fix (Combinator :+: ScopeRegister) b -> Parser b
forall a. Fix (Combinator :+: ScopeRegister) a -> Parser a
Parser ((:+:)
  Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) b
-> Fix (Combinator :+: ScopeRegister) b
forall k (f :: (k -> Type) -> k -> Type) (a :: k).
f (Fix f) a -> Fix f a
In (Combinator (Fix (Combinator :+: ScopeRegister)) b
-> (:+:)
     Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) b
forall k k (f :: k -> k -> Type) (k :: k) (a :: k)
       (g :: k -> k -> Type).
f k a -> (:+:) f g k a
L (Fix (Combinator :+: ScopeRegister) a
-> [Defunc (a -> Bool)]
-> [Fix (Combinator :+: ScopeRegister) b]
-> Fix (Combinator :+: ScopeRegister) b
-> Combinator (Fix (Combinator :+: ScopeRegister)) b
forall (k :: Type -> Type) a b.
k a -> [Defunc (a -> Bool)] -> [k b] -> k b -> Combinator k b
Match Fix (Combinator :+: ScopeRegister) a
p [Defunc (a -> Bool)]
fs ((Parser b -> Fix (Combinator :+: ScopeRegister) b)
-> [Parser b] -> [Fix (Combinator :+: ScopeRegister) b]
forall a b. (a -> b) -> [a] -> [b]
map Parser b -> Fix (Combinator :+: ScopeRegister) b
forall a. Parser a -> Fix (Combinator :+: ScopeRegister) a
unParser [Parser b]
qs) Fix (Combinator :+: ScopeRegister) b
def)))

{-|
One of the core @Selective@ operations. The behaviour of @branch p l r@ is to first to parse
@p@, if it fails then the combinator fails. If @p@ succeeded then if its result is a @Left@, then
the parser @l@ is executed and applied to the result of @p@, otherwise @r@ is executed and applied
to the right from a @Right@.

Crucially, only one of @l@ or @r@ will be executed on @p@'s success.

@since 0.1.0.0
-}
branch :: Parser (Either a b) -- ^ The first parser to execute
       -> Parser (a -> c)     -- ^ The parser to execute if the first returned a @Left@
       -> Parser (b -> c)     -- ^ The parser to execute if the first returned a @Right@
       -> Parser c
branch :: Parser (Either a b)
-> Parser (a -> c) -> Parser (b -> c) -> Parser c
branch (Parser Fix (Combinator :+: ScopeRegister) (Either a b)
c) (Parser Fix (Combinator :+: ScopeRegister) (a -> c)
p) (Parser Fix (Combinator :+: ScopeRegister) (b -> c)
q) = Fix (Combinator :+: ScopeRegister) c -> Parser c
forall a. Fix (Combinator :+: ScopeRegister) a -> Parser a
Parser ((:+:)
  Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) c
-> Fix (Combinator :+: ScopeRegister) c
forall k (f :: (k -> Type) -> k -> Type) (a :: k).
f (Fix f) a -> Fix f a
In (Combinator (Fix (Combinator :+: ScopeRegister)) c
-> (:+:)
     Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) c
forall k k (f :: k -> k -> Type) (k :: k) (a :: k)
       (g :: k -> k -> Type).
f k a -> (:+:) f g k a
L (Fix (Combinator :+: ScopeRegister) (Either a b)
-> Fix (Combinator :+: ScopeRegister) (a -> c)
-> Fix (Combinator :+: ScopeRegister) (b -> c)
-> Combinator (Fix (Combinator :+: ScopeRegister)) c
forall (k :: Type -> Type) a b c.
k (Either a b) -> k (a -> c) -> k (b -> c) -> Combinator k c
Branch Fix (Combinator :+: ScopeRegister) (Either a b)
c Fix (Combinator :+: ScopeRegister) (a -> c)
p Fix (Combinator :+: ScopeRegister) (b -> c)
q)))

{-|
This combinator parses repeated applications of an operator to a single final operand. This is
primarily used to parse prefix operators in expressions.

@since 0.1.0.0
-}
chainPre :: Parser (a -> a) -> Parser a -> Parser a
chainPre :: Parser (a -> a) -> Parser a -> Parser a
chainPre (Parser Fix (Combinator :+: ScopeRegister) (a -> a)
op) (Parser Fix (Combinator :+: ScopeRegister) a
p) = Fix (Combinator :+: ScopeRegister) a -> Parser a
forall a. Fix (Combinator :+: ScopeRegister) a -> Parser a
Parser ((:+:)
  Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) a
-> Fix (Combinator :+: ScopeRegister) a
forall k (f :: (k -> Type) -> k -> Type) (a :: k).
f (Fix f) a -> Fix f a
In (Combinator (Fix (Combinator :+: ScopeRegister)) a
-> (:+:)
     Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) a
forall k k (f :: k -> k -> Type) (k :: k) (a :: k)
       (g :: k -> k -> Type).
f k a -> (:+:) f g k a
L (Fix (Combinator :+: ScopeRegister) (a -> a)
-> Fix (Combinator :+: ScopeRegister) a
-> Combinator (Fix (Combinator :+: ScopeRegister)) a
forall (k :: Type -> Type) a. k (a -> a) -> k a -> Combinator k a
ChainPre Fix (Combinator :+: ScopeRegister) (a -> a)
op Fix (Combinator :+: ScopeRegister) a
p)))

{-|
This combinator parses repeated applications of an operator to a single initial operand. This is
primarily used to parse postfix operators in expressions.

@since 0.1.0.0
-}
chainPost :: Parser a -> Parser (a -> a) -> Parser a
chainPost :: Parser a -> Parser (a -> a) -> Parser a
chainPost (Parser Fix (Combinator :+: ScopeRegister) a
p) (Parser Fix (Combinator :+: ScopeRegister) (a -> a)
op) = Fix (Combinator :+: ScopeRegister) a -> Parser a
forall a. Fix (Combinator :+: ScopeRegister) a -> Parser a
Parser ((:+:)
  Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) a
-> Fix (Combinator :+: ScopeRegister) a
forall k (f :: (k -> Type) -> k -> Type) (a :: k).
f (Fix f) a -> Fix f a
In (Combinator (Fix (Combinator :+: ScopeRegister)) a
-> (:+:)
     Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) a
forall k k (f :: k -> k -> Type) (k :: k) (a :: k)
       (g :: k -> k -> Type).
f k a -> (:+:) f g k a
L (Fix (Combinator :+: ScopeRegister) a
-> Fix (Combinator :+: ScopeRegister) (a -> a)
-> Combinator (Fix (Combinator :+: ScopeRegister)) a
forall (k :: Type -> Type) a. k a -> k (a -> a) -> Combinator k a
ChainPost Fix (Combinator :+: ScopeRegister) a
p Fix (Combinator :+: ScopeRegister) (a -> a)
op)))

{-|
Creates a new register initialised with the value obtained from parsing the first
argument. This register is provided to the second argument, a function that generates a parser
depending on operations derived from the register. This parser is then performed.

Note: The rank-2 type here serves a similar purpose to that in the @ST@ monad. It prevents the
register from leaking outside of the scope of the function, safely encapsulating the stateful
effect of the register.

@since 0.1.0.0
-}
newRegister :: Parser a                        -- ^ Parser with which to initialise the register
            -> (forall r. Reg r a -> Parser b) -- ^ Used to generate the second parser to execute
            -> Parser b
newRegister :: Parser a -> (forall r. Reg r a -> Parser b) -> Parser b
newRegister (Parser Fix (Combinator :+: ScopeRegister) a
p) forall r. Reg r a -> Parser b
f = Fix (Combinator :+: ScopeRegister) b -> Parser b
forall a. Fix (Combinator :+: ScopeRegister) a -> Parser a
Parser ((:+:)
  Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) b
-> Fix (Combinator :+: ScopeRegister) b
forall k (f :: (k -> Type) -> k -> Type) (a :: k).
f (Fix f) a -> Fix f a
In (ScopeRegister (Fix (Combinator :+: ScopeRegister)) b
-> (:+:)
     Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) b
forall k k (g :: k -> k -> Type) (k :: k) (a :: k)
       (f :: k -> k -> Type).
g k a -> (:+:) f g k a
R (Fix (Combinator :+: ScopeRegister) a
-> (forall r. Reg r a -> Fix (Combinator :+: ScopeRegister) b)
-> ScopeRegister (Fix (Combinator :+: ScopeRegister)) b
forall (k :: Type -> Type) a b.
k a -> (forall r. Reg r a -> k b) -> ScopeRegister k b
ScopeRegister Fix (Combinator :+: ScopeRegister) a
p (Parser b -> Fix (Combinator :+: ScopeRegister) b
forall a. Parser a -> Fix (Combinator :+: ScopeRegister) a
unParser (Parser b -> Fix (Combinator :+: ScopeRegister) b)
-> (Reg r a -> Parser b)
-> Reg r a
-> Fix (Combinator :+: ScopeRegister) b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Reg r a -> Parser b
forall r. Reg r a -> Parser b
f))))

{-|
Fetches a value from a register and returns it as its result.

@since 0.1.0.0
-}
get :: Reg r a -> Parser a
get :: Reg r a -> Parser a
get (Reg ΣVar a
reg) = Fix (Combinator :+: ScopeRegister) a -> Parser a
forall a. Fix (Combinator :+: ScopeRegister) a -> Parser a
Parser ((:+:)
  Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) a
-> Fix (Combinator :+: ScopeRegister) a
forall k (f :: (k -> Type) -> k -> Type) (a :: k).
f (Fix f) a -> Fix f a
In (Combinator (Fix (Combinator :+: ScopeRegister)) a
-> (:+:)
     Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) a
forall k k (f :: k -> k -> Type) (k :: k) (a :: k)
       (g :: k -> k -> Type).
f k a -> (:+:) f g k a
L (ΣVar a -> Combinator (Fix (Combinator :+: ScopeRegister)) a
forall a (k :: Type -> Type). ΣVar a -> Combinator k a
GetRegister ΣVar a
reg)))

{-|
Puts the result of the given parser into the given register. The old value in the register will be
lost.

@since 0.1.0.0
-}
put :: Reg r a -> Parser a -> Parser ()
put :: Reg r a -> Parser a -> Parser ()
put (Reg ΣVar a
reg) (Parser Fix (Combinator :+: ScopeRegister) a
p) = Fix (Combinator :+: ScopeRegister) () -> Parser ()
forall a. Fix (Combinator :+: ScopeRegister) a -> Parser a
Parser ((:+:)
  Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) ()
-> Fix (Combinator :+: ScopeRegister) ()
forall k (f :: (k -> Type) -> k -> Type) (a :: k).
f (Fix f) a -> Fix f a
In (Combinator (Fix (Combinator :+: ScopeRegister)) ()
-> (:+:)
     Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) ()
forall k k (f :: k -> k -> Type) (k :: k) (a :: k)
       (g :: k -> k -> Type).
f k a -> (:+:) f g k a
L (ΣVar a
-> Fix (Combinator :+: ScopeRegister) a
-> Combinator (Fix (Combinator :+: ScopeRegister)) ()
forall a (k :: Type -> Type). ΣVar a -> k a -> Combinator k ()
PutRegister ΣVar a
reg Fix (Combinator :+: ScopeRegister) a
p)))

{-|
This combinator can be used to debug parsers that have gone wrong. Simply
wrap a parser with @debug name@ and when that parser is executed it will
print a debug trace on entry and exit along with the current context of the
input.

@since 0.1.0.0
-}
debug :: String   -- ^ The name that identifies the wrapped parser in the debug trace
      -> Parser a -- ^ The parser to track during execution
      -> Parser a
debug :: String -> Parser a -> Parser a
debug String
name (Parser Fix (Combinator :+: ScopeRegister) a
p) = Fix (Combinator :+: ScopeRegister) a -> Parser a
forall a. Fix (Combinator :+: ScopeRegister) a -> Parser a
Parser ((:+:)
  Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) a
-> Fix (Combinator :+: ScopeRegister) a
forall k (f :: (k -> Type) -> k -> Type) (a :: k).
f (Fix f) a -> Fix f a
In (Combinator (Fix (Combinator :+: ScopeRegister)) a
-> (:+:)
     Combinator ScopeRegister (Fix (Combinator :+: ScopeRegister)) a
forall k k (f :: k -> k -> Type) (k :: k) (a :: k)
       (g :: k -> k -> Type).
f k a -> (:+:) f g k a
L (String
-> Fix (Combinator :+: ScopeRegister) a
-> Combinator (Fix (Combinator :+: ScopeRegister)) a
forall (k :: Type -> Type) a. String -> k a -> Combinator k a
Debug String
name Fix (Combinator :+: ScopeRegister) a
p)))