-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfirst_follow.py
42 lines (34 loc) · 1.35 KB
/
first_follow.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
def first_follow(G):
def union(set_1, set_2):
set_1_len = len(set_1)
set_1 |= set_2
return set_1_len != len(set_1)
first = {symbol: set() for symbol in G.symbols}
first.update((terminal, {terminal}) for terminal in G.terminals)
follow = {symbol: set() for symbol in G.nonterminals}
follow[G.start].add('$')
while True:
updated = False
for head, bodies in G.grammar.items():
for body in bodies:
for symbol in body:
if symbol != '^':
updated |= union(first[head], first[symbol] - set('^'))
if '^' not in first[symbol]:
break
else:
updated |= union(first[head], set('^'))
else:
updated |= union(first[head], set('^'))
aux = follow[head]
for symbol in reversed(body):
if symbol == '^':
continue
if symbol in follow:
updated |= union(follow[symbol], aux - set('^'))
if '^' in first[symbol]:
aux = aux | first[symbol]
else:
aux = first[symbol]
if not updated:
return first, follow