> {-# LANGUAGE GADTs, MultiParamTypeClasses, FunctionalDependencies, > FlexibleInstances, TypeSynonymInstances, FlexibleContexts #-} > -- | This module defines data types, type classes and instances for NFA > module Text.Regex.PDeriv.Nfa where > import Data.List > -- | The type class of Nfa > class Nfa s a | s -> a where > pDeriv :: s -> a -> [s] > sigma :: s -> [a] > empty :: s -> Bool > -- | A function that builds an NFA > buildNFA :: (Nfa s a, Eq s, Eq a) => s -> NFA s a > buildNFA init = {- all `seq` delta `seq` final `seq` -} > NFA { all_states = all > , delta_states = delta > , init_states = [init] > , final_states = final } > where > sig = sigma init > (all, delta) = sig `seq` builder [] [] [init] > final = all `seq` [s | s <- all, empty s] > builder acc_states acc_delta [] = (acc_states, acc_delta) > builder acc_states acc_delta curr_states = > let all_sofar_states = acc_states ++ curr_states > new_delta = [ (s, l, s') | s <- curr_states, l <- sig, s' <- pDeriv s l] > -- new_states = nub [new_s | s <- curr_states, l <- sig , > --- new_s <- pDeriv s l, not (elem new_s all_sofar_states)] > new_states = all_sofar_states `seq` nub [ s' | (_,_,s') <- new_delta, not (s' `elem` all_sofar_states) ] > acc_delta_next = (acc_delta ++ new_delta) > in {- all_sofar_states `seq` new_delta `seq` new_states `seq` -} builder all_sofar_states acc_delta_next new_states > -- | the NFA data type > data NFA s a = NFA { all_states :: [s] > , delta_states :: [(s, a, s)] > , init_states :: [s] > , final_states :: [s] } > deriving Show > -- | the optimized NFA using Int to represent states, IntMap to represent delta > data SNFA s a = SNFA { mapping_states :: s -> Int > , sall_states :: [Int] > , sdelta_states :: [(Int,a,Int)] > , sinit_states :: [Int] > , sfinal_states :: [Int] } > > instance Show a => Show (SNFA s a) where > show s = "SNFA:\n" ++ show (sall_states s) ++ "\n" > ++ show (sdelta_states s) ++ "\n" > ++ show (sinit_states s) ++ "\n" > ++ show (sfinal_states s) > -- | The function 'toSNFA' converts from an NFA to an SNFA > toSNFA :: (Eq s, Eq a) => NFA s a -> SNFA s a > toSNFA (NFA { all_states = all > , delta_states = delta > , init_states = init > , final_states = final }) = > let -- generate mapping from states to Int > mapping = all `seq` \x -> let (Just i) = findIndex (x ==) all in i > sall_sts = [0..(length all)-1] > sdelta_sts = mapping `seq` delta `seq` ( map (\ (p,x,q) -> (mapping p,x,mapping q)) delta) > sfinal_sts = mapping `seq` final `seq` ( map mapping final ) > in {- sall_sts `seq` sdelta_sts `seq` sfinal_sts `seq` -} > SNFA { mapping_states = mapping > , sall_states = sall_sts > , sdelta_states = sdelta_sts > , sinit_states = [0] > , sfinal_states = sfinal_sts } > nofAllStates (NFA {all_states = all}) = length all > nofDelta (NFA {delta_states = delta}) = length delta > nofInitStates (NFA {init_states = init}) = length init > nofFinalStates (NFA {final_states = final}) = length final