上一篇:編譯原理-用例題理解-自頂向下語法分析及 FIRST,FOLLOW,SELECT集,LL(1)文法html
本筆記是對教材《編譯原理》- 張晶老師版 作學習筆記。
本篇就是第 5 章的筆記。算法
自底向上語法分析數組
自底向上語法分析從待輸入的符號串開始,利用文法的產生式步步向上歸約,試圖歸約到文法的開始符號。數據結構
從語法樹的角度看異步
自底向上分析的過程是以輸入符號串做爲端末結點符號串,向着根結點的方向往上構造語法樹,是開始符號正好是該語法樹的根結點。工具
自底向上語法分析過程其實是一個不斷進行直接歸約的過程學習
移進-規約大意:設計
用一個寄存符號的先進後出棧,把輸入符號一個一個地移進到棧裏,當棧頂符號串造成可歸約串時(某個產生式的右部時),即把這個可歸約串替換成(歸約成)該產生式的左部的非終結符。code
自底向上語法分析法基本思想
自左向右地掃描輸入符號串,一遍把輸入符號逐個移進分析棧,一邊檢查分析棧的棧頂符號串是否已經造成了句柄(句柄就是每一個產生式的右部),若是造成句柄就把棧頂符號串替換爲相應產生式左部的非終結符號,這種替換就稱規約,再根據規約後的新棧頂,繼續掃描,移進,規約。htm
題目:
給定文法 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 分析法。
句柄就是每一個產生式的右部。
句柄具備 「最左」 特徵,這一點對於移進-歸約過程很重要。
由於:句柄的 「最左」 性和符號棧的棧頂是相關的。對於規範句型來講,句柄的後面不會出現非終結符號(即,句柄的後面只能是終結符)。
基於這一點,咱們能夠用句柄來刻劃 「可歸約串」。所以,規範歸約的實質是,在移進過程當中,當發現棧頂呈現句柄時,就用相應產生式的左部符號進行替換。
優先分析法是在文法的一些符號之間創建所謂的優先關係,它又能夠分爲簡單優先分析法 和 算符優先分析法
根據分析過程當中迄今已經取得的信息,並向前查看若干個輸入符號來肯定當前應採起的分析動做,及移進,規約,接受或報錯。
每實現異步規約都是把一串符號的用某個產生式的左部符號來代替,咱們能夠把棧頂上的這串符號成爲 「可規約串」。事實上,存在種種不一樣的方法刻畫 「可規約串」。
對這個概念的不一樣定義,也就造成了上述不一樣的自底向上的分析法。
還有一個概念須要理解,句型,一塊兒看。
句型的短語,直接短語定義:
若 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)每一個句型都有一個語法樹
(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)文法中的任意兩個產生式沒有相同的右部(惟一性)
簡單優先關係矩陣
對上面例題,作出簡單優先關係矩陣
(圖片來自教材:《編譯原理》張晶老師版)
簡單優先分析法定義:
對簡單優先文法的分析方法就是簡單優先分析法。
簡單優先分析法的侷限性:
簡單優先分析法只適應於簡單優先文法。實際上,通常的程序設計語言的文法都不是簡單優先文法。
因此,雖然簡單優先分析法準確、規範,但分析效率較低,並且實際使用價值不大,更多能夠看書,此處再也不描述
算符優先分析法是一種古典又實用的方法。
簡單優先分析法 規定了文法符號間 (非終結符 VN 和終結符 VT) 的優先順序和結合性質,而後藉助這種優先關係和結合順序來尋找可歸約串(句柄)進行歸約。
算符優先分析法 規定了算符間 (終結符 VT) 的優先順序和結合性質,而後藉助這種優先關係和結合順序來尋找可歸約串(最左素短語)進行歸約。
通俗的說,算符優先分析法藉助於終結符之間的優先關係肯定可歸約串。因爲它不考慮非終結符之間的優先級關係,並且在規約過程當中只要找到句柄就規約,並不考慮規約到哪一個非終結符,於是算符優先規約並非規範規約,確切的說,可規約串是最左素短語,而不是句柄。
特別有利於表達式分析,宜於手工實現。
可是它能力不強,僅能對算符優先文法進行分析。
算符優先分析法的分析過程是一種自下而上的歸約過程,但這種歸約未必是嚴格的最左歸約。即 算符優先分析法不是一種規範歸約法。
使用工具: 優先表、總控程序、棧
定義算符優先分析法前,先定義算法文法。
算符文法定義
若在上下文無關文法 G 中,不含 ε-產生式,且不含形如 U → …AB…的產生式,則稱 G 爲算符文法,也稱 OG 文法 (Operater Grammar)
算符文法要知足:
算符優先分析法中,要利用 終結符 之間的 優先關係 來找出句柄,因此要先給出終結符之間存在的三種優先關係。
(圖片來自教材:《編譯原理》張晶老師版)
用語法樹表示:
題目:
對於文法 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)
題目:
對於文法 G(E): (1)E -> E+T|T (2)T -> T*F|F (3)F -> (E)|i
結果:
具體說一下怎麼來的,
第一個 FIRSTVT(E) 集
上面爲了容易理解,分開寫,但不直觀,同理也能夠根據 LASTVT 集規則計算出 LASTVT 集。
在這裏插入圖片描述 素短語是知足下面條件的短語:
最左素短語:
處於句型最左邊的那個素短語
算符優先分析算法就是根據 最左素短語 的定理構造的
工做原理: 對當前句型不斷尋找最左素短語進行歸約的過程。尋找最左素短語時,首先找到最左素短語的末尾終結符,而後再向前搜索最左素短語的首終結符。
使用的數據結構: 棧,數組。
有關約定:#做爲語句括號,視爲終結符,其優先級最低。
算符優先分析 比規範歸約要快得多,由於它跳過了全部單個非終結符的歸約。
忽略非終結符的歸約 在歸約過程當中存在某種 危險性,可能致使把原本不是文法句子的輸入串誤認爲是文法的句子,即會把錯誤的句子獲得正確的歸約。
兩個算法相似,所不一樣的是 算符優先分析算法 每一步歸約 不必定是規範歸約,而是找出最左素短語進行歸約,而且在尋找最左素短語的過程當中,只比較終結符之間優先關係,不受非終結符的影響
比較表格:
- | 簡單優先分析法 | 算符優先分析法 |
---|---|---|
語法分析類別 | 自上而下分析 | 自下而上分析 |
可規約串 | 句柄 | 最左素短語 |
肯定可規約串的根據 | 任意兩文法符號之間的簡單優先關係 | 任意兩終結符之間的算符優先關係 |
效率比較 | 效率較低 | 只考慮終結符,效率較高 |