編譯原理知識匯總
轉自:https://www.jianshu.com/p/eb63d31ad638
編譯原理
第一章 引言
1.從面向機器的語言到面向人類的語言
匯編指令:用符號表示的指令被稱為匯編指令
匯編語言:匯編指令的集合稱為匯編語言
2.語言之間的翻譯
轉換(也被稱為預處理):高級語言之間的翻譯,如FORTRAN
到ADA
的轉換
編譯:高級語言可以直接翻譯成機器語言,也可以翻譯成匯編語言,這兩個翻譯過程稱為編譯
匯編:從匯編語言到機器語言的翻譯被稱為匯編
交叉匯編:將一個匯編語言程序匯編成為可在另一機器上運行的機器指令成為交叉匯編
反匯編:把機器語言翻譯成匯編語言
反編譯:
3. 編譯器與解釋器
(1)語言翻譯的兩種基本形態
解釋器與編譯器的主要區別:運行目標程序時的控制權在解釋器
而不在目標程序.
(2)各自特點
- 編譯器:
工作效率高
,即時間快、空間省;交互性與動態性差,可移植性差
. - 解釋器:
工作效率低
,,即時間慢、空間費;交互性與動態性好,可移植性好
.
共同點:均完成對源程序
的翻譯.
差異:編譯器采用先翻譯後執行,解釋器采用邊翻譯邊執行.
4. 編譯器的工作原理與基本組成
(0)通用程序設計語言的主要成份 聲明+操作=完整定義
(1)以過程
為基本結構的程序設計語言的組成
- 聲明性語句:提供操作對象的性質,如數據類型、值、作用域等;
- 操作性語句:確定操作的計算次序,完成實際操作。
- 過程定義 = 過程頭+過程體
(2)以階段劃分編譯器
註:符號表管理器和出錯處理貫穿編譯器工作的各個階段.
(3)編譯器各階段工作
1> 詞法分析:詞法分析的輸入是源程序
,輸出是識別出的記號流
.目的是識別單詞
. 至少分以下幾類:關鍵字(保留字)、標識符、字面量、特殊符號
2> 語法分析: 輸入是詞法分析器返回的記號流
,輸出是語法樹
.目的是得到語言結構並以樹的形式表示.對於聲明性語句,進行符號表的查填,對於可執行語句,檢查結構合理的表達式運算是否有意義.
3> 語義分析:根據語義規則對語法樹中的語法單元進行靜態語義檢查,如類型檢查和轉換等,目的在於保證語法正確的結構在語義分析上也是合法的.
4> 中間代碼生成(可選):生成一種既接近目標語言,又與具體機器無關的表示,便於代碼優化與代碼生成.
(到目前為止,編譯器與解釋器可以一致)
5> 中間代碼優化(可選):局部優化、循環優化、全局優化等;優化實際上是一個等價變換,變換前後的指令序列完成同樣的功能,但在占用的空間上和程序執行的時間上都更省、更有效
6> 目標代碼生成:不同形式的目標代碼—匯編語言形式、可重定位二進制代碼形式、內存形式(Load-and-Go)
7> 符號表管理:合理組織符號,便於各階段查找\填寫等.
8> 出錯處理:
動態錯誤:源程序中的邏輯錯誤,發生在程序運行的時候。也稱為動態語義錯誤
靜態錯誤:靜態錯誤分為語法錯誤和靜態語義錯誤.
<1> 語法錯誤:有關語言結構上的錯誤,如單詞拼寫錯誤、表達式缺少操作數、begin和end不匹配
<2> 靜態語義錯誤:分析源程序時可以發現的語言意義上的錯誤,如加法的兩個操作數一個是整形變量,另一個是數組名
(4)編譯器的分析\綜合模式
邏輯上把編譯器分為分析(前端)部分
和綜合(後端)部分
.
1> 分析(前端):語言結構和意義的分析; 從詞法分析到中間代碼生成各階段的工作
2> 綜合(後端):語言意義處理;從中間代碼生成到目標代碼生成的各階段的工作
3> 編譯器和解釋器的區別往往是在形成中間代碼之後開始的.
5. 編譯器掃描的遍數
每個階段將程序完整分析一遍的工作模式稱為一遍掃描。
(將源程序或源程序的某種形式的中間表示完整分析一遍,亦稱作一遍掃描)
第二章 詞法分析
1. 詞法分析中的若幹問題
(1) 記號、模式與單詞
單詞的分類:關鍵字(保留字)、標識符、字面量、特殊符號
模式(pattern):產生/識別單詞的規則
記號(token):按照某個模式(或規則)識別出的元素(一組)
單詞(lexeme):被識別出的元素的值(字符串本身) ,也稱為詞值
(2) 詞法分析器的作用與工作方式
詞法分析器的作用:
1> 識別記號並交給語法分析器(根據模式識別記號)
2> 濾掉源程序中的無用成分,如註釋、空格和回車等
3> 處理與具體平臺有關的輸入(如文件結束符的不同表示等)
4> 調用符號表管理器和出錯處理器,進行相關處理
工作方式:
1.單獨一遍掃描
2.作為語法分析器的子程序
3.並行方式
2. 模式的形式化描述
(1) 字符串與語言
語言L是有限字母表∑上有限長度字符串的集合.
定義中強調兩個有限,因為計算機的表示能力有限 :
1> 字母表是有限的,即字母表中元素是有限多個;
2> 字符串的長度是有限的,即字符串中字符個數是有限多個。
(字符串與字符串集合相關的概念與運算,如前綴、後綴、子串、子序列等,字符串的並、交、連接、差、閉包)
(2) 正規式與正規集
令Σ是一個有限字母表,則Σ上的 正規式 及其表示的集合遞歸定義如下:
1. ε是正規式,它表示集合 L(ε) = {ε}
2. 若a是Σ上的字符,則a是正規式,它表示集合L(a)={a}
3. 若正規式r和s分別表示集合L(r)和L(s),則
(a) r|s是正規式,表示集合L(r)∪L(s),
(b) rs是正規式,表示集合L(r)L(s),
(c) r*是正規式,表示集合(L(r))*,
(d)(r)是正規式,表示的集合仍然是L(r)。
括弧用來改變運算的先後次序!
可用正規式描述(其結構)的語言稱為 正規語言 或 正規集 。
若運算的優先級和結合性做下述約定:
1. 三種運算均具有左結合性質;
2. 優先級從高到低順序排列為:閉包運算、連接運算、或運算。
則正規式中不必要的括號可以被省略。
若正規式P和Q表示了同一個正規集,則稱P和Q是等價的,記為P=Q
(3) 簡化正規式描述(主要是簡化書寫上的復雜)
(a) 正閉包 若r是表示L(r)的正規式,則r+是表示(L(r))+的正規式,且下述等式成立:r+ = rr* = rr,r = r+|ε;
+與*具有相同的運算結合性和優先級
(b) 可缺省 若r是正規式,則r?是表示L(r)∪{ε}的正規式,且下述等式成立:r? = r|ε
? 與 * 具有相同的運算結合性和優先級
(c) 串 若r是若幹字符進行連接運算構成的正規式,則:串“r” = r ,且: ε= “”, a = “a”(a是Σ的任一字符)
(d) 字符組 若r是若幹字符進行|運算構成的正規式,則可改寫為 [r’],其中r’可以有如下兩種書寫形式:
枚舉: 如 a|b|e|h,可寫為 [abeh]:
分段: 如0|1|2|3|4|5|6|7|8|9|a|b|c|d|e , 可寫為: [0-9a-e]
(e) 非字符組 若[r]是一個字符組形式的正規式,則[^r]是表示∑- L([r])的正規式。
3. 記號的識別——有限自動機
(1) 不確定的有限自動機(NondeterministicFinite Automaton, NFA)
NFA是一個五元組(5-tuple):M =(S,∑,move,s0,F),其中
(1) S是有限個狀態(state)的集合;
(2) ∑是有限個輸入字符(包括ε)的集合;
(3) move是一個狀態轉移函數,move(si,ch)=sj表示,當前狀態si下若遇到輸入字符ch,則轉移到狀態sj;
(4) s0是唯一的初態(也稱開始狀態);
(5) F是終態集(也稱接受狀態集),它是S的子集,包含了所有的終態。
<1> 直觀的表示方式
① 狀態轉換圖:用一個有向圖來直觀表示NFA
② 狀態轉換矩陣:用一個矩陣來直觀表示NFA (矩陣中,狀態對應行,字符對應列)
<2> NFA(識別記號)的特點
NFA識別記號的最大特點是它的不確定性,即在當前狀態下對同一字符有多於一個的下一狀態轉移。
具體體現:
定義: move函數是1對多的;
狀態轉換圖:從同一狀態出發,可通過多於一條標記相同字符的邊轉移到不同的狀態;
狀態轉換矩陣: M[si,a]是一個狀態的集合
<3> NFA識別記號存在的問題
1.只有嘗試了全部可能的路徑,才能確定一個輸入序列不被接受,而這些路徑的條數隨著路徑長度的增長成指數增長
2.識別過程中需要進行大量回朔,時間復雜度升高且算法復雜
(2) 確定的有限自動機(Deterministic Finite Automaton, DFA)
定義: DFA是NFA的一個特例,其中:
(1)沒有狀態具有ε狀態轉移(ε-transition),即狀態轉換圖中沒有標記ε的邊;
(2)對每個狀態s和每個字符a,最多有一個下一狀態。
特點:與NFA相比,DFA的特征:確定性
定義:move(si, a)函數都是 1對1 的;
轉換圖 從一個狀態出發的任2條邊上的標記均不同;
轉換矩陣:M[si,a]是一個狀態 且字母表不包括ε。
提示:正規式和有限自動機從兩個側面表示正規式。正規式是描述,自動機是識別。
4. 從正規式到詞法分析器
構造詞法分析器的一般方法和步驟:
1. 用正規式描述模式(為記號設計正規式);
2. 為每個正規式構造一個NFA,它識別正規式所表示的正規集;
3. 將構造的NFA轉換成等價的DFA,這一過程也被稱為確定化;
4. 優化DFA,使其狀態數最少,這一過程也被稱為最小化;
5. 根據優化後的DFA構造詞法分析器。
(1) 從正規式到NFA
Thompson 算法
(2) 從NFA到DFA
- smove(S, a):從狀態集S出發,標記為a的下一狀態全體。與move(s, a)的唯一區別:用狀態集取代狀態
- ε-閉包(T):從狀態集T出發,不經任何字符達到的狀態全體
- “子集法”構造DFA
(3) 最小化DFA
? ① 對於任何兩個狀態t和s,若從一狀態出發接受輸入字符串ω,而從另一狀態出發不接受ω.
或者,② 從t出發和從s出發到達不同的接受狀態,則稱ω對狀態t和s是可區分的.
? 不可區分的狀態位於一個組內,可以合並成一個狀態.
主要步驟:
? 1.初始劃分:終態組 , 非終態組;
? 2.利用可區分的概念,反復分裂劃分中的組Gi,直到不可再分裂;
? 3.由最終劃分構造D‘,關鍵是選代表和修改狀態轉移;
? 4.消除可能的死狀態和不可達狀態。
5. 從DFA構造詞法分析器
分類:表驅動型的詞法分析器;直接編碼的詞法分析器
比較:
表驅動 | 直接編碼 | |
---|---|---|
分析器的速度 | 慢 | 快 |
程序與模式的關系 | 無關 | 有關 |
適合的編寫方法 | 工具生成 | 手工編寫 |
分析器的規模 | 較大 | 較小 |
第三章 語法分析
詞法分析:記號的集合,字符串由字母組成,線性結構
語法分析:句子的集合,句子由記號組成,非線性結構(樹)
語法分析的雙重含義:
- 語法規則:上下文無關文法(子集:LL文法或LR文法)
- 語法分析:下推自動機(LL或LR分析器)、自上而下分析、自下而上分析
1. 語法分析的若幹問題
許多編譯器,特別是由自動生成工具構造的編譯器,往往其前端的中心部件就是語法分析器
(1)語法分析器的作用
- 根據詞法分析器提供的記號流,為語法正確的輸入構造分析樹(或語法樹)
- 檢查輸入中的語法(可能包括詞法)錯誤,並調用出錯處理器進行適
當處理
(2)語法錯誤的處理原則
源程序中可能出現的錯誤
語法(包括詞法)錯誤和語義錯誤(靜態語義錯誤和動態語義錯誤)
註:跟第一章的分類角度不同,第一章是從靜態錯誤(語法錯誤,靜態語義錯誤)和動態錯誤(動態語義錯誤)分類的,但是殊途同歸。
詞法錯誤:指非法字符或拼寫錯關鍵字、標識符等
語法錯誤:指語法結構出錯,如少分號、括號不匹配、begin/end不配對等
靜態語義錯誤:如類型不一致、參數不匹配等
動態語義錯誤(邏輯錯誤):如死循環、變量為零時作除數等
2. 上下文無關文法(CFG)
(1)上下文無關文法(Context Free Grammar,CFG)
CFG是一個四元組G =(N,T,P,S),其中
(1) N是非終結符(Nonterminals)的有限集合;
(2) T是終結符(Terminals)的有限集合,且N∩T=Φ;
(3) P是產生式(Productions)的有限集合,A→α,其中A∈N(左部),α∈(N∪T)*(右部),若α=ε,則稱A→ε為空產生式(也可以記為A →);
(4) S是非終結符,稱為文法的開始符號(Start symbol)
註: S ∈ N , N可以出現在產生式左邊和右邊,T絕不出現在產生式左邊.
(2)CFG產生語言的基本方法-推導
CFG(產生式)通過推導的方法產生語言,即(通俗地講)從開始符號S開始,反復使用產生式:將產生式左部的非終結符替換為右部的文法符號序列(展開產生式,用=>表示),直到得到一個終結符序列。
1> 直接推導:利用產生式產生句子的過程中,將用產生式A→γ的右部代替文法符號序列αAβ中的A得到αγβ的過程,稱αAβ直接推導出αγβ,記作:αAβ=>αγβ
2> 零步或多步推導:若對於任意文法符號序列α1,α2,...αn,有α1=>α2=>...=>αn,則稱此過程為零步或多步推導,記為:α1 =*> αn,其中α1=αn的情況為零步推導。
3> 至少一次推導:若α1≠αn,即推導過程中至少使用一次產生式,則稱此過程為至少一步推導,記為:α1 =+> αn
(推導具有自反性和傳遞性)
4> 由 CFGG 所產生的語言L(G)被定義為: L(G) = { ω┃S ωand ω∈T* },
? L(G)稱為上下文無關語言(Context Free Language, CFL),ω稱為句子。
? 若S =* > α,α∈(N∪T)*,則稱α為G的一個句型。句子一定是句型,反之不是。
5> 在推導過程中,若每次直接推導均替換句型中最左邊的非終結符,則稱為最左推導
,由最左推導產生的句型被稱為左句型
。 類似的可以定義最右推導與右句型,最右推導也被稱為規範推導。
(3)推導、分析樹與語法樹
1、分析樹既反映語言結構的實質,也反映推導過程。
2、對CFGG的句型,分析樹被定義為具有下述性質的一棵樹。
(1) 根由開始符號所標記;
(2) 每個葉子由一個終結符、非終結符、或ε標記;
(3) 每個內部結點由一個非終結符標記;
(4) 若A是某內部節點的標記,且X1,X2,...,Xn是該節點從左到右所有孩子的標記,則A→X1X2...Xn是一個產生式。若A→ε,則標記為A的結點可以僅有一個標記為ε的孩子。
註:分析樹的葉子,從左到右構成G的一個句型。若葉子僅由終結符標記,則構成一個句子。
3、對CFG G的句型,表達式的語法樹被定義為具有下述性質的一棵樹:
(1) 根與內部節點由表達式中的操作符標記;
(2) 葉子由表達式中的操作數標記;
(3)用於改變運算優先級和結合性的括號,被隱含在語法樹的結構中。
- 語法樹是表示表達式結構的最好形式
(4)二義性與二義性的消除
二義性:若文法G對 同 一句子產生不止一棵分析樹
,則稱G是二義的.
結論:
1> 一個句子有多於一棵分析樹,僅與文法和句子有關,與采用的推導方法無關;
2> 造成文法二義的根本原因:文法中缺少對文法符號優先級和結合性的規定
二義性消除的方法:
① 改寫二義文法為非二義文法;
② 規定二義文法中符號的優先級和結合性,使僅產生一棵分析樹。
3. 語法與文法簡介
(1)正規式與上下文無關文法
- 記號可以用正規式描述,正規式適合描述線性結構,如標識符、關鍵字、註釋等.
- 句子可以用CFG描述,CFG適合描述具有嵌套(層次)性質的非線性結構,如不同結構的句子if-then-else\while-do等
正規式所描述的語言結構均可以用CFG描述,反之不一定.
(2)上下文有關文法CSG
典型的這類語言結構包含:計數問題的抽象、變量的聲明與引用、過程調用時形參與實參的一致性檢查等.描述它們的文法被稱為上下文有關文法(Context Sensitive Grammar,CSG).這些語言結構無法用上下文無關文法CSG來描述.
(3)形式語言與自動機簡介
? 若文法G=(N,T,P,S)的每個產生式α→β中,均有α∈(N∪T),且至少含有一個非終結符,β∈(N∪T),則稱G為0型文法.
? 對0型文法施加以下第i條限制,即得到i型文法。
? 1> G的任何產生式α→β(S→ε除外)滿足|α|≤|β|;
? 2> G的任何產生式形如A→β,其中A∈N,β∈(N∪T)*;
? 3> G的任何產生式形如A→a或者A→aB(或者A→Ba),其中A和B∈N,a∈T。
文法 | 語言 | 自動機 |
---|---|---|
短語文法(0型) | 短語結構語言 | 圖靈機 |
CSG(1型) | CSL | 線性界線自動機 |
CFG(2型) | CFL | 下推自動機 |
正規文法(3型) | 正規集 | 有限自動機 |
4. 自上而下語法分析
分為:遞歸下降分析法、預測分析法
基本思想:對任何一個輸入序列ω,從S開始進行最左推導,直到得到一個合法的句子或發現一個非法結構。整個自上而下分析是一個試探的過程,是反復使用不同產生式謀求與輸入序列匹配的過程。
提前準備——重寫文法:1.消除左遞歸,以避免陷入死循環; 2.提取左因子,以避免回溯.
(1)消除左遞歸
定義:若文法G中的非終結符A,對某個文法符號序列α存在推導A =+> Aα,則稱G是左遞歸的。若G中有形如A→Aα的產生式,則稱該產生式對A直接左遞歸。
<1> 消除文法的直接左遞歸
A→Aα|β 替換為 A →βA‘
A‘→αA‘|ε
首先,整理A產生式為如下形式:A→ Aα1|Aα2|...|Aαm|β1|β2|...|βn
然後用下述產生式代替A產生式:A→ β1 A‘|β2 A‘| ...|βn A‘
? A‘→ α1 A‘ | α2 A‘ | ... | αm A‘ |ε
<2> 消除文法的左遞歸
核心思想:將無直接左遞歸的非終結符展開到其他產生式,然後消除其他產生式中的直接左遞歸(如果有的話)
若G產生句子的過程中出現A=+A的推導,則無法消除左遞歸(出現回路)
(2)提取左因子
<1> 提取文法的左因子
左因子產生原因:公共前綴:A → αβ1|αβ2
方法:將 A → αβ1|αβ2|γ
? 替換為 A→αA‘|γ A‘→β1|β2
(3)遞歸下降分析
直接以程序代碼(的方式)模擬產生式產生語言的過程:
基本思想:每個非終結符對應一個子程序(函數),過程體中:
- 產生式右部的非終結符:對應子程序調用,
- 產生式右部的終結符: 與輸入記號序列進行匹配。
特點:
1> 子程序是遞歸的(因為文法是遞歸的);
2> 程序與文法相關;
3> 它對文法的限制是不能有公共左因子和左遞歸;
4> 它是一種非形式化的方法,只要能寫出子程序,用什麽樣的方法和步驟均可。
(4)預測分析器
☆ 預測分析器由一張預測分析表、一個符號棧和一個驅動器組成,數學模型是下推自動機。
☆ 對文法的限制是不能有公共左因子和左遞歸
預測分析器的核心概念:
1> 分析方法:格局與格局變換
2> 分析表+驅動器(模擬算法)
3> 預測分析表的構造
4> LL(文法、語言、分析器)
☆ 開始格局的剩余輸入是全部輸入序列,而接收格局中剩余輸入應該為空,任何其他格局或出錯格局中的剩余輸入應該是全部輸入序列的一個後綴.
☆ 改變格局的動作:
① 匹配終結符: 若top=ip(但≠#),則pop且next(ip);
② 展開非終結符:若top^= X且M[X,ip^]=α(X→α),則pop且push(α);
③ 報告分析成功: 若top ^= ip^ = #,則分析成功並結束;
④ 報告出錯:其它情況,調用錯誤恢復例程.
☆ 驅動器算法
☆ 構造預測分析表
步驟:1. 構造文法符號X的FIRST集合和非終結符的FOLLOW集合;2. 根據兩個集合構造預測分析表.
通俗地講,α的FIRST集合就是從α開始可以導出的文法符號序列中的開頭終結符。而A的FOLLOW集合,就是從開始符號可以導出的所有含A的文法符號序列中緊跟A之後的終結符.
<1> 計算X的FIRST集合 -----自下而上計算
<2> 計算所有非終結符的FOLLOW集合 —— 自上而下計算
<3> 構造預測分析表
<4> LL(1)文法
文法G被稱為是LL(1)文法,當且僅當為它構造的預測分析表
中不含多重定義
的條目。由此分析表所組成的分析器被稱為LL(1)分析器
,它所分析的語言被稱為LL(1)語言
。
☆ 第一個L代表從左到右掃描輸入序列,第二個L表示產生最左推導,1表示在確定分析器的每一步動作時向前看一個終結符.
推論3.2 G是LL(1)的,當且僅當G的任何兩個產生式A→α|β滿足:
1. 對任何終結符a,α和β不能同時推導出以a開始的串;即First(α) ∩ First(β) = ∅
2. α和β最多有一個可以推導出ε;
3. 若β =*> ε,則α不能導出以FOLLOW(A)中終結符開始的任何串. 即First(α) ∩ Follow(A) = ∅
☆ 無論是遞歸下降子程序法還是非遞歸的預測分析法,他們都只能處理LL(1)文法.
5. 自下而上語法分析
☆ 自上而下分析采用的是推導;自下而上分析采用的是歸約(規範歸約—剪句柄—移進/歸約分析—SLR(1)分析器).
(1)自下而上分析的基本方法
☆ 基本思想:最左歸約.
對於每個輸入序列ω:從左到右掃描ω; 從ω開始,反復用產生式的左部替換產生式的右部(即當前句型中的句柄)、謀求對ω的匹配,最終得到文法的開始符號,或者發現一個錯誤。
☆ 基本概念:
a) > 設αβδ是文法G的一個句型,若存在S=*>αAδ,A=+>β, 則稱β是句型αβδ相對於A的"短語".
> 特別的,若 有A→β,則 稱β是句型αβδ相對於產生式A→β的"直接短語".
> 一個句型的最左直接短語被稱為"句柄".
特征:
1. 短語:以非終結符為根子樹中所有從左到右的葉子;
2. 直接短語:只有父子關系的子樹中所有從左到右排列的葉子(樹高為2);
3. 句柄:最左邊父子關系樹中所有從左到右排列的葉子(句柄是唯一的)
b)最左歸約:若 α是文法G的句子且滿足下述條件,則稱序列αn,αn-1,...,α0是α的一個最左歸約。
1) αn = α
2) α0 = S(S是G 的開始符號)
3) 對任何i(0<i<=n),αi-1是將αi中句柄替換為相應產生式左部非終結符得到的
☆ 最左歸約的逆過程是一個最右推導,分別稱最右推導和最左歸約為規範推導和規範歸約.
c)移進-歸約分析器
1. 工作方式:格局與格局變換
2. 分析表
3. 驅動器(模擬算法)
4. SLR分析表的構造
5. LR(文法、語言、分析器)
☆ 改變格局的動作:
1. 移進(shift):當前剩余輸入的下一終結符進棧。
2.歸約(reduce):將棧頂句柄替換為對應非終結符(最左歸約)
3.接受(accept):宣告分析成功
4. 報錯(error):發現語法錯誤,調用錯誤恢復例程
(2) LR分析
a) LR分析與LR文法
LR分析:允許左遞歸,但不能有二義
定義3.15 若為文法G構造的移進-歸約分析表中不含多重定義的條目,則稱G為"LR(k)文法",分析器被稱為是"LR(k)分析器",它所識別的語言被稱為"LR(k)語言"。"L"表示從左到右掃描輸入序列,"R"表示逆序的最右推導,"k"表示為確定下一動作向前看的終結符個數,一般情況下k<=1。當k=1時,簡稱"LR"。
構造SLR(1)分析器
<1> 活前綴與LR(0)項目
第1步 | 第2~N步 | 狀態 | |
---|---|---|---|
詞法--DFA | ε-closure(S) | ε-closure(smove(S,a)) | 狀態集 |
語法--DFA | closure(I) | closure(goto(I,x)) | 項目集 |
出現在移進-歸約分析器棧中的右句型的前綴,被稱為文法G的活前綴(viable prefix).
LR(0)項目(簡稱項目)是這樣一個產生式,在它右邊的某個位置有一個點"."。對於A→ε,它僅有一個項目A→.。
項目A→α.β顯示了分析過程中看到(移進)了產生式的多少。
β不為空的項目稱為可移進項目,β為空的項目稱為可歸約項目.
<2> 拓廣文法與識別活前綴的DFA
G‘ = G ∪ {S‘ → S}
其中:S‘ → S是識別S的初態,S‘ → S. 是識別S的終態. 目的是使最終構造的DFA狀態集中具有唯一的初態和終態. ① closure(I):從項目集I不經任何文法符號到達的項目全體;
② goto(I,x):所有從I經文法符號x能直接到達的項目全體。
項目[S’→.S]和所有“.”不在產生式右部最左邊的項目稱為核心項目(kernel items),
其它“.”在產生式右部最左邊的項目(不包括[S’→.S])稱為非核心項目(nonkernel items).
核心項目:J=goto(I,X),S‘→.S(作為項目集的代表)
非核心項目:closure(J)-J(特點:可由J某中某項目算得)
<3> 識別活前綴
定義3.21 若存在最右推導S’=*> αAω => αβ1β2ω,則稱項目[A→β1.β2] 對活前綴αβ1有效。
當一個項目集中同時存在:
1. A→β1.β2和B→β.:既可移進又可歸約,移進/歸約沖突
2.A→α.和B→β.:均可指導下一步分析,歸約/歸約沖突
解決方法:簡單向前看一個終結符:
1. 移進/歸約沖突:若FIRST(β2)∩FOLLOW(B)=Φ,沖突可解決
2. 歸約/歸約沖突:若FOLLOW(A)∩FOLLOW(B)=Φ,沖突可解決
若沖突可以解決,則稱文法為SLR(1)文法,構造的分析表為SLR(1)分析表。
SLR(1)文法:簡單向前看一個終結符即可解決沖突
☆ 二義文法不是SLR(1)文法
第四章 靜態語義分析
采用語法制導翻譯生成中間代碼
1. 語法制導翻譯簡介
(1)語法與語義的關系
語法是指語言的結構、即語言的“樣子”;
語義是指附著於語言結構上的實際含意,即語言的“意義”.
一個語法上正確的句子,它所代表的意義並不一定正確.
☆ 語義分析的作用
• 檢查結構正確的句子所表示的意思是否合法;
• 執行規定的語義動作,如:表達式求值、符號表的查詢/填寫、中間代碼生成等
☆ 應用最廣的語義分析方法是語法制導翻譯,他的基本思想是將語言結構的語義以屬性的形式賦予代表此結構的文法符號,而屬性的計算以語義規則的形式賦予由文法符號組成的產生式.
(2)屬性/語義規則的定義
定義4.1 對於產生式A→α,其中α是由文法符號X1X2...Xn組成的序列,它的語義規則可以表示為(4.1)所示關於屬性的函數f:
b := f(c1, c2, ..., ck) (4.1)
語義規則中的屬性存在下述性質與關系:
(1) 稱(4.1)中屬性b依賴於屬性c1, c2, ..., ck。
(2) 若b是A的屬性,c1, c2, ..., ck是α中文法符號的屬性,或者A的其它屬性,則稱b是A的綜合屬性。
(3) 若b是α中某文法符號Xi的屬性,c1, c2, ..., ck是A的屬性,或者是α中其它文法符號的屬性,則稱b是Xi的繼承屬性。
(4) 若語義規則的形式如下述(4.2),則可將其想像為產生式左部文法符號A的一個虛擬屬性。屬性之間的依賴關系,在虛擬屬性上依然存在。
f(c1, c2, ..., ck) (4.2) ■
☆ 繼承屬性從前輩和兄弟的屬性計算得到,綜合屬性從子孫和自身的其他屬性計算得到.
即,繼承屬性
"自上而下,包括兄弟",綜合屬性
"自下而上,包括自身".
(3)語義規則的兩種形式
☆ 語義規則的兩種形式(忽略實現細節,二者作用等價)
<1> 語法制導定義(Syntax Directed Definition)
用抽象的屬性和運算表示的語義規則;(公式,做什麽)
<2> 翻譯方案(Translation Scheme)
用具體的屬性和運算表示的語義規則。(程序段,如何做)
☆ 繼承屬性
是自上而下計算的,綜合屬性
是自下而上計算的.
(4)LR分析翻譯方案的設計
☆ LR分析中的語法制導翻譯實質上是對LR語法分析的擴充:
- 擴充LR分析器的功能
當執行歸約產生式
的動作時,也執行相應產生式對應的語義動作
。由於是歸約時執行語義動作,
? 因此限制語義動作僅能放在產生式右部的最右邊
;
- 擴充分析棧
? 增加一個與分析棧
並列的語義棧
,用於存放分析棧中文法符號所對應的屬性值
。
☆ 擴充後的LR分析最適合對綜合屬性的計算,而對於繼承屬性的計算還需要進行適當的處理.
2. 中間代碼簡介
☆ 中間代碼應具備的特性
1)便於語法制導翻譯
2)既與機器指令的結構相近,又與具體機器無關.
使用中間代碼的好處:一是便於編譯器程序的開發和移植,二是代碼進行優化處理.
☆ 中間代碼的主要形式:後綴式、樹、三地址碼等.最基本的中間代碼形式是樹??;最常用的中間代碼形式是三地址碼,它的實現形式常采用四元式形式。
☆ 符號表是幫助聲明語句實現存儲空間分配的重要數據結構。
(1)後綴式
操作數在前,操作符緊隨其後,無需用括號限制運算的優先級和結合性;便於求值.
(2)三地址碼
① 三元式 形式: (i) (op, arg1, arg2)
? 三地址碼:(i):= arg1 op arg2
序號的雙重含義:既代表此三元式,又代表三元式存放的結果
存放方式:數組結構,三元式在數組中的位置由下標決定
弱點:給代碼的優化
帶來困難
② 四元式 形式: ( i ) (op,arg1,arg2,result)
? 所表示的計算: result:= arg1 op arg2
-
四元式與三元式的唯一區別:將由序號所表示的運算結果改為:用(臨時)變量來表示。
-
此改變使得四元式的運算結果與其在四元式序列中的位置無關.為代碼的優化提供了極大方便,因為這樣可以刪除或移動四元式而不會影響運算結果.
③ 樹形表示
1> 語法樹真實反映句子結構,對語法樹稍加修改(加入語義信息),即可以作為中間代碼的一種形式(註釋語法樹)
2> 樹的優化表示-DAG
3> 樹與其他中間代碼的關系
☆ 樹表示的中間代碼
與後綴式
和三地址碼
之間有內在聯系
- 樹 → 後綴式
? 方法:對樹進行深度優先後序遍歷
,得到的線性序列就是後綴式
,或者說後綴式是樹的一個線性化序列;
- 樹 → 三元式/四元式
特點:樹的每個非葉子節點和它的兒子對應
一個三元式或四元式;
方法:對樹的非葉子節點進行深度優先後序遍歷,即得到一個三元式或四元式序列。
3. 符號表簡介
- 符號表的作用:連接聲明與引用的橋梁,記住每個符號的相關信息,如作用域和類型等,幫助編譯的各個階段正確有效地工作。
- 符號表的基本目標:有效記錄信息、快速準確查找。
-
符號表設計的基本要求:
- 正確存儲各類信息;
- 適應不同階段的需求;
- 便於有效地進行查找、插入、刪除和修改等操作;
- 空間可以動態擴充.
(1)構成名字的字符串
構成名字的字符串的存儲方式:直接存儲---定長數據(直接將構成名字的字符串放在符號表條目中)和間接存儲---變長數據(將構成名字的字符串統一存放在一個大的連續空間內,字符串與字符串之間采用特殊的分隔符隔開,符號表條目中僅存放指向該字符串首字符的指針).
(2)名字的作用域
☆ 程序語言範圍的劃分可以有兩種劃分範圍的方式:並列
和嵌套
☆ 名字的作用域規則:規定一個名字在什麽樣的範圍內應該表示什麽意義.
<1> 靜態作用域規則(static-scope rule):編譯時就可以確定名字的作用域,即僅從靜態讀程序就可確定名字的作用域
<2> 最近嵌套規則(most closely nested):名字的聲明在離其最近的內層起作用
(3)線性表
符號表以棧(線性表)的方式組織.
線性表上的操作:查找、插入、刪除、修改
查找:從表頭(棧頂)開始,遇到的第一個符合條件的名字;插入:先查找,再加入在表頭(棧頂);
關鍵字 = 名字+作用域;
(4)散列表
名字掛在兩個鏈上(便於刪除操作):
- 散列鏈(hash link): 鏈接所有具有
相同hash值
的元素,表頭在表頭數組中; - 作用域鏈(scope link):鏈接所有在
同一作用域
中的元素,表頭在作用域表中.
☆ 操作:查找、插入、刪除
4. 聲明語句的翻譯
(1)變量的聲明
☆ 一個變量的聲明應該由兩部分來完成:類型的定義
和變量的聲明
- 類型定義:為編譯器提供存儲空間大小的信息
- 變量聲明:為變量分配存儲空間
- 組合數據的類型定義和變量聲明:定義與聲明在一起,定義與聲明分離.
1> 簡單數據類型
的存儲空間是預先確定的,如int可以占4個字節,double可以占8個字節,char可以占1個字節等
2> 組合數據類型變量
的存儲空間,需要編譯器根據程序員提供的信息計算而定.
(2) 過程
1.過程(procedure):過程頭(做什麽) + 過程體(怎麽做);
- 函數: 有返回值的過程
- 主程序: 被操作系統調用的過程/函數
2.過程的三種形式:過程定義、過程聲明和過程調用。
過程定義:過程頭+過程體;
過程聲明:過程頭;
3. 左值與右值
1> 直觀上,出現在賦值號左邊和右邊的量分別稱為左值和右值;
2> 實質上,左值必須具有存儲空間,右值可以僅是一個值,而沒有存儲空間.
3> 形象地講,左值是容器,右值是內容.
4. 參數傳遞
1> 形參與實參
- 聲明時的參數稱為形參(parameter或formal parameter)
- 引用時的參數稱為實參(argument或actual parameter)
2> 常見的參數傳遞形式:(不同的語言提供不同的形式)
- 值調用(call by value)---過程內部對參數的修改,不影響作為實參的變量原來的值.
- 引用調用(call by reference)--- 過程內部對形參的修改,實質上是對實參的修改.
- 復寫-恢復(copy-in/copy-out)--- ① 過程內對參數的修改不直接影響實參,避免了副作用;
② 返回時將形參內容恢復給實參,實現參數值的返回.
- 換名調用(call by name)--- 宏調換
3> 參數傳遞方法的本質區別: 實參是代表左值、右值、還是實參本身的正文.
5. 作用域信息的保存
☆ 能夠畫出嵌套過程的嵌套關系樹(P191 4.33),根據語法制導翻譯(P193 4.35)畫出分析樹,寫出推導步驟,構造的符號表
5. 簡單算術表達式與賦值句
P197 例4.36 主要是變量類型的轉換
6. 數組元素的引用
(1)數組元素的地址計算
- 註意是行主存儲還是列主存儲
(2)☆數組元素引用的語法制導翻譯(考試熱點之一)
- P201 例4.37
7. 布爾表達式
布爾表達式的計算有兩種方法:數值表示的直接計算
和邏輯表示的短路計算
☆ 布爾表達式短路計算的翻譯:短路計算的控制流,真出口與假出口,真出口鏈與假出口鏈,拉鏈回填技術(P207 例4.41)(考試熱點之一)
8. 控制語句
控制語句的分類:①無條件轉移、②條件轉移、③循環語句、④分支語句
- 無條件轉移(goto)\條件轉移(if、while)
- 條件轉移的語法制導翻譯:P213 例4.42
多看課件PPT,多做題練手
作者:艦長同學
鏈接:https://www.jianshu.com/p/eb63d31ad638
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯系作者獲得授權並註明出處。
編譯原理知識匯總