編譯原理第七章-語義分析和中間程式碼產生
語義分析的任務是:
1.審查每一個語法結構的靜態語義,即驗證語法正確的結構是否有意義。
2.在語義正確的基礎上生成一種中間程式碼或目的碼。
語義分析的範圍是:
1.確定型別:確定識別符號所關聯的資料型別。
2.型別檢查:按語言的型別規則,檢查運算的合法性與運算分量型別的一致性,必要時作型別轉換。
3.識別含義:根據語言的語義定義(形式或非形式),識別程式中各構造成分組合到一起的含義,並作相應的語義處理(生成中間程式碼或目的碼)。
4.控制流檢查:控制流語句必須轉移到合法的地方。如C中,break語句規定跳出最內層的迴圈或switch語句。
5.一致性檢查:在很多場合要求物件只能被說明一次。如:pascal語言規定同一個識別符號在一個分程式中只能被說明一次等。
6.相關名字檢查:如:Ada,迴圈或塊可以有一個名字,它出現在這些結構的開頭或結尾。編譯程式必須檢查這兩個地方用的名字是否相同。
7.其它:如名字的作用域分析等也是語義分析的工作。
中間語言的表示形式:字尾式,三地址程式碼(包括三元式、四元式、簡潔三元式),DAG圖表示。
三元式由三個部分組成 算符:OP
語句的四元式及翻譯:
說明語句的翻譯程式語言中的說明語句都是給編譯程式提供資訊的,諸如型別、維數、每維的界種類等,因此一般不生成目標,只是在編譯時把有關資訊填入相應表格即可。型別轉換 我們可以把型別資訊反映到運算子中,例如用+i,*i表示定點+、*,用+r,*r表示浮點+、*。有的程式設計語言允許混合運算,有的不允許。如果不允許,則發現有型別不相同的運算分量就應該報錯。如果允許,就要進行型別轉換。
過程呼叫的翻譯
過程呼叫主要解決兩個問題:
(1)把程式控制轉移到子程式(過程段),執行完畢再返回。這個問題很好解決。
(2)傳遞實在引數。我們前面談到過幾種不同的引數傳遞方式(傳名、傳值、傳地址),它們的語義動作也就有所區別。中間程式碼: 把經過語法分析和語義分析而獲得的源程式中間表 示翻譯為中間程式碼表示。中間語言
語法樹
字尾式
三地址程式碼表示圖表示法
語法樹,有向非迴圈圖和字尾式表示源程式的自然層次結構。三地址語句的種類
1.賦值語句2.無條件轉移語句3.條件轉移語句4.複製語句5.過程呼叫語句6.索引語句7.地址和指標語句布林表示式:用布林運算子號(and,or,not)作用到布林變數或關係表示式上而組成布林表示式的作用:
1. 用作計算邏輯值
2. 用作控制流語句如if-then,if-then-else和while-do等之中的條件表示式
回填
生成跳轉語句時,將其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所指向的表中的每一個轉移指令中去
部分課後習題解答: