Subversion Repositories programming

Rev

Rev 135 | Rev 137 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 135 Rev 136
Line 27... Line 27...
27
    def __init__(self):
27
    def __init__(self):
28
        self.trans_func = {}
28
        self.trans_func = {}
29
        self.num_states = 0
29
        self.num_states = 0
30
        self.final_states = []
30
        self.final_states = []
31
        self.initial_state = 0
31
        self.initial_state = 0
-
 
32
        self.possible_letters = []
-
 
33
        self.dfa_table = []
32
 
34
 
33
    def __state_in_range(self, state):
35
    def __state_in_range(self, state):
34
        """Check if a given state is in the acceptable range"""
36
        """Check if a given state is in the acceptable range"""
35
 
37
 
36
        try:
38
        try:
Line 132... Line 134...
132
 
134
 
133
        self.__input_num_states()
135
        self.__input_num_states()
134
        self.__input_final_states()
136
        self.__input_final_states()
135
        self.__input_all_edges()
137
        self.__input_all_edges()
136
 
138
 
-
 
139
        # Make sure to visit all '^' states (to make printing easier, later)
-
 
140
        for i in range(self.num_states):
-
 
141
            self.__E(i)
-
 
142
 
137
    def main_menu(self):
143
    def main_menu(self):
138
        #NOTE: All of this code is not what it's supposed to be.
144
        #NOTE: All of this code is not what it's supposed to be.
139
        #      It is for TESTING ONLY.
145
        #      It is for TESTING ONLY.
140
        #
146
        #
141
        #TODO: Generate a menu :)
147
        #TODO: Generate a menu :)
142
 
148
 
143
        self.__input_automaton()
149
        self.__input_automaton()
144
 
150
 
145
        print self.trans_func
-
 
146
        print self.num_states
-
 
147
        print self.final_states
-
 
148
        print self.initial_state
-
 
149
        print
151
        print
-
 
152
        print
-
 
153
        print 'Initial State: %s' % (0, )
-
 
154
        print
-
 
155
        print ' Final     #   NFA  let1  let2'
-
 
156
        print '------------------------------'
150
 
157
 
-
 
158
        self.__generate_dfa_table()
151
        for i in range(self.num_states):
159
        for i in self.dfa_table:
-
 
160
            tempstr = ''
-
 
161
            for j in i:
152
            print 'E(%d): %s' % (i, self.__E(i))
162
                tempstr = '%s%6s' % (tempstr, j)
-
 
163
 
-
 
164
            print tempstr
153
 
165
 
154
    def __next_states(self, state, letter):
166
    def __next_states(self, state, letter):
155
        """Return the next states for the key (state, letter)"""
167
        """Return the next states for the key (state, letter)"""
156
 
168
 
157
        try:
169
        try:
Line 163... Line 175...
163
        if letter == '^' and state not in next:
175
        if letter == '^' and state not in next:
164
            next.append(state)
176
            next.append(state)
165
 
177
 
166
        return next
178
        return next
167
 
179
 
168
    def __E(self, state, storage=None, visited=None):
180
    def __E(self, state, letter='^', storage=None, visited=None):
169
        """Calculate E(state) and return it. This handles circular E()
181
        """Calculate E(state) and return it. This handles circular E()
170
        calculations."""
182
        calculations."""
171
 
183
 
172
        # Work around weird mutable default argument stuff
184
        # Work around weird mutable default argument stuff
173
        if storage is None:
185
        if storage is None:
Line 177... Line 189...
177
        if visited is None:
189
        if visited is None:
178
            visited = []
190
            visited = []
179
 
191
 
180
        # Find all of the direct next states that we can get to by
192
        # Find all of the direct next states that we can get to by
181
        # the empty string, and append anything that is not already there
193
        # the empty string, and append anything that is not already there
182
        for i in self.__next_states(state, '^'):
194
        for i in self.__next_states(state, letter):
183
            if i not in storage:
195
            if i not in storage:
184
                storage.append(i)
196
                storage.append(i)
185
 
197
 
186
        # Visit everything in storage that has not been visited already
198
        # Visit everything in storage that has not been visited already
187
        for i in storage:
199
        for i in storage:
188
            if i not in visited:
200
            if i not in visited:
189
                visited.append(i)
201
                visited.append(i)
190
                temp = self.__E(i, storage, visited)
202
                temp = self.__E(i, letter, storage, visited)
191
 
203
 
192
                # Avoid duplicating things in storage
204
                # Avoid duplicating things in storage
193
                for j in temp:
205
                for j in temp:
194
                    if j not in storage:
206
                    if j not in storage:
195
                        storage.append(j)
207
                        storage.append(j)
196
 
208
 
197
        return storage
209
        return storage
198
 
210
 
-
 
211
    def __by_letter(self, states, letter):
-
 
212
        """Returns a list of states to where you can go from a list of states,
-
 
213
        by a certain letter"""
-
 
214
 
-
 
215
        from_states = []
-
 
216
 
-
 
217
        for s in states:
-
 
218
            from_states.extend(self.__E(s))
-
 
219
 
-
 
220
        from_states = self.__unique_sort(from_states)
-
 
221
 
-
 
222
        new_states = []
-
 
223
 
-
 
224
        for s in from_states:
-
 
225
            new_states.extend(self.__next_states(s, letter))
-
 
226
 
-
 
227
        new_states = self.__unique_sort(new_states)
-
 
228
 
-
 
229
        return new_states
-
 
230
 
199
    def __unique_sort(self, li):
231
    def __unique_sort(self, li):
200
        """Make sure everything in a list is unique, and then sort it"""
232
        """Make sure everything in a list is unique, and then sort it"""
201
 
233
 
202
        newlist = []
234
        newlist = []
203
 
235
 
Line 206... Line 238...
206
                newlist.append(i)
238
                newlist.append(i)
207
 
239
 
208
        newlist.sort()
240
        newlist.sort()
209
        return newlist
241
        return newlist
210
 
242
 
-
 
243
    def __is_final_state(self, state):
-
 
244
        """Check if a state is a final state."""
-
 
245
 
-
 
246
        if state in self.final_states:
-
 
247
            return True
-
 
248
 
-
 
249
        return False
-
 
250
 
-
 
251
 
-
 
252
    def __is_list_final(self, states):
-
 
253
        """Check if at least one state in the list "states" is final"""
-
 
254
 
-
 
255
        for s in states:
-
 
256
            if self.__is_final_state(s):
-
 
257
                return True
-
 
258
 
-
 
259
        return False
-
 
260
 
-
 
261
    def __get_temp_record(self, num_letters):
-
 
262
        blank = None
-
 
263
        return [blank for i in range(num_letters + 3)]
-
 
264
 
211
    def __generate_dfa_table(self):
265
    def __generate_dfa_table(self):
212
 
266
 
213
        # get the list of all letters
267
        # get the list of all letters
214
        possible_letters = []
268
        possible_letters = []
215
 
269
 
216
        for (state, letter) in self.trans_func.keys():
270
        for (state, letter) in self.trans_func.keys():
217
            if letter not in possible_letters:
271
            if letter not in possible_letters:
218
                possible_letters.append(letter)
272
                possible_letters.append(letter)
219
 
273
 
220
        # DFA_TABLE STRUCTURE
-
 
221
        #
-
 
222
        # [ [Final, DFA_State_Number, [States_in_NFA], letter_1, letter_2, ..., letter_n]
-
 
223
        #   [Final, DFA_State_Number, [States_in_NFA], letter_1, letter_2, ..., letter_n]
274
        self.possible_letters = possible_letters
224
        #   [Final, DFA_State_Number, [States_in_NFA], letter_1, letter_2, ..., letter_n] ]
-
 
225
        #
-
 
226
 
275
 
227
        dfa_table = []
276
        #prime the dfa table
-
 
277
        self.make_basic_record(self.__E(0))
228
 
278
 
229
        # find the first state's definition
279
        while self.find_unresolved_letter() != (-1, -1): #loop until we've resolved everything
230
        def_in_nfa = self.__E(0)
280
            (record, letter_pos) = self.find_unresolved_letter()
231
        is_final = False
281
            self.resolve_letter(record, letter_pos)
232
 
282
 
-
 
283
    def resolve_letter(self, record, letter_pos):
-
 
284
        fromstates = self.dfa_table[record][2]
233
        temp_record = []
285
        tostates = []
234
 
286
 
235
        # find out if we're final
-
 
236
        for i in def_in_nfa:
287
        for s in fromstates:
237
            if i in self.final_states:
288
            tostates.extend(self.__next_states(s, self.possible_letters[letter_pos-3]))
238
                is_final = True
-
 
239
                break
-
 
240
 
289
 
241
        temp_record.append(is_final)
-
 
242
        temp_record.append(len(dfa_table))
290
        self.dfa_table[record][letter_pos] = self.make_basic_record(tostates)
243
        temp_record.append(def_in_nfa)
-
 
244
 
291
 
245
        # find out where we can go by each letter
292
    def find_unresolved_letter(self): # WORKING
246
        for l in possible_letters:
293
        """Returns an index pair of an unresolved letter that exists in the dfa_table.
247
            where_to_go = []
294
        If there are no more letters, return (-1, -1)"""
248
 
295
 
249
            for s in def_in_nfa:
296
        for i in range(len(self.dfa_table)):
250
                where_to_go.extend(self.__next_states(s, l))
297
            for j in range(len(self.possible_letters)):
-
 
298
                if self.dfa_table[i][j+3] == None:
-
 
299
                    return (i, j+3)
251
 
300
 
252
            where_to_go = self.__unique_sort(where_to_go)
301
        return (-1, -1)
253
 
302
 
254
            create_new_state = True
303
    def make_basic_record(self, from_states):
255
 
304
 
-
 
305
        if self.dfa_state_exists(from_states) == -1: #doesn't exist
-
 
306
            temp_record = self.__get_temp_record(len(self.possible_letters))
256
            for s in dfa_table:
307
            recordnum = len(self.dfa_table)
-
 
308
 
257
                if s[2] == where_to_go:
309
            temp_record[1] = recordnum
258
                    temp_record.append(s[1])
310
            temp_record[2] = self.__unique_sort(from_states)
259
                    create_new_state = False
311
            temp_record[0] = self.__is_list_final(from_states)
-
 
312
 
260
                    break
313
            self.dfa_table.append(temp_record)
-
 
314
 
-
 
315
        # always return a re-call of the function. This will not fail, since a new
-
 
316
        # record is added above if a record does not already exist.
-
 
317
        return self.dfa_state_exists(from_states)
261
 
318
 
262
            if create_new_state:
-
 
263
                # recurse???
-
 
264
                pass
-
 
265
 
-
 
266
################################################################################
-
 
267
# NEW STUFF IS AFTER THIS
-
 
268
################################################################################
-
 
269
 
-
 
270
        temp_record = [None for n in range(len(possible_letters) + 3)]
-
 
271
 
-
 
272
        # start at initial state
-
 
273
        # generate E(initial_state)
-
 
274
        # find out if we are a final state (based on E() )
-
 
275
        # name the state (starting at 0)
-
 
276
        #
-
 
277
 
319
 
278
    def output_dfa(self):
320
    def dfa_state_exists(self, from_states):
-
 
321
        """Find out if this state already exists in the dfa table.
-
 
322
        If it does exist, return it's dfa state name.
279
        #stuff here
323
        If it does not exist, return -1"""
-
 
324
 
-
 
325
        sorted_states = self.__unique_sort(from_states)
-
 
326
 
-
 
327
        for i in range(len(self.dfa_table)):
-
 
328
            if self.dfa_table[i][2] == sorted_states:
-
 
329
                return self.dfa_table[i][1]
-
 
330
 
280
        pass
331
        return -1
281
 
332
 
282
if __name__ == '__main__':
333
if __name__ == '__main__':
283
    automaton = nfa()
334
    automaton = nfa()
284
    automaton.main_menu()
335
    automaton.main_menu()
285
 
336
 
286
 
-