編譯原理中LR 0 專案集規範族的構造

2021-08-19 02:08:52 字數 3247 閱讀 2501

lr的第乙個l和ll的第乙個l含義相同,即從左到右掃瞄句子 ,第二個r表示right most最右推導。

在通常的描述中,後面還有乙個括號裡面的數字如,lr(0)、lr(1)這樣,括號裡面的數字表示用於決策所需的後續token分詞數。

首先看一下lr分析器的模型圖

可惜看出,lr分析器最關鍵的部分就是 lr分析表了,而lr分析表的構建是由已構造出的lr(0)專案集規範族來進行構造的。lr分析法貌似是不要求掌握的,而且這部分比我想象的還要複雜,今天看了好多。才勉強搞清楚這個專案集規範族的構造,但是用來鍛鍊思維確實不錯啊。

專案集,那麼字面上看就是專案的集合了,專案是什麼呢。這個也確實不好說,書上是說在文法g中每個產生式的右部適當位置新增乙個圓點構成lr(0)專案,舉個例子吧。

比如對於

a->xyz

這條產生式可以構造的lr(0)專案就有4個

a->.xyz    a->x.yz    a->xy.z     a->xyz.

這樣很清楚了吧,就是用.分割。這個分割產生的四個專案在進行真正的語法分析的時候對應不同的操作,比如規約還是移位。這裡不討論。重點是專案集規範族的構造,

在知道了lr(0)專案後,可以來看看專案集規範族的定義,

對於構成識別乙個文法活字首的dfa專案集(狀態)的全體我們稱之為這個文法的lr(0)專案集規範族。至於什麼是活字首呢,定義如下

對於任一文法g[s],若s』經過任意次推導得到αaω,繼續經過一次推導得到αβω,若γ是αβ的字首,則稱γ是g的乙個活字首。

現在知道了lr(0)專案,了解了活字首,和專案集規範族的定義,還須引入lr(0)專案集的閉包函式closure和狀態轉換函式go兩個概念,先給出數學上的定義,如果你覺得麻煩可以跳過,後面會給出一道例題。

① 閉包函式closure(i)的定義如下:

a)i的專案均在closure(i)中。

b)若a→α·bβ屬於closure(i),則每一形如b→·γ的專案也屬於closure(i)。

c)重複b)直到不出現新的專案為止。即closure(i)不再擴大。

② 轉換函式go(i,x)的定義:

go(i,x)=closure(j)

其中:i為包含某一項目的狀態,就是前面我們說的那四個了。,x為一文法符號,x∈(vn∪vt),j=。

這樣就可以使用閉包函式和轉換函式構造文法g′的lr(0)專案集規範族,其步驟如下:

a)置專案s′→·s為初態集的核,然後對核求閉包,closure()得到初態的專案集。

b)對初態集或其它所構造的專案集應用轉換函式go(i,x)=closure(j),求出新狀態j的專案集。

c)重複b)直到不出現新的專案為止。

開始拿個例題來說明,定義沒例題看起來看難了。

例題:對於下列文法,s→as|bs|a,構造該文法的lr(0)專案集規範族

思路就是利用閉包函式closure和轉換函式go來構造。通過計算函式closure和go得到文法的lr(0)專案集規範族,而go函式則把lr(0)專案集規範族連成乙個識別該文法所產生的活字首的dfa。dfa大家都知道,有窮自動機。

(1)將文法g(s)拓廣為g(s』)也就是該文法的增廣文法,目的是使語法分析器知道何時應該停止並接受該串,也就是說當使用s'->s進行規約的時候,就結束。

(0)s』→s

(1)s→as  

(2)s→bs  

(3)s→a

構造該文法的lr(0)專案集規範族,i就是產生式,至於i0 i1就是往下遞增就可以了。沒什麼特別的意思。:

i0=closure()=

//第一條是固定的,都是求s' →•s的閉包。而因為右側的s又可以推導出後面三個,所以後面三個式子是屬於該閉包的。在閉包的規則中可以看出,若a→α·bβ屬於closure(i),此時s' →•s屬於閉包,s相當於規則中的b,則每一形如b→·γ的專案也屬於closure(i),此處相當於s->後面的三個推導式。加上.就可以了

i1=go( i0 , a)=closure()=

//第二條你可能已經看出來了,其實就是把轉換函式go反過來用,在go函式中,x為一文法符號,j=。也就是在i0中,找到右側包含a的專案,然後將.右移一位來求他們的閉包函式,此處,i0中包含.a的專案為 s→•as和 s→•a,.右移一位變成s→a•s , s→a•,求閉包函式的規則和上面那條是一樣的,繼續找推導式右邊可以推導出來的式子就可以了,此處,右邊同樣是s可以推導出三個式子,前面加上.就可以了。

i2=go(i0 , b)=closure()=

//第三條仿照第二條進行推導,先在i0中找有.b的,然後右移一位,然後推導式右側的s繼續用題目給出的推導,然後前面加上.

i3=go(i0 , s)=closure()=

//第四條因為右側包含.s的只有一項。必須是.s。所以只有乙個,右移後求閉包即可。因為s是右側的第一位,所以不用再向下推導了,規則是:a→α·bβ屬於closure(i),此處是s』 →s•,則b→·γ的專案也屬於closure(i),此處s相當於規則中的α,無b。。。。

因為go(i1, a)=closure()=i1,

//第五條同理,在i1中找有右側有.a的專案,右移一位。進行求閉包,發現和i1求閉包的變數是一樣的。所以結果必然也和i1是一樣的。

go(i1, b)=closure(s→b•s)=i2.

//第六條沒有新的i產生。

i4=go(i1, s)=closure()=

//這第七條在i1找右側包含.s的專案,只有s→a•s,右移後求閉包,同第四條,無b,所以直接如此。

go(i2, a)= closure()=i1

go(i2, b)=closure()=i2

i5=go(i2, s)=closure()=

此時應該繼續求go(i3, a),go(i3, b)和,go(i3, s),但顯然i3中沒有.a,沒有.b也沒有.s,所以不用多此一舉了,

繼續求go(i4, a),go(i4, b)和,go(i4, s),顯然同上,也沒有。所以也不用求了,

繼續求go(i5, a),go(i5, b)和,go(i5, s),理由同上,沒有任何必要了

最終,專案集i0,i1,i2,i3,i4和i5構成了該文法的lr(0)專案集規範族。

編譯原理真是博大精深啊。就乙個簡單的三個推導式就得這麼多步驟才構造了乙個規範族,還要利用規範族來構造lr分析表,這。。手工果斷不是事啊。今天看了幾個小時才完全弄清楚lr(0)專案集規範族的構造。例題的步驟是我自己寫的。這篇文章寫了2個小時。。太費腦子了。。慢慢再寫產生活字首的dfa和lr分析表吧。

編譯原理中LR 0 專案集規範族的構造

此文略長。我也沒想到這寫起來這麼多,但對構造過程絕對清楚,一步步慢慢看吧。lr的第乙個l和ll的第乙個l含義相同,即從左到右掃瞄句子 第二個r表示right most最右推導。在通常的描述中,後面還有乙個括號裡面的數字如,lr 0 lr 1 這樣,括號裡面的數字表示用於決策所需的後續token分詞數...

編譯原理中LR 0 專案集規範族的構造

此文略長。我也沒想到這寫起來這麼多,但對構造過程絕對清楚,一步步慢慢看吧。lr的第乙個l和ll的第乙個l含義相同,即從左到右掃瞄句子 第二個r表示right most最右推導。在通常的描述中,後面還有乙個括號裡面的數字如,lr 0 lr 1 這樣,括號裡面的數字表示用於決策所需的後續token分詞數...

編譯原理LR 0 專案集規範族的構造詳解

學編譯原理的時候,感覺什麼ll 1 lr 0 slr 1 lalr 1 思想滿天飛。而且做題的時候,一不留意,一道題就寫了三頁紙了。就拿今天這個玩意兒來講,我真的是考試前花了最多的時間,搞懂了 差不多搞懂了 這是個什麼玩意兒。以下內容,做題的話應該夠了而且很!容!易!理!解!其他學術情況恕博主也是個...