上篇文章中,我已經說到了,lr(0)分析表是lr(0)分析器的重要組成部分,它是總控程式分析動作的依據,他是由lr(0)專案集規範族來進行
構造的。他的結構主要有兩個部分action 和goto
先看看指導原則,可以直接跳過,看例題的時候可以返回來對照參考。
假設已構造出lr(0)專案集規範族為:c=,其中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)專案集規範族中有如下專案集合:
即存在移進-歸約衝突和歸約-歸約衝突
* 如果follow(a)∩ follow(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,此處規則中的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」。到此解釋完了
反覆運用,直到填完表。
完成後的表如圖一所示。太複雜了。腦子燒糊了都,下篇有機會的話介紹如何使用來進行分析。其實剩下的部分不怎麼難了。應該可以看得懂了
參考:
LR語法分析 LR(0) SLR(1)
概述 lr 分析法是一種自下而上進行規範歸約的語法分析法,l指從左到右掃瞄輸入符號串,r是指構造最右推導的逆過程。對大多數無二義性上下文無關文法描述的語言都可用它進行有效的分析。主要分析器有lr 0 slr 1 lr 1 lalr 1 lr 0 在分析的每一步,只需根據當前棧頂狀態而不必向前檢視輸入...
LR(0)文法的分析
include include include include include include include include include include include include include using namespace std typedef long long ll const...
編譯原理 LR分析(主要是LR(0)分析)
lr方法的基本思想就是,在規範歸約的過程中,一方面要記住已移進和歸約出的整個字串,也就是說要記住歷史 一方面能夠根據所用的產生式的推測未來可能碰到的輸入符號,也就是說能夠對未來進行展望。這樣,當一串貌似控制代碼的字串出現在分析棧的頂部時,我們希望能夠根據歷史和展望以及現實的輸入符號這三部分的材料,決...