《編譯原理》-用例題理解-自底向上的語法分析,FIRSTVT,LASTVT集
上一篇:編譯原理-用例題理解-自頂向下語法分析及 FIRST,FOLLOW,SELECT集,LL(1)文法
本筆記是對教材《編譯原理》- 張晶老師版 做學習筆記。
本篇就是第 5 章的筆記。
(一)自底向上的語法分析概述
自底向上語法分析
自底向上語法分析從待輸入的符號串開始,利用文法的產生式步步向上歸約,試圖歸約到文法的開始符號。
從語法樹的角度看
自底向上分析的過程是以輸入符號串作為端末結點符號串,向着根結點的方向往上構造語法樹,是開始符號正好是該語法樹的根結點。
自底向上語法分析過程實際上是一個不斷進行直接歸約的過程
移進-規約大意:
用一個寄存符號的先進后出棧,把輸入符號一個一個地移進到棧里,當棧頂符號串形成可歸約串時(某個產生式的右部時),即把這個可歸約串替換成(歸約成)該產生式的左部的非終結符。
自底向上語法分析法基本思想
自左向右地掃描輸入符號串,一遍把輸入符號逐個移進分析棧,一邊檢查分析棧的棧頂符號串是否已經形成了句柄(句柄就是每個產生式的右部),如果形成句柄就把棧頂符號串替換為相應產生式左部的非終結符號,這種替換就稱規約,再根據規約后的新棧頂,繼續掃描,移進,規約。
例題:移進-規約
題目:
給定文法 G[S]:
(1)S -> aABe
(2)A -> b
(3)A -> Abc
(4)B -> d
解析:
步驟: 1 2 3 4 5 6 7 8 9 10
動作: 進 進 歸 進 進 歸 進 歸 進 歸
a b (2) b c (3) d (4) e (1)
執行時,首先分析棧中會存放 # 到棧底,圖上沒有體現出來,應該在 a 的下面加上 #,將余留輸入串最左邊的字符放在分析棧棧首,此時棧中為 a,分析上面 4 句文法,文法的右部沒有完全匹配的,所以沒有構成句柄。
此時,繼續移進第二個輸入符號 b,此時棧頂的 b 與文法的(4)產生式的右部匹配,用 A -> b 規約,得到棧中為 aA
然后移進 b,c,用文法的(3)產生式進行規約。
直到最后 aABe,用產生式(1)規約出 S 開始符號,接受。
用表格表示:
(圖片來自教材:《編譯原理》張晶老師版)
用樹型表示:
每一次規約就相當於構造一顆子樹,指導輸入串結束時,構造成整個語法樹。
(圖片來自教材:《編譯原理》張晶老師版)
關於規范規約
首先,自底向上的分析的移進 - 規約過程是自頂向下最右推導的逆過程。
怎么理解呢?
最右推導是每次先推導最右邊的非終結符,自頂向下的最右推導就是從開始符號開始,每次執行最右推導,推出輸入符號串,最右推導是先推出輸入串最右端的終結符,最后推出最左端的終結符。
那逆過程就是從輸入符號串開始,每次先從最左端的終結符推導,最后推出開始符號。也就是自底向上的分析的移進 - 規約過程。
理解這句話之后,因為最右推導被稱為規范推導,那么自左向右的規約則稱為規范規約。
關於句柄
歸約過程中,當句柄出現在棧頂符號串時,則用句柄歸約。所以關鍵是在分析過程中如何確定句柄。
尋找句柄的方法不同,也就形成了不同的自底向上分析法。我們將介紹兩種不同的方法,分別是優先分析法和 LR 分析法。
句柄就是每個產生式的右部。
句柄具有 “最左” 特征,這一點對於移進-歸約過程很重要。
因為:句柄的 “最左” 性和符號棧的棧頂是相關的。對於規范句型來說,句柄的后面不會出現非終結符號(即,句柄的后面只能是終結符)。
基於這一點,我們可以用句柄來刻划 “可歸約串”。因此,規范歸約的實質是,在移進過程中,當發現棧頂呈現句柄時,就用相應產生式的左部符號進行替換。
優先分析法
優先分析法是在文法的一些符號之間建立所謂的優先關系,它又可以分為簡單優先分析法 和 算符優先分析法
LR 分析法
根據分析過程中迄今已經取得的信息,並向前查看若干個輸入符號來確定當前應采取的分析動作,及移進,規約,接受或報錯。
可歸約串
每實現異步規約都是把一串符號的用某個產生式的左部符號來代替,我們可以把棧頂上的這串符號成為 “可規約串”。事實上,存在種種不同的方法刻畫 “可規約串”。
對這個概念的不同定義,也就形成了上述不同的自底向上的分析法。
- 優先分析法
- 簡單優先分析法(句柄)
- 算符優先分析法(最左素短語)
即在 算符優先分析 中,我們用 “最左素短語” 來刻畫 “可規約串”
- LR分析法(句柄)
(二)短語,直接短語,句柄
還有一個概念需要理解,句型,一起看。
句型的短語,直接短語定義:
若 S 是文法 G 的開始符號,αβδ 是該文法的一個 句型(能通過這個文法推導出來),即 S =*> αβδ,其中 α,δ ∈ V*,β ∈ V+。
如果有 S =*> αβδ 且 A=+>β,其中 A ∈ VN,則稱 β 是句型 αβδ 相對於非終結符 A 的 短語。
另外,如果滿足 S=*>αβδ,且 A -> β 是文法 G 的一個產生式,則稱 β 是句型 αβδ 相對於非終結符 A 的 直接短語。
句型的句柄定義:
在一個句型中可以有多個直接短語,位於句型 最左邊的直接短語 就稱為 句柄。
例題:找短語,直接短語,句柄
題目:
給定文法:
(1)T -> T*F
(2)F -> F↑P|P
(3)P -> (T)|a
對於句型 T*P↑(T*F)
解析:
(1)根據 T =*> T*P↑(T) 和 T =*> T*F(即產生式1),可知 T*F 是該句型的 相對於 T 的 直接短語。
(2)根據 T =*> T*P↑P(由產生式1和2推出) 和 P =*> (T*F)(由產生式1和3推出),可知 (T*F) 是該句型的 相對於 F 的短語。
(3)根據 T =*> T*F↑(T*F) 和 F => P,可知 P 是該句型的 相對於 F 的 直接短語。
(4)根據 T =*> T*F 和 F =*> P↑(T*F),可知 P↑(T*F) 是該句型的 相對於 F 的短語。
(5)根據 T =*> T 和 T =*> T*P↑(T*F),可知 T*P↑(T*F) 是該句型的 相對於 T 的 短語。
綜上,T*P↑(T*F) 共有 5 個短語,其中兩個是直接短語,由於直接短語 P 是句型的最左直接短語,所以 P 是句型的 句柄。
通俗的說一下,上面 5 個短語的兩個條件能推出該句型,可以看出來。那么條件又是怎么來的呢?怎么知道怎么划分短語呢?這個就是通過句型和文法中個各個產生式來推,但這樣很不直觀,也容易漏。
怎么更快的找出所有短語,直接短語和句柄呢?
找出所有短語,直接短語和句柄,一種方法是根據定義尋找,顯然,這種方法不直觀,而且很難知道是否已窮盡所有情況;
另一種方法是利用語法樹,首先為給定句型構造一顆語法樹然后利用這棵語法樹就可以找出該句型全部的短語,直接短語和句柄。
還對上題分析,使用語法樹分析:
(圖片來自教材:《編譯原理》張晶老師版)
從底向上看,找子樹
(1)T -> T*F
(2)P -> (T*F)
(3)F -> P
(4)F -> P↑(T*F)
(5)T -> T*P↑(T*F)
再根據文法中的產生式判斷:
- 直接短語(文法中包含產生式),有子樹(1),子樹(3),就是說他倆為直接短語
- 句柄(最左直接短語),比較(1)和(3)誰在左邊
對語法樹的剪枝方法
(1)每個句型都有一個語法樹
(2)每個語法樹(整棵樹)的端末結點自左向右排列就組成一個 句型
(3)每棵 子樹的端末結點 自左向右排列就組成一個 短語
(4)每棵 簡單子樹的端末結點 自左向右排列就組成一個 直接短語
(5)最左簡單子樹的端末結點自左向右排列就組成一個 句柄
(三)簡單優先分析法
優先分析法分為:
- 簡單優先分析法(句柄)
- 算符優先分析法(最左素短語)
簡單優先分析法是一種典型的 自底向上 的分析法,它符號串進行語法分析的過程是一個 規范規約 的過程。
它首先對文法 按一定規則 求出 所有符號(即終結符和非終結符) 之間的 優先關系,然后在分析過程中根據文法符號之間的 簡單優先關系 來尋找符號串中可以進行規約的子串(即句柄)來進行規約。
簡單優先文法
由於簡單優先分析法是按照文法符號之間的 優先關系 來確定句柄的,所以首先要介紹兩個文法符號之間存在的優先關系,然后介紹優先關系是 怎樣確定的 和 如何構造關系表。
三種簡單優先關系:
在簡答優先文法中,兩個文法符號之間可以是下述三種優先關系之一:
注意:
上面所引入的是三種優先關系都是對文法中的符號序偶來定義的,這三種關系和數學中的 =,<,> 不同,它們是有序的,就是不滿足交換律,即
Si <· Sj 不一定有 Sj <· Si
詳細:
(1)第一種關系 - Si 和 Sj 優先級相同
(2)第二種關系 - Si 的優先級低於 Sj
(3)第三種關系 - Si 的優先級高於 Sj
(4)第四種關系 - 不存在優先關系。這個上面沒有體現。
例題:已知文法,求優先關系
題目:
給定文法:
(1)S -> (R)|A|∧
(2)R -> T
(3)T -> S,T|S
注意:(3)中的逗號是終結符
求文法符號之間的優先關系:
解析:
為了更好理解,直接上截圖,注意逗號的理解,並列逗號和終結符中的逗號。
簡單優先文法定義:
簡單文法是滿足以下條件的文法:
(1)在文法字匯表中,任意兩個符號之間至多存在一種簡單優先關系
(2)文法中的任意兩個產生式沒有相同的右部(唯一性)
簡單優先關系矩陣
對上面例題,做出簡單優先關系矩陣
(圖片來自教材:《編譯原理》張晶老師版)
簡單優先分析法定義:
對簡單優先文法的分析方法就是簡單優先分析法。
簡單優先分析法的局限性:
簡單優先分析法只適應於簡單優先文法。實際上,一般的程序設計語言的文法都不是簡單優先文法。
所以,雖然簡單優先分析法准確、規范,但分析效率較低,而且實際使用價值不大,更多可以看書,此處不再描述
(四)算符優先分析法
算符優先分析法是一種古典又實用的方法。
算符優先文法(OPG文法)定義
簡單優先分析法 規定了文法符號間 (非終結符 VN 和終結符 VT) 的優先順序和結合性質,然后借助這種優先關系和結合順序來尋找可歸約串(句柄)進行歸約。
算符優先分析法 規定了算符間 (終結符 VT) 的優先順序和結合性質,然后借助這種優先關系和結合順序來尋找可歸約串(最左素短語)進行歸約。
通俗的說,算符優先分析法借助於終結符之間的優先關系確定可歸約串。由於它不考慮非終結符之間的優先級關系,而且在規約過程中只要找到句柄就規約,並不考慮規約到哪個非終結符,因而算符優先規約並不是規范規約,確切的說,可規約串是最左素短語,而不是句柄。
特別有利於表達式分析,宜於手工實現。
但是它能力不強,僅能對算符優先文法進行分析。
算符優先分析法的分析過程是一種自下而上的歸約過程,但這種歸約未必是嚴格的最左歸約。即 算符優先分析法不是一種規范歸約法。
使用工具: 優先表、總控程序、棧
定義算符優先分析法前,先定義算法文法。
算符文法定義
若在上下文無關文法 G 中,不含 ε-產生式,且不含形如 U → …AB…的產生式,則稱 G 為算符文法,也稱 OG 文法 (Operater Grammar)
算符文法要滿足:
- 不含ε-產生式;
- 產生式右部不包含兩個相鄰非終結符
算符優先分析法中,要利用 終結符 之間的 優先關系 來找出句柄,所以要先給出終結符之間存在的三種優先關系。
(圖片來自教材:《編譯原理》張晶老師版)
用語法樹表示:
例題:判斷 G 是否是 OPG 文法
題目:
對於文法 G(E):
(1)E -> E+T|T
(2)T -> T*F|F
(3)F -> (E)|i
(1)判斷 G 是否是 OG 文法(算符文法);
(2)再找出 G 中所有終結符對的優先關系;
(3)最后判斷 G 是否是 OPG 文法(算符優先文法)
解析:
(1)判斷 G 是否是 OG 文法(算符文法),根據算符文法要滿足:
- 不含ε-產生式;
- 產生式右部不包含兩個相鄰非終結符
(2)再找出 G 中所有終結符對的優先關系,得出優先關系表
具體怎么構造關系表,在下面有提
(圖片來自教材:《編譯原理》張晶老師版)
(3)最后判斷 G 是否是 OPG 文法(算符優先文法)
由於對於 G(E) 的任何終結符對(a,b)至多只有一種優先關系成立,即優先關系表中不存在多重入口,所以,文法 G(E) 是一個算符優先文法
優先關系表的構造
由定義構造缺乏可操作性。所以選擇由算法構造。
為了找出所有優先關系,使得優先關系表沒有疏漏,要對 G 的每個非終結符 T 構造兩個集合:FIRSTVT集(最左終結符集),LASTVT集(最右終結符集)
FIRSTVT 集,LASTVT 集定義:
FIRSTVT(T) 的構造規則(必背)
(1)若有 T→a… 或 T→Ra…,則 a∈FIRSTVT(T);
(2)若 a∈FIRSTVT(R),且有產生式 T→R…,則 a∈FIRSTVT(T)
LASTVT(T) 的構造規則(必背)
(1)若有 T→…a 或 T→…aR,則 a∈LASTVT(T);
(2)若 a∈LASTVT(R),且有產生式 T→…R,則 a∈LASTVT(T)
例題:求 FIRSTVT,LASTVT 集
題目:
對於文法 G(E):
(1)E -> E+T|T
(2)T -> T*F|F
(3)F -> (E)|i
結果:
具體說一下怎么來的,
第一個 FIRSTVT(E) 集
- 由文法(1)和規則(1)得出 + ∈ FIRSTVT(E)
- 由文法(2)和規則(1)得出 * ∈ FIRSTVT(T)
- 由文法(1)和規則(2)得出 * ∈ FIRSTVT(E)
- 由文法(3)和規則(1)得出 ( ∈ FIRSTVT(F)
- 由文法(2)和規則(2)得出 ( ∈ FIRSTVT(T)
- 由文法(1)和規則(2)得出 ( ∈ FIRSTVT(E)
- 由文法(3)和規則(1)得出 i ∈ FIRSTVT(F)
- 由文法(2)和規則(2)得出 i ∈ FIRSTVT(T)
- 由文法(1)和規則(2)得出 i ∈ FIRSTVT(E)i
上面為了容易理解,分開寫,但不直觀,同理也可以根據 LASTVT 集規則計算出 LASTVT 集。
素短語
在這里插入圖片描述 素短語是滿足下面條件的短語:
- 至少包含一個終結符。
- 該短語不再包含滿足第一個條件的更小的短語。
最左素短語:
處於句型最左邊的那個素短語
算符優先分析算法就是根據 最左素短語 的定理構造的
算符優先分析算法的實現
工作原理: 對當前句型不斷尋找最左素短語進行歸約的過程。尋找最左素短語時,首先找到最左素短語的末尾終結符,然后再向前搜索最左素短語的首終結符。
使用的數據結構: 棧,數組。
有關約定:#作為語句括號,視為終結符,其優先級最低。
算符優先分析的局限性
算符優先分析 比規范歸約要快得多,因為它跳過了所有單個非終結符的歸約。
忽略非終結符的歸約 在歸約過程中存在某種 危險性,可能導致把本來不是文法句子的輸入串誤認為是文法的句子,即會把錯誤的句子得到正確的歸約。
總結
算符優先分析算法與簡單優先分析算法的比較
兩個算法類似,所不同的是 算符優先分析算法 每一步歸約 不一定是規范歸約,而是找出最左素短語進行歸約,並且在尋找最左素短語的過程中,只比較終結符之間優先關系,不受非終結符的影響
比較表格:
- | 簡單優先分析法 | 算符優先分析法 |
---|---|---|
語法分析類別 | 自上而下分析 | 自下而上分析 |
可規約串 | 句柄 | 最左素短語 |
確定可規約串的根據 | 任意兩文法符號之間的簡單優先關系 | 任意兩終結符之間的算符優先關系 |
效率比較 | 效率較低 | 只考慮終結符,效率較高 |