原理實(shí)驗講義pl0編譯程序注釋_第1頁
原理實(shí)驗講義pl0編譯程序注釋_第2頁
原理實(shí)驗講義pl0編譯程序注釋_第3頁
原理實(shí)驗講義pl0編譯程序注釋_第4頁
原理實(shí)驗講義pl0編譯程序注釋_第5頁
已閱讀5頁,還剩26頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

PL0編譯程序 PL0(input,{帶有代碼生成的PL0編譯程序 norw=11;{保留字的個數(shù)}txmax=100;{標(biāo)識符表長度}nmax14;數(shù)字的最大位數(shù)}al=10;{標(biāo)識符的長度}amax2047;最大地址levmax3;程序體嵌套的最大深度}cxmax=200;{代碼數(shù)組的大小}symbol=(nul,ident,number,plus,minus,times,slash,oddsym,eql,neq,lss,leq,gtr,geq,lparen,rparen,comma,semicolon, es,beginsym,endsym,ifsym,thensym,whilesym,dosym,callsym,constsym,varsym,procsym);alfa=packedarray[1..al]ofchar;object=(constant,variable,procedure);symset=setofsymbol;fct=(lit,opr,lod,sto,cal,int,jmp,jpc);instruction=packedf {功能碼l0..levmax;相對層數(shù)a0..amax;相對地址{LIT0,a:取常數(shù)aOPR0,a:執(zhí)行運(yùn)算aLODl,a:取層差為l的層﹑相對地a的變量STOl,a:存到層差為l的層﹑相對地址為a的變量CALl,a:調(diào)用層差為l的過程INT0,at寄存器增加JMP0,a:轉(zhuǎn)移到指令地址aJPC0,a:條件轉(zhuǎn)移到指令地址achchar最近讀到的字符symsymbol最近讀到的符號}id:alfa;{最近讀到的標(biāo)識符}num:integer;{最近讀到的數(shù)}ccinteger當(dāng)前行的字符計數(shù)}ll:integer;{當(dāng)前行的長度}kk,err:cxinteger代碼數(shù)組的當(dāng)前下標(biāo)linearray[1..81]ofchar當(dāng)前行}a:alfa;{當(dāng)前標(biāo)識符的字符串}code:array[0..cxmax]ofinstruction;{中間代碼數(shù)組}word:array[1..norw]ofalfa;{存放保留字的字符串}wsymarray[1..norwofsymbol存放保留字的記號}ssymarray[charofsymbol存放算符和標(biāo)點(diǎn)符號的記號}mnemonic:array[fct]ofpackedarray[1..5]ofchar;{中間代碼算符的字符串declbegsysstatbegsysfacbegsyssymset;table:array[0..txmax]of{符號表}name:casekind:objectconstant:(val:variable,procedure:(level,adr:procedureerror(n: n(‘****’,‘‘:cc―1,‘↑’,n: err:=err+{cc為當(dāng)前行已讀的字符數(shù)n為錯誤號}{錯誤數(shù)errend i,j,k: getch取下一字符ifccllthen{如果cc指向行末ifeof(inputthen{如果已到文件尾 PLETE’);goto{讀新的一行l(wèi)l:=0;cc:=0;write(cx:5,‘{cx5位數(shù)whileeoln(input)do{如果不是行末ll:=ll+1;read(ch);write(ch);line[ll]:=ch wrin;ll:=ll+1; {line[ll]中是行末符cccc1;ch {chline中下一個字符endbegin{getsym}whilechdogetch;跳過無用空白ifchin[‘A’..’Z’]begin{標(biāo)識符或保留字krepeat{處理字母開頭的字母﹑數(shù)字串ifk<albegink:=k+1;a[k]:=until(chin[‘A’..’Z’,ifk≥ thenkk:=krepeata[kk]kkkk―1如果標(biāo)識符長度不是untilkk=k; 大長度,后面補(bǔ)空白}id:=a; i:=1; j:=norw;{id中存放當(dāng)前標(biāo)識符或保留字的字符串 ki+j)div2;用二分查找法在保留字表中ifidword[k]thenj 當(dāng)前的標(biāo)識符ifid≥word[k]theni:=k+untili>ifi―1>jthensym:=wsym[k]elsesym:={如果找到,當(dāng)前記號sym為保留字,否則sym為標(biāo)識符endifchin[‘0’..’9’]begin{數(shù)字k num symnumber當(dāng)前記號sym為數(shù)字repeat{計算數(shù)字串的值num:=10*num+{ord(ch)和ord(0)是ch和0在ASCII碼中的序號}k:=k+1; until(chinifk>nmax {當(dāng)前數(shù)字串的長度超過上界,則報告錯誤endifchthen{處理賦值號 ifch=‘=’ sym:= es;getchend sym:=nul;endelse{處理其它算符或標(biāo)點(diǎn)符號 sym:= end gen(x:fct;y,z:ifcxcxmaxthen{如果當(dāng)前指令序號>代碼的最大長度beginwrite(‘PROGRAMTOOLONG’);gotowithcode[cx]do{在代碼數(shù)組cx位置生成一條新代碼} f:=x;{功能碼}l:=y;{層號}a:=z{地址}cxcx1指令序號加end test(s1,s2:symset;n:if(symins1){如果當(dāng)前記號不屬于集合S1,則報告錯誤 s1:=s1+while(symins1)do{跳過一些記號,直到當(dāng)前記號屬于end block(lev,tx:integer;fsys:dxinteger本過程數(shù)據(jù)空間分配下標(biāo)}tx0:integer;{本過程標(biāo)識表起始下標(biāo)}cx0:integer;{本過程代碼起始下標(biāo)} enter(k:begin{object填入符號表中}txtx1;符號表指針加withtable[tx]do{在符號表中增加新的一個條目} name:=id;{當(dāng)前標(biāo)識符的名字}kindk;當(dāng)前標(biāo)識符的種類casekconstantbegin{當(dāng)前標(biāo)識符是常數(shù)名ifnumamaxthen{當(dāng)前常數(shù)值大于上界,則出錯beginerror(30);num:=0end;val:=numvariablebegin{當(dāng)前標(biāo)識符是變量名level:=lev;{定義該變量的過程的嵌套層數(shù)}adrdx;變量地址為當(dāng)前過程數(shù)據(jù)空間棧頂}dx:=dx+1;{棧頂指針加1}procedurelevellev本過程的嵌套層數(shù)end position(id:alfa):integer;{返回id在符號表的 i:begin{在標(biāo)識符表中查標(biāo)識符table[0].nameid;在符號表棧的最下方預(yù)填標(biāo)識符id}i:=tx;{符號表棧頂指針}whiletable[i].name≠iddoi:={從符號表棧頂往下查標(biāo)識符position:=i{若查到,i為id的,否則i=0endifsymidentthen{當(dāng)前記號是常數(shù)名 ifsymin es]then{當(dāng)前記號是等號或賦值號ifsym esthenifsymnumberthen{等號后面是常數(shù) enter(constant將常數(shù)名加入符號表}elseerror(2){等號后面不是常數(shù)出錯endelseerror(3){標(biāo)識符后不是等號或賦值號出錯endelseerror(4)常數(shù)說明中沒有常數(shù)名標(biāo)識符end{constdeclaration}; ifsymidentthen{如果當(dāng)前記號是標(biāo)識符 enter(variable將該變量名加入符號表的下一條目}endelseerror(4){如果變量說明未出現(xiàn)標(biāo)識符,則出錯end{vardeclaration}; i:integer; {列出本程序體生成的代碼foricx0tocx―1do{cx0:本過程第一個代碼的序號{cx―1:本過程最后一個代碼的序號withcode[ido{打印第i條代碼 n(i,mnemonic[f]:5,l:3,a:{i:代碼序號mnemonic[f]:功能碼的字符串;l:相對層號(層差);a:相對地址或運(yùn)算號碼end statement(fsys: i,cx1,cx2: expression(fsys: addop: term(fsys: mulop: factor(fsys:vari: test(facbegsys,fsys,{測試當(dāng)前的記號是否因子的開始符號否則出錯,跳過一些記號whilesyminfacbegsys{如果當(dāng)前的記號是否因子的開始符號ifsymidentthen{當(dāng)前記號是標(biāo)識符i:=position(id);{查符號表,返回id的ifi=0thenerror(11){若在符號表中查不到id,則出錯,否則,做以下工作withtable[i]docasekindofconstant:gen(lit,0,{id是常數(shù),生成指令,將常數(shù)val取到棧頂variable:gen(lod,lev―level,{id是變量,生成指令,將該變量取到棧頂;lev:當(dāng)前語句所在過程的層號;level:定義該變量的過程層號adr:變量在其過程的數(shù)據(jù)空間的相對地址}procedure:error(21){id是過程名,則出錯getsym{取下一記號endifsymnumberthen{當(dāng)前記號是數(shù)字ifnumamaxthen{若數(shù)值越界,則出錯beginerror(30);num:=0gen(lit,0,{生成一條指令,將常數(shù)num取到棧頂}getsym{取下一記號}endifsymlparenthen{如果當(dāng)前記號是左括號 getsym;{取下一記號}expression([rparen]+fsys處理表達(dá)式}ifsym=rparenthengetsym{如果當(dāng)前記號是右括號,則取下一記號,否則出錯elsetest(fsys,[lparen],{測試當(dāng)前記號是否同步,否則出錯,跳過一些記號endendbeginfactor(fsys+[times,slash]);{處理項中第一個因子whilesymin[times,slash]{當(dāng)前記號是“乘”或“除”號mulopsym;運(yùn)算符存入mulop}getsym;{取下一記號}factor(fsys+[times,slash]);{處理一個因子ifmulop=timesthengen(opr,0,{若mulop是“乘”號,生成一條乘法指令elsegen(opr,0,{否則mulop是除號,生成一條除法指令endbeginifsymin[plusminusthen{若第一個記號是加號或減號addop:=sym; term(fsys+[plus,minus]);{處理一個項ifaddop=minusthengen(opr,0,{若第一個項前是負(fù)號,生成一條“負(fù)運(yùn)算”指令endelseterm(fsys+[plus,{第一個記號不是加號或減號,則處理一個項whilesymin[plusminusdo{若當(dāng)前記號是加號或減號addopsym;當(dāng)前算符存入addop}getsym;{取下一記號}term(fsys+[plus,minus]);{處理一個項ifaddop=plusthengen(opr,0,{若addop是加號,生成一條加法指令elsegen(opr,0,{否則addop是減號,生成一條減法指令end condition(fsys: relop:ifsymoddsymthen{如果當(dāng)前記號 expression(fsys處理算術(shù)表達(dá)式}gen(opr,0,6){生成指令,判定表達(dá)式的值是否為奇數(shù)是,則取“真”;不是,則取“假”}endelse{如果當(dāng)前記號不是“odd”}expression([eql,neq,lss,gtr,leq,geq]+{處理算術(shù)表達(dá)式if(symin[eql,neq,lss,leq,gtr,geq]){如果當(dāng)前記號不是關(guān)系符,則出錯;否則,做以下工作} relopsym;關(guān)系符存入relop}getsym;{取下一記號}expression(fsys);{處理關(guān)系符右邊的算術(shù)表達(dá)式caserelopeql:gen(opr,0,{生成指令,判定兩個表達(dá)式的值是否相等}neq:gen(opr,0,9);{生成指令,判定兩個表達(dá)式的值是否不等}lss:gen(opr,0,10);geq:gen(opr,0,11);gtr:gen(opr,0,12);leq:gen(opr,0,13);{生成指令,判定前一表達(dá)式是否小于等于后一表達(dá)式endbeginifsymidentthen{處理賦值語句 i:={在符號表中查id,返回id在符號表中的ifi=0thenerror(11){若在符號表中查不到id,則出錯,否則做以下工作iftable[i].kind≠variable{若標(biāo)識符id不是變量,則出錯begin{對非變量賦值error(12i0;getsym;{取下一記號ifsym esthengetsymelse{若當(dāng)前是賦值號,取下一記號,否則出錯}expression(fsys);{處理表達(dá)式}ifi0then{若賦值號左邊的變量id有定義withtable[i]dogen(sto,lev―level,{生成一條存數(shù)指令,將棧頂(表達(dá)式)的值存入變量id中;lev:當(dāng)前語句所在過程的層號;level:定義變量id的過程的層號adr:變量id在其過程的數(shù)據(jù)空間的相對地址endifsymcallsymthen{處理過程調(diào)用語句 getsym;{取下一記號ifsym≠identthenerror(14){如果下一記號不是標(biāo)識符(過程名),則出錯否則做以下工作iposition(id查符號表,返回id在表中的位置ifi=0thenerror(11){如果在符號表中查不到,則出錯;否則,做以下工作withtable[i]ifkind=procedure{如果在符號表中id是過程名}gen(cal,lev―level,adr){生成一條過程調(diào)用指令lev:當(dāng)前語句所在過程的層level:定義過程名id的層號adr:過程id的代碼中第一條指令的地址elseerror(15id不是過程名,則出錯}getsym{取下一記號}endelseifsymifsymthen{處理條件語句getsym;{取下一記號condition([thensym,dosym]+fsys);{處理條件表達(dá)式ifsym=thensymthengetsymelse{如果當(dāng)前記號是“then”,則取下一記號;否則出錯}cx1:=cx;{cx1記錄下一代碼的地址}gen(jpc,0,0);{生成指令,表達(dá)式為“假”轉(zhuǎn)到某地址(待填否則順序執(zhí)行statement(fsys處理一個語句}code[cx1].a:=cx{將下一個指令的地址回填到上面的jpc指令地址欄endifsymbeginsymthen{處理語句序列 statement([semicolon,{取下一記號,處理第一個語句whilesymin[semicolon]+statbegsys{如果當(dāng)前記號是分號或語句的開始符號,則做以下工作ifsym=semicolonthengetsymelse{如果當(dāng)前記號是分號,則取下一記號,否則出錯}statement([semicolon,endsym]+fsys處理下一個語句}ifsym=endsymthengetsymelse{如果當(dāng)前記號是“end”,則取下一記號,否則出錯endifsymwhilesymthen{處理循環(huán)語句cx1cx;cx1記錄下一指令地址,即條件表達(dá)式的getsym;{取下一記號}condition([dosym]+fsys處理條件表達(dá)式}cx2:=cx;{記錄下一指令的地址}gen(jpc,0,0生成一條指令,表達(dá)式為“假”轉(zhuǎn)到某地址(待回填),否則順序執(zhí)行}ifsym=dosymthengetsymelse{如果當(dāng)前記號是“do”,則取下一記號,否則出錯}statement(fsys);{處理“do”后面的語句}gen(jmp,0,cx1生成無條件轉(zhuǎn)移指令,轉(zhuǎn)移到“while”后的code[cx2].a:={把下一指令地址回填到前面生成的jpc指令的地址欄test(fsys,[],{測試下一記號是否正常,否則出錯,跳過一些記號endbegindx:=3;{本過程數(shù)據(jù)空間棧頂指針}tx0tx;標(biāo)識符表的長度(當(dāng)前指針)}table[tx].adrcx;本過程名的地址,即下一條指令的序號}gen(jmp,0,0);{生成一條轉(zhuǎn)移指令}iflev>levmaxthen{如果當(dāng)前過程層號>最大層數(shù),則出錯ifsymconstsymthen{處理常數(shù)說明語句 constdeclaration;{處理一個常數(shù)說明whilesymcommado{如果當(dāng)前記號是逗號begingetsym;constdeclarationend處理下一個常數(shù)說明ifsym=semicolonthengetsymelse{如果當(dāng)前記號是分號,則常數(shù)說明已處理完,否則出錯untilsym≠{跳過一些記號,直到當(dāng)前記號不是標(biāo)識符(出錯時才用到ifsymvarsymthen{當(dāng)前記號是變量說明語句開始符號 vardeclaration;{處理一個變量說明whilesymcommado{如果當(dāng)前記號是逗號 {處理下一個變量說明ifsym=semicolonthengetsymelse{如果當(dāng)前記號是分號,則變量說明已處理完,否則出錯untilsym≠{跳過一些記號,直到當(dāng)前記號不是標(biāo)識符(出錯時才用到whilesymprocsymdo{處理過程說明 ifsymidentthen{如果當(dāng)前記號是過程名 {把過程名填入符號表elseerror(4否則,缺少過程名出錯ifsym=semicolonthengetsymelse{當(dāng)前記號是分號,則取下一記號,否則,過程名后漏掉分號出block(lev+1,tx,semicolon]+fsys處理過程體{lev+1:過程嵌套層數(shù)加1;tx:符號表當(dāng)前棧頂指針,也是新過程符號表起始位置;[semicolon]+fsys:過程體開始和末尾符號集}ifsymsemicolonthen{如果當(dāng)前記號是分號 getsym;{取下一記號}test(statbegsys+[ident,procsymfsys6){測試當(dāng)前記號是否語句開始符號或過程說明開始符號否則報告錯誤6,并跳過一些記號elseerror(5){如果當(dāng)前記號不是分號,則出錯end;test(statbegsys+[ident],declbegsys,{檢測當(dāng)前記號是否語句開始符號,否則出錯,并跳過一記號until(symin{回到說明語句的處理(出錯時才用),的開始符號}code[table[tx0].adr].a:=cx; {table[tx0].adr是本過程名的第1條代碼(jmp,0,0)的地址,本語句即是將下一代碼(本過程語句的第1條代碼)的地址回填到該jmp指令中,得(jmp,0,withtable[tx0do{本過程名的第1條代碼的地址改為下一地址cx} adr:=cx;{代碼開始地址}cx0cx;cx0記錄起始代碼地址gen(int0,dx生成一條指令,在棧頂為本過程留出數(shù)據(jù)空間}statement([semicolon,endsym]+fsys);{處理一個語句}gen(opr0,0生成返回指令test(fsys8測試過程體語句后的符號是否正常,否則出錯}listcode;{打印本過程的中間代碼序列} stacksize500;運(yùn)行時數(shù)據(jù)空間(棧)的上界 p,b,t:integer;{程序地址寄存器,址寄存器,棧頂?shù)刂穒instruction;指令寄存器s:array[1..stacksize]ofinteger;{數(shù)據(jù)棧 base(l:integer): b1:b1:=b;{順靜態(tài)鏈求層差為l的外層的址whilel>0 b1:= l:=l―1base:=end t:=0;{棧頂?shù)刂芳拇嫫鱹b:=1;{址寄存器p0;程序地址寄存器s[1]:= s[2]:= s[3]:={最外層主程序數(shù)據(jù)空間棧最下面預(yù)留三個單元{每個過程運(yùn)行時的數(shù)據(jù)空間的前三個單元是:SLDLRA;SL:指向本過程靜態(tài)直接外層過程的SL單元;DL:指向調(diào)用本過程的過程的數(shù)據(jù)空間的第一個單元;RA:返回地址}icode[p{i取程序地址寄存器p指示的當(dāng)前指令pp+1;程序地址寄存器p1,指向下一條指令withidocasefoflitbegin{當(dāng)前指令是取常數(shù)指令(lit,0,t:= s[t]:={棧頂指針加1,把常數(shù)a取到棧頂oprcaseaof{當(dāng)前指令是運(yùn)算指令(opr0,a)}0:begin{a=0時,是返回調(diào)用過程指令}tb―1;恢復(fù)調(diào)用過程棧頂ps[t+3];程序地址寄存器p取返回地址}b:=s[t+2];{址寄存器b指向調(diào)用過程的址s[t]:=―s[t一元負(fù)運(yùn)算,棧頂元素的值反號begin{加法t:= s[t]:=s[t]+begin{減法t:= s[t]:=begin{乘法t:= s[t]:=s[t]*begin{整數(shù)除法t:= s[t]:=s[t]div:s[t]:={算s[t]是否奇數(shù),是則s[t]=1,否則s[t]=0}8:begin t:=t―1;s[t]:=ord(s[t]=end;{判兩個表達(dá)式的值是否相等是則s[t]=1,否則s[t]=0}9:begin t:=t―1;s[t]:=ord(s[t]≠end;{判兩個表達(dá)式的值是否不等是則s[t]=1,否則s[t]=0}10:begin t:=t―1;s[t]:=ord(s[t]<end;{判前一表達(dá)式是否小于后一表達(dá)式是則s[t]=1,否則s[t]=0}11:begin t:=t―1;s[t]:=ord(s[t]≥end;{判前一表達(dá)式是否大于或等于后一表達(dá)式是則s[t]=1,否則s[t]=0}12:begin t:=t―1;s[t]:=ord(s[t]>end;{判前一表達(dá)式是否大于后一表達(dá)式是則s[t]=1,否則s[t]=0}13:begin t:=t―1;s[t]:=ord(s[t]≤end;{判前一表達(dá)式是否小于或等于后一表達(dá)式是則s[t]=1,否則lod:begin{當(dāng)前指令是取變量指令(lod,l,a)}t:=t+1; s[t]:=s[base(l)+a]{棧頂指針加1,根據(jù)靜態(tài)鏈SL,將層差為l,相對地址a的變量值取到棧頂}sto:begin{當(dāng)前指令是保存變量值(sto,l,a)指令}s[base(l)+a]:=s[t]; {根據(jù)靜態(tài)鏈SL,將棧頂?shù)闹荡嫒雽硬顬閘,相對地址為a的變量中}tt―1棧頂指針減calbegin{當(dāng)前指令是(cal,l,s[t+1]:=base(l);{根據(jù)層差l找到本過程的靜態(tài)直接外層過程的數(shù)據(jù)空間的SL單元,將其地址存入本過程新的數(shù)據(jù)空間的SL單元}s[t+2]:={調(diào)用過程的數(shù)據(jù)空間的起始地址存入本過程DL單元}s[t+3]:=p;{調(diào)用過程cal指令的下一條的地址存入本過程RA單元}b:=t+1;{b指向被調(diào)用過程新的數(shù)據(jù)空間起始地址}p:=a{指令地址寄器指向被調(diào)用過程的地址int:t:=t+{若當(dāng)前指令是(int0,a),則數(shù)據(jù)空間棧頂留出a大小的空間}jmp:p:=a;{若當(dāng)前指令是(jmp,0,a),則程序轉(zhuǎn)到a執(zhí)行}jpc:begin{當(dāng)前指令是(jpc,0,a)}ifs[t]=0thenp:={如果當(dāng)前運(yùn)算結(jié)果為“假”(0),程序轉(zhuǎn)到地址執(zhí)行,否則順序執(zhí)行tt―1數(shù)據(jù)棧頂指針減end{with,untilp={程序一直執(zhí)行到p取最外層主程序的返回地址0時為止}wri

溫馨提示

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

最新文檔

評論

0/150

提交評論