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 :: DFA a -> Runner e a
dfa2Runner DFA a
dfa = Runner :: forall k (e :: k) a.
(Int -> Int)
-> (Int -> Maybe a) -> (Int -> Int -> Int) -> Runner e a
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 = StartState -> EnumMap StartState StateNum -> Maybe StateNum
forall k a. Enum k => k -> EnumMap k a -> Maybe a
EnumMap.lookup
                    do Int -> StartState
forall a. Enum a => Int -> a
toEnum Int
s0
                    do DFA a -> EnumMap StartState StateNum
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  -> StateNum -> Int
forall a. Enum a => a -> Int
fromEnum StateNum
s

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

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