-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathThompson.py
148 lines (138 loc) · 5.89 KB
/
Thompson.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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
from Postfix import Postfix
from AFN import Afn
from FSM import Fsm
from Alphabet import Alphabet
from Transition import Transition
from Symbol import Symbol
from State import State
from Stack import Stack
from Regex import Regex
from PlotAutomaton import PlotAutomaton
class Thompson:
def __init__(self, regex):
self.regex = Regex(regex)
self.modRegex = self.modRegex()
self.automata = Afn([],Fsm([],None, Alphabet()),Transition({}))
self.pila = Stack()
@staticmethod
def isConcat(character, nextCharacter):
if Symbol.isOperand(character) and Symbol.isOperand(nextCharacter):
return True
elif Symbol.isRightParenthesis(character) and Symbol.isLeftParenthesis(nextCharacter):
return True
elif Symbol.isStar(character) and Symbol.isOperand(nextCharacter):
return True
elif Symbol.isStar(character) and Symbol.isLeftParenthesis(nextCharacter):
return True
elif Symbol.isOperand(character) and Symbol.isLeftParenthesis(nextCharacter):
return True
else:
return False
def modRegex(self):
list = [char for char in self.regex.expression+'$']
nlist = []
for i in range(len(list)-1):
if Thompson.isConcat(list[i], list[i+1]) and list[i+1] != '$':
nlist.append(list[i])
nlist.append('.')
elif(list[i] != list[-1] and list[i+1] != '$'):
nlist.append(list[i])
else:
nlist.append(list[i])
return "".join(nlist)
def getAlphabetFromRegex(self):
l = [char for char in self.regex.expression]
al = []
for i in range(len(l)-1):
if Symbol.isOperand(l[i]):
al.append(l[i])
return list(dict.fromkeys(al))
def plantillaOperandoOEpsilon(self,x):
if self.automata.Fsm.Q == []:
ins = State('q0', True, False)
fs = State('q1', False, True)
di = {(ins, x): [fs]}
self.pila.push(di)
self.automata.Fsm.Q.append(ins)
self.automata.Fsm.Q.append(fs)
else:
ns1n = 'q'+str(max([int(x.getName().split('q')[1]) for x in self.automata.Fsm.Q])+1)
ns1 = State(ns1n, True, False)
self.automata.Fsm.Q.append(ns1)
ns2n = 'q'+str(max([int(x.getName().split('q')[1]) for x in self.automata.Fsm.Q])+1)
ns2 = State(ns2n, False, True)
self.automata.Fsm.Q.append(ns2)
self.pila.push({(ns1, x): [ns2]})
def plantillaEstrella(self):
x = self.pila.stack.pop()
ns1n = 'q'+str(max([int(x.getName().split('q')[1]) for x in self.automata.Fsm.Q])+1)
ns1 = State(ns1n, True, False)
self.automata.Fsm.Q.append(ns1)
ns2n = 'q'+str(max([int(x.getName().split('q')[1]) for x in self.automata.Fsm.Q])+1)
ns2 = State(ns2n, False, True)
self.automata.Fsm.Q.append(ns2)
initTrans = Transition.getInitialStateFromTransition(x)
finalTrans = Transition.getFinalStateFromTransition(x)
initTrans.setIsInitialState(False)
finalTrans.setIsFinalState(False)
starStates = [initTrans, ns2]
x[(ns1, 'Ɛ')] = starStates
x[(finalTrans, 'Ɛ')] = starStates
self.pila.push(x)
def plantillaConcatenacion(self):
x1 = self.pila.pop()
x2 = self.pila.pop()
initTransx1 = Transition.getInitialStateFromTransition(x1)
initTransx1.setIsInitialState(False)
finTransx2 = Transition.getFinalStateFromTransition(x2)
finTransx2.setIsFinalState(False)
for key, value in x2.items():
if finTransx2 in x2[key]:
value.remove(finTransx2)
value.append(initTransx1)
x2[key] = value
self.pila.push({**x2, **x1})
self.automata.Fsm.Q.remove(finTransx2)
def plantillaOr(self):
x1 = self.pila.pop()
x2 = self.pila.pop()
initTransx1 = Transition.getInitialStateFromTransition(x1)
initTransx1.setIsInitialState(False)
finTransx1 = Transition.getFinalStateFromTransition(x1)
finTransx1.setIsFinalState(False)
initTransx2 = Transition.getInitialStateFromTransition(x2)
initTransx2.setIsInitialState(False)
finTransx2 = Transition.getFinalStateFromTransition(x2)
finTransx2.setIsFinalState(False)
ns1n = 'q'+str(max([int(x.getName().split('q')[1]) for x in self.automata.Fsm.Q])+1)
ns1 = State(ns1n, True, False)
self.automata.Fsm.Q.append(ns1)
ns2n = 'q'+str(max([int(x.getName().split('q')[1]) for x in self.automata.Fsm.Q])+1)
ns2 = State(ns2n, False, True)
self.automata.Fsm.Q.append(ns2)
newDict = {**x2, **x1}
newDict[(ns1, 'Ɛ')] = [initTransx1, initTransx2]
newDict[(finTransx1, 'Ɛ')] = [ns2]
newDict[(finTransx2, 'Ɛ')] = [ns2]
self.pila.push(newDict)
def getAFNFromTransitions(self):
self.automata.Transition.dict = self.pila.peek()
self.automata.Fsm.Sigma = Alphabet([Symbol(x) for x in self.getAlphabetFromRegex()])
self.automata.Fsm.q0 = Transition.getInitialStateFromTransition(self.pila.peek())
self.automata.F = Transition.getFinalStateFromTransition(self.pila.peek())
def ThompsonContruction(self):
#compute transitions
for x in Postfix(Regex(self.modRegex)).postfix:
if Symbol.isOperand(x):
self.plantillaOperandoOEpsilon(x)
elif Symbol.isOperator(x):
if Symbol.isStar(x):
self.plantillaEstrella()
elif Symbol.isConcat(x):
self.plantillaConcatenacion()
elif Symbol.isOr(x):
self.plantillaOr()
self.getAFNFromTransitions()
def printAutomaton(self):
P = PlotAutomaton(self.automata)
P.plotAutomaton(self.regex)