北航編譯原理課件10語(yǔ)義分析和代碼生成_第1頁(yè)
北航編譯原理課件10語(yǔ)義分析和代碼生成_第2頁(yè)
北航編譯原理課件10語(yǔ)義分析和代碼生成_第3頁(yè)
北航編譯原理課件10語(yǔ)義分析和代碼生成_第4頁(yè)
北航編譯原理課件10語(yǔ)義分析和代碼生成_第5頁(yè)
已閱讀5頁(yè),還剩99頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第十章語(yǔ)義分析和代碼生成語(yǔ)義分析的概念棧式抽象機(jī)及其匯編指令聲明的處理表達(dá)式的處理賦值語(yǔ)句的處理控制語(yǔ)句的處理過(guò)程調(diào)用和返回第十章語(yǔ)義分析和代碼生成語(yǔ)義分析的概念假定:源語(yǔ)言:通用的過(guò)程語(yǔ)言生成代碼:棧式抽象機(jī)的(偽)匯編程序翻譯方法:自頂向下的屬性翻譯語(yǔ)法成分翻譯子程序參數(shù)設(shè)置:繼承屬性為值形參綜合屬性為變量形參語(yǔ)法成分翻譯動(dòng)作子程序參數(shù)設(shè)置:繼承屬性為值形參綜合屬性不設(shè)形參,而作為動(dòng)作子程序的返回值(由RETURN語(yǔ)句返回)假定:源語(yǔ)言:通用的過(guò)程語(yǔ)言10.1語(yǔ)義分析的概念1、上下文有關(guān)分析:即標(biāo)識(shí)符的作用域2、類(lèi)型的一致性檢查3、語(yǔ)義處理:

聲明語(yǔ)句:其語(yǔ)義是聲明變量的類(lèi)型等,并不要求做其他的操作。編譯程序的工作是填符號(hào)表,登錄名字的特征信息,分配存儲(chǔ)。

執(zhí)行語(yǔ)句:語(yǔ)義是要做某種操作。語(yǔ)義處理的任務(wù):按某種操作的目標(biāo)結(jié)構(gòu)生成代碼。10.1語(yǔ)義分析的概念1、上下文有關(guān)分析:即標(biāo)識(shí)符的作用域

用上下文無(wú)關(guān)文法只能描述語(yǔ)言的語(yǔ)法結(jié)構(gòu),而不能描述其語(yǔ)義。例如,對(duì)于有嵌套子程序結(jié)構(gòu)的程序段:BEGIN…BEGINαINTIβIEND…I…END若存在文法規(guī)則:VAR::=I

BEGIN…<BLOCK>…I...END

BEGIN…δVAR...ENDδ

∈V*且不包含變量I的聲明文法規(guī)則應(yīng)改為:INTIβVAR::=INTIβI第一次I的歸約正確第二次I的歸約錯(cuò)誤用上下文無(wú)關(guān)文法只能描述語(yǔ)言的語(yǔ)法結(jié)構(gòu),例如

然而上下文有關(guān)文法不僅構(gòu)造困難,而且其分析器十分復(fù)雜,分析效率又低,顯然是不實(shí)用的

因此,通常我們把與語(yǔ)義相關(guān)的上下文有關(guān)信息填入符號(hào)表中,并通過(guò)查符號(hào)表中的這些信息來(lái)分析程序的語(yǔ)義是否正確然而上下文有關(guān)文法不僅構(gòu)造困難,因10.2棧式抽象機(jī)及其匯編指令棧式抽象機(jī):由三個(gè)存儲(chǔ)器、一個(gè)指令寄存器和多個(gè)地址寄存器組成。存儲(chǔ)器:數(shù)據(jù)存儲(chǔ)器(存放AR的運(yùn)行棧)操作存儲(chǔ)器(操作數(shù)棧)指令存儲(chǔ)器10.2棧式抽象機(jī)及其匯編指令棧式抽象機(jī):由三個(gè)存儲(chǔ)器、一計(jì)算機(jī)的存儲(chǔ)大致情況如下:P-code指令PC程序指令存儲(chǔ)器棧底運(yùn)行棧堆(堆底)NPSPBP當(dāng)前模塊活動(dòng)記錄(數(shù)據(jù)段)計(jì)算機(jī)的存儲(chǔ)大致情況如下:P-code指令PC程序指令存儲(chǔ)器指令名稱(chēng)操作碼地址指令意義加載指令LODD將D的內(nèi)容→棧頂立即加載LDC常量常量→棧頂?shù)刂芳虞dLDA(D)變量D的地址→棧頂存儲(chǔ)STOD棧頂內(nèi)容

→變量D間接存ST@D將棧頂內(nèi)容→D所指單元間接存STN將棧頂內(nèi)容→次棧頂所指單元加ADD棧頂和次棧頂內(nèi)容相加,結(jié)果留棧頂減SUB次棧頂內(nèi)容減棧頂內(nèi)容乘MUL存入………棧式抽象機(jī)指令代碼如下:指令名稱(chēng)操作碼地址指令意義加載指令LODD將D的內(nèi)容→棧頂立指令名稱(chēng)操作碼地址指令意義等于比較EQL不等比較NEQ大于比較GRT次棧頂內(nèi)容與棧頂內(nèi)容比較,結(jié)果(1或0)留棧頂小于比較LES大于等于GTE小于等于LSE邏輯與AND邏輯或ORL邏輯非NOT轉(zhuǎn)子JSRlab分配ALCM在運(yùn)行棧頂分配大小為M的活動(dòng)記錄區(qū)指令名稱(chēng)操作碼地址指令意義等于比較EQL不等比較NEQ大于比10.3聲明的處理語(yǔ)義的表示:

給出語(yǔ)言結(jié)構(gòu)的屬性翻譯文法來(lái)說(shuō)明其語(yǔ)義及語(yǔ)義動(dòng)作,并把這些語(yǔ)義動(dòng)作插入屬性翻譯文法產(chǎn)生式中的適當(dāng)位置。編譯程序處理聲明語(yǔ)句要完成的主要任務(wù)為:編譯程序的任務(wù):1)

分離出每一個(gè)被聲明的實(shí)體,并把它們的名字填入符號(hào)表中2)把被聲明實(shí)體的有關(guān)特性信息盡可能多地填入符號(hào)表中對(duì)于已聲明的實(shí)體,在處理對(duì)該實(shí)體的引用時(shí)要做的事情:1)檢查對(duì)所聲明的實(shí)體引用(種類(lèi),類(lèi)型等)是否正確2)根據(jù)實(shí)體的特征信息,例如類(lèi)型,所分配的目標(biāo)代碼地址(可能為數(shù)據(jù)區(qū)單元地址,或目標(biāo)程序入口地址)生成相應(yīng)的目標(biāo)代碼10.3聲明的處理語(yǔ)義的表示: 給出語(yǔ)言結(jié)構(gòu)的屬性翻譯文法聲明的兩種方式:(1)類(lèi)型說(shuō)明符放在變量的前面。如:C語(yǔ)言:inta;在填表時(shí)已知類(lèi)型和a的值(名字):直接填入符號(hào)表。(2)類(lèi)型說(shuō)明符放在變量的后面,如:Pascal,PL/1,Ada等,需要返填。

聲明有常量聲明,變量(包括簡(jiǎn)單變量,數(shù)組變量和記錄變量等)和過(guò)程(函數(shù))聲明等,這里主要討論常量聲明和簡(jiǎn)單變量、數(shù)組聲明的處理。如PL/I聲明語(yǔ)句:DECLARE(X,Y(N),YTOTAL)FLOAT;聲明的兩種方式:聲明有常量聲明,變量(包括簡(jiǎn)單聲明語(yǔ)句的輸入文法為:<declaration>→DECLARE@dec_on↑x‘(’<entitylist>‘)’<type>↑t@fix_up↓x,t

<entitylist>→<entityname>↑n@name_defn↓n

|<entityname>↑n,@name_defn↓n<entitylist><type>↑t→FIXED↑t|FLOAT↑t|CHAR↑t<declaration>→DECLARE‘(’<entitylist>‘)’<type><entitylist>→<entityname>|<entityname>,<entitylist><type>→FIXED|FLOAT|CHAR屬性翻譯文法為:聲明語(yǔ)句的輸入文法為:<declaration>→DECLA@name_defn↓n是將由各實(shí)體名所得的n繼承屬性值,依次填入從x開(kāi)始的符號(hào)表中。注:顯然應(yīng)有內(nèi)部計(jì)數(shù)器或內(nèi)部指針,指向下一個(gè)該填的符號(hào)表項(xiàng)。@fix_up↓x,t是將類(lèi)型信息t和相應(yīng)的數(shù)據(jù)存儲(chǔ)區(qū)分配地址填入從x位置開(kāi)始的符號(hào)表中。(反填)當(dāng)然,如果聲明語(yǔ)句中,類(lèi)型說(shuō)明符放在頭上,就無(wú)需“反填”處理了。動(dòng)作程序@dec_on↑x是把符號(hào)表當(dāng)前可用表項(xiàng)的入口地址(指向符號(hào)表入口的指針,或稱(chēng)表項(xiàng)下標(biāo)值)賦給屬性變量x。@name_defn↓n是將由各實(shí)體名所得的n繼承屬性值,10.3.1常量類(lèi)型聲明處理常量標(biāo)識(shí)符通常被看作是全局名。常量聲明的ATG如下:<constdel>

→constant<type>↑t<entity>↑n:=<constexpr>↑c(diǎn),s

@insert↓t,n,c,s;<type>↑t→real↑t|integer↑t|string↑t

<constexpr>↑c(diǎn),s→<integerconst>↑c(diǎn),s|<realconst>↑c(diǎn),s

|<stringconst>↑c(diǎn),s由該文法產(chǎn)生的一個(gè)聲明實(shí)例為:constantintegerSYMBSIZE:=1024;10.3.1常量類(lèi)型聲明處理常量標(biāo)識(shí)符通常被看作是全局名。翻譯處理過(guò)程為:

先識(shí)別類(lèi)型(integer),將它賦給屬性t;然后識(shí)別常量名字(SYMBSIZE),將它賦給屬性n;最后識(shí)別常量表達(dá)式,并將其值賦給c,其類(lèi)型賦給屬性s?!顯insert的功能是:①檢查聲明的類(lèi)型t和常量表達(dá)式的類(lèi)型s是否一致,若不一致,則輸出錯(cuò)誤信息②把名字n,類(lèi)型t和常量表達(dá)式的值c填入符號(hào)表中<constdel>

→constant<type>↑t<entity>↑n:= <constexpr>↑c(diǎn),s@insert↓t,n,c,s;翻譯處理過(guò)程為:先識(shí)別類(lèi)型(integer),將它賦10.3.2簡(jiǎn)單變量聲明處理ATG文法:<svardel>

→<type>↑t,i<entity>↑n

@svardef↓t,i,n

@allocsv↓i

;<type>↑t,i→real↑t,i|integer↑t,i|character↑t(<number>)↑i

|logical↑t,i

簡(jiǎn)單變量聲明的例子:realx;integerj;character(20)s;n:變量名t:類(lèi)型值i:該類(lèi)型變量所需數(shù)據(jù)空間的大小10.3.2簡(jiǎn)單變量聲明處理ATG文法:<svardelproceduresvardef(t,i,n);j:=tableinsert(n,t,i);/*將有關(guān)信息填入符號(hào)表*/ifj=0//填表時(shí)要檢查是否重名thenerrmsg(duplident,statementno);elseifj=-1//符號(hào)表已滿thenerrmsg(tblovflow,statementno);endsvardef;procedureallocsv(i);codeptr:=codeptr+i;//codeptr為分配地址指針endallocsv;@allocsv和@svardef可以合并@svardef動(dòng)作符號(hào)是把n,i和t填入符號(hào)表中。proceduresvardef(t,i,n);

對(duì)于變長(zhǎng)字符串(或其它大小可變的數(shù)據(jù)實(shí)體),往往需要采用動(dòng)態(tài)申請(qǐng)存儲(chǔ)空間的辦法把可變長(zhǎng)實(shí)體存儲(chǔ)在堆中。我們可通過(guò)指向存放該實(shí)體數(shù)據(jù)區(qū)的指針來(lái)引用該實(shí)體,有時(shí)還應(yīng)得到該實(shí)體存儲(chǔ)空間的大小信息,并一起填入符號(hào)表內(nèi)。10.3.3數(shù)組變量聲明的處理

對(duì)于靜態(tài)數(shù)組,即數(shù)組的大小在編譯時(shí)是已知的,編譯程序在處理數(shù)組聲明時(shí),可建立一個(gè)數(shù)組模板(又稱(chēng)為數(shù)組信息向量)以便以后的程序中引用該數(shù)組元素時(shí),可按照該模板提供的信息,計(jì)算數(shù)組元素(下標(biāo)變量)的存儲(chǔ)地址。對(duì)于動(dòng)態(tài)數(shù)組,其大小只有在運(yùn)行時(shí)才能最后確定。我們?cè)诰幾g時(shí)僅為該模板分配一個(gè)空間,而模板本身的內(nèi)容將在運(yùn)行時(shí)才能填入。對(duì)于變長(zhǎng)字符串(或其它大小可變的數(shù)據(jù)實(shí)體),往往

大部分程序設(shè)計(jì)語(yǔ)言,數(shù)組元素是按行(優(yōu)先)存放在存儲(chǔ)器中的*,如聲明數(shù)組arrayB(N,-2:1) char;B:*FORTRAN例外,它按列(優(yōu)先)存放數(shù)組元素實(shí)際數(shù)組B各元素的存儲(chǔ)次序?yàn)椋篖OC是數(shù)組首地址(該數(shù)組第一個(gè)元素的地址)LOC→大部分程序設(shè)計(jì)語(yǔ)言,數(shù)組元素是按行(優(yōu)先)存放在存儲(chǔ)a)n維數(shù)組的地址計(jì)算公式設(shè)數(shù)組的維數(shù)為n,各維的下界和上界為L(zhǎng)(i)和U(i)例如,上例二維數(shù)組BL(1)=1(隱含值),U(1)=NL(2)=-2,U(2)=1還假定n維數(shù)組元素的下標(biāo)為V(1),V(2),…,V(n)則該數(shù)組元素的地址計(jì)算公式為:其中P(i)=

1當(dāng)i=n時(shí)當(dāng)1≤i<n時(shí)注:E為數(shù)組元素大小(字節(jié)數(shù))a)n維數(shù)組的地址計(jì)算公式例如,上例二維數(shù)組B還假定n維數(shù)其中P(i)=

1當(dāng)i=n時(shí)當(dāng)1≤i<n時(shí)U(2)L(2)L(1)U(1)U(3)L(3)v2v3v1A(v1,v2,v3)[

V(1)-L(1)]*[U(2)-L(2)+1]*[U(3)-L(3)+1]*E+[

V(2)-L(2)]*[U(3)-L(3)+1]*E+[V(3)-L(3)]*1*EP(2)P(3)P(1)其中P(i)=1若令(不變部分)則地址

RC為數(shù)組元素地址計(jì)算公式中的不變部分。因?yàn)椋灰罃?shù)組的維數(shù)和每一維的上下界值,便可求得RC值。以前面所舉的二維數(shù)組B為例,若N=3則P(1)=[U(2)-L(2)+1]=1-(-2)+1 =4P(2)=1RC==-[1×4+(-2)×1]×E=-2E因此,若有數(shù)組元素B(2,1),則它的地址為:=LOC–2E+(2×4+1×1)×E=LOC+7×E若令(不變部分)則地址RC為數(shù)組元素地址計(jì)算公式中的U(2)L(2)L(1)U(1)U(3)L(3)v2v3v1A(v1,v2,v3)三維數(shù)組的例子數(shù)組模板的一般形式如下左圖所示,而對(duì)于數(shù)組B的模板如下右圖所示:1-213142-2U(n)L(n)P(n)U(1)L(1)P(1)nRC...數(shù)組信息向量表arrayB(3,-2:1)char;U(2)L(2)L(1)U(1)U(3)L(3)v2v3v1b)數(shù)組信息向量表(模板)功能:1、用于計(jì)算下標(biāo)變量地址2、檢查下標(biāo)是否越界U(n)L(n)P(n).......U(1)L(1)P(1)nRC上界下界計(jì)算地址用常量大?。?n+2注:1、數(shù)組模板所需的空間大小取決于數(shù)組的維數(shù),即3n+2

無(wú)論是常界或變界數(shù)組,在編譯時(shí)就能確定數(shù)組模板的大小2、常界數(shù)組,在編譯時(shí)就可造信息向量表;而變界數(shù)組信息向量表要在目標(biāo)程序運(yùn)行時(shí)才能造。編譯程序要生成相應(yīng)的指令一般形式:b)數(shù)組信息向量表(模板)U(n)L(n)P(n)....1-213142-2以前面所舉的二維數(shù)組B為例,若N=3

P(1)=[U(2)-L(2)+1]=1-(-2)+1 =4P(2)=1RC=

=-[1×4+(-2)×1]=-2數(shù)組信息向量表U(2)--上界L(2)--下界P(2)--計(jì)算地址常量U(1)--上界L(1)--下界P(1)--計(jì)算地址常量n---維數(shù)RC1-213142-2以前面所舉的二維數(shù)組B為例,若N=3數(shù)組聲明的ATG文法:<arraydel>→array↑k@init↑j<entity>↑n(<sublist>↑j

)<type>↑t@symbinsert↓j,n,t<sublist>↑j

→<subscript>@dimen#↑j|<subscript>,<sublist>↑j@dimen#↑j<subscript>→<integerexpr>↑u@bannds↓u |<integerexpr>↑l:@lowerbnd↓l<integerexpr>↑u@upperbnd↓u,l1)動(dòng)作程序@init的功能為在分配給數(shù)組模板區(qū)中保留兩個(gè)存儲(chǔ)單元,用來(lái)放RC和n,并將維數(shù)計(jì)數(shù)器j清0。2)@dimen#

↑j:j:=j+1,即統(tǒng)計(jì)維數(shù)數(shù)組聲明的ATG文法:<arraydel>→array1)@init:p:=p+2;j:=0;/*維數(shù)計(jì)數(shù)器*/RCnP(1)L(1)U(1).......P(n)L(n)U(n)運(yùn)行棧指針p活動(dòng)記錄數(shù)組信息表1)@init:RCnP(1)L(1)U(1)......實(shí)際P(i)計(jì)算公式可利用P(i)=[U(i+1)-L(i+1)+1]×P(i+1)4)@lowerbnd把l=>L(i)

@upperbnd把u=>U(i),并計(jì)算P(i)5)最后的動(dòng)作程序@symbinsert是把數(shù)組名n,數(shù)組維數(shù)j和數(shù)組元素類(lèi)型t及數(shù)組標(biāo)志k填入符號(hào)表中;為數(shù)組分配存儲(chǔ)空間3)@bannds將省略下界表達(dá)式情況的u=>U(i),但應(yīng)把相應(yīng)的L(i)置成隱含值1,然后計(jì)算P(i)注:由于P(i)的計(jì)算要依賴(lài)于P(i+1),所以實(shí)際P(i)的值是反填的P(i)=

1當(dāng)i=n時(shí)當(dāng)1≤i<n時(shí)實(shí)際P(i)計(jì)算公式可利用P(i)=[U(i+1)4)@lowerbnd↓l生成將l=>L(i)的代碼@upperbnd↓u生成把u=>U(i)的代碼,生成計(jì)算P(i)的代碼;生成將P(i)的值送模板區(qū)的代碼;5)@symbinsert↓j,n,ta)把n,j,t,填入符號(hào)表中b)生成調(diào)用運(yùn)行子程序代碼(計(jì)算RC,并將計(jì)算結(jié)果和數(shù)組 名一起存入模板區(qū);計(jì)算數(shù)組所需數(shù)據(jù)區(qū)大小,為數(shù)組分 配存儲(chǔ)空間,并將頭地址填入符號(hào)表。)對(duì)于變界數(shù)組:4)@lowerbnd↓l5)@symbinsert↓j10.4表達(dá)式的處理

分析表達(dá)式的主要目的是生成計(jì)算該表達(dá)式值的代碼。通常的做法是把表達(dá)式中的操作數(shù)裝載(LOAD)到操作數(shù)棧(或運(yùn)行棧)棧頂單元或某個(gè)寄存器中,然后執(zhí)行表達(dá)式所指定的操作,而操作的結(jié)果保留在棧頂或寄存器中。注:操作數(shù)棧即操作棧,它可以和前述的運(yùn)行棧(動(dòng)態(tài)存儲(chǔ)分配)合而為一,也可單獨(dú)設(shè)棧。本章中所指的操作數(shù)棧實(shí)際應(yīng)與動(dòng)態(tài)運(yùn)行(存儲(chǔ)分配)棧分開(kāi)。請(qǐng)看下面的整型表達(dá)式ATG文法:10.4表達(dá)式的處理分析表達(dá)式的主要目的是生成有關(guān)的語(yǔ)義動(dòng)作為:procedureadd;emit(‘ADD’);end;procedurepush(j);integerj;emit(‘LOD’,symbtbl(j).objaddr);end;procedurepushi(i);/*壓入整數(shù)*/integeri;emitl(‘LDC’,i);end;1.<expression>→<expr>2.<expr>→<term><terms>3.<terms>→ε4.|+<term>@add<terms>5.|-<term>@sub<terms>6.<term>→<factor><factors>7.<factors>→ε8.|*<factor>@mul<factors>9.|/<factor>@div<factors>10.<factor>→<variable>↑n@lookup↓n↑j

@push↓j11.|<integer>↑i@pushi↓i12.|(<expr>)procedurelookup(n);stringn;integerj;j:=symblookup(n);

/*名字n表項(xiàng)在符號(hào)表中的位置*/ifj<1then/*error*/elsereturn(j);end;proceduremul;emit(‘MUL’);end;有關(guān)的語(yǔ)義動(dòng)作為:procedureadd;procedu對(duì)于輸入表達(dá)式x+y*3,可以生成如下目標(biāo)代碼:

LOD,<ll,on>xLOD,<ll,on>yLDC,3MULADD

上面所述的表達(dá)式處理實(shí)際上忽略了出現(xiàn)在表達(dá)式中各操作數(shù)類(lèi)型的不同,且變量也僅限于簡(jiǎn)單變量。

下面假定表達(dá)式中允許整型和實(shí)型混合運(yùn)算,并允許在表達(dá)式中出現(xiàn)下標(biāo)變量(數(shù)組元素)。因此應(yīng)該增加有關(guān)類(lèi)型一致性檢查和類(lèi)型轉(zhuǎn)換的語(yǔ)義動(dòng)作,也要相應(yīng)產(chǎn)生計(jì)算下標(biāo)變量地址和取下標(biāo)變量值的有關(guān)指令。對(duì)于輸入表達(dá)式x+y*3,可以生成如下目標(biāo)代碼:<expression>→<expr>↑t<expr>↑t→<term>↑s<terms>↓s

↑t<terms>↓s

↑u→@echo↓s

↑u

|+<term>↑t

@add↓t,s

↑v<terms>↓v

↑u |-<term>↑t

@sub↓t,s

↑v<terms>↓v

↑u<term>↑u→<factor>↑s<factors>↓s

↑u<factors>↓s

↑u→@echo↓s

↑u

|*<factor>↑t

@mul↓t,s

↑v<factors>↓v

↑u |/<factor>↑t@div↓t,s

↑v<factors>↓v

↑u<factor>↑t→<variable>↑i@type↓i↑t |<integer>↑i@pushi↓i↑t

|<real>↑r@pushi↓r↑t<variable>↑j→<identifier>↑n@lookup↓n↑j@push↓j

|<identifier>↑n@lookup↓n↑j(@template↓j↑k<sublist>↓k,j)<sublist>↓k,j→<subscript>↑t@offset↓k,t↑i

<subscripts>↓i,j<subscripts>↓k,j→@checkdim↓k,j

|,<subscript>↑t@offset↓k,t↑i

<subscripts>↓i,j<subscript>↑t→<expr>↑t<expression>→<expr>↑t語(yǔ)義動(dòng)作add等應(yīng)作相應(yīng)改變:procedureadd(t,s);stringt,s;ift=‘real’ands=‘integer’thenbeginemit(‘CVN’);/*次棧頂轉(zhuǎn)為實(shí)數(shù)*/emit(‘ADD’);return(‘real’);end;ift=‘integer’ands=‘real’thenbeginemit(‘CNV’);/*棧頂轉(zhuǎn)為實(shí)數(shù)*/emit(‘ADD’);return(‘real’);end;emit(‘ADD’);return(t);end;proceduretemplate(j);integerj;emitl(‘TMP’,symbtbl(j).objaddr);k:=0;/*維數(shù)計(jì)數(shù)器初始化*/return(k);end;procedureoffset(k,t);integerk;stringt;k:=k+1;ift≠‘integer’thenerrmsy(‘?dāng)?shù)組下標(biāo)應(yīng)為整型表達(dá)式’,statno);elseemitl(‘OFS’,k);return(k);end;procedurecheckdim(k,j);integerk,j;ifk≠symbtbl(j).dimthenerrmsy(‘?dāng)?shù)組維數(shù)與聲明不匹配’,statno);elsebeginemit(‘ARR’);emit(‘DER’);end;end;語(yǔ)義動(dòng)作add等應(yīng)作相應(yīng)改變:procedureadd(★過(guò)程template發(fā)送一條目標(biāo)機(jī)指令‘TMP’,該指令把數(shù)組的模板地址加載到操作數(shù)棧頂,并將下標(biāo)(維數(shù))計(jì)數(shù)器k清0?!?/p>

offset過(guò)程要確保每一個(gè)下標(biāo)都是整型,而且發(fā)送一條‘OFS’指令,該指令在運(yùn)行時(shí)要完成以下功能:1.檢查第k個(gè)下標(biāo)值是否在棧頂并是否在上下界范圍內(nèi)2.使用下列遞歸函數(shù),計(jì)算地址計(jì)算公式中可變部分:VP(0)=0;VP(k)=VP(k-1)+V(k)*P(k)1≤k≤n該VP函數(shù)是由計(jì)算公式導(dǎo)出的

★過(guò)程template發(fā)送一條目標(biāo)機(jī)指令‘TMP’,該指令下面以數(shù)組元素B(2,1)為例,說(shuō)明(a)執(zhí)行TMP指令并形成第一個(gè)下標(biāo)值的情況(b)執(zhí)行第一個(gè)OFS指令并形成第二個(gè)下標(biāo)值的情況(c)執(zhí)行第二個(gè)OFS指令及ARR指令后的情況(d)執(zhí)行DER指令,最后在棧頂形成下標(biāo)變量B(2,1)的值(a)B(2,1)值...→數(shù)據(jù)棧(b)(c)(d)12*4=8locB...V(2)→VP(1)→棧底18+1=9locB...V(2)→VP(2)→棧底LOC+(-2)+9=LOC+720locB...V(1)→VP(0)→棧底操作數(shù)棧1-213142-2...B的模板U(2)L(2)P(2)U(1)L(1)P(1)#dimRClocB下面以數(shù)組元素B(2,1)為例,說(shuō)明(a)B(2,1)值→數(shù)

處理邏輯表達(dá)式(關(guān)系表達(dá)式)的方法與處理算術(shù)表達(dá)式的方式基本相同。下面是邏輯表達(dá)式~(x=y&y≠z|z<x)生成的指令序列:LOD,(ll,on)xLOD,(ll,on)yEQLLOD,(ll,on)yLOD,(ll,on)zNEQANDLOD,(ll,on)zLOD,(ll,on)xLESORLNOT處理邏輯表達(dá)式(關(guān)系表達(dá)式)的方法與處理算術(shù)表達(dá)式LO10.5賦值語(yǔ)句的處理X:=Y+X;<assignstat>→@setL↑L<variable>↓L↑t:=

@resetL↑L<expr>↑s@storin↓t,s;proceduresetL;return(true);end;指示取變量地址LDA(ll,on)xLOD(ll,on)yLOD(ll,on)xADDSTN@setL是設(shè)置變量為“左值”(被賦變量),即將屬性L置true@resetL是設(shè)置變量為非被賦變量,即把屬性L置成falseprocedureresetL;return(false);end;指示取變量之值procedurestorin(t,s);stringt,s;ift≠sthen/*生成進(jìn)行類(lèi)型轉(zhuǎn)換的指令*/emit(‘STN’);end;10.5賦值語(yǔ)句的處理X:=Y+X;<assignsta10.6控制語(yǔ)句的處理IF<log_expr>

THEN<stat_list>

labA:IF<log_expr>

THEN<stat_list>

ELSElabA:<stat_list>labB:

10.6.1if語(yǔ)句JMF,labAJMF,labAJMP,labB其屬性翻譯文法及相應(yīng)的語(yǔ)義動(dòng)作程序:1.<if_stat>→<if_head>↑y<if_tail>↓y2.<if_head>↑y→IF<log_expr>@brf↑yTHEN<statlist>3.<if_tail>↓y→@labprod↓y

|ELSE@br↑z@labprod↓y<stat_list>@labprod↓z10.6控制語(yǔ)句的處理10.6.1if語(yǔ)句JMF,la

動(dòng)作程序@brf的功能是生成JMF指令,并將轉(zhuǎn)移標(biāo)號(hào)返回給屬性yprocedurebrf;stringlabx;labx:=genlab;/*產(chǎn)生一標(biāo)號(hào)賦給labx*/emitl(‘JMF’,labx);return(labx);end;

動(dòng)作程序@labprod是把從繼承屬性y得到的標(biāo)號(hào)設(shè)置到目標(biāo)程序中procedurelabprod(y);stringy;setlab(y);/*在目標(biāo)程序當(dāng)前位置設(shè)標(biāo)號(hào)*/end;

動(dòng)作程序@br是是生成JMP指令,并將轉(zhuǎn)移標(biāo)號(hào)返回給屬性zprocedurebr;stringlabz;labz:=genlab;emitl(‘JMP’,labz);return(labz);end;動(dòng)作程序@brf的功能是生成procedure10.6.4for循環(huán)語(yǔ)句for語(yǔ)句例子:

fori:=1tonbyzdo<statement>...

endfor;ATG文法1.<forloop>→<forhead>↑a,f,r<restofloop>↓a,f,r2.<forhead>↑a,f,r→for<id>↑a:=<expr>@initload↑sto@labgen↑r<expr>by

@loadid↓a<expr>@compare↓a,s↑f3.<restofloop>↓a,f,r→do<statlist>endfor

@retbranch↓r@labemit↓f@initload只生成給循環(huán)變量賦初值的指令。10.6.4for循環(huán)語(yǔ)句for語(yǔ)句例子:ATG文法1for<id>:=<expr1>to<expr2>by<expr3>do<statlist>LDA,(<id>)LOD,(expr1)loop:

start:<statement>…

JMP,loop

end_loop:LOD,(expr2)LOD,(id)LOD,(expr3)STNJMP,startBGT,end_loopADD

STO,(id)@initload↑s@labgen↑r@compare↓a,s↑f@retbranch↓r@labprod↓f@loadid↓afor<id>:=<expr1>toprocedurelabgenstringr;r:=genlab;setlab(r);return(r);end;procedurecompare(a,s);addressa;stringf,s;emit(‘ADD’);emitl(‘STO’,a);f:=genlab;emitl(‘BGT’,f);setlab(s);return(f);end;procedurelabprod(f)//即labemitstringf;setlab(f);end; procedureloadid(a)addressa;emitl(‘LOD’,a);end;procedurelabgenprocedurecom10.7過(guò)程調(diào)用和返回

實(shí)現(xiàn):

調(diào)用段(過(guò)程語(yǔ)句的目標(biāo)程序段):計(jì)算實(shí)參值=>操作數(shù)棧棧頂被調(diào)用段(過(guò)程說(shuō)明的目標(biāo)程序段):從棧頂取得值=>形參單元10.7.1參數(shù)傳遞的基本形式如C語(yǔ)言,Ada語(yǔ)言的in參數(shù),Pascal的值參數(shù)。1.傳值(callbyvalue)—值調(diào)用過(guò)程體中對(duì)形參的處理: 對(duì)形參的訪問(wèn)等于對(duì)相應(yīng)實(shí)參的訪問(wèn)特點(diǎn):數(shù)據(jù)傳遞是單向的10.7過(guò)程調(diào)用和返回實(shí)現(xiàn):10.7.1參數(shù)傳2.傳地址(callbyreference)—引用調(diào)用

實(shí)現(xiàn):

調(diào)用段:計(jì)算實(shí)參地址=>操作數(shù)棧棧頂被調(diào)用段:從棧頂取得地址=>形參單元

過(guò)程體中對(duì)形參的處理: 通過(guò)對(duì)形參的間接訪問(wèn)來(lái)訪問(wèn)相應(yīng)的實(shí)參

特點(diǎn):結(jié)果隨時(shí)送回調(diào)用段如:FORTRAN,Pascal的變量形參。如:ALGOL的換名形參。3.傳名(callbyname)

又稱(chēng)“名字調(diào)用”。即把實(shí)參名字傳給形參。這樣在過(guò)程體中引用形參時(shí),都相當(dāng)于對(duì)當(dāng)時(shí)實(shí)參變量的引用。當(dāng)實(shí)參變量為下標(biāo)變量時(shí),傳名和傳地址調(diào)用的效果可能會(huì)完全不同。傳名參數(shù)傳遞方式,實(shí)現(xiàn)比較復(fù)雜,其目標(biāo)程序運(yùn)行效率較低,現(xiàn)已很少采用。2.傳地址(callbyreference)—引用調(diào)用10.7.2過(guò)程調(diào)用處理與調(diào)用有關(guān)的動(dòng)作如下:1.檢查該過(guò)程名是否已定義(過(guò)程名和函數(shù)名不能用錯(cuò))實(shí)參和形參在類(lèi)型、順序、個(gè)數(shù)上是否一致。(查符號(hào)表)2.加載實(shí)參(值或地址)3.加載返回地址4.轉(zhuǎn)入過(guò)程體入口地址例:有過(guò)程調(diào)用:process_symb(symb,cursor,replacestr);調(diào)用該過(guò)程生成的目標(biāo)代碼為:LOD,(addrofsymb)LOD,(addrofcursor)LOD,(addrofreplacestr)JSR,(addrofprocess_symb)<retaddr>:….傳值調(diào)用

若實(shí)參并非上例中所示變量,而是表達(dá)式,則應(yīng)生成相應(yīng)計(jì)算實(shí)參表達(dá)式值的指令序列。

JSR指令先把返回地址壓入操作數(shù)棧,然后轉(zhuǎn)到被調(diào)過(guò)程入口地址。10.7.2過(guò)程調(diào)用處理與調(diào)用有關(guān)的動(dòng)作如下:1.檢查設(shè)過(guò)程說(shuō)明的首部有如下形式:procedureprocess_symb(string:symbal,int:cur,string:repl);

則過(guò)程體目標(biāo)代碼的開(kāi)始處應(yīng)生成以下指令,以存儲(chǔ)返回地址和形參的值。ALC,4+x/*x為定長(zhǎng)項(xiàng)空間*/STO,<actrecloc1>/*保存返回地址*/STO,<actrecloc4>/*保存replacestr*/STO,<actrecloc3>/*保存cursor*/STO,<actrecloc2>/*保存symb*/

過(guò)程調(diào)用時(shí),實(shí)參加載指令是把實(shí)參變量?jī)?nèi)容(或地址)送入操作數(shù)棧頂,過(guò)程聲明處理時(shí),應(yīng)先生成把操作數(shù)棧頂?shù)膶?shí)參送運(yùn)行棧AR中形參單元的指令。

將操作數(shù)棧頂單元內(nèi)容存入運(yùn)行棧(動(dòng)態(tài)存儲(chǔ)分配的數(shù)據(jù)區(qū))當(dāng)前活動(dòng)記錄的形式參數(shù)單元。可認(rèn)為此時(shí)運(yùn)行棧和操作數(shù)棧不是一個(gè)棧(分兩個(gè)棧處理)設(shè)過(guò)程說(shuō)明的首部有如下形式:procedureproce過(guò)程調(diào)用的ATG文法:<proccall>→<callhead>↑i,z@initm↑m<args>↓i,z@genjsr↓i<callhead>↑i,z→<id>↑n@lookupproc↓n↑i,z<args>↓i,z→@chklength↓i,z|(<arglist>↓i,z)<arglist>↓i,z→<expr>↑t@chktype↓t,i,m,z↑z<exprs>↓i,z<exprs>↓i,z→@chklength↓i,z

|,<expr>↑t

@chktype↓t,i,m,z↑z<exprs>↓i,zprocedurelookupproc(n);stringn;integeri,z;i:=lookup(n);/*查符號(hào)表*/ifi<1thenbeginerror(‘過(guò)程’,n,‘未定義’,statno);errorrecovery(panic);/*應(yīng)急處理過(guò)程*/return(i:=0,z:=0);endelsereturn(i,z:=symtbl[i].dim);/*z為形參數(shù)目*/end;過(guò)程調(diào)用的ATG文法:<proccall>→<callprocedurechktype(t,i,m,z);stringt;integerm,i,z;ifz<1thenbeginerror(‘實(shí)參數(shù)大于形參數(shù)’,symtbl[i].name,statno);return(z);endm:=m+1;/*實(shí)參計(jì)數(shù)*/ift≠symtbl[i+m].typethenerror(‘實(shí)參和形參類(lèi)型不匹配’,symtbl[i+m].name,statno);z:=z-1;/*減去已匹配的形參數(shù)*/return(z);/*剩下待匹配的形參數(shù)*/end;@chklenth應(yīng)檢驗(yàn)z最后值為0。否則表示實(shí)參數(shù)目小于形參數(shù)目。@genjsr生成JSR指令。該指令轉(zhuǎn)移地址為symbtbl[i].addrLOD,(addrofsymb)LOD,(addrofcursor)LOD,(addrofreplacestr)JSR,(addrofprocess_symb)<retaddr>:….procedurechktype(t,i,m,z)過(guò)程說(shuō)明(定義)的ATG文法如下:<procdefn>→<procdefnhead>@initcnt↑j

<parameters>↓j↑k

@emitstores↓k<procdefnhead>→procedure↑t<id>↑n

@tblinsert↓t,n<parameters>↓j↑k→@echo↓j↑k|(<parmlist>↓j↑k)<parmlist>↓j↑l→<type>↑t:<id>↑n

@tblinsert↓t,n

@upcnt↓j↑k

<parms>↓k↑l<parms>↓j↑l→@echo↓j↑l|,<type>↑t:<id>↑n

@tblinsert↓t,n

@upcnt↓j↑k

<parms>↓k↑l@tblinsert是把過(guò)程名和它的形參名填入符號(hào)表中:proceduretblinsert(t,n);stringt,n;integerhloc;iflookup(n)>0thenerror(‘名字定義重復(fù)’,statno);elsebeginhloc:=hashfctn(n);/*求散列函數(shù)值*/

hashtbl[hloc]:=s;/*s為符號(hào)表指針(下標(biāo)),為全局量*/symbtbl[s].name:=n;symbtbl[s].type:=t;s:=s+1;end;過(guò)程說(shuō)明(定義)的ATG文法如下:<procdefn>→<procedureemitstores(k);integerk;emitl(‘ALC’,k+x+…);emitl(‘STO’,<ll,x+1>);/*保存返回地址*/fori:=k+x+1downtox+2/*保存參數(shù)值*/emitl(‘STO’,<ll,i>)end;end;←s注:實(shí)際ALC指令所分配的空間應(yīng)在所有局部變量定義處理完以后,并考慮固定空間(前述‘x’)大小,反填回去。ALC,4+x/*x為定長(zhǎng)項(xiàng)空間*/STO,<actrecloc1>/*保存返回地址*/STO,<actrecloc4>/*保存replacestr*/STO,<actrecloc3>/*保存cursor*/STO,<actrecloc2>/*保存symb*/procedureemitstores(k);←s注:實(shí)10.7.3返回語(yǔ)句和過(guò)程體結(jié)束的處理其語(yǔ)義動(dòng)作有:1)若為函數(shù)過(guò)程,應(yīng)將操作數(shù)棧(或運(yùn)行棧)頂?shù)暮瘮?shù)結(jié)果值送入(存回)函數(shù)值結(jié)果單元2)生成無(wú)條件轉(zhuǎn)移返回地址的指令(JMPRA)3)產(chǎn)生刪除運(yùn)行棧中被調(diào)用過(guò)程活動(dòng)記錄的指令(只要根據(jù)DL—活動(dòng)鏈,把a(bǔ)bp退回去即可)10.7.3返回語(yǔ)句和過(guò)程體結(jié)束的處理其語(yǔ)義動(dòng)作有:1)第十章語(yǔ)義分析和代碼生成語(yǔ)義分析的概念棧式抽象機(jī)及其匯編指令聲明的處理表達(dá)式的處理賦值語(yǔ)句的處理控制語(yǔ)句的處理過(guò)程調(diào)用和返回第十章語(yǔ)義分析和代碼生成語(yǔ)義分析的概念假定:源語(yǔ)言:通用的過(guò)程語(yǔ)言生成代碼:棧式抽象機(jī)的(偽)匯編程序翻譯方法:自頂向下的屬性翻譯語(yǔ)法成分翻譯子程序參數(shù)設(shè)置:繼承屬性為值形參綜合屬性為變量形參語(yǔ)法成分翻譯動(dòng)作子程序參數(shù)設(shè)置:繼承屬性為值形參綜合屬性不設(shè)形參,而作為動(dòng)作子程序的返回值(由RETURN語(yǔ)句返回)假定:源語(yǔ)言:通用的過(guò)程語(yǔ)言10.1語(yǔ)義分析的概念1、上下文有關(guān)分析:即標(biāo)識(shí)符的作用域2、類(lèi)型的一致性檢查3、語(yǔ)義處理:

聲明語(yǔ)句:其語(yǔ)義是聲明變量的類(lèi)型等,并不要求做其他的操作。編譯程序的工作是填符號(hào)表,登錄名字的特征信息,分配存儲(chǔ)。

執(zhí)行語(yǔ)句:語(yǔ)義是要做某種操作。語(yǔ)義處理的任務(wù):按某種操作的目標(biāo)結(jié)構(gòu)生成代碼。10.1語(yǔ)義分析的概念1、上下文有關(guān)分析:即標(biāo)識(shí)符的作用域

用上下文無(wú)關(guān)文法只能描述語(yǔ)言的語(yǔ)法結(jié)構(gòu),而不能描述其語(yǔ)義。例如,對(duì)于有嵌套子程序結(jié)構(gòu)的程序段:BEGIN…BEGINαINTIβIEND…I…END若存在文法規(guī)則:VAR::=I

BEGIN…<BLOCK>…I...END

BEGIN…δVAR...ENDδ

∈V*且不包含變量I的聲明文法規(guī)則應(yīng)改為:INTIβVAR::=INTIβI第一次I的歸約正確第二次I的歸約錯(cuò)誤用上下文無(wú)關(guān)文法只能描述語(yǔ)言的語(yǔ)法結(jié)構(gòu),例如

然而上下文有關(guān)文法不僅構(gòu)造困難,而且其分析器十分復(fù)雜,分析效率又低,顯然是不實(shí)用的

因此,通常我們把與語(yǔ)義相關(guān)的上下文有關(guān)信息填入符號(hào)表中,并通過(guò)查符號(hào)表中的這些信息來(lái)分析程序的語(yǔ)義是否正確然而上下文有關(guān)文法不僅構(gòu)造困難,因10.2棧式抽象機(jī)及其匯編指令棧式抽象機(jī):由三個(gè)存儲(chǔ)器、一個(gè)指令寄存器和多個(gè)地址寄存器組成。存儲(chǔ)器:數(shù)據(jù)存儲(chǔ)器(存放AR的運(yùn)行棧)操作存儲(chǔ)器(操作數(shù)棧)指令存儲(chǔ)器10.2棧式抽象機(jī)及其匯編指令棧式抽象機(jī):由三個(gè)存儲(chǔ)器、一計(jì)算機(jī)的存儲(chǔ)大致情況如下:P-code指令PC程序指令存儲(chǔ)器棧底運(yùn)行棧堆(堆底)NPSPBP當(dāng)前模塊活動(dòng)記錄(數(shù)據(jù)段)計(jì)算機(jī)的存儲(chǔ)大致情況如下:P-code指令PC程序指令存儲(chǔ)器指令名稱(chēng)操作碼地址指令意義加載指令LODD將D的內(nèi)容→棧頂立即加載LDC常量常量→棧頂?shù)刂芳虞dLDA(D)變量D的地址→棧頂存儲(chǔ)STOD棧頂內(nèi)容

→變量D間接存ST@D將棧頂內(nèi)容→D所指單元間接存STN將棧頂內(nèi)容→次棧頂所指單元加ADD棧頂和次棧頂內(nèi)容相加,結(jié)果留棧頂減SUB次棧頂內(nèi)容減棧頂內(nèi)容乘MUL存入………棧式抽象機(jī)指令代碼如下:指令名稱(chēng)操作碼地址指令意義加載指令LODD將D的內(nèi)容→棧頂立指令名稱(chēng)操作碼地址指令意義等于比較EQL不等比較NEQ大于比較GRT次棧頂內(nèi)容與棧頂內(nèi)容比較,結(jié)果(1或0)留棧頂小于比較LES大于等于GTE小于等于LSE邏輯與AND邏輯或ORL邏輯非NOT轉(zhuǎn)子JSRlab分配ALCM在運(yùn)行棧頂分配大小為M的活動(dòng)記錄區(qū)指令名稱(chēng)操作碼地址指令意義等于比較EQL不等比較NEQ大于比10.3聲明的處理語(yǔ)義的表示:

給出語(yǔ)言結(jié)構(gòu)的屬性翻譯文法來(lái)說(shuō)明其語(yǔ)義及語(yǔ)義動(dòng)作,并把這些語(yǔ)義動(dòng)作插入屬性翻譯文法產(chǎn)生式中的適當(dāng)位置。編譯程序處理聲明語(yǔ)句要完成的主要任務(wù)為:編譯程序的任務(wù):1)

分離出每一個(gè)被聲明的實(shí)體,并把它們的名字填入符號(hào)表中2)把被聲明實(shí)體的有關(guān)特性信息盡可能多地填入符號(hào)表中對(duì)于已聲明的實(shí)體,在處理對(duì)該實(shí)體的引用時(shí)要做的事情:1)檢查對(duì)所聲明的實(shí)體引用(種類(lèi),類(lèi)型等)是否正確2)根據(jù)實(shí)體的特征信息,例如類(lèi)型,所分配的目標(biāo)代碼地址(可能為數(shù)據(jù)區(qū)單元地址,或目標(biāo)程序入口地址)生成相應(yīng)的目標(biāo)代碼10.3聲明的處理語(yǔ)義的表示: 給出語(yǔ)言結(jié)構(gòu)的屬性翻譯文法聲明的兩種方式:(1)類(lèi)型說(shuō)明符放在變量的前面。如:C語(yǔ)言:inta;在填表時(shí)已知類(lèi)型和a的值(名字):直接填入符號(hào)表。(2)類(lèi)型說(shuō)明符放在變量的后面,如:Pascal,PL/1,Ada等,需要返填。

聲明有常量聲明,變量(包括簡(jiǎn)單變量,數(shù)組變量和記錄變量等)和過(guò)程(函數(shù))聲明等,這里主要討論常量聲明和簡(jiǎn)單變量、數(shù)組聲明的處理。如PL/I聲明語(yǔ)句:DECLARE(X,Y(N),YTOTAL)FLOAT;聲明的兩種方式:聲明有常量聲明,變量(包括簡(jiǎn)單聲明語(yǔ)句的輸入文法為:<declaration>→DECLARE@dec_on↑x‘(’<entitylist>‘)’<type>↑t@fix_up↓x,t

<entitylist>→<entityname>↑n@name_defn↓n

|<entityname>↑n,@name_defn↓n<entitylist><type>↑t→FIXED↑t|FLOAT↑t|CHAR↑t<declaration>→DECLARE‘(’<entitylist>‘)’<type><entitylist>→<entityname>|<entityname>,<entitylist><type>→FIXED|FLOAT|CHAR屬性翻譯文法為:聲明語(yǔ)句的輸入文法為:<declaration>→DECLA@name_defn↓n是將由各實(shí)體名所得的n繼承屬性值,依次填入從x開(kāi)始的符號(hào)表中。注:顯然應(yīng)有內(nèi)部計(jì)數(shù)器或內(nèi)部指針,指向下一個(gè)該填的符號(hào)表項(xiàng)。@fix_up↓x,t是將類(lèi)型信息t和相應(yīng)的數(shù)據(jù)存儲(chǔ)區(qū)分配地址填入從x位置開(kāi)始的符號(hào)表中。(反填)當(dāng)然,如果聲明語(yǔ)句中,類(lèi)型說(shuō)明符放在頭上,就無(wú)需“反填”處理了。動(dòng)作程序@dec_on↑x是把符號(hào)表當(dāng)前可用表項(xiàng)的入口地址(指向符號(hào)表入口的指針,或稱(chēng)表項(xiàng)下標(biāo)值)賦給屬性變量x。@name_defn↓n是將由各實(shí)體名所得的n繼承屬性值,10.3.1常量類(lèi)型聲明處理常量標(biāo)識(shí)符通常被看作是全局名。常量聲明的ATG如下:<constdel>

→constant<type>↑t<entity>↑n:=<constexpr>↑c(diǎn),s

@insert↓t,n,c,s;<type>↑t→real↑t|integer↑t|string↑t

<constexpr>↑c(diǎn),s→<integerconst>↑c(diǎn),s|<realconst>↑c(diǎn),s

|<stringconst>↑c(diǎn),s由該文法產(chǎn)生的一個(gè)聲明實(shí)例為:constantintegerSYMBSIZE:=1024;10.3.1常量類(lèi)型聲明處理常量標(biāo)識(shí)符通常被看作是全局名。翻譯處理過(guò)程為:

先識(shí)別類(lèi)型(integer),將它賦給屬性t;然后識(shí)別常量名字(SYMBSIZE),將它賦給屬性n;最后識(shí)別常量表達(dá)式,并將其值賦給c,其類(lèi)型賦給屬性s?!顯insert的功能是:①檢查聲明的類(lèi)型t和常量表達(dá)式的類(lèi)型s是否一致,若不一致,則輸出錯(cuò)誤信息②把名字n,類(lèi)型t和常量表達(dá)式的值c填入符號(hào)表中<constdel>

→constant<type>↑t<entity>↑n:= <constexpr>↑c(diǎn),s@insert↓t,n,c,s;翻譯處理過(guò)程為:先識(shí)別類(lèi)型(integer),將它賦10.3.2簡(jiǎn)單變量聲明處理ATG文法:<svardel>

→<type>↑t,i<entity>↑n

@svardef↓t,i,n

@allocsv↓i

;<type>↑t,i→real↑t,i|integer↑t,i|character↑t(<number>)↑i

|logical↑t,i

簡(jiǎn)單變量聲明的例子:realx;integerj;character(20)s;n:變量名t:類(lèi)型值i:該類(lèi)型變量所需數(shù)據(jù)空間的大小10.3.2簡(jiǎn)單變量聲明處理ATG文法:<svardelproceduresvardef(t,i,n);j:=tableinsert(n,t,i);/*將有關(guān)信息填入符號(hào)表*/ifj=0//填表時(shí)要檢查是否重名thenerrmsg(duplident,statementno);elseifj=-1//符號(hào)表已滿thenerrmsg(tblovflow,statementno);endsvardef;procedureallocsv(i);codeptr:=codeptr+i;//codeptr為分配地址指針endallocsv;@allocsv和@svardef可以合并@svardef動(dòng)作符號(hào)是把n,i和t填入符號(hào)表中。proceduresvardef(t,i,n);

對(duì)于變長(zhǎng)字符串(或其它大小可變的數(shù)據(jù)實(shí)體),往往需要采用動(dòng)態(tài)申請(qǐng)存儲(chǔ)空間的辦法把可變長(zhǎng)實(shí)體存儲(chǔ)在堆中。我們可通過(guò)指向存放該實(shí)體數(shù)據(jù)區(qū)的指針來(lái)引用該實(shí)體,有時(shí)還應(yīng)得到該實(shí)體存儲(chǔ)空間的大小信息,并一起填入符號(hào)表內(nèi)。10.3.3數(shù)組變量聲明的處理

對(duì)于靜態(tài)數(shù)組,即數(shù)組的大小在編譯時(shí)是已知的,編譯程序在處理數(shù)組聲明時(shí),可建立一個(gè)數(shù)組模板(又稱(chēng)為數(shù)組信息向量)以便以后的程序中引用該數(shù)組元素時(shí),可按照該模板提供的信息,計(jì)算數(shù)組元素(下標(biāo)變量)的存儲(chǔ)地址。對(duì)于動(dòng)態(tài)數(shù)組,其大小只有在運(yùn)行時(shí)才能最后確定。我們?cè)诰幾g時(shí)僅為該模板分配一個(gè)空間,而模板本身的內(nèi)容將在運(yùn)行時(shí)才能填入。對(duì)于變長(zhǎng)字符串(或其它大小可變的數(shù)據(jù)實(shí)體),往往

大部分程序設(shè)計(jì)語(yǔ)言,數(shù)組元素是按行(優(yōu)先)存放在存儲(chǔ)器中的*,如聲明數(shù)組arrayB(N,-2:1) char;B:*FORTRAN例外,它按列(優(yōu)先)存放數(shù)組元素實(shí)際數(shù)組B各元素的存儲(chǔ)次序?yàn)椋篖OC是數(shù)組首地址(該數(shù)組第一個(gè)元素的地址)LOC→大部分程序設(shè)計(jì)語(yǔ)言,數(shù)組元素是按行(優(yōu)先)存放在存儲(chǔ)a)n維數(shù)組的地址計(jì)算公式設(shè)數(shù)組的維數(shù)為n,各維的下界和上界為L(zhǎng)(i)和U(i)例如,上例二維數(shù)組BL(1)=1(隱含值),U(1)=NL(2)=-2,U(2)=1還假定n維數(shù)組元素的下標(biāo)為V(1),V(2),…,V(n)則該數(shù)組元素的地址計(jì)算公式為:其中P(i)=

1當(dāng)i=n時(shí)當(dāng)1≤i<n時(shí)注:E為數(shù)組元素大?。ㄗ止?jié)數(shù))a)n維數(shù)組的地址計(jì)算公式例如,上例二維數(shù)組B還假定n維數(shù)其中P(i)=

1當(dāng)i=n時(shí)當(dāng)1≤i<n時(shí)U(2)L(2)L(1)U(1)U(3)L(3)v2v3v1A(v1,v2,v3)[

V(1)-L(1)]*[U(2)-L(2)+1]*[U(3)-L(3)+1]*E+[

V(2)-L(2)]*[U(3)-L(3)+1]*E+[V(3)-L(3)]*1*EP(2)P(3)P(1)其中P(i)=1若令(不變部分)則地址

RC為數(shù)組元素地址計(jì)算公式中的不變部分。因?yàn)椋灰罃?shù)組的維數(shù)和每一維的上下界值,便可求得RC值。以前面所舉的二維數(shù)組B為例,若N=3則P(1)=[U(2)-L(2)+1]=1-(-2)+1 =4P(2)=1RC==-[1×4+(-2)×1]×E=-2E因此,若有數(shù)組元素B(2,1),則它的地址為:=LOC–2E+(2×4+1×1)×E=LOC+7×E若令(不變部分)則地址RC為數(shù)組元素地址計(jì)算公式中的U(2)L(2)L(1)U(1)U(3)L(3)v2v3v1A(v1,v2,v3)三維數(shù)組的例子數(shù)組模板的一般形式如下左圖所示,而對(duì)于數(shù)組B的模板如下右圖所示:1-213142-2U(n)L(n)P(n)U(1)L(1)P(1)nRC...數(shù)組信息向量表arrayB(3,-2:1)char;U(2)L(2)L(1)U(1)U(3)L(3)v2v3v1b)數(shù)組信息向量表(模板)功能:1、用于計(jì)算下標(biāo)變量地址2、檢查下標(biāo)是否越界U(n)L(n)P(n).......U(1)L(1)P(1)nRC上界下界計(jì)算地址用常量大?。?n+2注:1、數(shù)組模板所需的空間大小取決于數(shù)組的維數(shù),即3n+2

無(wú)論是常界或變界數(shù)組,在編譯時(shí)就能確定數(shù)組模板的大小2、常界數(shù)組,在編譯時(shí)就可造信息向量表;而變界數(shù)組信息向量表要在目標(biāo)程序運(yùn)行時(shí)才能造。編譯程序要生成相應(yīng)的指令一般形式:b)數(shù)組信息向量表(模板)U(n)L(n)P(n)....1-213142-2以前面所舉的二維數(shù)組B為例,若N=3

P(1)=[U(2)-L(2)+1]=1-(-2)+1 =4P(2)=1RC=

=-[1×4+(-2)×1]=-2數(shù)組信息向量表U(2)--上界L(2)--下界P(2)--計(jì)算地址常量U(1)--上界L(1)--下界P(1)--計(jì)算地址常量n---維數(shù)RC1-213142-2以前面所舉的二維數(shù)組B為例,若N=3數(shù)組聲明的ATG文法:<arraydel>→array↑k@init↑j<entity>↑n(<sublist>↑j

)<type>↑t@symbinsert↓j,n,t<sublist>↑j

→<subscript>@dimen#↑j

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論