2.在語義正確的基礎上生成一種中間代碼或目標代碼。
2.類型檢查:按語言的類型規則,檢查運算的合法性與運算分量類型的一致性,必要時作類型轉換。
3.識別含義:根據語言的語義定義(形式或非形式),識別程序中各構造成分組合到一起的含義,並作相應的語義處理
5.一致性檢查:在很多場合要求對象只能被說明一次。如:pascal語言規定同一個標識符在一個分程序中只能被說明一次等。
6.相關名字檢查:如:Ada,循環或塊可以有一個名字,它出現在這些結構的開頭或結尾。編譯程序必須檢查這兩個地方用的名字是否相同。
無循環有向圖(DAG)
DAG與抽象語法樹基本上一樣,對表達式中的每個子表達式,DAG中都有一個結點。一個內部結點表示一個操作符,它的孩子表示操作數。
兩者所不同的是,在一個DAG中代表公共子表達式的結點具有多個父結點,而在一棵抽象語法樹中公共子表達式被表示爲重複的子樹。
逆波蘭表示法
波蘭表示是一種既不須考慮優先關係、又不用括號的一種表示表達式的方法(前綴式)。
現在我們要介紹的剛好是另一種波蘭表示形式,稱爲後綴式,即運算符在後。
算符:OP
第一運算分量:ARG1
第二運算分量:ARG2
{E.val:=TRIP(OP,E1.val,E2.val)}
這兒TRIP(OP,ARG1,ARG2)是一個語義過程,它產生(OP,ARG1,ARG2)並放入三元式表中,返回三元式在表中的位置
(2)E→i {E.val:=Entry(i)}
Entry是一個語義過程,它查找i在符號表中的位置。若用LOOKUP(NAME)函數表示對NAME查找符號表,找到則返回表項位置,找不到則返回NULL。 於是可如下實現:
詞法分析器掃描到標識符i時送回(種別碼,i值),語法分析器把i放入語義變量i.LEXCAL中,這時就可以調用Entry過程:
無循環有向圖(DAG)
DAG與抽象語法樹基本上一樣,對表達式中的每個子表達式,DAG中都有一個結點。一個內部結點表示一個操作符,它的孩子表示操作數。
兩者所不同的是,在一個DAG中代表公共子表達式的結點具有多個父結點,而在一棵抽象語法樹中公共子表達式被表示爲重複的子樹
三:某些語句的四元式及翻譯
說明語句的翻譯
爲局部名字建立符號表條目
爲它分配存儲單元
符號表中包含名字的類型和分配給它的存儲單元的相對地址等信息
程序語言中的說明語句都是給編譯程序提供信息的,諸如類型、維數、每維的界種類等,因此一般不生成目標,只是在編譯時把有關信息填入相應表格即可。
四:循環與分情況語句的翻譯
例如F1→for i:=E1 對應的語義動作:
(1)產生四元式:emit(:=,E1.place,--,ENTRY(i));
(2)保留ENTRY(i):F1.place:=ENTRY(i);
(3)因爲goto over 的轉移地址暫時填不上,必須
建鏈:F1.chain:=nextquad;
(4)產生無條件轉移指令:emit(j,--,--,0);
(5)保留again的地址:F1.quad:=nextquad;
五:過程調用的翻譯
1. 過程調用主要解決兩個問題:
(1)把程序控制轉移到子程序(過程段),執行完畢再返回。這個問題很好解決。
(2)傳遞實在參數。我們前面談到過幾種不同的參數傳遞方式(傳名、傳值、傳地址),它們的語義動作也就有所區別。
語法樹
後綴式
三地址代碼表示
語法樹,有向非循環圖和後綴式表示源程序的自然層次結構。
1. 用作計算邏輯值
2. 用作控制流語句如if-then,if-then-else和while-do等之中的條件表達式
控制流語句中的布爾表達式的翻譯
回填
一遍掃描:語法制導翻譯技術是屬於一遍掃描分析