代码
def inputGrammer():
grammer=[]
print('箭头请用符号→')
print('空串请用符号ε')
print('____________________________')
while(True):
production=input()
if(production=='$'):
break;
elif (production[-1:] == '$'):
grammer.append(production[:-1])
break;
else:
grammer.append(production)
return grammer
def cut(grammer):
grammer1 = []
for i in range(len(grammer)):
s=grammer[i]
if '|' in s:
while True:
index = s.find('|')
grammer1.append(s[:index])
index2 = s.find('→')
s1=s[:index2 + 1] + s[index + 1:]
if '|' not in s1:
grammer1.append(s1)
break
else:
s=s1
else:
grammer1.append(grammer[i])
return grammer1
First={}
Follow={}
def initializeFirstAndFollow(grammer):
VN=[]
for i in range(len(grammer)):
s=grammer[i]
for j in range(len(s)):
if(s[j]>='A' and s[j]<='Z'):
if(j<len(s)-1 and s[j+1]=='\''):
vn=s[j]+'\''
if vn not in VN:
VN.append(vn)
else:
vn = s[j] + ''
if vn not in VN:
VN.append(vn)
global First
global Follow
for i in range(len(VN)):
First[VN[i]]=[]
Follow[VN[i]]=[]
Follow[VN[0]].append('$')
def findFirstVN(s):
length=len(s)
for i in range(length):
if s[i]>='A' and s[i]<='Z':
if(i<length-1):
if(s[i+1]=='\''):
return s[i:i+2]
else:
return s[i]
else:
return s[i]
return '$'
def findNextVN(s):
length=len(s)
vn=findFirstVN(s)
index=s.find(vn)
length1=len(vn)
return findFirstVN(s[index+length1:])
def findLastVN(s):
length=len(s)
index=0
if s[length-1:]<'A' or s[length-1:]>'Z':
if s[length-1:]!='\'':
return findFirstVN(s)
for i in range(length):
if s[i]>='A' and s[i]<='Z':
index=i
if index==length-1:
return s[index]
else:
if s[index+1]=='\'':
return s[index:index+2]
else:
return s[index]
def lookVT(grammer):
global First
for i in range(len(grammer)):
s = grammer[i]
index = s.find('→')
left = s[:index]
right= s[index + 1:]
if right[0]<'A' or right[0]>'Z':
if right[0]=='i' and 'id' not in First[left]:
First[left].append('id')
else:
if right[0] not in First[left]:
First[left].append(right[0])
def FFirst(grammer):
'''
扫描文法中的每一个产生式,对于产生式右边第一个符号不是非终结符的情况,
把右边非终结符First集中的元素加入到左边非终结符的First集中去
如果右边非终结符的First集中包含空串ε,则应找到该非终结符之后的一个非终结符
把这个非终结符First集中的元素加入到左边非终结符的First集中去,此次类推
'''
for i in range(len(grammer)):
s = grammer[i]
index = s.find('→')
right = s[index + 1:]
if right[0]<'A' or right[0]>'Z':
continue
vn1 = findFirstVN(s)
vn2 = findNextVN(s)
flag=1
while flag==1 and '$'!=vn2:
for ss in First[vn2]:
if ss not in First[vn1]:
First[vn1].append(ss)
if 'ε' in First[vn2]:
flag=1
index=s.find(vn2)
vn2=findLastVN(s[index:])
else:
flag=0
def handleFirst(grammer):
lookVT(grammer)
FFirst(grammer)
FFirst(grammer)
def scanVT(s):
global Follow
s1=s
index=s1.find('→')
s1=s1[index+1:]
for i in range(len(s1)):
if s1[i]<'A' or s1[i]>'Z':
if s1[i]!='\'':
if i>0 and s1[i-1]=='\'':
vn=s1[i-2:i]
elif i>0:
vn=s1[i-1]
else:
vn='$'
if len(s1)==1 or s1=='id':
vn='$'
if vn!='$':
if s1[i] =='i' or s1[i]=='d':
if 'id' not in Follow[vn]:
Follow[vn].append('id')
else:
if s1[i] not in Follow[vn]:
Follow[vn].append(s1[i])
vn1=findFirstVN(s1)
vn2=findNextVN(s1)
if vn1!='$' and vn2!='$' and vn1+vn2 in s1:
for si in First[vn2]:
if si not in Follow[vn1] and si!='ε':
Follow[vn1].append(si)
def FFollow(grammer):
'''
扫描文法的每一个产生式,把第一个非终结符的Follow集去除空串ε加入到最后一个非终结符的Follow集中去
如果最后一个非终结符的First集中有空串ε,
则把第一个非终结符的Follow集去除空串ε加入到倒数第二个非终结符的FOllow集中去,依次类推
'''
for i in range(len(grammer)):
s = grammer[i]
vn1 = findFirstVN(s)
vn2 = findLastVN(s)
flag=1
while flag==1 and vn1!=vn2:
for ss in Follow[vn1]:
if ss not in Follow[vn2]:
Follow[vn2].append(ss)
if 'ε' in First[vn2]:
flag=1
index=s.find(vn2)
vn2=findLastVN(s[:index])
else:
flag=0
def handleFollow(grammer):
global Follow
for i in range(len(grammer)):
s=grammer[i]
scanVT(s)
FFollow(grammer)
def showFirst():
global First
for i in First.keys():
print('First(',i,')= ',end="{ ")
for j in First[i]:
if j!=First[i][-1]:
print(j,end=", ")
else:
print(j, end="")
print("} ")
def showFollow():
for i in Follow.keys():
print('Follow(',i,')= ',end="{ ")
for j in Follow[i]:
if j!=Follow[i][-1]:
print(j,end=", ")
else:
print(j,end="")
print("} ")
if __name__ == '__main__':
print('____________________________')
g=inputGrammer()
grammer=cut(g)
initializeFirstAndFollow(grammer)
print('____________________________')
handleFirst(grammer)
showFirst()
print('____________________________')
handleFollow(grammer)
showFollow()
print('____________________________')
输入
输出
检查