Atitti. 語法樹AST、字尾表示式、DAG、三地址程式碼
Atitti. 語法樹AST、字尾表示式、DAG、三地址程式碼
抽象語法樹的觀點認為任何複雜的語句巢狀情況都可以藉助於樹的形式加以描述。確實,不得不承認應用抽象語法樹可以使語句翻譯變得相對容易,它很好地描述了語句、表示式之間的聯絡。不過,由於Neo Pascal並不會顯式構造抽象語法樹,所以不得不借助於其他資料結構實現。根據先前的經驗,棧結構就是不二之選。
DAG(有向無環圖)
字尾表示式:也稱為逆波蘭表示式,這種形式簡單明晰,便於儲存。在處理表達式翻譯時,字尾表示式有著其他形式無法比擬的優勢。不過,由於字尾表示式的應用領域比較單一,所以很少獨立作為一個實際編譯器的IR存在。
1. 字尾表示式
不包含括號,運算子放在兩個運算物件的後面,所有的計算按運算子出現的順序,嚴格從左向右進行(不再考慮運算子的優先規則,如:(2 + 1) * 3 , 即2 1 + 3 *
作者:: ★(attilax)>>> 綽號:老哇的爪子(全名::Attilax Akbar Al Rapanui 阿提拉克斯阿克巴阿爾拉帕努伊)漢字名:艾龍, EMAIL:[email protected]
轉載請註明來源: http://blog.csdn.net/attilax
1.1. 字首記法、中綴記法和字尾記法
它們都是對錶達式的記法,因此也被稱為字首記法、中綴記法和字尾記法。它們之間的區別在於運算子相對與運算元的位置不同:字首表示式的運算子位於與其相關的運算元之前;中綴和字尾同理。
中綴表示式(中綴記法)中綴表示式是一種通用的算術或邏輯公式表示方法,操作符以中綴形式處於運算元的中間。中綴表示式是人們常用的算術表示方法。雖然人的大腦很容易理解與分析中綴表示式,但對計算機來說中綴表示式卻是很複雜的,因此計算表示式的值時,通常需要先將中綴表示式轉換為字首或字尾表示式,然後再進行求值。對計算機來說,計算字首或字尾表示式的值非常簡單。
三地址程式碼:也稱為"四元組",即操作符和三個運算元地址。這是一種最為常見的IR。甚至有些書籍認為IR就是中間程式碼(即三地址程式碼
所謂的三地址,指的就是每一行程式碼通常包含三個地址資訊,即運算元1、運算元2、結果運算元。例如,(ADD A,1,C )這行三地址程式碼的含義就是A+1→C。這種形式初看與組合語言有點類似
當然,三地址程式碼也不是完美的,由於它是相對離散的,在分析源程式結構方面,它就不及語法樹便捷
三地址程式碼的理由如下:三地址程式碼是一種線性IR。由於輸入源程式及輸出目標程式都是線性的,因此,線性IR有著其他形式無法比擬的優勢。另外,相對於其他表示形式而言,程式設計師對於線性表示形式通常會有一種莫名的親切感,編譯器設計者當然也不例外。早期編譯器設計者往往都是組合語言程式設計的高手,可以非常自然、流暢地閱讀線性的三地址程式碼形式。同時,線性表示形式也會降低輸入輸出的實現難度。隨著編譯器"端"、"遍"等概念的出現,IR已經不僅僅是一種儲存在記憶體中的資料結構。有時它也需要以檔案形式轉存輸出,作為介面供其他系統讀取使用。
為什麼將其設計為"三地址"的形式呢?實際上,這是電腦科學家經過多年實踐探索後才得到共識的。三地址程式碼並不是唯一的線性IR,只能說是最為常見的而已。在編譯技術領域,二地址程式碼、單地址程式碼(即棧式機程式碼)都曾出現過,也曾在某些應用領域盛行一時,尤其是單地址程式碼。
然而,單地址程式碼的情況則截然不同了,在現代編譯器設計中,單地址程式碼也是應用比較廣泛的一種IR。尤其是近年隨著混合語言的日漸壯大,單地址程式碼也重新進入了人們的視野。由於執行單地址程式碼程式的棧式機架構相對比較簡單,可以非常方便地構造相關的直譯器或虛擬機器,所以單地址程式碼深受混合語言設計者的歡迎。讀者熟悉的Java位元組碼、.NET的IL都是單地址程式碼
三地址程式碼是在二地址程式碼的基礎上發展而來的。二地址程式碼的不足之處在於它通常會給其中一個源操作分量帶來一定副作用。當然,這種設計的靈感最初是來源於x86指令系統的,但是卻忘了一個重要的區別:x86指令中往往都是以暫存器作為暫存空間的。而暫存空間對於二地址程式碼卻是一個棘手的問題。為了解決二地址程式碼的不足,人們提出了一個對源操作分量不產生任何副作用的形式,那就是三地址程式碼。也就是說,在一行三地址程式碼中,任何運算都不會改變兩個源操作分量。這是三地址程式碼與二地址程式碼的主要區別。這個特性是非常重要的,它將使得編譯器更自由地複用名字與值,不必考慮程式碼帶來的副作用。
最後,再來談談IR的級別,即IR依賴於目標機的程度。按級別分類,可將IR分成三類:高階形式(HIR)、中級形式(MIR)、低階形式(LIR),也可稱為高階中間語言、中級中間語言、低階中間語言。
高階形式(HIR)是一種儘可能保持了源語言程式結構的IR,這種形式能較好地保留源程式的原始語義資訊。由於高階形式太接近源語言程式結構,所以很少有編譯器將其獨立作為IR傳遞給後端。
中級形式(MIR)既要以一種與語言無關的方式在一定程度上反映源語言的特性,又要能夠適應多種體系結構的IR。中級形式是一種比較常用的IR,它兼顧了源語言、目標機的特性,又能適用於大多數優化演算法。當一個編譯器僅設計一種IR時,中級形式是較理想的選擇。
低階形式(LIR)就是在一定程度上包含某些目標機特性的IR,比目標語言稍高階,常作為一些機器相關的優化演算法的輸入。不過,實際上,除了一些較大型的編譯器需要使用低階形式之外,低階形式並不是很常見。因為更多編譯器設計者更願意直接基於目標語言作優化。
表5-6 if語句的翻譯方案
if語句 |
翻譯方案 |
if <表示式> then <語句1> else <語句2> |
<表示式翻譯> (JNT , <表示式結果> , null , __L1 ) <語句1> (JMP , __L2 , null , null ) (LABEL , __L1 , null , null ) <語句2> (LABEL , __L2 , null , null ) |
如果省略了else部分,那麼只需將翻譯方案中第4~6行語句省略,並將第7行的"__L2"替換為"__L1"即可。semantic068、semantic069、semantic070主要的功能就是根據翻譯方案翻譯輸入的if語句。也就是說,試圖依靠這三個語義子程式,完成翻譯方案中黑體語句的生成。在上述翻譯方案中,可以暫且將"__L1"稱為"假分支標號",而將"__L2"稱為"出口標號"。另外,需注意一點,當輸入語句是if-then結構時,第7行語句的標號不應該取出口標號,而應該取假分支標號,因為此時並不存在真正意義的假分支,因此,可以將假分支標號當作出口標號使用。
while語句的翻譯方案
while語句 |
翻譯方案 |
while <表示式> do <語句> |
(LABEL ,__L1,null,null) <表示式翻譯> (JNT ,<表示式結果>,null,__L0) <語句> (JMP ,__L1,null,null) (LABEL ,__L0,null,null) |
5.1.2 IR設計及其級別 - 51CTO.COM.html
相關推薦
Atitti. 語法樹AST、字尾表示式、DAG、三地址程式碼
Atitti. 語法樹AST、字尾表示式、DAG、三地址程式碼 抽象語法樹的觀點認為任何複雜的語句巢狀情況都可以藉助於樹的形式加以描述。確實,不得不承認應用抽象語法樹可以使語句翻譯變得相對容易,它很好地描述了語句、表示式之間的聯絡。不過,由於Neo Pascal並不會
字首、中綴、字尾表示式轉換詳解
字首、中綴、字尾表示式轉換詳解 昨天參加了ebay實習生筆試題,其中一道題目給定了字首表示式,讓我們求轉換成中綴表示式時輔助棧的做多情況下容乃幾個元素以及中綴表示式的值。當時沒有做出來,會後後網上查了些資料,發現很少有文章將字首、中綴和字尾表示式之間的轉化覆蓋了,所以寫
基礎演算法與資料結構(二)字首、中綴、字尾表示式
目錄 簡介 字首表示式計算 字尾表示式計算 簡介 中綴表示式(正常的表示式) \[ (1+2)*3-4 \] 字首表示式(運算子位於運算元之前) \[ -*+1234 \] 字尾表示式(運算子位於運算元之後) \[ 12+3*4- \] 字首表示式計算 從右向左遍歷,
中綴、字首、字尾表示式相互相互轉換與求值
轉載至:https://www.cnblogs.com/nzbbody/p/3335226.html 表示式轉化(中綴,字尾,字首) 1、為什麼要把中綴表示式轉化為字尾,字首? 計算機沒法計算帶有括號,以及區分優先順序的表示式,或者說很難計算。使用字尾,字首,消除了括號和優先順序
字首表示式、中綴表示式、字尾表示式及其轉換
中綴式到其他式子的轉換方法 一箇中綴表示式如: a+bc-(d+e) 第一步:按照運算子的優先順序對所有的運算單位加括號~ 式子變成拉:((a+(bc))-(d+e)) 第二步:轉換字首與字尾表示式 字首:把運算子號移動到對應的括號前面 則變成拉:-( +(a
【轉載】字首、中綴、字尾表示式(逆波蘭表示式)
在這裡首先感謝部落格園的chensongxian這位大佬貢獻了這篇部落格,當時看了這篇部落格,我茅塞頓開,在此轉載,如有冒犯,聯絡我,我會立刻刪除。 介紹 字首表示式、中綴表示式、字尾表示式都是四則運算的表達方式,用以四則運算表示式求值 ,即數學表示式的求職 中綴表
回爐篇8—資料結構(7)之前、中、字尾表示式
前言: 前面我們介紹了三種資料結構,第一種陣列主要用作資料儲存,但是後面的兩種棧和佇列我們說主要作為程式功能實現的輔助工具,其中在介紹棧時我們知道棧可以用來做單詞逆序,匹配關鍵字元等等,那它還有別的什麼功能嗎?以及資料結構與本篇部落格的主題字首、中綴、字尾表示式有什麼關係呢?
字首表示式、中綴表示式、字尾表示式。
表示式 表示式:就是式子。是由數字、算符、數字分組符號、自由量和約束量組成的。人們一般習慣寫出來的式子,叫做中綴表示式。 因為在計算機中,不方便表達 數字分組符號。所以 波蘭人發明了一種把去符號化的表示式。字首表示式 字首表示式 字首表示式:沒有括號,算符在前 數字在後。波
字首、中綴、字尾表示式相互轉換
這裡只提供了使用棧的方法,還可以利用樹的遍歷實現。 中綴表示式轉換為字首表示式。 首先建立算術符棧OPTR和表示式棧RESULT並置空,然後依次逆序檢查中綴表示式每個字元,不同字元按不同情況處理: (1).若是空格直接跳過。 (2).若是運算元直接壓入RESULT棧。 (3).若是‘
字首表示式、字尾表示式和中綴表示式的計算(double型)
有關中綴表示式的計算以及中綴表示式與字首表示式、字尾表示式之間的轉換 後續文章會繼續給出 這裡只講字首表示式與字尾表示式計算的實現方法 字首表示式 計算方法: 將得到的字串處理為
【軟考】字首、中綴、字尾表示式
關鍵字:概念, 字首表示式, 字首記法, 中綴表示式, 中綴記法, 波蘭式, 字尾表示式, 字尾記法, 逆波蘭式 它們都是對錶達式的記法,因此也被稱為字首記法、中綴記法和字尾記法。它們之間的區別在於運算子相對與運算元的位置不同:字首表示式的運算子位於
順序棧應用-字首、中綴、字尾表示式
轉載自 http://blog.csdn.net/antineutrino/article/details/6763722/ 關鍵字:概念, 字首表示式, 字首記法, 中綴表示式, 中綴記法, 波蘭式, 字尾表示式, 字尾記法, 逆波蘭式 它們都是對錶達式的記法,因此也被稱為字首記法、中綴記
棧---定義、應用(遞迴、字尾表示式實現數學表示式求值)
一、定義 棧是限定僅在表尾進行插入和刪除操作的線性表。因此,棧的表尾端稱為棧頂;表頭端稱為棧底。不含任何資料元素的棧稱為空棧。棧又稱為後進先出(Last In First Out)的線性表,簡稱LIF0結構。 理解棧的定義需要注意:首先它是一個線性表,也即棧
字首表示式、中綴表示式、字尾表示式總結
一、字首表示式 (1)定義 字首表示式是一種沒有括號的算術表示式,其將運算子寫在前面,運算元寫在後面。例如表示式1-(2+3)的字首表示式是- 1 + 2 3。 (2)求值方法 對字首表示式求值,要
波蘭表示法與逆波蘭表示法(字首、中綴、字尾表示式)
1、為什麼要把中綴表示式轉化為字尾,字首? 計算機沒法計算帶有括號,以及區分優先順序的表示式,或者說很難計算。使用字尾,字首,消除了括號和優先順序。 2、計算機如何計算字尾,字首表示式? 計算字尾:從左到右遍歷字尾表示式,遇到運算元,放進棧,遇到操作符,棧頂兩個數出
字首表示式、中綴表示式、字尾表示式
中綴表示式就是我們日常看到的數學表示式:比如(2+4)*2,對於人類來說很直觀,但是對於計算機而言,這種表示式很不容易理解。於是就有了字首表示式和字尾表示式。 字首表示式 字首表示式是指將操作符放在前面,然後再放置運算元,比如對前面表示式而言,字首表示式
《資料結構和演算法》之中綴表示式、字尾表示式轉換
一,在上篇博文中討論了逆波蘭表示式的計算問題,在這裡討論一下中綴表示式如何轉換為字尾表示式 問題示例:如何將1+(2-3)*4+10/5 轉換為字尾表示式 1 2 3 - 4 * + 10 5 / +這樣的輸出 問題分析: 第一步,
構建 語法樹 來解析 數學表示式
構建 語法樹 來解析 數學表示式 本文主要講如何把一個數學表示式轉化成語法樹,並通過語法樹來解出結果。 引入 這個主要是用來學習語法樹的構建,數學表示式只是一個引子,本專案可以引申到 HTTP 請求報文解析,SQL語句的解析的諸如此類的擁有固定規則的字串的解析。 思考 我
中綴表示式生成二叉樹並利用字尾表示式進行求值運算
這次是某人的課程作業,題目不難,但是很複雜 原題如下 以字元序列的形式從鍵盤輸入不含變數的整數算術四則表示式(可以有小括號); 檢查表示式的正確性 將其轉換為二叉樹的儲存表示; 通過後序遍歷得到其後綴表示式序列,輸出該序列; 利用字尾表示式進行求值運算,
自制指令碼語言(10) 抽象語法樹AST與三地址線性IR
摘要:介紹了YF language程式語言的AST及IR表示 根據前面定義的語法,基本上AST就已經被決定了。因為語法每reduce一次,要麼組建一個新AST,要麼在已有的AST上新增資料。這裡照慣例採用了訪問者模式,將Code Generator設為訪問者,遍歷