編譯原理——第七章
第七章 語義分析和中間程式碼的產生
知識總結
一、中間語言
1、語法樹
語法樹,有向非迴圈圖和字尾式表示源程式的自然層次結構
2、字尾式
中 綴式: a:=b*-c+b*-c
字尾式:
a b c - * b c - * + =
3、三地址程式碼表示
一般形式 x:=y op z
三地址語句的種類:
4、語法制導翻譯生成三地址程式碼
需要用到的量:
(1)E.place表示存放E值的名字。
(2)E.code表示對E求值的三地址語句序列。
(3) newtemp是個函式,對它的呼叫將產生 一個新的臨時變數。
5、三地址程式碼的具體實現
(1)四元式 op, arg1, arg2, result
(2)三元式 op, arg1, arg2
(3)間接三元式 間接碼錶+三元式表
二、說明語句
說明語句的翻譯:對每個區域性名字在符號表中建立相應的表項,填寫有關的資訊。如:型別、巢狀深度、相對地址、內情向量等。
相對地址:相對靜態資料區基址或活動資料中區域性資料區基址的一個偏移值。
過程中的說明語句 :
一個過程中的所有說明語句作為一個類集來處理。
一個全程變數Offset來記錄下 一個數據在符號表中的相對地址。
三、賦值語句的翻譯
賦值語句的翻譯:
表示式的成分可以是整型量、實型量、陣列 元素和記錄。
1、符號表中的名字
名字可以理解為指向符號表中相應該名字表項的指標。
過程lookup(id.name)
lookup(id.name)= id.entry
nil
emit 它將生成的三地址程式碼送到輸出檔案上
例:
emit(E.place‘:=’E1.place‘+’E2.place) 或
emit(= , E1.place,E2.place, E.place)
2、陣列元素地址分配(複雜賦值語句)
陣列元素地址的計算公式
①一維陣列的陣列元素計算公式
A[i]的地址:
base+(i-low )* w
=bace-low*w + i*w
常量部分+變數部分:bace-low*w + i*w
②二維陣列
A[i1,i2]的地址:
base+((i1 一low1)* n2+i2 一low2)*w)
= base-((low1 *n2)+low2)*w + ((i1*n2)+i2)* w
令c= ((low1 *n2)+low2)*w 則常量部分=a[low1,low2]-c
③多維陣列A[i1,i2,...,ik] 的地址的計算:
常量部分c=((...((low1*n2+low2)*n3+low3)...)*nk+lowk) * w
變數部分v= ((...((i1*n2+i2)*n3+i3...)*nk+ik)*w
所以a[i1,i2,…in]的地址
=base-c+v
四、布林表示式的翻譯
布林表示式: 用布林運算子號(and,or,not)作用到布林變數或關係表示式上而組成
布林表示式的作用:
1. 用作計算邏輯值
2. 用作控制流語句如if-then,if-then-else和while-do等之中的條件表示式
翻譯布林表示式的方法
表示一個布林表示式的值
方法一:用數值表示真和假,從而對布林表示式的求值可以象對算術表示式的求值那樣一步一步地來計算
方法二:另一種方法是根據布林表示式的特點,採用了某種優化措施。
數值表示法:用1表示真,0表示假來實現布林表示式的翻譯。
布林表示式的數值表示法的翻譯模式
·emit用於將一個三地址語句輸送到檔案中
·Nextquat是一個計數器,指向下一個三地址語句在輸出序列中的索引序號,也就是即將生成的三地址語句序號。
每執行一次emit後,nextquat自動加1
五、控制語句的翻譯
控制流語句中的布林表示式的翻譯:
對於出現在條件語句 if E then s1 else s2中的布林表示式E,其作用就是控制對S1和S2的選擇
因此,作為條件的布林表示式,把它設計成兩個出口:E.true 和 E.false
考慮E的上下文,對於IF語句,E.true 指向S1, E.false指向S2;
對於while語句E.true 指向迴圈的開始, E.false指向while 的下一語句
基本思想: 假定E 形如a<b,則將生成如下的E的程式碼:
三地址表示:
E.true: if a<b goto E.true (真出口)
E.false: goto E.false (假出口)
四元式表示:
E.true:(j<, a , b , E.true) (真出口)
E.false: (j, , , E.false ) (假出口)
用四元式實現三地址碼,真假出口可表示為:
真出口:
(jnz,a,_,P)表示 if a goto P
(jrop,x,y,P)表示 if x rop y goto P
假出口:
(j,_,_,P)表示 goto P
回填
生成跳轉語句時,將其E.true和E.false鏈成一個連結串列,記錄在E.truelist和E.falselist中
等到轉移目標確定以後,再將轉移出口填入E.truelist和E.falselist中
翻譯模式中用到的三個函式:
①.makelist(i):建立一個僅包含i的新表,i 是四元式陣列的一個索引(下標),或說 i是四元式程式碼序列的一個標號。
②.merge(p1,p2):連線由指標p1和p2指向的兩個表並且返回一個指向連線後的表的指標。 Merg(p1,p2)= p1 p2=0;
p1 p2≠0;
③.backpatch(p,t):把i作為目標標號回填到p所指向的表中的每一個轉移指令中去。此處的“表”都是為“反填”所拉的鏈.
使用回填翻譯控制流語句
先記錄要回填的轉移指令地址,在適當的時候進行回填,以便賦值和布林表示式的求值得到合適的連線,以完成程式的控制流程。
六、過程呼叫的處理
1. 過程呼叫主要解決兩個問題:
(1)把程式控制轉移到子程式(過程段),執行完畢再返回。這個問題很好解決。
(2)傳遞實在引數。我們前面談到過幾種不同的引數傳遞方式(傳名、傳值、傳地址),它們的語義動作也就有所區別。
知識應用
總結
這是這學期所學的最後一個章節,趕得緊,也就能理解一些淺顯的東西。臨近考試,還需要把以前的章節重新回顧一下。