-
Notifications
You must be signed in to change notification settings - Fork 0
/
follow.py
65 lines (60 loc) · 1.97 KB
/
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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
from state import Rule
_first = {}
_follow = {}
def first_pos(symbol):
first = set()
if not symbol.startswith('`'):
return set([symbol])
for r in [i for i in Rule.augmented if i.lhs == symbol]:
whole_rhs_has_e = True
for s in r.rhs:
has_e=False
for f in first_pos(s):
if f == '!εpslon':
has_e=True
else:
first.add(f)
if not has_e:
whole_rhs_has_e=False
break
if whole_rhs_has_e:
first.add('!εpslon')
global _first
_first[symbol]=list(first)
return list(first)
def follow_pos(symbol, A=None):
follow = set()
if symbol.endswith("'"):
follow.add('$')
for r in [i for i in Rule.augmented if symbol in i.rhs]:
occurences = r.rhs.count(symbol) # if symbol appears many time in a rule
# B --> a A
if symbol == r.rhs[-1]:
if symbol != r.lhs and A != r.lhs: # (to prevent this problem X => Y , Y => X , and i want follow(y))
for f in follow_pos(r.lhs, symbol):
follow.add(f)
continue
# (B --> a A Beta)
beta = r.rhs
for i in range(occurences):
j=beta.index(symbol)
beta = r.rhs[j+1:]
s=beta[0]
f = first_pos(s)
for f1 in f:
if f1 == '!εpslon':
if symbol == r.lhs or A == r.lhs: continue # don't repeat yourself
for f2 in follow_pos(r.lhs, symbol):
follow.add(f2)
else:
follow.add(f1)
global _follow
_follow[symbol]=list(follow)
return follow
def test_frstfllw(symbols):
c=[]
for s in symbols:
f = first_pos(s)
fo = follow_pos(s)
c.append([s,' '.join(f),' '.join(fo)])
return c