上一個文章實現了對LL(1)文法各非終結符求first集和follow集,我們這篇文章則是繼續求得LL(1)的預測分析集。
看一下預測分析集的求解方法:
這裏我們需要求對於一個串的first集,求解方法如下:
任意符號α的FIRST集求法:
1. α爲終結符,則把它自身加入FIRSRT(α)
2. α爲非終結符,則:
(1)若存在產生式α->a...,則把a加入FIRST(α),其中a可以爲ε
(2)若存在一串非終結符Y1,Y2, ..., Yk-1,且它們的FIRST集都含空串,且有產生式α->Y1Y2...Yk...,那麼把FIRST(Yk)-{ε}加入FIRST(α)。如果k-1抵達產生式末尾,那麼把ε加入FIRST(α)
注意(2)要連續進行,通俗地描述就是:沿途的Yi都能推出空串,則把這一路遇到的Yi的FIRST集都加進來,直到遇到第一個不能推出空串的Yk爲止。
重複1,2步驟直至每個FIRST集都不再增大爲止。
這地方借鑑自:【編譯原理】語法分析LL(1)分析法的FIRST和FOLLOW集
通過這一步驟編寫求一個串的first集合:
dirFirst = defaultdict(set)
def getDirFirst(curPro):
res = []
# 對於一個字符串求first集
for i in range(1,len(curPro)):
if curPro[i] in vt:
res.append(curPro[i])
break
elif curPro[i] in vn:
if 'epsilon' in first[curPro[i]]:
res.extend(first[curPro[i]])
else:
res.extend(first[curPro[i]])
break
# 去重
ress = []
for i in res:
if i not in ress:
ress.append(i)
return ress
對於文法G的每個產生式 A->α ,進行如下處理
(1)對於FIRST(α)中每個終結符號a,將 A->α 加入到 M[A,a] 中。
(2)如果 ε在FIRST(α)中,那麼對於FOLLOW(A)中每個終結符號b,將 A->α 加入到 M[A,b] 中。如果 ε在FIRST(α),且] 中。
求預測分析表:
1.先構建一個這樣的表
2.然後依次填入非終結符號
3.按照規則1填寫其餘內容
4.按照規則2填寫內容
至此整個構建全部完成
此處借鑑自:FIRST集合、FOLLOW集合以及LL(1)文法
預測分析表中我們爲了兩個字符串作爲兩維表的索引,利用pandas中的DataFrame存儲表格信息。
dfData = [[[] for i in range(len(vt))] for i in range(len(vn))]
M = pd.DataFrame(data = dfData,index=vn,columns=vt)
# print(M)
# print(M.loc['E']['+'])
def getM():
#step1
for curPro in productions:
A = curPro[0]
dirFirst = getDirFirst(curPro)
# print(A)
# print(dirFirst)
for a in dirFirst:
if a=='epsilon':
continue
M.loc[A][a].append(curPro)
#step2
for curPro in productions:
A = curPro[0]
dirFirst = getDirFirst(curPro)
# print(curPro)
# print(' ',dirFirst)
if 'epsilon' in dirFirst:
for b in follow[A]:
M.loc[A][b].append(curPro)
getM()
print(M)
運行結果爲:
id ( ) + \ * epsilon $
E [[E, T, E']] [[E, T, E']] [] [] [] [] []
T [[T, F, T']] [[T, F, T']] [] [] [] [] []
E' [] [] [[E', epsilon]] [[E', +, T, E']] [] [] [[E', epsilon]]
T' [] [] [[T', epsilon]] [[T', epsilon]] T [[T', *, F, T']] [] [[T', epsilon]]
F [[F, id]] [[F, (, E, )]] [] [] [] [] []