1
1
{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
2
- {-# LANGUAGE PatternGuards #-}
2
+
3
+ {-# LANGUAGE PatternGuards #-}
4
+ {-# LANGUAGE ScopedTypeVariables #-}
5
+
3
6
module DFAMin (minimizeDFA ) where
4
7
5
8
import AbsSyn
@@ -31,19 +34,22 @@ import Data.List as List
31
34
-- end;
32
35
-- end;
33
36
34
- minimizeDFA :: Ord a => DFA Int a -> DFA Int a
37
+ minimizeDFA :: forall a . Ord a => DFA Int a -> DFA Int a
35
38
minimizeDFA dfa@ DFA { dfa_start_states = starts,
36
39
dfa_states = statemap
37
40
}
38
41
= DFA { dfa_start_states = starts,
39
42
dfa_states = Map. fromList states }
40
43
where
44
+ equiv_classes :: [EquivalenceClass ]
41
45
equiv_classes = groupEquivStates dfa
42
46
47
+ numbered_states :: [(Int , EquivalenceClass )]
43
48
numbered_states = number (length starts) equiv_classes
44
49
45
50
-- assign each state in the minimized DFA a number, making
46
51
-- sure that we assign the numbers [0..] to the start states.
52
+ number :: Int -> [EquivalenceClass ] -> [(Int , EquivalenceClass )]
47
53
number _ [] = []
48
54
number n (ss: sss) =
49
55
case filter (`IS.member` ss) starts of
@@ -53,6 +59,7 @@ minimizeDFA dfa@DFA { dfa_start_states = starts,
53
59
-- to multiple starts states, we just have to duplicate
54
60
-- that state.
55
61
62
+ states :: [(Int , State Int a )]
56
63
states = [
57
64
let old_states = map (lookup statemap) (IS. toList equiv)
58
65
accs = map fix_acc (state_acc (head old_states))
@@ -64,35 +71,44 @@ minimizeDFA dfa@DFA { dfa_start_states = starts,
64
71
| (n, equiv) <- numbered_states
65
72
]
66
73
74
+ fix_acc :: Accept a -> Accept a
67
75
fix_acc acc = acc { accRightCtx = fix_rctxt (accRightCtx acc) }
68
76
77
+ fix_rctxt :: RightContext SNum -> RightContext SNum
69
78
fix_rctxt (RightContextRExp s) = RightContextRExp (get_new s)
70
79
fix_rctxt other = other
71
80
81
+ lookup :: Ord k => Map k v -> k -> v
72
82
lookup m k = Map. findWithDefault (error " minimizeDFA" ) k m
83
+
84
+ get_new :: Int -> Int
73
85
get_new = lookup old_to_new
74
86
75
87
old_to_new :: Map Int Int
76
88
old_to_new = Map. fromList [ (s,n) | (n,ss) <- numbered_states,
77
89
s <- IS. toList ss ]
78
90
91
+ type EquivalenceClass = IntSet
79
92
80
- groupEquivStates :: ( Ord a ) => DFA Int a -> [IntSet ]
93
+ groupEquivStates :: forall a . Ord a => DFA Int a -> [EquivalenceClass ]
81
94
groupEquivStates DFA { dfa_states = statemap }
82
95
= go init_p init_q
83
96
where
97
+ accepting , nonaccepting :: Map Int (State Int a )
84
98
(accepting, nonaccepting) = Map. partition acc statemap
85
99
where acc (State as _) = not (List. null as)
86
100
101
+ nonaccepting_states :: EquivalenceClass
87
102
nonaccepting_states = IS. fromList (Map. keys nonaccepting)
88
103
89
104
-- group the accepting states into equivalence classes
105
+ accept_map :: Map [Accept a ] [Int ]
90
106
accept_map = {-# SCC "accept_map" #-}
91
107
foldl' (\ m (n,s) -> Map. insertWith (++) (state_acc s) [n] m)
92
108
Map. empty
93
109
(Map. toList accepting)
94
110
95
- -- accept_groups :: Ord s => [Set s ]
111
+ accept_groups :: [ EquivalenceClass ]
96
112
accept_groups = map IS. fromList (Map. elems accept_map)
97
113
98
114
init_p = nonaccepting_states : accept_groups
@@ -118,6 +134,7 @@ groupEquivStates DFA { dfa_states = statemap }
118
134
| s <- IS. toList a ]
119
135
120
136
-- The outer loop: recurse on each set in Q
137
+ go :: [EquivalenceClass ] -> [EquivalenceClass ] -> [EquivalenceClass ]
121
138
go p [] = p
122
139
go p (a: q) = go1 0 p q
123
140
where
@@ -145,6 +162,3 @@ groupEquivStates DFA { dfa_states = statemap }
145
162
replaceyin (z: zs)
146
163
| z == y = i : d : zs
147
164
| otherwise = z : replaceyin zs
148
-
149
-
150
-
0 commit comments