module Language.Lexer.Tlex.Runner (
    TlexContext (..),
    TlexResult (..),
    Runner (..),
    runRunner,
) where

import           Language.Lexer.Tlex.Prelude


class (Enum e, Monad m) => TlexContext p e m | m -> p, m -> e where
    tlexGetInputPart :: m (Maybe e)
    tlexGetMark :: m p

data TlexResult p a
    = TlexEndOfInput
    | TlexError
    | TlexAccepted p a
    deriving (TlexResult p a -> TlexResult p a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall p a.
(Eq p, Eq a) =>
TlexResult p a -> TlexResult p a -> Bool
/= :: TlexResult p a -> TlexResult p a -> Bool
$c/= :: forall p a.
(Eq p, Eq a) =>
TlexResult p a -> TlexResult p a -> Bool
== :: TlexResult p a -> TlexResult p a -> Bool
$c== :: forall p a.
(Eq p, Eq a) =>
TlexResult p a -> TlexResult p a -> Bool
Eq, Int -> TlexResult p a -> ShowS
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall p a. (Show p, Show a) => Int -> TlexResult p a -> ShowS
forall p a. (Show p, Show a) => [TlexResult p a] -> ShowS
forall p a. (Show p, Show a) => TlexResult p a -> String
showList :: [TlexResult p a] -> ShowS
$cshowList :: forall p a. (Show p, Show a) => [TlexResult p a] -> ShowS
show :: TlexResult p a -> String
$cshow :: forall p a. (Show p, Show a) => TlexResult p a -> String
showsPrec :: Int -> TlexResult p a -> ShowS
$cshowsPrec :: forall p a. (Show p, Show a) => Int -> TlexResult p a -> ShowS
Show)


data Runner e a = Runner
    { forall {k} (e :: k) a. Runner e a -> Int -> Int
tlexInitial :: Int -> Int
    -- ^ StartState -> (StateNum | -1)
    , forall {k} (e :: k) a. Runner e a -> Int -> Maybe a
tlexAccept  :: Int -> Maybe a
    -- ^ StateNum -> Maybe Action
    , forall {k} (e :: k) a. Runner e a -> Int -> Int -> Int
tlexTrans   :: Int -> Int -> Int
    -- ^ StateNum -> CodeUnit -> (StateNum | -1)
    }
    deriving forall k (e :: k) a b. a -> Runner e b -> Runner e a
forall k (e :: k) a b. (a -> b) -> Runner e a -> Runner e b
forall a b. a -> Runner e b -> Runner e a
forall a b. (a -> b) -> Runner e a -> Runner e b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: forall a b. a -> Runner e b -> Runner e a
$c<$ :: forall k (e :: k) a b. a -> Runner e b -> Runner e a
fmap :: forall a b. (a -> b) -> Runner e a -> Runner e b
$cfmap :: forall k (e :: k) a b. (a -> b) -> Runner e a -> Runner e b
Functor

runRunner :: Enum s => TlexContext p c m => Runner c a -> s -> m (TlexResult p a)
runRunner :: forall s p c (m :: * -> *) a.
(Enum s, TlexContext p c m) =>
Runner c a -> s -> m (TlexResult p a)
runRunner Runner c a
runner s
s0 = case forall {k} (e :: k) a. Runner e a -> Int -> Int
tlexInitial Runner c a
runner do forall a. Enum a => a -> Int
fromEnum s
s0 of
        Int
-1 -> forall a. HasCallStack => String -> a
error String
"unknown initial state"
        Int
s  -> Int -> m (TlexResult p a)
go Int
s
    where
        go :: Int -> m (TlexResult p a)
go Int
s = case forall {k} (e :: k) a. Runner e a -> Int -> Maybe a
tlexAccept Runner c a
runner Int
s of
            Just a
x  -> do
                TlexResult p a
acc <- forall {m :: * -> *} {p} {e} {a}.
TlexContext p e m =>
a -> m (TlexResult p a)
buildAccepted a
x
                Maybe c
mc <- forall p e (m :: * -> *). TlexContext p e m => m (Maybe e)
tlexGetInputPart
                case Maybe c
mc of
                    Maybe c
Nothing -> forall (f :: * -> *) a. Applicative f => a -> f a
pure TlexResult p a
acc
                    Just c
c  -> Int -> c -> Maybe (TlexResult p a) -> m (TlexResult p a)
goTrans Int
s c
c do forall a. a -> Maybe a
Just TlexResult p a
acc
            Maybe a
Nothing -> do
                Maybe c
mc <- forall p e (m :: * -> *). TlexContext p e m => m (Maybe e)
tlexGetInputPart
                case Maybe c
mc of
                    Maybe c
Nothing -> forall (f :: * -> *) a. Applicative f => a -> f a
pure forall p a. TlexResult p a
TlexEndOfInput
                    Just c
c  -> Int -> c -> Maybe (TlexResult p a) -> m (TlexResult p a)
goTrans Int
s c
c forall a. Maybe a
Nothing

        goTrans :: Int -> c -> Maybe (TlexResult p a) -> m (TlexResult p a)
goTrans Int
s c
c Maybe (TlexResult p a)
preAccepted = case forall {k} (e :: k) a. Runner e a -> Int -> Int -> Int
tlexTrans Runner c a
runner Int
s do forall a. Enum a => a -> Int
fromEnum c
c of
            Int
-1 -> forall {f :: * -> *} {p} {a}.
Applicative f =>
Maybe (TlexResult p a) -> f (TlexResult p a)
goEnd Maybe (TlexResult p a)
preAccepted
            Int
ns -> do
                Maybe (TlexResult p a)
nacc <- case forall {k} (e :: k) a. Runner e a -> Int -> Maybe a
tlexAccept Runner c a
runner Int
ns of
                    Just a
x -> do
                        TlexResult p a
acc <- forall {m :: * -> *} {p} {e} {a}.
TlexContext p e m =>
a -> m (TlexResult p a)
buildAccepted a
x
                        forall (f :: * -> *) a. Applicative f => a -> f a
pure do forall a. a -> Maybe a
Just TlexResult p a
acc
                    Maybe a
Nothing -> forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe (TlexResult p a)
preAccepted
                Maybe c
mc <- forall p e (m :: * -> *). TlexContext p e m => m (Maybe e)
tlexGetInputPart
                case Maybe c
mc of
                    Maybe c
Nothing -> forall {f :: * -> *} {p} {a}.
Applicative f =>
Maybe (TlexResult p a) -> f (TlexResult p a)
goEnd Maybe (TlexResult p a)
nacc
                    Just c
nc -> Int -> c -> Maybe (TlexResult p a) -> m (TlexResult p a)
goTrans Int
ns c
nc Maybe (TlexResult p a)
nacc

        buildAccepted :: a -> m (TlexResult p a)
buildAccepted a
x = do
            p
m <- forall p e (m :: * -> *). TlexContext p e m => m p
tlexGetMark
            forall (f :: * -> *) a. Applicative f => a -> f a
pure do forall p a. p -> a -> TlexResult p a
TlexAccepted p
m a
x

        goEnd :: Maybe (TlexResult p a) -> f (TlexResult p a)
goEnd Maybe (TlexResult p a)
preAccepted = case Maybe (TlexResult p a)
preAccepted of
            Maybe (TlexResult p a)
Nothing  -> forall (f :: * -> *) a. Applicative f => a -> f a
pure forall p a. TlexResult p a
TlexError
            Just TlexResult p a
acc -> forall (f :: * -> *) a. Applicative f => a -> f a
pure TlexResult p a
acc