11{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
2- {-# LANGUAGE PatternGuards #-}
2+
3+ {-# LANGUAGE PatternGuards #-}
4+ {-# LANGUAGE ScopedTypeVariables #-}
5+
36module DFAMin (minimizeDFA ) where
47
58import AbsSyn
@@ -31,19 +34,22 @@ import Data.List as List
3134-- end;
3235-- end;
3336
34- minimizeDFA :: Ord a => DFA Int a -> DFA Int a
37+ minimizeDFA :: forall a . Ord a => DFA Int a -> DFA Int a
3538minimizeDFA dfa@ DFA { dfa_start_states = starts,
3639 dfa_states = statemap
3740 }
3841 = DFA { dfa_start_states = starts,
3942 dfa_states = Map. fromList states }
4043 where
44+ equiv_classes :: [EquivalenceClass ]
4145 equiv_classes = groupEquivStates dfa
4246
47+ numbered_states :: [(Int , EquivalenceClass )]
4348 numbered_states = number (length starts) equiv_classes
4449
4550 -- assign each state in the minimized DFA a number, making
4651 -- sure that we assign the numbers [0..] to the start states.
52+ number :: Int -> [EquivalenceClass ] -> [(Int , EquivalenceClass )]
4753 number _ [] = []
4854 number n (ss: sss) =
4955 case filter (`IS.member` ss) starts of
@@ -53,6 +59,7 @@ minimizeDFA dfa@DFA { dfa_start_states = starts,
5359 -- to multiple starts states, we just have to duplicate
5460 -- that state.
5561
62+ states :: [(Int , State Int a )]
5663 states = [
5764 let old_states = map (lookup statemap) (IS. toList equiv)
5865 accs = map fix_acc (state_acc (head old_states))
@@ -64,35 +71,44 @@ minimizeDFA dfa@DFA { dfa_start_states = starts,
6471 | (n, equiv) <- numbered_states
6572 ]
6673
74+ fix_acc :: Accept a -> Accept a
6775 fix_acc acc = acc { accRightCtx = fix_rctxt (accRightCtx acc) }
6876
77+ fix_rctxt :: RightContext SNum -> RightContext SNum
6978 fix_rctxt (RightContextRExp s) = RightContextRExp (get_new s)
7079 fix_rctxt other = other
7180
81+ lookup :: Ord k => Map k v -> k -> v
7282 lookup m k = Map. findWithDefault (error " minimizeDFA" ) k m
83+
84+ get_new :: Int -> Int
7385 get_new = lookup old_to_new
7486
7587 old_to_new :: Map Int Int
7688 old_to_new = Map. fromList [ (s,n) | (n,ss) <- numbered_states,
7789 s <- IS. toList ss ]
7890
91+ type EquivalenceClass = IntSet
7992
80- groupEquivStates :: ( Ord a ) => DFA Int a -> [IntSet ]
93+ groupEquivStates :: forall a . Ord a => DFA Int a -> [EquivalenceClass ]
8194groupEquivStates DFA { dfa_states = statemap }
8295 = go init_p init_q
8396 where
97+ accepting , nonaccepting :: Map Int (State Int a )
8498 (accepting, nonaccepting) = Map. partition acc statemap
8599 where acc (State as _) = not (List. null as)
86100
101+ nonaccepting_states :: EquivalenceClass
87102 nonaccepting_states = IS. fromList (Map. keys nonaccepting)
88103
89104 -- group the accepting states into equivalence classes
105+ accept_map :: Map [Accept a ] [Int ]
90106 accept_map = {-# SCC "accept_map" #-}
91107 foldl' (\ m (n,s) -> Map. insertWith (++) (state_acc s) [n] m)
92108 Map. empty
93109 (Map. toList accepting)
94110
95- -- accept_groups :: Ord s => [Set s ]
111+ accept_groups :: [ EquivalenceClass ]
96112 accept_groups = map IS. fromList (Map. elems accept_map)
97113
98114 init_p = nonaccepting_states : accept_groups
@@ -118,6 +134,7 @@ groupEquivStates DFA { dfa_states = statemap }
118134 | s <- IS. toList a ]
119135
120136 -- The outer loop: recurse on each set in Q
137+ go :: [EquivalenceClass ] -> [EquivalenceClass ] -> [EquivalenceClass ]
121138 go p [] = p
122139 go p (a: q) = go1 0 p q
123140 where
@@ -145,6 +162,3 @@ groupEquivStates DFA { dfa_states = statemap }
145162 replaceyin (z: zs)
146163 | z == y = i : d : zs
147164 | otherwise = z : replaceyin zs
148-
149-
150-
0 commit comments