module Language.Lexer.Tlex.Pipeline.Scanner2Nfa ( scanRule2Nfa, scanner2Nfa, ) where import Language.Lexer.Tlex.Prelude import qualified Data.EnumMap.Strict as EnumMap import qualified Language.Lexer.Tlex.Machine.NFA as NFA import qualified Language.Lexer.Tlex.Machine.Pattern as Pattern import qualified Language.Lexer.Tlex.Machine.State as MState import qualified Language.Lexer.Tlex.Pipeline.Pattern2Nfa as Pattern2Nfa import qualified Language.Lexer.Tlex.Syntax as Tlex scanRule2Nfa :: Enum e => Pattern.AcceptPriority -> MState.StateNum -> Tlex.ScanRule e m -> NFA.NFABuilder m () scanRule2Nfa :: forall e m. Enum e => AcceptPriority -> StateNum -> ScanRule e m -> NFABuilder m () scanRule2Nfa AcceptPriority p StateNum b ScanRule e m r = do StateNum e <- forall m. NFABuilder m StateNum NFA.newStateNum forall e m. Enum e => StateNum -> StateNum -> Pattern e -> NFABuilder m () Pattern2Nfa.pattern2Nfa StateNum b StateNum e do forall e a. ScanRule e a -> Pattern e Tlex.scanRulePattern ScanRule e m r forall m. StateNum -> Accept m -> NFABuilder m () NFA.accept StateNum e do Tlex.Accept { $sel:accPriority:Accept :: AcceptPriority accPriority = AcceptPriority p , $sel:accSemanticAction:Accept :: m accSemanticAction = forall e a. ScanRule e a -> a Tlex.scanRuleSemanticAction ScanRule e m r } scanner2Nfa :: Enum e => Tlex.Scanner e m -> NFA.NFABuilder m () scanner2Nfa :: forall e m. Enum e => Scanner e m -> NFABuilder m () scanner2Nfa Tlex.Scanner{ [ScanRule e m] $sel:scannerRules:Scanner :: forall e a. Scanner e a -> [ScanRule e a] scannerRules :: [ScanRule e m] scannerRules } = forall (t :: * -> *) (m :: * -> *) b a. (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m () foldM_ do \(AcceptPriority p, [StateNum] bs, EnumMap StartState StateNum is) ScanRule e m scanRule -> forall {e} {a}. Enum e => AcceptPriority -> [StateNum] -> EnumMap StartState StateNum -> ScanRule e a -> StateT (NFABuilderContext a) Identity (AcceptPriority, [StateNum], EnumMap StartState StateNum) aggScanRule AcceptPriority p [StateNum] bs EnumMap StartState StateNum is ScanRule e m scanRule do (AcceptPriority Pattern.mostPriority, [], forall k a. EnumMap k a EnumMap.empty) do [ScanRule e m] scannerRules where aggScanRule :: AcceptPriority -> [StateNum] -> EnumMap StartState StateNum -> ScanRule e a -> StateT (NFABuilderContext a) Identity (AcceptPriority, [StateNum], EnumMap StartState StateNum) aggScanRule AcceptPriority p0 [StateNum] bs0 EnumMap StartState StateNum is0 ScanRule e a scanRule = do StateNum b <- forall m. NFABuilder m StateNum NFA.newStateNum forall e m. Enum e => AcceptPriority -> StateNum -> ScanRule e m -> NFABuilder m () scanRule2Nfa AcceptPriority p0 StateNum b ScanRule e a scanRule EnumMap StartState StateNum is1 <- forall {t :: * -> *} {m}. Foldable t => EnumMap StartState StateNum -> StateNum -> t StartState -> StateT (NFABuilderContext m) Identity (EnumMap StartState StateNum) registerStartState EnumMap StartState StateNum is0 StateNum b do forall e a. ScanRule e a -> [StartState] Tlex.scanRuleStartStates ScanRule e a scanRule forall (f :: * -> *) a. Applicative f => a -> f a pure (forall a. Enum a => a -> a succ AcceptPriority p0, StateNum bforall a. a -> [a] -> [a] :[StateNum] bs0, EnumMap StartState StateNum is1) registerStartState :: EnumMap StartState StateNum -> StateNum -> t StartState -> StateT (NFABuilderContext m) Identity (EnumMap StartState StateNum) registerStartState EnumMap StartState StateNum is0 StateNum b t StartState ss = forall (t :: * -> *) (m :: * -> *) b a. (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m b foldM do \EnumMap StartState StateNum is StartState s -> do (EnumMap StartState StateNum is', StateNum sn) <- case forall k a. Enum k => k -> EnumMap k a -> Maybe a EnumMap.lookup StartState s EnumMap StartState StateNum is of Just StateNum x -> forall (f :: * -> *) a. Applicative f => a -> f a pure (EnumMap StartState StateNum is, StateNum x) Maybe StateNum Nothing -> do StateNum x <- forall m. NFABuilder m StateNum NFA.newStateNum forall m. StateNum -> StartState -> NFABuilder m () NFA.initial StateNum x StartState s forall (f :: * -> *) a. Applicative f => a -> f a pure (forall k a. Enum k => k -> a -> EnumMap k a -> EnumMap k a EnumMap.insert StartState s StateNum x EnumMap StartState StateNum is, StateNum x) forall m. StateNum -> StateNum -> NFABuilder m () NFA.epsilonTrans StateNum sn StateNum b forall (f :: * -> *) a. Applicative f => a -> f a pure EnumMap StartState StateNum is' do EnumMap StartState StateNum is0 do t StartState ss