-
Notifications
You must be signed in to change notification settings - Fork 2
/
main.py
executable file
·130 lines (104 loc) · 4.02 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
import json
import re
import sys
import webbrowser
import os
def remove_space(str):
return ''.join([x for x in str if x is not ' ' and x is not '\t'])
def change(set):
return str(sorted(set)).replace('[', '{').replace(']', '}').replace('\'', '')
"""
Take all states between '{' and '}' and put it into list to be iterated later
Set the alphabet and the states ascendingly
"""
def read_line(str, state, alphabet):
result = dict()
if 'epsilon' not in alphabet:
alphabet = sorted(alphabet.union(['epsilon']))
result.update({state: {}})
set_states = [s for s in re.findall(r'(?<={)[a-zA-Z0-9,]*(?=})', str)]
for col, current_set_state in zip(sorted(alphabet), set_states):
result[state].update({col: set(current_set_state.split(',')) if current_set_state else set()})
return result
"""
Read the data from the input file and put it in the main table as dictionary
Check whether the current line is a start state and/or final state
If it is, add it to its respective variable
"""
def read_file(path, alphabet):
e_nfa_table = dict()
start_state, final_state = '', set()
with open(path) as f:
for line in f:
line = remove_space(line)
tmp = line[:line.find('{')]
line = line[line.find('{'):]
start_state_index = tmp.find('->')
final_state_index = tmp.find('*')
current_state = re.search(r'(?<=-|>|\*)\w+', tmp)
if current_state is not None:
current_state = current_state.group()
else:
current_state = tmp
if start_state_index is not -1:
start_state = current_state
if final_state_index is not -1:
final_state.add(current_state)
e_nfa_table.update(read_line(line, current_state, alphabet))
e_nfa_table.update({'start_state': start_state,
'final_state': final_state})
return e_nfa_table
"""
Convert the E-NFA to DFA from the transition table recursively
"""
def convert(transition_table, alphabet, current_state, result):
for a in alphabet:
set_union = set()
for s in current_state:
set_union |= transition_table[s][a]
eclose = set()
for e in set_union:
eclose |= transition_table[e]['epsilon']
current_state_string = change(current_state)
eclose_string = change(eclose)
if eclose & transition_table['final_state']:
result['final_state'] = result['final_state'].union([eclose_string])
if current_state_string not in result['result']:
result['result'].update({current_state_string: {}})
result['result'][current_state_string].update({a: eclose_string})
if eclose_string not in result['result']:
convert(transition_table, alphabet, eclose, result)
return result
if __name__ == '__main__':
"""
command line arguments
0 for this file name, 1 for the path to the localhost document root with trailing slash, and 2 for the input file for the transition table
"""
args = sys.argv[3:]
alphabet = set()
LOCALHOST_DOCUMENT_ROOT_PATH = sys.argv[1]
while True:
LOCALHOST_DOCUMENT_ROOT_PATH = os.path.abspath(LOCALHOST_DOCUMENT_ROOT_PATH)
if os.path.isdir(LOCALHOST_DOCUMENT_ROOT_PATH):
break
else:
print('Directory doesn\'t exist')
LOCALHOST_DOCUMENT_ROOT_PATH = input('Input the absolute path to your localhost document root: ')
for arg in args:
alphabet = alphabet.union([arg])
transition_table = read_file(sys.argv[2], alphabet.copy())
first_state = transition_table[transition_table['start_state']]['epsilon']
result = convert(transition_table, alphabet, first_state,
{'start_state': change(first_state),
'final_state': {change(first_state)} if first_state & transition_table['final_state'] else set(),
'alphabet' : sorted(list(alphabet)),
'result' : {}})
result['final_state'] = sorted(list(result['final_state']))
temp_result_state = []
for k, v in sorted(result['result'].items()):
temp_result_state.append({'from': k, 'to': v})
result['result'] = temp_result_state
fp = open(LOCALHOST_DOCUMENT_ROOT_PATH + '/dfa/result.json', 'w')
json.dump(result, fp, indent = 4, sort_keys = True)
fp.close()
webbrowser.open_new_tab('http://localhost/dfa')