    -- | This module contains the definitions for a generic parser, with
    --   running state.  These are the parts that are shared between the State
    --   and StateLazy variations.  Do not import this module directly, but only
    --   via T.P.Poly.State or T.P.Poly.StateLazy.
    module Text.ParserCombinators.Poly.StateParser
      ( -- * The Parser datatype
        Parser(P)   -- datatype, instance of: Functor, Monad, PolyParse
      , Result(..)  -- internal to the parser monad
        -- ** basic parsers
      , next        -- :: Parser s t t
      , eof         -- :: Parser s t ()
      , satisfy     -- :: (t->Bool) -> Parser s t t
      , onFail      -- :: Parser s t a -> Parser s t a -> Parser s t a
        -- ** State-handling
      , stUpdate    -- :: (s->s) -> Parser s t ()
      , stQuery     -- :: (s->a) -> Parser s t a
      , stGet       -- :: Parser s t s
        -- ** re-parsing
      , reparse     -- :: [t] -> Parser s t ()
      ) where

    import Text.ParserCombinators.Poly.Base
    import Text.ParserCombinators.Poly.Result
    import Control.Applicative
    import qualified Control.Monad.Fail as Fail

    -- | This @Parser@ datatype is a fairly generic parsing monad with error
    --   reporting, and running state.
    --   It can be used for arbitrary token types, not just String input.
    --   (If you do not require a running state, use module Poly.Plain instead)
    newtype Parser s t a = P (s -> [t] -> Result ([t],s) a)

    instance Functor (Parser s t) where
        fmap :: forall a b. (a -> b) -> Parser s t a -> Parser s t b
    fmap a -> b
    f (P s -> [t] -> Result ([t], s) a
    p) = (s -> [t] -> Result ([t], s) b) -> Parser s t b
    forall s t a. (s -> [t] -> Result ([t], s) a) -> Parser s t a
    P (\s
    s-> (a -> b) -> Result ([t], s) a -> Result ([t], s) b
    forall a b. (a -> b) -> Result ([t], s) a -> Result ([t], s) b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap a -> b
    f (Result ([t], s) a -> Result ([t], s) b)
    -> ([t] -> Result ([t], s) a) -> [t] -> Result ([t], s) b
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . s -> [t] -> Result ([t], s) a
    p s
    s)

    instance Applicative (Parser s t) where
        pure :: forall a. a -> Parser s t a
    pure a
    x    = (s -> [t] -> Result ([t], s) a) -> Parser s t a
    forall s t a. (s -> [t] -> Result ([t], s) a) -> Parser s t a
    P (\s
    s [t]
    ts-> ([t], s) -> a -> Result ([t], s) a
    forall z a. z -> a -> Result z a
    Success ([t]
    ts,s
    s) a
    x)
        Parser s t (a -> b)
    pf <*> :: forall a b. Parser s t (a -> b) -> Parser s t a -> Parser s t b
    <*> Parser s t a
    px = do { f <- Parser s t (a -> b)
    pf; x <- px; return (f x) }
    #if defined(GLASGOW_HASKELL) && GLASGOW_HASKELL > 610
        p  <*  q  = p `discard` q
    #endif

    instance Monad (Parser s t) where
        return :: forall a. a -> Parser s t a
    return       = a -> Parser s t a
    forall a. a -> Parser s t a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure
        (P s -> [t] -> Result ([t], s) a
    f) >>= :: forall a b. Parser s t a -> (a -> Parser s t b) -> Parser s t b
    >>= a -> Parser s t b
    g  = (s -> [t] -> Result ([t], s) b) -> Parser s t b
    forall s t a. (s -> [t] -> Result ([t], s) a) -> Parser s t a
    P (\s
    s-> Result ([t], s) a -> Result ([t], s) b
    continue (Result ([t], s) a -> Result ([t], s) b)
    -> ([t] -> Result ([t], s) a) -> [t] -> Result ([t], s) b
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . s -> [t] -> Result ([t], s) a
    f s
    s)
          where
            continue :: Result ([t], s) a -> Result ([t], s) b
    continue (Success ([t]
    ts,s
    s) a
    x)        = let (P s -> [t] -> Result ([t], s) b
    g') = a -> Parser s t b
    g a
    x in s -> [t] -> Result ([t], s) b
    g' s
    s [t]
    ts
            continue (Committed Result ([t], s) a
    r)             = Result ([t], s) b -> Result ([t], s) b
    forall z a. Result z a -> Result z a
    Committed (Result ([t], s) a -> Result ([t], s) b
    continue Result ([t], s) a
    r)
            continue (Failure ([t], s)
    tss String
    e)           = ([t], s) -> String -> Result ([t], s) b
    forall z a. z -> String -> Result z a
    Failure ([t], s)
    tss String
    e

    #if !MIN_VERSION_base(4,13,0)
        fail         = Fail.fail
    #endif

    instance Fail.MonadFail (Parser s t) where
        fail :: forall a. String -> Parser s t a
    fail String
    e       = (s -> [t] -> Result ([t], s) a) -> Parser s t a
    forall s t a. (s -> [t] -> Result ([t], s) a) -> Parser s t a
    P (\s
    s [t]
    ts-> ([t], s) -> String -> Result ([t], s) a
    forall z a. z -> String -> Result z a
    Failure ([t]
    ts,s
    s) String
    e)

    instance Alternative (Parser s t) where
        empty :: forall a. Parser s t a
    empty     = String -> Parser s t a
    forall a. String -> Parser s t a
    forall (m :: * -> *) a. MonadFail m => String -> m a
    fail String
    "no parse"
        Parser s t a
    p <|> :: forall a. Parser s t a -> Parser s t a -> Parser s t a
    <|> Parser s t a
    q   = Parser s t a
    p Parser s t a -> Parser s t a -> Parser s t a
    forall s t a. Parser s t a -> Parser s t a -> Parser s t a
    `onFail` Parser s t a
    q

    instance PolyParse (Parser s t)

    instance Commitment (Parser s t) where
        commit :: forall a. Parser s t a -> Parser s t a
    commit (P s -> [t] -> Result ([t], s) a
    p)         = (s -> [t] -> Result ([t], s) a) -> Parser s t a
    forall s t a. (s -> [t] -> Result ([t], s) a) -> Parser s t a
    P (\s
    s-> Result ([t], s) a -> Result ([t], s) a
    forall z a. Result z a -> Result z a
    Committed (Result ([t], s) a -> Result ([t], s) a)
    -> ([t] -> Result ([t], s) a) -> [t] -> Result ([t], s) a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Result ([t], s) a -> Result ([t], s) a
    forall z a. Result z a -> Result z a
    squash (Result ([t], s) a -> Result ([t], s) a)
    -> ([t] -> Result ([t], s) a) -> [t] -> Result ([t], s) a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . s -> [t] -> Result ([t], s) a
    p s
    s)
          where
            squash :: Result z a -> Result z a
    squash (Committed Result z a
    r) = Result z a -> Result z a
    squash Result z a
    r
            squash Result z a
    r             = Result z a
    r
        (P s -> [t] -> Result ([t], s) a
    p) adjustErr :: forall a. Parser s t a -> (String -> String) -> Parser s t a
    `adjustErr` String -> String
    f  = (s -> [t] -> Result ([t], s) a) -> Parser s t a
    forall s t a. (s -> [t] -> Result ([t], s) a) -> Parser s t a
    P (\s
    s-> Result ([t], s) a -> Result ([t], s) a
    forall z a. Result z a -> Result z a
    adjust (Result ([t], s) a -> Result ([t], s) a)
    -> ([t] -> Result ([t], s) a) -> [t] -> Result ([t], s) a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . s -> [t] -> Result ([t], s) a
    p s
    s)
          where
            adjust :: Result z a -> Result z a
    adjust (Failure z
    zs String
    e)  = z -> String -> Result z a
    forall z a. z -> String -> Result z a
    Failure z
    zs (String -> String
    f String
    e)
            adjust (Committed Result z a
    r)   = Result z a -> Result z a
    forall z a. Result z a -> Result z a
    Committed (Result z a -> Result z a
    adjust Result z a
    r)
            adjust  Result z a
    good           = Result z a
    good

        oneOf' :: forall a. [(String, Parser s t a)] -> Parser s t a
    oneOf' = [(String, String)] -> [(String, Parser s t a)] -> Parser s t a
    forall {s} {t} {a}.
    [(String, String)] -> [(String, Parser s t a)] -> Parser s t a
    accum []
          where accum :: [(String, String)] -> [(String, Parser s t a)] -> Parser s t a
    accum [(String, String)]
    errs [] =
                    String -> Parser s t a
    forall a. String -> Parser s t a
    forall (m :: * -> *) a. MonadFail m => String -> m a
    fail (String
    "failed to parse any of the possible choices:\n"
                                String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++Int -> String -> String
    indent Int
    2 (((String, String) -> String) -> [(String, String)] -> String
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap (String, String) -> String
    showErr ([(String, String)] -> [(String, String)]
    forall a. [a] -> [a]
    reverse [(String, String)]
    errs)))
                accum [(String, String)]
    errs ((String
    e,P s -> [t] -> Result ([t], s) a
    p):[(String, Parser s t a)]
    ps) =
                    (s -> [t] -> Result ([t], s) a) -> Parser s t a
    forall s t a. (s -> [t] -> Result ([t], s) a) -> Parser s t a
    P (\s
    s [t]
    ts-> case s -> [t] -> Result ([t], s) a
    p s
    s [t]
    ts of
                               Failure ([t], s)
    _ String
    err ->
                                           let (P s -> [t] -> Result ([t], s) a
    p) = [(String, String)] -> [(String, Parser s t a)] -> Parser s t a
    accum ((String
    e,String
    err)(String, String) -> [(String, String)] -> [(String, String)]
    forall a. a -> [a] -> [a]
    :[(String, String)]
    errs) [(String, Parser s t a)]
    ps
                                           in s -> [t] -> Result ([t], s) a
    p s
    s [t]
    ts
                               r :: Result ([t], s) a
    r@(Success ([t], s)
    _ a
    a)  -> Result ([t], s) a
    r
                               r :: Result ([t], s) a
    r@(Committed Result ([t], s) a
    _)  -> Result ([t], s) a
    r )
                showErr :: (String, String) -> String
    showErr (String
    name,String
    err) = String
    nameString -> String -> String
    forall a. [a] -> [a] -> [a]
    ++String
    ":\n"String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++Int -> String -> String
    indent Int
    2 String
    err

    infixl 6 `onFail`       -- not sure about precedence 6?

    -- | @p `onFail` q@ means parse p, unless p fails, in which case
    --   parse q instead.
    --   Can be chained together to give multiple attempts to parse something.
    --   (Note that q could itself be a failing parser, e.g. to change the error
    --   message from that defined in p to something different.)
    --   However, a severe failure in p cannot be ignored.
    onFail :: Parser s t a -> Parser s t a -> Parser s t a
    (P s -> [t] -> Result ([t], s) a
    p) onFail :: forall s t a. Parser s t a -> Parser s t a -> Parser s t a
    `onFail` (P s -> [t] -> Result ([t], s) a
    q) = (s -> [t] -> Result ([t], s) a) -> Parser s t a
    forall s t a. (s -> [t] -> Result ([t], s) a) -> Parser s t a
    P (\s
    s [t]
    ts-> s -> [t] -> Result ([t], s) a -> Result ([t], s) a
    continue s
    s [t]
    ts (Result ([t], s) a -> Result ([t], s) a)
    -> Result ([t], s) a -> Result ([t], s) a
    forall a b. (a -> b) -> a -> b
    $ s -> [t] -> Result ([t], s) a
    p s
    s [t]
    ts)
          where
            continue :: s -> [t] -> Result ([t], s) a -> Result ([t], s) a
    continue s
    s [t]
    ts (Failure ([t], s)
    _ String
    _) = s -> [t] -> Result ([t], s) a
    q s
    s [t]
    ts
        --  continue _ _  (Committed r)   = r       -- no, remain Committed
            continue s
    _ [t]
    _  Result ([t], s) a
    r               = Result ([t], s) a
    r

    ------------------------------------------------------------------------

    -- | Simply return the next token in the input tokenstream.
    next :: Parser s t t
    next :: forall s t. Parser s t t
    next = (s -> [t] -> Result ([t], s) t) -> Parser s t t
    forall s t a. (s -> [t] -> Result ([t], s) a) -> Parser s t a
    P (\s
    s [t]
    ts-> case [t]
    ts of
                      []      -> ([t], s) -> String -> Result ([t], s) t
    forall z a. z -> String -> Result z a
    Failure ([],s
    s) String
    "Ran out of input (EOF)"
                      (t
    t:[t]
    ts') -> ([t], s) -> t -> Result ([t], s) t
    forall z a. z -> a -> Result z a
    Success ([t]
    ts',s
    s) t
    t )

    -- | Succeed if the end of file/input has been reached, fail otherwise.
    eof  :: Parser s t ()
    eof :: forall s t. Parser s t ()
    eof  = (s -> [t] -> Result ([t], s) ()) -> Parser s t ()
    forall s t a. (s -> [t] -> Result ([t], s) a) -> Parser s t a
    P (\s
    s [t]
    ts-> case [t]
    ts of
                      []      -> ([t], s) -> () -> Result ([t], s) ()
    forall z a. z -> a -> Result z a
    Success ([],s
    s) ()
                      (t
    t:[t]
    ts') -> ([t], s) -> String -> Result ([t], s) ()
    forall z a. z -> String -> Result z a
    Failure ([t]
    ts,s
    s) String
    "Expected end of input (eof)" )

    -- | Return the next token if it satisfies the given predicate.
    satisfy :: (t->Bool) -> Parser s t t
    satisfy :: forall t s. (t -> Bool) -> Parser s t t
    satisfy t -> Bool
    pred = do { x <- Parser s t t
    forall s t. Parser s t t
    next
                      ; if pred x then return x else fail "Parse.satisfy: failed"
                      }
    ------------------------------------------------------------------------
    -- State handling

    -- | Update the internal state.
    stUpdate   :: (s->s) -> Parser s t ()
    stUpdate :: forall s t. (s -> s) -> Parser s t ()
    stUpdate s -> s
    f  = (s -> [t] -> Result ([t], s) ()) -> Parser s t ()
    forall s t a. (s -> [t] -> Result ([t], s) a) -> Parser s t a
    P (\s
    s [t]
    ts-> ([t], s) -> () -> Result ([t], s) ()
    forall z a. z -> a -> Result z a
    Success ([t]
    ts, s -> s
    f s
    s) ())

    -- | Query the internal state.
    stQuery    :: (s->a) -> Parser s t a
    stQuery :: forall s a t. (s -> a) -> Parser s t a
    stQuery s -> a
    f   = (s -> [t] -> Result ([t], s) a) -> Parser s t a
    forall s t a. (s -> [t] -> Result ([t], s) a) -> Parser s t a
    P (\s
    s [t]
    ts-> ([t], s) -> a -> Result ([t], s) a
    forall z a. z -> a -> Result z a
    Success ([t]
    ts,s
    s) (s -> a
    f s
    s))

    -- | Deliver the entire internal state.
    stGet      :: Parser s t s
    stGet :: forall s t. Parser s t s
    stGet       = (s -> [t] -> Result ([t], s) s) -> Parser s t s
    forall s t a. (s -> [t] -> Result ([t], s) a) -> Parser s t a
    P (\s
    s [t]
    ts-> ([t], s) -> s -> Result ([t], s) s
    forall z a. z -> a -> Result z a
    Success ([t]
    ts,s
    s) s
    s)

    ------------------------------------------------------------------------
    -- | Push some tokens back onto the front of the input stream and reparse.
    --   This is useful e.g. for recursively expanding macros.  When the
    --   user-parser recognises a macro use, it can lookup the macro
    --   expansion from the parse state, lex it, and then stuff the
    --   lexed expansion back down into the parser.
    reparse    :: [t] -> Parser s t ()
    reparse :: forall t s. [t] -> Parser s t ()
    reparse [t]
    ts  = (s -> [t] -> Result ([t], s) ()) -> Parser s t ()
    forall s t a. (s -> [t] -> Result ([t], s) a) -> Parser s t a
    P (\s
    s [t]
    inp-> ([t], s) -> () -> Result ([t], s) ()
    forall z a. z -> a -> Result z a
    Success (([t]
    ts[t] -> [t] -> [t]
    forall a. [a] -> [a] -> [a]
    ++[t]
    inp),s
    s) ())

    ------------------------------------------------------------------------