1. 程式人生 > >第七章 語義分析和中間程式碼生成

第七章 語義分析和中間程式碼生成

1、   編譯程式的任務是把源語言程式翻譯成目標程式,有些編譯程式在編譯過程中,不產生中間語言,而是直接從源語言程式翻譯成目標語言程式。


以上編譯過程省略了中間語言,它不利於編譯所產生的目的碼的優化.為了產生高質量的程式碼,可以將源語言程式首先翻譯成一種特殊形式的中間語言程式碼形式,並對其進行優化,然後再將它翻譯成最終的目的碼。


中間程式碼

中間程式碼也叫中間語言

Intermediate code /language)是:源程式的一種內部表示,不依賴目標機的結構,複雜性介於源語言和機器語言之間。

中間程式碼的優點

1、邏輯結構清楚;

2、利於不同目標機上實現同一種語言;

3、利於進行與機器無關的優化;

語義分析

在詞法分析和語法分析之後,編譯程式要完成語義分析和翻譯工作。由於編譯器完成的分析是靜態定義的,所以語義分析也可稱作靜態語義分析 taticsemantic analysis)。

語義分析的具體工作

1、型別檢查;

2、控制流檢查;

3、一致性檢查;

4、相關名字檢查

語法制導翻譯

對文法中的每個產生式都附加一個語義動作或語義子程式,且在語法分析過程中,每當需要使用一個產生式進行推導或規約時,語法分析程式除執行相應的語法分析動作之外,還要執行相應地語義動作或語義子程式。每個語義子程式都指明瞭相應產生式中各個符號的具體含義,並規定了使用該產生式進行分析時所應採取的語義動作。

由此可見:抽象文法符號的具體語義資訊,是在語法分析同步的語義處理過程中獲取和加工的。

屬性文法

將語義以“屬性”的形式附加到各文法符號上,再根據產生式所蘊含的語義,給出每個文法符號的屬性的求值規則,從而形成一種帶有語義屬性的前後文無關文法,即屬性文法

屬性

一個文法符號X的語義資訊我們稱之為語義屬性或簡稱為屬性(Atrributes

X.TYPE表示為X的型別

X.VAL表示為X的值

例:

對於文法:E→E+T | T

T→ digit



語法制導翻譯的實質

根據文法中每個產生式所蘊含的語義,為其配備一個(或多個)語句或子程式,對所要完成的功能進行描述,在語法分析過程中,當分析器使用該產生式進行語法分析時(不論是推導還是規約),除完成語法分析動作之外,還將呼叫為其配備的語義子程式,進行相應地語義處理,完成語義翻譯工作。

中間程式碼常見的幾種形式

1、字尾式

2、圖表示法

抽象語法樹、DAG

3、三地址程式碼

三元式、四元式、間接三元式

字尾式

字尾式是波蘭邏輯學家盧卡西維奇(J.Lukasiewicz提出的一種對錶達式的表示方法:每一運算子都置於其運算物件之後,即運算元寫在前面,算符寫在後面

它的特點是:表示式中各個運算是按運算子出現的順序進行的,故無需用括號來指示運算順序,因而又稱為無括號式。

結論

從以上兩個例子我們可得出:

1、在兩種表示中,運算物件出現的順序相同;

2、在後綴表示中,運算子按實際計算順序從左到右排列,且每一運算子總是跟在運算物件之後。

圖表示法-抽象語法樹

在語法樹中去掉一些對翻譯不必要的資訊後,獲得的更有效的源程式的中間表示,這種經過變換後的語法樹稱為抽象語法樹

    抽象語法樹中,操作符和關鍵字都不作為葉子節點出現,而是把它們作為內部節點,即這些葉子節點的父節點。



抽象語法樹的表示方法

1、每一個結點用一個記錄來表示,該記錄包括一個運算子域和若干個指向子結點的指標域。

例: a:=b*-c+b*-c

方法1


方法2

把所有的結點安排在一個記錄的陣列中,結點的位置或索引作為指向地點的指標。


圖表示法-DAG

DAG(Directed Acyclic Graph)有向無迴圈圖

對錶達式中的每個子表示式,DAG都有一個結點,一個內部結點代表一個操作符,他的孩子代表運算元。在一個DAG中代表公共子表示式的節點具有多個父結點(與抽象語法樹中公共子表示式被表示為重複的子樹不同)


例: a:=b*-c+b*-c


三地址程式碼

三地址程式碼最基本的用法形式:

x:=y op z

其中x、y、z為名字、常數或編譯時產生的臨時變數;op代表運算子號。每個語句的右邊只能有一個運算子。

例如:x+y*z可以翻譯為:

T1:=y*z

T2:=x+T1

T1、T2位編譯時產生的臨時變數

三地址程式碼可以看成是抽象語法樹一種線性表示


三地址程式碼可以看成是DAG的一種線性表示


三地址碼的各種形式:

1.x:=yop z          x := op zx:=y 2.Goto L             ifx relopy gotoLif a goto L 3.Paramx         call p,nreturn y 4.x:=y[i]             x[i]:=y 5.x:=&yx:=*y*x:=y

賦值語句翻譯為三地址碼的屬性文法

三地址程式碼四元式

四元式實際上是一種“三地址語句”的等價表示,是一個帶有四個域的記錄結構。它

的一般形式為:

op,arg1,arg2,result)

需要指出的是:每個四元式只能有一個運算子,所以,一個複雜的表示式只能由多個四元式構成的序列表示。

例:a:=b*-c+b*-c


三地址程式碼-三元式

三元式顧名思義就是帶有三個域的記錄結構,他的一般形式為

(i)(op,arg1,arg2)

其中,(i)為三元式的編號,也代表了該式的運算結果,op,arg1,arg2的含義與四元式類似,區別在於arg可以是某三元式的序號,表示用該三元式的結果作為運算物件。

例:a=b*-c+b*-c


三元式和四元式的比較

相同點:

1、無論在一個三元式序列還是四元式序列中,各個三元式或四元式都是按相應表示式的實際運算順序出現的;

2、對同一表示式而言,所需的三元式或

四元式的個數一般都是相同的。

不同點:

1、由於三元式沒有result欄位,且不需要臨時變數,故三元式比四元式佔用的儲存空間少;

2、在進行程式碼優化處理時,常常需要挪動一些運算的位置,這對於三元式序列來說是很困難的,但對於四元式來說,由於四元式之間的相互聯絡是通過臨時變數來實現的,所以,更改其中一些四元式給整個系列帶來的影響就比較小。

三地址程式碼-間接三元式

建立兩個與三元式有關的表格,一個稱為三元式表,用於存放各三元式本身;另一個稱為執行表,它按照三元式的執行順序,依次列出相應各三元式在三元式表中的位置,也就是說我們用一個三元式表連同執行表來表示中間程式碼。通常我們稱這種表示方法為間接三元式

三元式

x:=(a+b)*c

b:=a+b

y:=c*(a+b

(1)(+,a,b)           (5) (+,a,b

(2)(*,(1),c)      (6)(*,c,(5))

(3)(:=,x,(2))   (7)(:=,y,(6))

(4)(:=,b,(1))

間接三元式   

執行表                           三元式表

(1)                  (1)(+,a,b

(2)                  (2)(*,(1),c)

(3)                  (3)(:=,x,(2))

(4)                  (4)(:=,b,(1))

(1)                  (5)(:=,y,(2))

(2)

(5)

三元式與間接三元式之間的區別

1、由於間接三元式在執行表中已經依次列出每次要執行的那個三元式,若其中有相同的三元式,則僅需在三元式表中儲存其中之一,即三元式的項數一般比執行表的項數少;

2、當進行程式碼優化需要挪動運算順序時,則只需對執行表進行相應地調整,而不必再改動三元式本身,這樣,就避免了前面講到的因改變三元式的順序所引起的麻煩。




語法制導的翻譯方法

就是對文法中的每個產生式都附加一個

語義動作或語義子程式,且在語法分析過程中,每當需要使用一個產生式進行推導或歸約時,語法分析程式除執行相應的語法分析動作之外,還要執行相應地語義動作或語義子程式。每個語義子程式都指明瞭相應產生式中各個符號的具體含義,並規定了使用該產生式進行分析時所應採取的語義動作

這種模式既把語法分析與語義處理分開,又

令其平行地進行,讓其在同一遍掃描中同時完成語法分析和語義處理兩項工作。

7.2 說明語句的翻譯

一.過程中的說明語句

說明語句的翻譯,主要工作是填符號表、分配地址

說明語句的文法產生式及語義動作如下:


7.3  賦值語句的翻譯

7.3.1 簡單算術表示式及賦值語句的翻譯

簡單算術表示式及賦值語句的產生式及語義動作如下:


Lookup為查符號表過程

Emit過程用於生成三地址碼指令語句並送往輸出檔案

7.3.2陣列元素的引用

一、陣列元素的地址計算

1、一維陣列

設陣列A[low..n],每個元素佔w個單元,則

LOC(A[i])=base+(i-low)*w

=i*w+(base-low*w)

其中varpart=i*w      C=low*w

conspart=base-C

即地址 D= varpart+conspart

2、二維陣列(按行存放)

i1,i2的下界為low1,low2,陣列是n1×n2,每個元素佔w個單元,則 

LOC(A[i1,i2])=base+((i1-low1)*n2+i2-low2)*w

=(i1*n2+i2)*w+(base-(low1*n2+low2)*w)

其中varpart=(i1*n2+i2)*w

C=(low1*n2+low2)*w)

conspart=base-C

即地址D=varpart+conspart


例:

A [x] 地址可變部分為x*W, 應生成指令:

(T’:=X*W)

A [x,y]   地址可變部分為(x*n2+y) *W, 應生成指令:

(T1:=X*n2)

(T1:=T1+y)

(T’:=T1*W)

A [x,y,z]地址可變部分為((x*n2+y)*n3+z) *W, 應生成指令:

(T1:=X*n2)

(T1:=T1+y)

(T2:=T1*n3)

(T3:=T2+z)

(T’:=T3*W)

地址不變部分的指令為:(T=A-C)

地址結果指令為:(T’’=T[T’])

二、賦值語句中陣列元素的翻譯


含陣列元素的賦值語句的文法





7.4布林表示式的翻譯



相關推薦

語義分析中間程式碼生成

1、   編譯程式的任務是把源語言程式翻譯成目標程式,有些編譯程式在編譯過程中,不產生中間語言,而是直接從源語言程式翻譯成目標語言程式。 以上編譯過程省略了中間語言,它不利於編譯所產生的目的碼的優

編譯原理-語義分析中間程式碼產生

語義分析的任務是:1.審查每一個語法結構的靜態語義,即驗證語法正確的結構是否有意義。2.在語義正確的基礎上生成一種中間程式碼或目的碼。語義分析的範圍是:1.確定型別:確定識別符號所關聯的資料型別。2.型別檢查:按語言的型別規則,檢查運算的合法性與運算分量型別的一致性,必要時作

編譯原理——語義分析中間程式碼的產生

1、知識點圖重點記憶:說明語句的翻譯     程式語言中的說明語句都是給編譯程式提供資訊的,諸如型別、維數、每維的界種類等,因此一般不生成目標,只是在編譯時把有關資訊填入相應表格即可。賦值語句的翻譯 1.簡單算術表示式的賦值語句:      所謂簡單指不考慮陣列元素、記錄、函

語義分析中間程式碼的產生

一.語義分析概述1.語義分析的任務 1)審查每一個語法結構的靜態語義,即驗證語法正確的結構是否有意義。如:賦值語句:x:=x+y,左邊變數型別與右邊變數型別是否一致。2)在語義正確的基礎上生成一種中間程式碼或目的碼。2.語義分析的範圍1)確定型別:確定識別符號所關聯的資料型別

《利用python進行資料分析.三版》 資料清洗準備

7.1 處理缺失資料 缺失資料在pandas中呈現的方式有些不完美,但對於大多數使用者可以保證功能正常。對於數值資料,pandas使用浮點值NaN(Not a Number)表示缺失資料。我們稱其為哨兵值,可以方便的檢測出來。 處理缺失資料有以下幾個方

-語義分析之類型檢查

編譯 表達式 第十章 階段 靜態 實現 循環 由於 靜態類型 由於Java是靜態類型的語言,所以在編譯階段,所有的變量都能得出確定的類型。 1、類型循環繼承、循環引用 Java是單繼承的,也就是說Java只能繼承一個實現類。但是在繼承過程中可能會形成循環,接口也是。

(譯)Netty In Action—事件迴圈執行緒模型

請尊重勞動成果,未經本人允許,拒絕轉載,謝謝! 這章包涵以下內容 - 執行緒模型概覽 - 事件迴圈概念和實現 - 任務排程 - 實現細節 簡單地說,執行緒模型指定了OS、程式語言、框架或應用程式的上下文中的執行緒管理的關鍵方面。執行緒創造的方式和時間明顯對於應用程

5 概率分析隨機演算法

練習 5.1-1 證明:因為在過程HIRE-ASSISTANT的第4行中,我們總能決定哪一個應聘者最佳,所以我們能比較任意兩個應聘者的好壞,則意味著我們知道應聘者排名的全部次序。 5.2-1 當面試的第一個應聘者是最好的應聘者時,你正好僱用一次。所以你正好僱用一次的概

NeHe OpenGL教程 課:光照鍵盤 程式碼

#include <windows.h> // Windows的標頭檔案 #include <glew.h> // 包含最新的gl.h,glu.h庫 #include <glut.h> // 包含OpenGL實用庫 #include <stdio.h

:模組庫類

第一節:關於模組和類庫 使用系統標準庫 什麼是模組? 可以說,一個 xxx.py 就是一個模組。 什麼是類庫? 裝有很多個模組的資料夾包,可以稱為一個類庫,更多的時候,這些python檔案都是有機關聯的。 有了模組和類庫,我們可以輕鬆地站在巨人的肩膀上進行程

4 需求分析model設計

本章主要內容: django app的設計 各個app models的設計 資料表生成與修改 django app的設計 安裝環境python27下 建立虛擬環境 mkvirtualenv mxonline pip inst

linux學習使用RAIDLVM磁碟陣列技術

一、RAID磁碟冗餘陣列 1988年,加利福尼亞大學伯克利分校首次提出並定義了RAID技術的概念。RAID技術通過把多個硬碟裝置

編譯原理實驗報告一:PL0語言編譯器分析(PL0,詞法分析,語法分析中間程式碼生成

實驗報告一:PL0語言編譯器分析一、實驗目的       通過閱讀與解析一個實際編譯器(PL/0語言編譯器)的原始碼, 加深對編譯階段(包括詞法分析、語法分析、語義分析、中間程式碼生成等)和編譯系統軟體結構的理解,並達到提高學習興趣的目的。二、實驗要求(1)   要求掌握基本

編譯原理實驗報告三:語法分析(PL0,詞法分析,語法分析中間程式碼生成

實驗報告三:語法分析一、實驗目的       通過設計、開發一個S語言的語法分析程式,實現對源程式的語法檢查和結構分析,加深對相關課堂教學內容的理解,提高語法分析方法的實踐能力。二、實驗要求根據下列S語言的語法規則,進行語法分析(1) <程式>→[<常量說明

快學scala 引入 讀書筆記及習題答案程式碼

chapter 7 包和引入 標籤:快學scala 一、筆記 scala中的包名是相對的,原始檔的目錄與包之間沒有強制的關聯關係,完全可以在同一檔案中為多個包貢獻內容。  包可以包含類、物件和特質,但是不能包含函式和變數的定義,這是java虛擬機器的侷限,但是包物件

之main函數啟動例程

gcc 清理 其它 運行 start call 返回 argv -a main函數和啟動例程 為什麽匯編程序的入口是_start,而C程序的入口是main函數呢?本節就來解釋這個問題。在講例 18.1 “最簡單的匯編程序”時,我們的匯編和鏈接步驟是: $ as hello

需求分析項目經理學習總結------(

總結 重新 需求 需求分析 需求量 團隊項目 div 改進 缺點 本周我看了第八章需求分析跟第九章項目經理,以下是我的學習總結。 一 .如何了解用戶的軟件需求 1.獲取和引導需求。軟件團隊需要找到軟件的利益相關者,了解和挖掘他們對軟件的需求,引導他們表達出軟件的需求。軟件團

深入.NET平臺C#編程筆記 深入理解多態

定義 方式 目前 rtu ride 筆記 總結 理解 hello 第七章 深入理解多態 1.裏氏替換原則: 在一個軟件系統中,如果子類出現在父類出現的位置,而整個軟件功能又沒有影響,那麽咱們稱為裏氏替換。 父類變量指向子類對象!! 2.Is 和as Is

Python課----正則日誌分析

python一、正則表達式:1、分類: 1、BRE基本正則,grep、sed,vi等軟件支持,vim有擴展 2、ERE擴展正則,egrep、grep-E,sed-r等 3、PCRE最重要的,高級語言中的2、基本語法: 1、元字符 metacharacter.匹配除了換行符外任意一字符,叠代

if條件語句的知識實踐(郵件報警)

current num 任務 bar == 數字 tee centos dev 範例7-2:開發一個腳本判斷系統剩余內存的大小,如果低於100MB,就郵件報警給系統管理員,並將腳本加入系統定時任務,即每3分鐘執行一次。首先搞定郵件服務,我的centos 7上面沒有mail包