-
Notifications
You must be signed in to change notification settings - Fork 2
/
CFG.py
120 lines (94 loc) · 3.47 KB
/
CFG.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
class Grammar:
def __init__(self):
self.CFG = {}
self.keys = list(self.CFG.keys())
self.values = list(self.CFG.values())
self.index = 0
def updateKeyVal(self):
self.keys = list(self.CFG.keys())
self.values = list(self.CFG.values())
def createProduction(self, key, value):
if key not in self.keys:
self.CFG.update({key: [value]})
self.updateKeyVal()
else:
self.CFG[key].append(value)
def newVar(self):
newvar = 'VAR' + str(self.index)
self.index += 1
return newvar
def CFGtoCNF(self):
startSymbol = self.keys[0]
# If start symbol S is at the RHS of any production in the grammar, create a new production as: S0 -> S
startInRHS = False
for value in self.values:
for item in value:
if startSymbol in item:
startInRHS = True
break
if startInRHS:
self.createProduction('S0', [startSymbol])
# Eliminate unit production
recheck = True
while recheck:
changed = False
for rule in self.CFG:
for unit in self.CFG[rule]:
if (len(unit) == 1):
if not unit[0].islower():
self.CFG[rule].remove(unit)
for item in self.CFG[unit[0]]:
# print(unit)
# print(item)
self.CFG[rule].append(item)
changed = True
self.updateKeyVal()
recheck = changed
# remove useless production
for rule in list(self.CFG):
useless = True
for value in self.values:
for item in value:
if rule in item or rule == 'S0':
useless = False
break
if useless:
# print(self.CFG[rule])
del self.CFG[rule]
self.updateKeyVal()
# Eliminate RHS with more than two non-terminals.
recheck = True
while recheck:
changed = False
for key in self.keys:
for value in self.CFG[key]:
if len(value) > 2:
newVar = self.newVar()
newVal = [value[0], value[1]]
self.createProduction(newVar, newVal)
del self.CFG[key][(self.CFG[key]).index(value)][0:2]
self.CFG[key][(self.CFG[key]).index(
value)].insert(0, newVar)
self.updateKeyVal()
changed = True
recheck = changed
def parseCFG(self, filename):
file = open(filename, 'r')
CFG = {}
# read rules line by line
rules = file.readline()
while rules != "":
# remove enter
rules = rules.replace("\n", "")
# split parent and child
parent, child = rules.split(" -> ")
# Create empty list if parent not in CFG
if parent not in CFG:
CFG[parent] = []
CFG[parent].append(child.split(' '))
rules = file.readline()
file.close()
self.CFG = CFG
self.updateKeyVal()
self.CFGtoCNF()
return self.CFG