Compilerbau: Nichtdeterministische endliche Automaten |
|
1module NFA
2 ( I, Alphabet
3 , Q, SetOfQ
4 , Delta
5 , Delta'
6 , NFA
7 , Token, Tokens
8
9 , epsilon
10 , emptySet
11 , singleSet
12 , isEmptySet
13 , card
14 , extendDelta
15 , epsilonClosure
16 , containsFinalState
17
18 , run
19 , accept
20
21 , dfaToNfa
22 , showTokens
23 )
24where
25
26import DFA
27 ( I
28 , Alphabet
29 , Q
30 , SetOfQ
31 , Input
32 , Token
33 , DFA
34 )
35
36import DFAexample1
37
38import Data.Maybe
39import Data.List
40
41type Delta = Q -> Maybe I -> SetOfQ
42 -- Delta for DFA's extended
43 -- result is a set of states,
44 -- the emty set represents undefined in the DFA
45 -- input domain is extended: epsilon is represented by Nothing
46
47type Delta' = SetOfQ -> Maybe I -> SetOfQ
48 -- Delta extended to work with sets of states
49
50type Tokens = ([(SetOfQ, Token)], Input)
51
52type NFA = (SetOfQ, Alphabet, Q, SetOfQ, Delta)
53 -- the complete automaton, consisting of start state,
54 -- set of final states and transition relation
55
56type NFAState = (SetOfQ, Token, Input)
57 -- single state in DFA is extended to a set of all possible states
58
59-- auxiliary functions and predicates
60
61epsilon :: Maybe I
62epsilon = Nothing
63
64emptySet :: [a]
65emptySet = []
66
67singleSet :: a -> [a]
68singleSet q = [q]
69
70isEmptySet :: [a] -> Bool
71isEmptySet = null
72
73card :: [a] -> Int
74card = length
75
76extendDelta :: Delta -> Delta'
77extendDelta delta qs c
78 = foldr union emptySet . map (\ q' -> delta q' c) $ qs
79
80
81epsilonClosure :: Delta' -> SetOfQ -> SetOfQ
82epsilonClosure delta' qs
83 | card qs == card qs'
84 = qs'
85 | otherwise
86 = epsilonClosure delta' qs'
87 where
88 qs' = qs `union` delta' qs epsilon
89
90containsFinalState :: SetOfQ -> SetOfQ -> Bool
91containsFinalState finalStates qs
92 = not (isEmptySet (qs `intersect` finalStates))
93
94
95-- the main function
96
97run :: NFA -> Input -> Tokens
98
99run (_allStates, _allSymbols, start, finalStates, delta) input
100 | null input
101 &&
102 containsFinalState finalStates start'
103 = ([(start', "")], "")
104 | otherwise
105 = loop input
106 where
107 start' :: SetOfQ
108 start' = closure (singleSet start)
109
110 delta' :: Delta'
111 delta' = extendDelta delta
112
113 closure :: SetOfQ -> SetOfQ
114 closure = epsilonClosure delta'
115
116 -- the main loop
117
118 loop :: Input -> Tokens
119 loop inp
120 | null s
121 = ([], inp)
122 | null inp'
123 = ([(qs,s)], "")
124 | otherwise
125 = let
126 (ts, rest) = loop inp'
127 in
128 ((qs, s) : ts, rest)
129 where
130 init = (start', "", inp)
131 (qs, s, inp') = symbol init init
132
133 -- scan one symbol
134
135 symbol :: NFAState -> NFAState -> NFAState
136 symbol lastFinalState currState@(qs, s, i)
137 | isFinalState && longestMatch -- success: token recognized
138 = currState
139
140 | isFinalState && not longestMatch -- token may still be longer
141 = symbol currState nextState
142
143 | not isFinalState && longestMatch -- failure: restore last possible token
144 = lastFinalState
145
146 | not isFinalState && not longestMatch -- token not yet complete
147 = symbol lastFinalState nextState
148
149 where
150 isFinalState = containsFinalState finalStates qs
151
152 longestMatch = null i -- EOF or delta undefined
153 ||
154 isEmptySet (delta' qs nextChar')
155
156 nextChar = head i
157 nextChar' = Just nextChar
158 -- compute next state
159 -- and read next input char
160 nextState = ( closure (delta' qs nextChar')
161 , s ++ [nextChar]
162 , tail i
163 )
164
165-- word test
166
167accept :: NFA -> Input -> Bool
168accept a
169 = oneSymbol . run a
170 where
171 oneSymbol ([_], "") = True
172 oneSymbol _ = False
173
174-- every DFA is also a NFA
175
176dfaToNfa :: DFA -> NFA
177dfaToNfa (states, alphabet, start, finalStates, delta)
178 = (states, alphabet, start, finalStates, delta')
179 where
180 delta' _ Nothing = []
181 delta' q (Just c) = maybeToList (delta q c)
182
183
184
185-- format result
186
187showTokens :: Tokens -> String
188showTokens (ts, rest)
189 = concatMap showToken ts
190 ++
191 showRest rest
192 where
193 showToken (qs, s)
194 = showStates qs ++ "\t: " ++ show s ++ "\n"
195 showStates
196 = foldr1 (\ s1 s2 -> s1 ++ "," ++ s2) . map show . sort
197 showRest ""
198 = ""
199 showRest r
200 = "input not accepted: " ++ show r ++ "\n"
|
1nfa1 :: NFA
2nfa1
3 = (states, alphabet, q0, f, delta)
4 where
5 states = [1..6]
6 alphabet = "a"
7 q0 = 1
8 f = [1,4,6]
9 delta 1 (Just 'a') = [2,5]
10 delta 2 (Just 'a') = [3]
11 delta 3 (Just 'a') = [4]
12 delta 4 (Just 'a') = [2]
13 delta 5 (Just 'a') = [6]
14 delta 6 (Just 'a') = [5]
15 delta _ _ = []
|
1nfa2 :: NFA
2nfa2
3 = (states, alphabet, q0, f, delta)
4 where
5 states = [1..6]
6 alphabet = "a"
7 q0 = 1
8 f = [2,5]
9 delta 1 Nothing = [2,5]
10 delta 2 (Just 'a') = [3]
11 delta 3 (Just 'a') = [4]
12 delta 4 (Just 'a') = [2]
13 delta 5 (Just 'a') = [6]
14 delta 6 (Just 'a') = [5]
15 delta _ _ = []
|
|
Letzte Änderung: 11.11.2017 | © Prof. Dr. Uwe Schmidt |