轉自:https://www.jianshu.com/p/eb63d31ad638php
彙編指令:用符號表示的指令被稱爲彙編指令
彙編語言:彙編指令的集合稱爲彙編語言css
轉換(也被稱爲預處理):高級語言之間的翻譯,如FORTRAN
到ADA
的轉換
編譯:高級語言能夠直接翻譯成機器語言,也能夠翻譯成彙編語言,這兩個翻譯過程稱爲編譯
彙編:從彙編語言到機器語言的翻譯被稱爲彙編
交叉彙編:將一個彙編語言程序彙編成爲可在另外一機器上運行的機器指令成爲交叉彙編
反彙編:把機器語言翻譯成彙編語言
反編譯:把彙編語言翻譯成高級語言前端
(1)語言翻譯的兩種基本形態程序員
解釋器與編譯器的主要區別:運行目標程序時的控制權在解釋器
而不在目標程序.算法
(2)各自特色後端
工做效率高
,即時間快、空間省;交互性與動態性差,可移植性差
.工做效率低
,,即時間慢、空間費;交互性與動態性好,可移植性好
.共同點:均完成對源程序
的翻譯.
差別:編譯器採用先翻譯後執行,解釋器採用邊翻譯邊執行.數組
(0)通用程序設計語言的主要成份 聲明+操做=完整定義
ruby
(1)以過程
爲基本結構的程序設計語言的組成bash
(2)以階段劃分編譯器數據結構
注:符號表管理器和出錯處理貫穿編譯器工做的各個階段.
(3)編譯器各階段工做
1> 詞法分析:詞法分析的輸入是源程序
,輸出是識別出的記號流
.目的是識別單詞
. 至少分如下幾類:關鍵字(保留字)、標識符、字面量、特殊符號
2> 語法分析: 輸入是詞法分析器返回的記號流
,輸出是語法樹
.目的是獲得語言結構並以樹的形式表示.對於聲明性語句,進行符號表的查填,對於可執行語句,檢查結構合理的表達式運算是否有意義.
3> 語義分析:根據語義規則對語法樹中的語法單元進行靜態語義檢查,如類型檢查和轉換等,目的在於保證語法正確的結構在語義分析上也是合法的.
4> 中間代碼生成(可選):生成一種既接近目標語言,又與具體機器無關的表示,便於代碼優化與代碼生成.
(到目前爲止,編譯器與解釋器能夠一致)
5> 中間代碼優化(可選):局部優化、循環優化、全局優化等;優化其實是一個等價變換,變換先後的指令序列完成一樣的功能,但在佔用的空間上和程序執行的時間上都更省、更有效
6> 目標代碼生成:不一樣形式的目標代碼—彙編語言形式、可重定位二進制代碼形式、內存形式(Load-and-Go)
7> 符號表管理:合理組織符號,便於各階段查找\填寫等.
8> 出錯處理:
動態錯誤:源程序中的邏輯錯誤,發生在程序運行的時候。也稱爲動態語義錯誤
靜態錯誤:靜態錯誤分爲語法錯誤和靜態語義錯誤.
<1> 語法錯誤:有關語言結構上的錯誤,如單詞拼寫錯誤、表達式缺乏操做數、begin和end不匹配 <2> 靜態語義錯誤:分析源程序時能夠發現的語言意義上的錯誤,如加法的兩個操做數一個是整形變量,另外一個是數組名
(4)編譯器的分析\綜合模式
邏輯上把編譯器分爲分析(前端)部分
和綜合(後端)部分
.
1> 分析(前端):語言結構和意義的分析; 從詞法分析到中間代碼生成各階段的工做
2> 綜合(後端):語言意義處理;從中間代碼生成到目標代碼生成的各階段的工做
3> 編譯器和解釋器的區別每每是在造成中間代碼以後開始的.
每一個階段將程序完整分析一遍的工做模式稱爲一遍掃描。
(將源程序或源程序的某種形式的中間表示完整分析一遍,亦稱做一遍掃描)
(1) 記號、模式與單詞
單詞的分類:關鍵字(保留字)、標識符、字面量、特殊符號
模式(pattern):產生/識別單詞的規則
記號(token):按照某個模式(或規則)識別出的元素(一組)
單詞(lexeme):被識別出的元素的值(字符串自己) ,也稱爲詞值
(2) 詞法分析器的做用與工做方式
詞法分析器的做用:
1> 識別記號並交給語法分析器(根據模式識別記號)
2> 濾掉源程序中的無用成分,如註釋、空格和回車等
3> 處理與具體平臺有關的輸入(如文件結束符的不一樣表示等)
4> 調用符號表管理器和出錯處理器,進行相關處理
工做方式:
1.單獨一遍掃描
2.做爲語法分析器的子程序
3.並行方式
(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])的正規式。
(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]是一個狀態 且字母表不包括ε。 提示:正規式和有限自動機從兩個側面表示正規式。正規式是描述,自動機是識別。
構造詞法分析器的通常方法和步驟: 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.消除可能的死狀態和不可達狀態。
分類:表驅動型的詞法分析器;直接編碼的詞法分析器
比較:
表驅動 | 直接編碼 | |
---|---|---|
分析器的速度 | 慢 | 快 |
程序與模式的關係 | 無關 | 有關 |
適合的編寫方法 | 工具生成 | 手工編寫 |
分析器的規模 | 較大 | 較小 |
詞法分析:記號的集合,字符串由字母組成,線性結構
語法分析:句子的集合,句子由記號組成,非線性結構(樹)
語法分析的雙重含義:
許多編譯器,特別是由自動生成工具構造的編譯器,每每其前端的中心部件就是語法分析器
(1)語法分析器的做用
(2)語法錯誤的處理原則
源程序中可能出現的錯誤
語法(包括詞法)錯誤和語義錯誤(靜態語義錯誤和動態語義錯誤)
注:跟第一章的分類角度不一樣,第一章是從靜態錯誤(語法錯誤,靜態語義錯誤)和動態錯誤(動態語義錯誤)分類的,可是異曲同工。
詞法錯誤:指非法字符或拼寫錯關鍵字、標識符等
語法錯誤:指語法結構出錯,如少分號、括號不匹配、begin/end不配對等
靜態語義錯誤:如類型不一致、參數不匹配等
動態語義錯誤(邏輯錯誤):如死循環、變量爲零時做除數等
(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)推導、分析樹與語法樹
一、分析樹既反映語言結構的實質,也反映推導過程。
二、對CFGG的句型,分析樹被定義爲具備下述性質的一棵樹。
(1) 根由開始符號所標記;
(2) 每一個葉子由一個終結符、非終結符、或ε標記;
(3) 每一個內部結點由一個非終結符標記;
(4) 若A是某內部節點的標記,且X1,X2,...,Xn是該節點從左到右全部孩子的標記,則A→X1X2...Xn是一個產生式。若A→ε,則標記爲A的結點能夠僅有一個標記爲ε的孩子。
注:分析樹的葉子,從左到右構成G的一個句型。若葉子僅由終結符標記,則構成一個句子。
三、對CFG G的句型,表達式的語法樹被定義爲具備下述性質的一棵樹:
(1) 根與內部節點由表達式中的操做符標記;
(2) 葉子由表達式中的操做數標記;
(3)用於改變運算優先級和結合性的括號,被隱含在語法樹的結構中。
(4)二義性與二義性的消除
二義性:若文法G對 同 一句子產生不止一棵分析樹
,則稱G是二義的.
結論:
1> 一個句子有多於一棵分析樹,僅與文法和句子有關,與採用的推導方法無關;
2> 形成文法二義的根本緣由:文法中缺乏對文法符號優先級和結合性的規定
二義性消除的方法:
① 改寫二義文法爲非二義文法;
② 規定二義文法中符號的優先級和結合性,使僅產生一棵分析樹。
(1)正規式與上下文無關文法
正規式所描述的語言結構都可以用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型) | 正規集 | 有限自動機 |
分爲:遞歸降低分析法、預測分析法
基本思想:對任何一個輸入序列ω,從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)文法.
☆ 自上而下分析採用的是推導;自下而上分析採用的是歸約(規範歸約—剪句柄—移進/歸約分析—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)語法與語義的關係
語法是指語言的結構、即語言的「樣子」;
語義是指附着於語言結構上的實際含意,即語言的「意義」.
一個語法上正確的句子,它所表明的意義並不必定正確.
☆ 語義分析的做用
• 檢查結構正確的句子所表示的意思是否合法;
• 執行規定的語義動做,如:表達式求值、符號表的查詢/填寫、中間代碼生成等
☆ 應用最廣的語義分析方法是語法制導翻譯,他的基本思想是將語言結構的語義以屬性的形式賦予表明此結構的文法符號,而屬性的計算以語義規則的形式賦予由文法符號組成的產生式.
(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分析最適合對綜合屬性的計算,而對於繼承屬性的計算還須要進行適當的處理.
☆ 中間代碼應具有的特性
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> 樹與其餘中間代碼的關係
☆ 樹表示的中間代碼
與後綴式
和三地址碼
之間有內在聯繫
方法:對樹進行深度優前後序遍歷
,獲得的線性序列就是後綴式
,或者說後綴式是樹的一個線性化序列;
特色:樹的每一個非葉子節點和它的兒子對應
一個三元式或四元式;
方法:對樹的非葉子節點進行深度優前後序遍歷,即獲得一個三元式或四元式序列。
(1)構成名字的字符串
構成名字的字符串的存儲方式:直接存儲---定長數據(直接將構成名字的字符串放在符號表條目中)和間接存儲---變長數據(將構成名字的字符串統一存放在一個大的連續空間內,字符串與字符串之間採用特殊的分隔符隔開,符號表條目中僅存放指向該字符串首字符的指針).
(2)名字的做用域
☆ 程序語言範圍的劃分能夠有兩種劃分範圍的方式:並列
和嵌套
☆ 名字的做用域規則:規定一個名字在什麼樣的範圍內應該表示什麼意義.
<1> 靜態做用域規則(static-scope rule):編譯時就能夠肯定名字的做用域,即僅從靜態讀程序就可肯定名字的做用域 <2> 最近嵌套規則(most closely nested):名字的聲明在離其最近的內層起做用
(3)線性表
符號表以棧(線性表)的方式組織.
線性表上的操做:查找、插入、刪除、修改
查找:從表頭(棧頂)開始,遇到的第一個符合條件的名字;插入:先查找,再加入在表頭(棧頂);
關鍵字 = 名字+做用域;
(4)散列表
名字掛在兩個鏈上(便於刪除操做):
相同hash值
的元素,表頭在表頭數組中;同一做用域
中的元素,表頭在做用域表中.☆ 操做:查找、插入、刪除
(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)畫出分析樹,寫出推導步驟,構造的符號表
P197 例4.36 主要是變量類型的轉換
(1)數組元素的地址計算
(2)☆數組元素引用的語法制導翻譯(考試熱點之一)
布爾表達式的計算有兩種方法:數值表示的直接計算
和邏輯表示的短路計算
☆ 布爾表達式短路計算的翻譯:短路計算的控制流,真出口與假出口,真出口鏈與假出口鏈,拉鍊回填技術(P207 例4.41)(考試熱點之一)
控制語句的分類:①無條件轉移、②條件轉移、③循環語句、④分支語句
多看課件PPT,多作題練手