Neha13 commited on
Commit
ead4048
·
verified ·
1 Parent(s): df6f1ef

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +219 -169
app.py CHANGED
@@ -1,21 +1,14 @@
1
-
2
- import copy
3
  import streamlit as st
4
-
5
- stateMap = {}
6
- diction = {}
7
- start_symbol = ""
8
- rules = []
9
- statesDict={}
10
- stateCount = 0
11
- separatedRulesList = []
12
 
13
  def grammarAugmentation(rules, nonterm_userdef, start_symbol):
14
  newRules = []
15
  newChar = start_symbol + "'"
16
  while (newChar in nonterm_userdef):
17
  newChar += "'"
 
18
  newRules.append([newChar, ['.', start_symbol]])
 
19
  for rule in rules:
20
  k = rule.split("->")
21
  lhs = k[0].strip()
@@ -27,22 +20,19 @@ def grammarAugmentation(rules, nonterm_userdef, start_symbol):
27
  newRules.append([lhs, rhs1])
28
  return newRules
29
 
30
- def findClosure(input_state, dotSymbol):
31
- global separatedRulesList
32
-
33
  closureSet = []
34
-
35
- if isinstance(input_state, int):
36
  for rule in separatedRulesList:
37
  if rule[0] == dotSymbol:
38
  closureSet.append(rule)
39
  else:
40
  closureSet = input_state
41
-
42
  prevLen = -1
43
  while prevLen != len(closureSet):
44
  prevLen = len(closureSet)
45
-
46
  tempClosureSet = []
47
  for rule in closureSet:
48
  indexOfDot = rule[1].index('.')
@@ -51,14 +41,13 @@ def findClosure(input_state, dotSymbol):
51
  for in_rule in separatedRulesList:
52
  if dotPointsHere == in_rule[0] and in_rule not in tempClosureSet:
53
  tempClosureSet.append(in_rule)
54
-
55
  for rule in tempClosureSet:
56
  if rule not in closureSet:
57
  closureSet.append(rule)
58
  return closureSet
59
 
60
- def compute_GOTO(state):
61
- global statesDict, stateCount
62
  generateStatesFor = []
63
  for rule in statesDict[state]:
64
  if rule[1][-1] != '.':
@@ -66,13 +55,13 @@ def compute_GOTO(state):
66
  dotPointsHere = rule[1][indexOfDot + 1]
67
  if dotPointsHere not in generateStatesFor:
68
  generateStatesFor.append(dotPointsHere)
 
69
  if len(generateStatesFor) != 0:
70
  for symbol in generateStatesFor:
71
- GOTO(state, symbol)
72
- return
73
 
74
- def GOTO(state, charNextToDot):
75
- global statesDict, stateCount, stateMap
76
  newState = []
77
  for rule in statesDict[state]:
78
  indexOfDot = rule[1].index('.')
@@ -82,204 +71,265 @@ def GOTO(state, charNextToDot):
82
  shiftedRule[1][indexOfDot] = shiftedRule[1][indexOfDot + 1]
83
  shiftedRule[1][indexOfDot + 1] = '.'
84
  newState.append(shiftedRule)
85
-
86
  addClosureRules = []
87
  for rule in newState:
88
  indexDot = rule[1].index('.')
89
  if rule[1][-1] != '.':
90
- closureRes = findClosure(newState, rule[1][indexDot + 1])
91
  for rule in closureRes:
92
  if rule not in addClosureRules and rule not in newState:
93
  addClosureRules.append(rule)
94
-
95
  for rule in addClosureRules:
96
  newState.append(rule)
97
-
98
  stateExists = -1
99
  for state_num in statesDict:
100
  if statesDict[state_num] == newState:
101
  stateExists = state_num
102
  break
103
-
104
  if stateExists == -1:
105
  stateCount += 1
106
  statesDict[stateCount] = newState
107
  stateMap[(state, charNextToDot)] = stateCount
108
  else:
109
  stateMap[(state, charNextToDot)] = stateExists
110
- return
111
 
112
- def generateStates(I0):
113
- global statesDict, stateCount
114
-
115
- statesDict[0] = I0
116
- stateCount = 0
117
  prev_len = -1
118
  called_GOTO_on = []
 
119
  while (len(statesDict) != prev_len):
120
  prev_len = len(statesDict)
121
  keys = list(statesDict.keys())
 
122
  for key in keys:
123
  if key not in called_GOTO_on:
124
  called_GOTO_on.append(key)
125
- compute_GOTO(key)
126
- return
127
-
128
- def first(rule):
129
- global rules, term_userdef, diction, firsts
130
- if len(rule) != 0 and rule[0] in term_userdef:
131
- return [rule[0]]
132
- if len(rule) != 0 and rule[0] == '#':
133
- return ['#']
 
134
  if len(rule) != 0:
135
- fres = []
136
- rhs_rules = diction[rule[0]]
137
- for itr in rhs_rules:
138
- indivRes = first(itr)
139
- if '#' in indivRes:
140
- indivRes.remove('#')
141
- if len(rule) > 1:
142
- indivRes += first(rule[1:])
 
143
  else:
144
- indivRes.append('#')
145
- fres.extend(indivRes)
146
- return list(set(fres))
147
- return []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
148
 
149
- def follow(nt):
150
- global start_symbol, diction, firsts, follows
151
  solset = set()
152
  if nt == start_symbol:
153
  solset.add('$')
 
154
  for curNT in diction:
155
  rhs = diction[curNT]
 
156
  for subrule in rhs:
157
  if nt in subrule:
158
  while nt in subrule:
159
  index_nt = subrule.index(nt)
160
  subrule = subrule[index_nt + 1:]
161
- if subrule:
162
- res = first(subrule)
 
163
  if '#' in res:
 
164
  res.remove('#')
165
- solset.update(res)
166
- solset.update(follow(curNT))
167
- else:
168
- solset.update(res)
 
 
 
 
 
169
  else:
170
  if nt != curNT:
171
- solset.update(follow(curNT))
 
 
 
 
 
 
 
172
  return list(solset)
173
 
 
 
 
174
 
175
- def createParseTable(statesDict, stateMap, T, NT):
176
- global separatedRulesList, diction
177
-
178
- parse_table = {i: {} for i in range(len(statesDict))}
179
-
180
- for (state, symbol) in stateMap:
181
- if symbol in T:
182
- parse_table[state][symbol] = f'S{stateMap[(state, symbol)]}'
183
- elif symbol in NT:
184
- parse_table[state][symbol] = str(stateMap[(state, symbol)])
185
-
186
- for state in statesDict:
187
- for item in statesDict[state]:
188
- if item[1][-1] == '.':
189
- prod = f"{item[0]} -> {' '.join(item[1][:-1])}"
190
-
191
- if prod == f"{separatedRulesList[0][0]} -> {separatedRulesList[0][1][1]}":
192
- parse_table[state]['$'] = 'ACC'
193
- else:
194
- rule_index = next(
195
- (i for i, rule in enumerate(separatedRulesList) if rule == item),
196
- None
197
- )
198
-
199
- if rule_index is None:
200
- print(f"Warning: Rule for item {item} not found in separatedRulesList.")
201
- continue
202
-
203
- for symbol in T + ['$']:
204
- if symbol not in parse_table[state]:
205
- parse_table[state][symbol] = f'R{rule_index}'
206
-
207
- return parse_table
208
-
209
-
210
- def main():
211
- st.title("SLR(1) Parser Generator")
212
-
213
- st.header("Grammar Input")
214
- rules = st.text_area("Enter the grammar rules (one per line):",
215
- "E -> E + T | T\nT -> T * F | F\nF -> ( E ) | id")
216
- rules = rules.split('\n')
217
 
218
- nonterm_userdef = st.text_input("Enter the non-terminal symbols (separated by space):", "E T F")
219
- nonterm_userdef = nonterm_userdef.split()
 
 
 
 
 
 
 
220
 
221
- term_userdef = st.text_input("Enter the terminal symbols (separated by space):", "id + * ( )")
222
- term_userdef = term_userdef.split()
 
 
 
 
 
223
 
224
- start_symbol = st.text_input("Enter the start symbol:", "E")
225
-
226
- if st.button("Generate SLR(1) Parser"):
227
- st.subheader("Original Grammar Input:")
228
- for rule in rules:
229
- st.write(rule)
230
-
231
- st.subheader("Grammar after Augmentation:")
232
- global separatedRulesList
233
- separatedRulesList = grammarAugmentation(rules, nonterm_userdef, start_symbol)
234
- for rule in separatedRulesList:
235
- st.write(f"{rule[0]} -> {' '.join(rule[1])}")
236
-
237
- start_symbol = separatedRulesList[0][0]
238
- st.subheader("Calculated Closure: I0")
239
- I0 = findClosure(0, start_symbol)
240
-
241
- st.write("I0:")
242
- for rule in I0:
243
- st.write(f"{rule[0]} -> {' '.join(rule[1])}")
244
 
245
- generateStates(I0)
 
246
 
247
- st.subheader("Generated States:")
248
- for state, rules in statesDict.items():
249
- st.write(f"I{state}:")
250
- for rule in rules:
251
- st.write(f" {rule[0]} -> {' '.join(rule[1])}")
252
- st.write("")
253
 
254
- st.subheader("SLR(1) Parsing Table")
255
- table = createParseTable(statesDict, stateMap, term_userdef, nonterm_userdef)
256
-
257
- cols = ['State'] + term_userdef + ['$'] + nonterm_userdef
258
- table_data = []
259
- for state in range(len(statesDict)):
260
- row = [f'I{state}']
261
- for symbol in term_userdef + ['$'] + nonterm_userdef:
262
- row.append(table[state].get(symbol, ''))
263
- table_data.append(row)
264
-
265
- st.table([cols] + table_data)
266
 
267
- compact_table = "State`" + '`'.join(term_userdef + ['$'] + nonterm_userdef) + '`'
268
- for state in range(len(statesDict)):
269
- compact_table += f"I{state}"
270
- for symbol in term_userdef + ['$'] + nonterm_userdef:
271
- compact_table += table[state].get(symbol, '')
272
- st.subheader("Follow Sets")
273
- follow_sets = {}
274
- for nt in nonterm_userdef:
275
- follow_set = follow(nt)
276
- follow_sets[nt] = follow_set
277
- st.write(f"Follow({nt}): {{ {' , '.join(follow_set)} }}")
278
- compact_follow = "Non-Terminal`Follow Set\n"
279
- for nt, follow_set in follow_sets.items():
280
- compact_follow += f"{nt}`{{ {' , '.join(follow_set)} }}\n"
281
-
282
- st.text_area("Compact Follow Sets Representation:", value=compact_follow, height=300)
283
-
284
- if __name__ == "__main__":
285
- main()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import streamlit as st
2
+ import copy
 
 
 
 
 
 
 
3
 
4
  def grammarAugmentation(rules, nonterm_userdef, start_symbol):
5
  newRules = []
6
  newChar = start_symbol + "'"
7
  while (newChar in nonterm_userdef):
8
  newChar += "'"
9
+
10
  newRules.append([newChar, ['.', start_symbol]])
11
+
12
  for rule in rules:
13
  k = rule.split("->")
14
  lhs = k[0].strip()
 
20
  newRules.append([lhs, rhs1])
21
  return newRules
22
 
23
+ def findClosure(input_state, dotSymbol, separatedRulesList, start_symbol):
 
 
24
  closureSet = []
25
+
26
+ if dotSymbol == start_symbol:
27
  for rule in separatedRulesList:
28
  if rule[0] == dotSymbol:
29
  closureSet.append(rule)
30
  else:
31
  closureSet = input_state
32
+
33
  prevLen = -1
34
  while prevLen != len(closureSet):
35
  prevLen = len(closureSet)
 
36
  tempClosureSet = []
37
  for rule in closureSet:
38
  indexOfDot = rule[1].index('.')
 
41
  for in_rule in separatedRulesList:
42
  if dotPointsHere == in_rule[0] and in_rule not in tempClosureSet:
43
  tempClosureSet.append(in_rule)
44
+
45
  for rule in tempClosureSet:
46
  if rule not in closureSet:
47
  closureSet.append(rule)
48
  return closureSet
49
 
50
+ def compute_GOTO(state, statesDict, separatedRulesList, stateMap, stateCount):
 
51
  generateStatesFor = []
52
  for rule in statesDict[state]:
53
  if rule[1][-1] != '.':
 
55
  dotPointsHere = rule[1][indexOfDot + 1]
56
  if dotPointsHere not in generateStatesFor:
57
  generateStatesFor.append(dotPointsHere)
58
+
59
  if len(generateStatesFor) != 0:
60
  for symbol in generateStatesFor:
61
+ stateCount = GOTO(state, symbol, statesDict, separatedRulesList, stateMap, stateCount)
62
+ return stateCount
63
 
64
+ def GOTO(state, charNextToDot, statesDict, separatedRulesList, stateMap, stateCount):
 
65
  newState = []
66
  for rule in statesDict[state]:
67
  indexOfDot = rule[1].index('.')
 
71
  shiftedRule[1][indexOfDot] = shiftedRule[1][indexOfDot + 1]
72
  shiftedRule[1][indexOfDot + 1] = '.'
73
  newState.append(shiftedRule)
74
+
75
  addClosureRules = []
76
  for rule in newState:
77
  indexDot = rule[1].index('.')
78
  if rule[1][-1] != '.':
79
+ closureRes = findClosure(newState, rule[1][indexDot + 1], separatedRulesList, start_symbol)
80
  for rule in closureRes:
81
  if rule not in addClosureRules and rule not in newState:
82
  addClosureRules.append(rule)
83
+
84
  for rule in addClosureRules:
85
  newState.append(rule)
86
+
87
  stateExists = -1
88
  for state_num in statesDict:
89
  if statesDict[state_num] == newState:
90
  stateExists = state_num
91
  break
92
+
93
  if stateExists == -1:
94
  stateCount += 1
95
  statesDict[stateCount] = newState
96
  stateMap[(state, charNextToDot)] = stateCount
97
  else:
98
  stateMap[(state, charNextToDot)] = stateExists
99
+ return stateCount
100
 
101
+ def generateStates(statesDict, separatedRulesList, stateMap, stateCount):
 
 
 
 
102
  prev_len = -1
103
  called_GOTO_on = []
104
+
105
  while (len(statesDict) != prev_len):
106
  prev_len = len(statesDict)
107
  keys = list(statesDict.keys())
108
+
109
  for key in keys:
110
  if key not in called_GOTO_on:
111
  called_GOTO_on.append(key)
112
+ stateCount = compute_GOTO(key, statesDict, separatedRulesList, stateMap, stateCount)
113
+ return stateCount
114
+
115
+ def first(rule, diction, term_userdef):
116
+ if len(rule) != 0 and (rule is not None):
117
+ if rule[0] in term_userdef:
118
+ return rule[0]
119
+ elif rule[0] == '#':
120
+ return '#'
121
+
122
  if len(rule) != 0:
123
+ if rule[0] in list(diction.keys()):
124
+ fres = []
125
+ rhs_rules = diction[rule[0]]
126
+
127
+ for itr in rhs_rules:
128
+ indivRes = first(itr, diction, term_userdef)
129
+ if type(indivRes) is list:
130
+ for i in indivRes:
131
+ fres.append(i)
132
  else:
133
+ fres.append(indivRes)
134
+
135
+ if '#' not in fres:
136
+ return fres
137
+ else:
138
+ newList = []
139
+ fres.remove('#')
140
+ if len(rule) > 1:
141
+ ansNew = first(rule[1:], diction, term_userdef)
142
+ if ansNew != None:
143
+ if type(ansNew) is list:
144
+ newList = fres + ansNew
145
+ else:
146
+ newList = fres + [ansNew]
147
+ else:
148
+ newList = fres
149
+ return newList
150
+ fres.append('#')
151
+ return fres
152
 
153
+ def follow(nt, start_symbol, rules, diction):
 
154
  solset = set()
155
  if nt == start_symbol:
156
  solset.add('$')
157
+
158
  for curNT in diction:
159
  rhs = diction[curNT]
160
+
161
  for subrule in rhs:
162
  if nt in subrule:
163
  while nt in subrule:
164
  index_nt = subrule.index(nt)
165
  subrule = subrule[index_nt + 1:]
166
+
167
+ if len(subrule) != 0:
168
+ res = first(subrule, diction, term_userdef)
169
  if '#' in res:
170
+ newList = []
171
  res.remove('#')
172
+ ansNew = follow(curNT, start_symbol, rules, diction)
173
+ if ansNew != None:
174
+ if type(ansNew) is list:
175
+ newList = res + ansNew
176
+ else:
177
+ newList = res + [ansNew]
178
+ else:
179
+ newList = res
180
+ res = newList
181
  else:
182
  if nt != curNT:
183
+ res = follow(curNT, start_symbol, rules, diction)
184
+
185
+ if res is not None:
186
+ if type(res) is list:
187
+ for g in res:
188
+ solset.add(g)
189
+ else:
190
+ solset.add(res)
191
  return list(solset)
192
 
193
+ def createParseTable(statesDict, stateMap, T, NT, separatedRulesList, rules, diction):
194
+ rows = list(statesDict.keys())
195
+ cols = T + ['$'] + NT
196
 
197
+ Table = []
198
+ tempRow = []
199
+ for y in range(len(cols)):
200
+ tempRow.append('')
201
+ for x in range(len(rows)):
202
+ Table.append(copy.deepcopy(tempRow))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
203
 
204
+ for entry in stateMap:
205
+ state = entry[0]
206
+ symbol = entry[1]
207
+ a = rows.index(state)
208
+ b = cols.index(symbol)
209
+ if symbol in NT:
210
+ Table[a][b] = Table[a][b] + f"{stateMap[entry]} "
211
+ elif symbol in T:
212
+ Table[a][b] = Table[a][b] + f"S{stateMap[entry]} "
213
 
214
+ numbered = {}
215
+ key_count = 0
216
+ for rule in separatedRulesList:
217
+ tempRule = copy.deepcopy(rule)
218
+ tempRule[1].remove('.')
219
+ numbered[key_count] = tempRule
220
+ key_count += 1
221
 
222
+ for stateno in statesDict:
223
+ for rule in statesDict[stateno]:
224
+ if rule[1][-1] == '.':
225
+ temp2 = copy.deepcopy(rule)
226
+ temp2[1].remove('.')
227
+ for key in numbered:
228
+ if numbered[key] == temp2:
229
+ follow_result = follow(rule[0], start_symbol, rules, diction)
230
+ for col in follow_result:
231
+ index = cols.index(col)
232
+ if key == 0:
233
+ Table[stateno][index] = "Accept"
234
+ else:
235
+ Table[stateno][index] = Table[stateno][index] + f"R{key} "
236
+
237
+ return Table, cols, rows
 
 
 
 
238
 
239
+ # Streamlit app
240
+ st.title("SLR(1) Parser Generator")
241
 
242
+ # Input section
243
+ st.header("Grammar Input")
244
+ st.write("Enter grammar rules in the format: A -> B | C")
 
 
 
245
 
246
+ # Initialize session state for rules
247
+ if 'rules' not in st.session_state:
248
+ st.session_state.rules = ["E -> E + T | T", "T -> T * F | F", "F -> ( E ) | id"]
 
 
 
 
 
 
 
 
 
249
 
250
+ # Display rules input
251
+ rules = []
252
+ for i in range(len(st.session_state.rules)):
253
+ rule = st.text_input(f"Rule {i+1}", value=st.session_state.rules[i], key=f"rule_{i}")
254
+ rules.append(rule)
255
+
256
+ # # Add/remove rule buttons
257
+ # col1, col2 = st.columns(2)
258
+
259
+ # with col1:
260
+ # if st.button("Add Rule"):
261
+ # st.session_state.rules.append("") # Add a new empty rule
262
+ # # Trigger the rerun by changing the rules list
263
+ # # st.experimental_rerun()
264
+ # with col2:
265
+ # if st.button("Remove Rule") and len(st.session_state.rules) > 1:
266
+ # st.session_state.rules.pop() # Remove last rule
267
+ # # Trigger the rerun by changing the rules list
268
+ # # st.experimental_rerun()
269
+
270
+ # Other inputs
271
+ nonterm_userdef = st.text_input("Non-terminal symbols (separated by space)", "E T F").split()
272
+ term_userdef = st.text_input("Terminal symbols (separated by space)", "id + * ( )").split()
273
+ start_symbol = st.text_input("Start symbol", "E")
274
+
275
+ if st.button("Generate Parser"):
276
+ st.header("Results")
277
+
278
+ # Display original grammar
279
+ st.subheader("Original Grammar")
280
+ for rule in rules:
281
+ st.write(rule)
282
+
283
+ # Grammar augmentation
284
+ separatedRulesList = grammarAugmentation(rules, nonterm_userdef, start_symbol)
285
+
286
+ st.subheader("Augmented Grammar")
287
+ for rule in separatedRulesList:
288
+ st.write(f"{rule[0]} -> {' '.join(rule[1])}")
289
+
290
+ # Initialize variables
291
+ statesDict = {}
292
+ stateMap = {}
293
+ stateCount = 0
294
+ diction = {}
295
+
296
+ # Calculate closure
297
+ I0 = findClosure(0, start_symbol, separatedRulesList, start_symbol)
298
+ statesDict[0] = I0
299
+
300
+ st.subheader("Initial Closure (I0)")
301
+ for rule in I0:
302
+ st.write(f"{rule[0]} -> {' '.join(rule[1])}")
303
+
304
+ # Generate states
305
+ stateCount = generateStates(statesDict, separatedRulesList, stateMap, stateCount)
306
+ # Display generated states
307
+ with st.expander("🔍 View Generated States"):
308
+ for state_num, state_rules in statesDict.items():
309
+ st.markdown(f"**I{state_num}:**")
310
+ for rule in state_rules:
311
+ st.write(f"{rule[0]} -> {' '.join(rule[1])}")
312
+
313
+
314
+ # Create parsing table
315
+ rules.insert(0, f"{separatedRulesList[0][0]} -> {separatedRulesList[0][1][1]}")
316
+ for rule in rules:
317
+ k = rule.split("->")
318
+ k[0] = k[0].strip()
319
+ k[1] = k[1].strip()
320
+ rhs = k[1]
321
+ multirhs = rhs.split('|')
322
+ for i in range(len(multirhs)):
323
+ multirhs[i] = multirhs[i].strip()
324
+ multirhs[i] = multirhs[i].split()
325
+ diction[k[0]] = multirhs
326
+
327
+ Table, cols, rows = createParseTable(statesDict, stateMap, term_userdef, nonterm_userdef, separatedRulesList, rules, diction)
328
+
329
+ # Display parsing table
330
+ st.subheader("SLR(1) Parsing Table")
331
+
332
+ # Create DataFrame for better display
333
+ import pandas as pd
334
+ df = pd.DataFrame(Table, columns=cols, index=[f"I{i}" for i in rows])
335
+ st.dataframe(df)