上篇文章中,我已經說到了,LR(0)分析表是LR(0)分析器的重要組成部分,它是總控程序分析動作的依據,他是由LR(0)項目集規范族來進行構造的。他的結構主要有兩個部分ACTION 和GOTO
先看看指導原則,可以直接跳過,看例題的時候可以返回來對照參考。
假設已構造出LR(0)項目集規范族為:C={I0,I1, … , In},其中Ik為項目集的名字,k為狀態名,令包含S′→·S項目的集合Ik的下標k為分析器的初始狀態。那么分析表的ACTION表和GOTO表構造步驟為:
① 若項目A→α·aβ屬於Ik且轉換函數GO(Ik,a)= Ij,當a為終結符時則置ACTION[k,a]為Sj。
② 若項目A→α· 屬於Ik,則對任何終結符a 和’#'號置ACTION[k,a]和ACTION[k,#]為”rj”,j為在文法G′中某產生式A→α的序號。
③ 若GO(Ik,A)=Ij,則置GOTO[k,A]為”j”,其中A為非終結符。
④ 若項目S′→S·屬於Ik,則置ACTION[k,#]為”acc”,表示接受。
⑤ 凡不能用上述方法填入的分析表的元素,均應填上”報錯標志”。為了表的清晰我們僅用空白表示錯誤標志。
上篇文章的例題是這樣的:LR(0)項目集規范簇也已經算出來了,共有6個I,從I0-I5,最終構造的LR(0)的分析表共7行,包括標題行,也就是ACTION和GOTO,然后是狀態行,狀態行和ACTION的交處分割成三列,分別是終結符號,和#終結符。也就是分割多少列取決於終結符的數目,GOTO列是非終結符,分割多少列也取決於非終結符的數目。,然后就是具體的6個狀態了,畫出表的結構后,如下,先不用管表的內容怎么寫。
然后對照構造原則來填寫表,這時你會發現要一個個從那么多的GO函數和I項目組中找對應的式子實在太難了,看不清楚,這時候,我們用GO函數把LR(0)項目集規范族連成一個識別該文法所產生的活前綴的DFA,有點像流程圖了,首先把各個I項目畫出來,然后需要把他們的關系表示出來,關系由GO函數確定,比如I5=GO(I2, S),則在I2和I5之間畫一個箭頭,由I2指向I5,線上寫上S,由括號里的第二個值確定,此題構造的DFA如下圖,很簡單吧。
然后我們正式開始吧。第一條指導規則說到, 若項目A→α·aβ屬於Ik且轉換函數GO(Ik,a)= Ij,當a為終結符時則置ACTION[k,a]為Sj,我們先考察對於I0,發現S->·aS屬於I0,且GO(I0,a)=I1,所有我們ACTION[0,a]置為S1.同理S->·bS屬於I0,GO(I0,b)=I2,所以ACTION[0,b]置為S2。
再來看第二條規則,若項目A→α· 屬於Ik,則對任何終結符a 和’#'號置ACTION[k,a]和ACTION[k,#]為”rj”,j為在文法G′中某產生式A→α的序號,也就是說這里的j可不是I項目的標號,而是增廣文法
(0)S’→S
(1)S→aS
(2)S→bS
(3)S→a
的標號,從0-3啦。我們考察I1,發現S→·aS屬於I1,且GO(I1,a)=I1,所以應該置1和a的交的格子為S1,但是此時運用第二條規則會發現S->a·也屬於I1,則又應該置ACTION[1,a]為=r3,ACTION[1,#]為r3,這樣就發生了沖突。這是因為大多數文法不能滿足LR(0)文法的條件,對於此沖突,我們不能確定看到S->a的時候是規約還是移進,有些文法是可以直接構造的,為此,此處不能夠早LR(0)分析表了,我們構造經過改進后得到了一種新的SLR(1)文法,並沒有什么太大差別,主要就是解決沖突。
解決沖突的指導原則如下:
* 假設一個LR(0)項目集規范族中有如下項目集合:
{X → α.bβ,A → γ.,B → δ.}
即存在移進-歸約沖突和歸約-歸約沖突
* 如果FOLLOW(A)∩ FOLLOW(B)∩ {b} =ф,則可以如下來解決沖突(假設當前符號是 a ):
1、若 a = b,則移進
2、若 a∈ FOLLOW(A),則用產生式 A → γ歸約
3、若 a∈ FOLLOW(B),則用產生式 B → δ歸約
4、否則,報錯
此處的沖突發生時,當前符號是a,並且此時項目集中無B推導式,且指導規則中的b在此處其實是S->.aS中的a,所以計算Follow(S)∩ {a} ,發現為空,所以可以解決沖突,因為此時,當前符號是a,此處規則中的b也是a,所以,移進,也就是置ACTION[1,a]為=S1,運用分析表的ACTION表和GOTO表構造步驟的第一步,而不是置為r3,所以沖突解決。
然后再看構造步驟中的第三步,若GO(Ik,A)=Ij,則置GOTO[k,A]為”j”,其中A為非終結符。此題中,只有S為非終結符,看DFA中的I0,發現GO(I0,S)=I3,所以置GOTO[0,S]為3,ok
第四個步驟,若項目S′→S·屬於Ik,則置ACTION[k,#]為”acc”,很簡單,DFA中,I3符合,所以置ACTION[3,#]為”acc”。到此解釋完了
反復運用,直到填完表。
完成后的表如圖一所示。太復雜了。腦子燒糊了都,下篇有機會的話介紹如何使用來進行分析。其實剩下的部分不怎么難了。應該可以看得懂了
我的網站中的原文鏈接:http://leaver.me/archives/574.html
參考:
http://metc.gdut.edu.cn/compile/nandian/n-7.htm
http://jpkc.hdu.edu.cn/computer/byyl/online/4-3.htm