module Language.Lexer.Tlex.Pipeline.Dfa2Runner (
    dfa2Runner,
) where

import           Language.Lexer.Tlex.Prelude

import qualified Data.EnumMap.Strict                 as EnumMap
import qualified Data.IntMap                         as IntMap
import qualified Language.Lexer.Tlex.Machine.DFA     as DFA
import qualified Language.Lexer.Tlex.Machine.Pattern as Pattern
import qualified Language.Lexer.Tlex.Machine.State   as MState
import qualified Language.Lexer.Tlex.Runner          as Tlex


dfa2Runner :: Enum e => DFA.DFA a -> Tlex.Runner e a
dfa2Runner :: forall e a. Enum e => DFA a -> Runner e a
dfa2Runner DFA a
dfa = Tlex.Runner
    { $sel:tlexInitial:Runner :: Int -> Int
tlexInitial = Int -> Int
dfaTlexInitial
    , $sel:tlexAccept:Runner :: Int -> Maybe a
tlexAccept = Int -> Maybe a
dfaTlexAccept
    , $sel:tlexTrans:Runner :: Int -> Int -> Int
tlexTrans = Int -> Int -> Int
dfaTlexTrans
    }
    where
        dfaTlexInitial :: Int -> Int
dfaTlexInitial Int
s0 =
            let ms :: Maybe StateNum
ms = forall k a. Enum k => k -> EnumMap k a -> Maybe a
EnumMap.lookup
                    do forall a. Enum a => Int -> a
toEnum Int
s0
                    do forall a. DFA a -> EnumMap StartState StateNum
DFA.dfaInitials DFA a
dfa
            in case Maybe StateNum
ms of
                Maybe StateNum
Nothing -> Int
-1
                Just StateNum
s  -> forall a. Enum a => a -> Int
fromEnum StateNum
s

        dfaTlexAccept :: Int -> Maybe a
dfaTlexAccept Int
s0 =
            let dstState :: DFAState a
dstState = forall a. StateArray a -> StateNum -> a
MState.indexArray
                    do forall a. DFA a -> StateArray (DFAState a)
DFA.dfaTrans DFA a
dfa
                    do forall a. Enum a => Int -> a
toEnum Int
s0
            in case forall a. DFAState a -> [Accept a]
DFA.dstAccepts DFAState a
dstState of
                []    -> forall a. Maybe a
Nothing
                Accept a
acc:[Accept a]
_ -> forall a. a -> Maybe a
Just do forall a. Accept a -> a
Pattern.accSemanticAction Accept a
acc

        dfaTlexTrans :: Int -> Int -> Int
dfaTlexTrans Int
s0 Int
c =
            let dstState :: DFAState a
dstState = forall a. StateArray a -> StateNum -> a
MState.indexArray
                    do forall a. DFA a -> StateArray (DFAState a)
DFA.dfaTrans DFA a
dfa
                    do forall a. Enum a => Int -> a
toEnum Int
s0
            in case forall a. Int -> IntMap a -> Maybe a
IntMap.lookup Int
c do forall a. DFAState a -> IntMap StateNum
DFA.dstTrans DFAState a
dstState of
                Just StateNum
s1 -> forall a. Enum a => a -> Int
fromEnum StateNum
s1
                Maybe StateNum
Nothing -> case forall a. DFAState a -> Maybe StateNum
DFA.dstOtherTrans DFAState a
dstState of
                    Just StateNum
s1 -> forall a. Enum a => a -> Int
fromEnum StateNum
s1
                    Maybe StateNum
Nothing -> Int
-1