@ydleenudt
2015-06-10T02:11:23.000000Z
字数 26647
阅读 1197
第一步:记录表达式的标记,处理表达式,标记常量的入口位置。
第二步:每次将表达式的值与常量进行比较,形成跳转指令,执行完一条语句之后产生无条件跳转指令。
procedure casestatement; {case}var x:item;coni,conj:integer;begingetsym;cx1:=cx;expression([ofsym]+fsys,x);cx2:=cx;if (x.typ = ints) or (x.typ = chars)thenbeginif sym=ofsym thenbegingetsym;conj:=0;while sym<>elsesym dobeginif (sym = intcon) or (sym = charcon) thenbeginconi:=cx1;if conj<>0 thenbeginwhile coni<cx2 dobegincode[cx]:=code[coni];cx:=cx+coni:=coni+1;endend;conj:=1;gen(lit,0,num);coni:=cx1;endelse error(12);getsym;if sym=colon thenbegingetsym;gen(eq,0,0);cx2:=cx;gen(jpc,0,0);statement([semicolon]+fsys);if sym=semicolon thenbegingetsym;labtab[lx]:=cx;lx:=lx+1;gen(jmp,0,0);code[cx2].a:=cxendelse error(23)endelse error(24){colon}end;if sym=elsesym thenbegingetsym;statement([endsym]+fsys);lx:=lx-1;while lx>=0 dobegin code[labtab[lx]].a:=cx;lx:=lx-1endend;if sym=endsym then getsymelse error(36)endelse error(17)endend;
在第一条语句前记录标记,处理完语句之后,判断布尔表达式的值,并产生跳转指令。
procedure repeatstatement;{repeat}var x:item;begingetsym;cx1:=cx; labtab[lx]:=cx;lx:=lx+1;statement([untilsym]+fsys);if sym<>semicolon then error(23);getsym;while (not (sym in ([untilsym]))) dobeginstatement([untilsym]+fsys);if sym<>semicolon then error(23);getsymend;if sym=untilsym thenbegingetsym;expression([endsym]+fsys,x);if x.typ <> bool then error(34);gen(jpc,0,cx1);labtab[lx]:=cx;lx:=lx+1endend;
第一步:通过词法扫描,先处理控制变量,将其装入符号表,读入初值之后存入控制变量对应的地址中。
第二步:读入终止值,每次判断是否满足条件,记录语句的标号,之后进入语句,处理完之后,将控制变量加一,并判断是否跳转。
procedure forstatement;{for}begingetsym;if sym=ident thenbegini:=position(id);getsym;if i=0 then error(10)elseif nametab[i].kind<>variable thenbeginerror(30);i:=0endelsebeginx.typ:=nametab[i].typ;x.ref:=nametab[i].ref;if nametab[i].normalthen gen(loda,nametab[i].lev,nametab[i].adr)else gen(lod,nametab[i].lev,nametab[i].adr)end;if sym=becomes thenbegingetsym;expression([tosym]+fsys,ini);if ini.typ<>ints then error(12)else begingen(sto,0,0);if sym=tosym thenbegingetsym;cx1:=cx;labtab[lx]:=cx;lx:=lx+1;gen(loda,nametab[i].lev,nametab[i].adr);gen(lodt,0,0);expression([dosym]+fsys,fin);if sym=dosym thenbegingen(le,0,0);cx2:=cx;labtab[lx]:=cx;lx:=lx+1;gen(jpc,0,0);getsym;statement(fsys);if nametab[i].normal thenbegingen(loda,nametab[i].lev,nametab[i].adr);gen(loda,nametab[i].lev,nametab[i].adr);gen(lodt,0,0)endelse gen(lod,nametab[i].lev,nametab[i].adr);gen(lit,0,1);gen(add,0,0);gen(sto,0,0);gen(jmp,0,cx1);code[cx2].a:=cxendendendendendelse error(33)end;
program plcopiler;uses dos;const norw=25; { no. of reserved words }txmax=100; { length of identifier table }bmax=25; { length of block inormation table }arrmax=30; { length of array information table }nmax=6; { max. no. of digits in numbers }al=10; { length of identifiers }amax=2047; { maxinum address }levmax=7; { maxinum depth of block nesting }cxmax=1000; { size of code array }type symbol=(nul,ident,intcon,charcon,plus,minus,times,divsym,eql,neq,lss,leq,gtr,geq, ofsym,arraysym,programsym,modsym,andsym,orsym,notsym,lbrack,rbrack,lparen,rparen,comma,semicolon,period,becomes,colon,beginsym,endsym,ifsym,casesym,thensym,elsesym,whilesym,repeatsym,dosym,callsym,constsym,typesym,varsym,procsym,forsym,untilsym,functionsym,tosym);alfa = string[al];index=-32767..+32767;oobject = (konstant,typel,variable,prosedure);types=(notyp,ints,chars,bool,arrays);symset = set of symbol;opcod = (lit,lod,ilod,loda,lodt,sto,lodb,cpyb,jmp,jpc,red,wrt,cal,retp,endp,udis,opac,entp,ands,ors,nots,imod,mus,add,sub,mult,idiv,eq,ne,ls,le,gt,ge); { opration code }instruction = packed recordf:opcod;l:0..levmax;a:0..amax;end;item=recordtyp:types;ref:integerend;var ch:char; { last character read }sym:symbol; { last symbol read}id:alfa; { last identifier read 10}num:integer; { last number read }cc:integer; { character count }ll:integer; { line length }kk,err:integer;line:string[81];a:alfa;i:integer;word:array[1..norw] of alfa;wsym:array[1..norw] of symbol;ssym:array[char] of symbol;mnemonic:array[opcod] of string[5];declbegsys,statbegsys,facbegsys,constbegsys,typebegsys:symset;nametab:array[0..txmax] of { name table }recordname:alfa;kind:oobject ;typ: types;lev: 0..levmax;normal:boolean;ref:index;link:index;case oobject ofvariable,prosedure:(adr:integer);konstant :(val:integer);typel :(size:integer);end;tx: integer; { index of nametab}atab:array[1..amax] of { array information table }recordinxtyp,eltyp:types;elref,low,high,elsize,size:index;end;ax:integer; {index of atab }btab:array[0..bmax] of { block information table }recordlast,lastpar,psize,vsize:index;end;bx:integer; { index of btab }display:array[0..levmax] of integer;code:array[0..cxmax] of instruction;cx:integer; { code allocation index }labtab:array[0..100] of integer;lx:integer;{********************************************************}sfile:text; { source program file }sfilename:string; { source program file name }fcode:file of instruction;labfile:file of integer;listfile :text;listfilename:string;dir:dirstr;name:namestr;ext:extstr;{*********************************************************}procedure initial;beginword[ 1]:='and ';word[ 2]:='array ';word[ 3]:='begin ';word[ 4]:='call ';word[ 5]:='case ';word[ 6]:='const ';word[ 7]:='do ';word[ 8]:='else ';word[ 9]:='end ';word[10]:='for ';word[11]:='function ';word[12]:='if ';word[13]:='mod ';word[14]:='not ';word[15]:='of ';word[16]:='or ';word[17]:='procedure ';word[18]:='program ';word[19]:='repeat ';word[20]:='then ';word[21]:='to ';word[22]:='type ';word[23]:='until ';word[24]:='var ';word[25]:='while ';wsym[ 1]:=andsym;wsym[ 2]:=arraysym;wsym[ 3]:=beginsym;wsym[ 4]:=callsym;wsym[ 5]:=casesym;wsym[ 6]:=constsym;wsym[ 7]:=dosym;wsym[ 8]:=elsesym;wsym[ 9]:=endsym;wsym[10]:=forsym;wsym[11]:=functionsym;wsym[12]:=ifsym;wsym[13]:=modsym;wsym[14]:=notsym;wsym[15]:=ofsym;wsym[16]:=orsym;wsym[17]:=procsym;wsym[18]:=programsym;wsym[19]:=repeatsym;wsym[20]:=thensym;wsym[21]:=tosym;wsym[22]:=typesym;wsym[23]:=untilsym;wsym[24]:=varsym;wsym[25]:=whilesym;ssym['+']:=plus; ssym['-']:=minus;ssym['*']:=times; ssym['/']:=divsym;ssym['[']:=lbrack; ssym[']']:=rbrack;ssym['(']:=lparen; ssym[')']:=rparen;ssym['=']:=eql; ssym[',']:=comma;ssym['.']:=period;ssym['<']:=lss; ssym['>']:=gtr;ssym[';']:=semicolon;mnemonic[lit]:='LIT '; mnemonic[lod]:='LOD ';mnemonic[sto]:='STO '; mnemonic[cal]:='CAL ';mnemonic[jmp]:='JMP '; mnemonic[jpc]:='JPC ';mnemonic[red]:='RED '; mnemonic[wrt]:='WRT ';mnemonic[ilod]:='ILOD '; mnemonic[loda]:='LODA ';mnemonic[lodt]:='LODt '; mnemonic[lodb]:='LODB ';mnemonic[cpyb]:='COPYB '; mnemonic[endp]:='ENDP ';mnemonic[retp]:='RETP '; mnemonic[udis]:='ADIS ';mnemonic[mus]:='MUS '; mnemonic[add]:='ADD ';mnemonic[sub]:='SUB '; mnemonic[mult]:='MULT ';mnemonic[idiv]:='DDIV '; mnemonic[eq]:='EQ ';mnemonic[ne]:='NE '; mnemonic[ls]:='LS ';mnemonic[le]:='LE '; mnemonic[gt]:='GT ';mnemonic[ge]:='GE '; mnemonic[opac]:='OPAC ';mnemonic[entp]:='ENTP'; mnemonic[imod]:='IMOD ';mnemonic[ands]:='ANDS'; mnemonic[ors]:='ORS ';mnemonic[nots]:='NOTS';declbegsys:=[constsym,varsym,typesym,procsym];statbegsys:=[beginsym,callsym,ifsym,whilesym,casesym,repeatsym,untilsym,forsym];facbegsys :=[ident,intcon,lparen,notsym,charcon];typebegsys:=[ident,arraysym];constbegsys:=[plus,minus,intcon,charcon,ident];err:=0; a[0]:=#10;display[0]:=0;cc:=0; cx:=0; ll:=0; ch:=' '; kk:=al; bx:=1; tx:=-1;lx:=0end; {init}procedure enterpreid;procedure enter(x0:alfa;x1:oobject;x2:types;x3:integer);begintx:=tx+1;with nametab[tx] dobeginname:=x0;link:=tx-1;kind:=x1;typ:=x2;ref:=0;normal:=true;lev:=0;case kind ofvariable,prosedure: adr:=x3;konstant: val:=x3;typel: size:=x3endendend;beginenter(' ',variable,notyp,0); { sentinel }enter('char ',typel, chars,1);enter('integer ',typel,ints, 1);enter('boolean ',typel,bool, 1);enter('false ',konstant,bool, 0);enter('true ',konstant,bool, 1);enter('read ',prosedure,notyp,1);enter('write ',prosedure,notyp,2);btab[0].last:=tx; btab[0].lastpar:=1;btab[0].psize:=0; btab[0].vsize:=0end; {enterprid}procedure error(n:integer);begin writeln(listfile,'****',' ':cc-1,'^',n:2);err:=err+1end; { error }procedure getsym;label 1;var i,k,j:integer;procedure getch;beginif cc=ll then { get character to end of line }{ read next line }beginif eof(sfile) thenbeginwriteln('program incomplete');close(sfile);exit;end;ll:=0; cc:=0; write(listfile,cx:4,' '); {print code address }while not eoln(sfile) dobeginll:=ll+1; read(sfile,ch); write(listfile,ch);line[ll]:=chend;writeln(listfile); readln(sfile);ll:=ll+1; line[ll]:=' ' {process end-line}end;cc:=cc+1; ch:=line[cc]end; { getch }begin {getsym}1: while ch=' ' do getch;case ch of'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z':begin { identifier or reserved(关键字) word }k:=0;repeatif k<al thenbegin k:=k+1; a[k]:=ch end;getchuntil not (ch in ['a'..'z','0'..'9']);if k>=kk then kk:=k { kk: last identifier length }elserepeata[kk]:=' '; kk:=kk-1until kk=k;id:=a; i:=1; j:=norw; { binary search reserved word table }repeatk:=(i+j) div 2;if id<=word[k] then j:=k-1;if id>=word[k] then i:=k+1;until i>j;if i-1>j then sym:=wsym[k]else sym:=identend;'{' :beginrepeatgetchuntil ch = '}';getch;goto 1end;'0','1','2','3','4','5','6','7','8','9':begin { number }k:=0; num:=0; sym:=intcon;repeatnum:=10*num+(ord(ch)-ord('0'));k:=k+1; getchuntil not (ch in ['0'..'9']);if k>nmax then error(47)end;':':begingetch;if ch='=' thenbegin sym:=becomes; getch endelse sym:=colonend ;'<' :begingetch;if ch='=' thenbegin sym:=leq; getch endelseif ch='>' thenbegin sym:=neq; getch endelse sym:=lssend ;'>' :begingetch;if ch='=' thenbegin sym:=geq; getch endelse sym:=gtrend ;'.' :begingetch;if ch='.'then beginsym:=colon;getchendelse sym:=periodend;'''' :begingetch;sym:=charcon;num:=ord(ch);getch;if ch='''' then getchelse error(48)end;'+','-','*','/','(',')','=','[',']',';',',':beginsym:=ssym[ch];getchend;elsebeginerror(0); getch;goto 1endend { case }end; { getsym }procedure enterarray (tp:types ; l,h:integer);beginif l>h then error(14);if ax=amax thenbeginerror(2);writeln('too many arrays in program ');close(sfile);close(listfile);exitendelse beginax:=ax+1;with atab[ax] dobegininxtyp:=tp; low:=l; high:=hendendend; { enterarray }procedure enterblock;beginif bx=bmax thenbeginerror(3);writeln('too many procedure in program ');close(sfile);close(listfile);exitendelse beginbx:=bx+1; btab[bx].last:=0; btab[bx].lastpar:=0endend; { enterblock }procedure gen(x:opcod; y,z:integer); {产生代码程序gen}beginif cx>cxmax thenbeginerror(49);writeln('program too long');close(sfile);close(listfile);exitend;with code[cx] dobeginf:=x; l:=y; a:=zend;cx:=cx+1end; { gen }procedure test(s1,s2:symset;n:integer);beginif not (sym in s1) thenbeginerror(n); s1:=s1+s2;while not (sym in s1) do getsymendend; { test }procedure block( fsys:symset;level:integer);typeconstrec=recordtp:types;i:integerend;var dx:integer; { data allocation index }tx0:integer; { initial table index }cx0:integer; { initial code index }prt,prb:integer;procedure enter( k:oobject);var j,l:integer;beginif tx=txmaxthen beginerror(1);writeln('program too long');close(sfile);close(listfile);exitendelse beginnametab[0].name:=id;j:=btab[display[level]].last; l:=j;while nametab[j].name<>id do j:=nametab[j].link;if j<>0then error(l)else begintx:=tx+1;with nametab[tx] dobeginname:=id; link:=l;kind:=k; typ:=notyp; ref:=0;lev:=level; normal:=false;case kind ofvariable,prosedure: adr:=0;konstant: val:=0;typel: size:=0end { initial value }end;btab[display[level]].last:=txendendend; { enter }function position(id:alfa):integer;var i,j:integer;beginnametab[0].name:=id; j:=level;repeati:=btab[display[j]].last;while nametab[i].name<>id doi:=nametab[i].link;j:=j-1until (j<0) or (i<>0);if (i=0) then error(10);position:=iend; { position }procedure constant(fsys:symset; var c:constrec);var x,sign:integer;beginc.tp:=notyp; c.i:=0;test(constbegsys,fsys,50);if sym in constbegsysthen beginif sym=charconthen beginc.tp:=chars; c.i:=num;getsymend elsebeginsign:=1;if sym in [plus,minus]then beginif sym=minus then sign:=-1;getsymend;if sym=identthen beginx:=position(id);if x<>0then if nametab[x].kind<>konstantthen error(12)else beginc.tp:=nametab[x].typ;c.i:=sign*nametab[x].valend;getsymend else if sym=intconthen beginc.tp:=ints; c.i:=sign*num;getsymendend;test(fsys,[],6)endend; { constant }procedure typ(fsys:symset;var tp:types; var rf,sz:integer);var eltp:types;elrf,x:integer;elsz,offset,t0,t1:integer;procedure arraytyp(var aref,arsz:integer);var eltp:types;low,high:constrec;elrf,elsz:integer;beginconstant([colon,rbrack,rparen,ofsym]+fsys,low);if (low.tp<>ints) and (low.tp<>chars)then error(50);if sym=colon then getsym else error(38);constant([rbrack,comma,rparen,ofsym]+fsys,high);if high.tp<>low.tpthen beginerror(40); high.i:=low.i;end;enterarray(low.tp,low.i,high.i);aref:=ax;if sym=commathen begingetsym;eltp:=arrays;arraytyp(elrf,elsz)end else beginif sym=rbrackthen getsymelse beginerror(28);if sym=rparen then getsymend;if sym=ofsym then getsym else error(17);typ(fsys,eltp,elrf,elsz)end;with atab[aref] dobeginarsz:=(high-low+1)*elsz; size:=arsz;eltyp:=eltp; elref:=elrf; elsize:=elszend;end; { arraytyp }begin { typ }tp:=notyp; rf:=0; sz:=0;test(typebegsys,fsys,10);if sym in typebegsysthen beginif sym=identthen beginx:=position(id);if x<>0then with nametab[x] doif kind<>typelthen error(19)else begintp:=typ;rf:=ref;sz:=size;if tp=notyp then error(18);end;getsym;end else if sym=arraysymthen begingetsym;if sym=lbrackthen getsymelse beginerror(16);if sym=lparenthen getsymend;tp:=arrays;arraytyp(rf,sz)end ;test(fsys,[],13)endend; {typ}procedure paramenterlist; {formal parameter list}vartp:types;valpar:boolean;rf,sz,x,t0:integer;begingetsym;tp:=notyp;rf:=0;sz:=0;test([ident,varsym],fsys+[rparen],7);while sym in [ident,varsym] dobeginif sym <> varsymthen valpar:=trueelse begingetsym;valpar:=falseend;t0:=tx;if sym=identthen beginenter(variable);getsymend else error(22);while sym=comma dobegingetsym;if sym=identthen beginenter(variable);getsymend else error(22);end;if sym=colonthen begingetsym;if sym <> identthen error(22)else beginx :=position(id); getsym;if x<>0then with nametab[x] doif kind <> typelthen error(19)else begintp:= typ; rf:=ref;if valpar then sz:=size else sz:=1end;end;test ([semicolon,rparen],[comma,ident]+fsys,14)end else error(24);while t0 < tx dobegint0 :=t0+1;with nametab[t0] dobegintyp :=tp;ref :=rf;adr :=dx;lev :=level;normal :=valpar;dx :=dx+szendend;if sym <> rparenthen beginif sym=semicolonthen getsymelse beginerror(23);if sym=comma then getsymend;test([ident,varsym],[rparen]+fsys,13)endend {while};if sym=rparenthen begingetsym;test([semicolon],fsys,13)end else error(25)end {parameterlist};procedure constdeclaration;var c:constrec;beginif sym=ident thenbeginenter(konstant);getsym;if sym = eqlthen getsymelsebeginerror(26);if sym=becomes then getsymend;constant([semicolon,comma,ident]+fsys,c);nametab[tx].typ:=c.tp;nametab[tx].ref:=0;nametab[tx].val:=c.i;if sym=semicolon then getsym else error(23)endelse error(22);test(fsys+[ident],[],13)end; { constdeclaration }procedure typedeclaration;vartp:types;rf,sz,t1:integer;beginif sym=ident thenbeginenter(typel);t1:=tx;getsym;if sym = eql then getsymelse beginerror(26);if sym=becomes then getsym;end;typ ([semicolon,comma,ident]+fsys,tp,rf,sz);nametab[tx].typ:=tp;nametab[tx].ref:=rf;nametab[tx].size:=sz;if sym=semicolon then getsym else error(23)endelse error(22);test(fsys+[ident],[],13)end; { typedeclaration }procedure vardeclaration;var tp:types;t0,t1,rf,sz:integer;beginif sym=ident thenbegint0:=tx;enter(variable); getsym;while sym = comma dobegingetsym;if sym =identthen beginenter(variable);getsym;end else error(22);end;if sym = colon then getsym else error(24);t1:=tx;typ ([semicolon,comma,ident]+fsys,tp,rf,sz);while t0 < t1 dobegint0:=t0+1;with nametab[t0] dobegintyp:=tp; ref:=rf;lev:=level; adr:=dx;normal:=true;dx:=dx+szendend;if sym=semicolon then getsym else error(23)endelse error(22);test(fsys+[ident],[],13)end; { vardeclaration }procedure procdeclaration;begingetsym;if sym <> identthen beginerror(22); id:=' 'end;enter(prosedure);nametab[tx].normal:=true;getsym;block([semicolon]+fsys,level+1);if sym = semicolon then getsym else error(23);end; {procdeclaration}procedure listcode;var i:integer;beginfor i:=cx0 to cx-1 dowith code[i] dowriteln(listfile,i:4,mnemonic[f]:7,l:3,a:5)end; { listcode }procedure statement(fsys:symset);var i,cx1,cx2,cx3:integer;x:item;procedure arrayelement(fsys:symset;var x:item); forward;procedure expression(fsys:symset;var x: item);var relop:symbol;y:item;procedure simpleexpression(fsys:symset;var x:item);var addop:symbol;y:item;procedure term(fsys:symset;var x: item);var mulop:symbol;y:item;procedure factor(fsys:symset;var x:item);var i:integer;beginx.typ:=notyp;x.ref:=0;test(facbegsys,fsys,13);if sym in facbegsys then { facbegsys :=[ident,intcon,lparen,notsym,charcon];}begincase sym ofident :begini:=position(id);getsym;if i=0 then error(10)elsewith nametab[i] docase kind ofkonstant: beginx.typ:=typ;x.ref:=0;gen(lit,0,val);end;variable:beginx.typ:=typ;x.ref:=ref;if (typ = ints) or (typ = bool) or(typ=chars)then if normal then gen(lod,lev,adr)else gen(ilod,lev,adr)else if typ=arrays thenbeginif normal then gen(loda,lev,adr)else gen(lod,lev,adr);if sym = lbrackthen arrayelement(fsys,x);if x.typ <> arraysthen gen(lodt,0,0)endend;prosedure,typel:error(41)end;end ;intcon,charcon :beginif sym = intcon then x.typ:=intselse x.typ:=chars;x.ref:=0;gen(lit,0,num);getsymend;lparen :begingetsym;expression([rparen]+fsys,x);if sym=rparen then getsymelse error(25)end;notsym :begingetsym;factor(fsys,x);if x.typ = boolthen gen(nots ,0,0)else error(43)end;end ;{ case }test(fsys+[rbrack,rparen],facbegsys,23)end { of if }end; { factor }begin { term }factor(fsys+[times,divsym,modsym,andsym],x);while sym in [times,divsym,modsym,andsym] dobeginmulop:=sym; getsym;factor(fsys+[times,divsym,modsym,andsym],y);if x.typ<>y.typthen beginerror(40);x.typ:=notyp;x.ref:=0endelsebeginif mulop=times thenif x.typ = intsthen gen(mult,0,0)else error(43);if mulop=divsym thenif x.typ = intsthen gen(idiv,0,0)else error(43);if mulop=modsym thenif x.typ = intsthen gen(imod,0,0)else error(43);if mulop=andsym thenif x.typ = boolthen gen(ands,0,0)else error(43)endendend; { term}begin { simpleexpression }if sym in [plus,minus] thenbeginaddop:=sym; getsym;term(fsys+[plus,minus,orsym],x);if addop=minus then gen(mus,0,0)end else term(fsys+[plus,minus,orsym],x);while sym in [plus,minus,orsym] dobegin addop:=sym; getsym;term(fsys+[plus,minus,orsym],y);if x.typ<>y.typthen beginerror(40);x.typ:=notyp;x.ref:=0endelsebeginif addop=plus thenif x.typ = intsthen gen(add,0,0)else error(43);if addop=minus thenif x.typ = intsthen gen(sub,0,0)else error(43);if addop=orsym thenif x.typ = boolthen gen(ors,0,0)else error(43)endendend; { simpleexpression }begin {expression}simpleexpression([eql,neq,lss,gtr,leq,geq]+fsys,x);while (sym in [eql,neq,lss,leq,gtr,geq]) dobeginrelop:=sym; getsym; simpleexpression(fsys,y);if x.typ<> y.typthen error(40);case relop ofeql:gen(eq,0,0);neq:gen(ne,0,0);lss:gen(ls,0,0);geq:gen(ge,0,0);gtr:gen(gt,0,0);leq:gen(le,0,0)end;x.typ:=boolendend; { expression }procedure arrayelement(fsys:symset;var x:item);var cc:integer;addr,p:index;y:item;beginp:=x.ref;if sym=lbrack thenbeginrepeatgetsym;expression(fsys+[comma],y);if x.typ <> arrays then error(40)elsebeginif y.typ <> atab[p].inxtyp then error(44);gen(lit,0,atab[p].low);gen(sub,0,0);gen(lit,1,atab[p].elsize);gen(mult,0,0);gen(add,0,0);x.typ:=atab[p].eltyp;x.ref:=atab[p].elref;p:=atab[p].elref;enduntil sym <> comma;if sym=rbrack then getsym else error(28);end else error(16);test(fsys,[],13);end; {arrayelement}procedure assignment;var x,y:item;begini:=position(id);if i=0 then error(10)elseif nametab[i].kind<>variable thenbegin { giving value to non-variation }error(30); i:=0end;getsym;x.typ:=nametab[i].typ;x.ref:=nametab[i].ref;with nametab[i] doif normalthen gen(loda,lev,adr)else gen(lod,lev,adr);if sym = lbrackthen arrayelement(fsys+[becomes],x);if sym = becomes then getsymelse beginerror(33);if sym=eql then getsymend;expression(fsys,y);if x.typ <> y.typ then error(40)elseif x.typ = arraysthen if x.ref = y.refthen gen(cpyb,0,atab[x.ref].size)else error(40)else gen(sto,0,0);end;procedure ifstatement;var x:item;begingetsym; expression([thensym,dosym]+fsys,x);if x.typ <> bool then error(34);if sym=thensym then getsym else error(35);cx1:=cx; gen(jpc,0,0);statement(fsys+[elsesym]);if sym = elsesymthen begingetsym;cx2:=cx; gen(jmp,0,0);code[cx1].a:=cx;labtab[lx]:=cx;lx:=lx+1;statement(fsys);code[cx2].a:=cx;labtab[lx]:=cx;lx:=lx+1;endelsebegincode[cx1].a:=cx;labtab[lx]:=cx;lx:=lx+1;endend; {ifstatement}procedure casestatement; {case}var x:item;coni,conj:integer;begingetsym;cx1:=cx;expression([ofsym]+fsys,x);cx2:=cx;if (x.typ = ints) or (x.typ = chars)thenbeginif sym=ofsym thenbegingetsym;conj:=0;while sym<>elsesym dobeginif (sym = intcon) or (sym = charcon) thenbeginconi:=cx1;if conj<>0 thenbeginwhile coni<cx2 dobegincode[cx]:=code[coni];cx:=cx+1;coni:=coni+1;endend;conj:=1;gen(lit,0,num);coni:=cx1;endelse error(12);getsym;if sym=colon thenbegingetsym;gen(eq,0,0);cx2:=cx;gen(jpc,0,0);statement([semicolon]+fsys);if sym=semicolon thenbegingetsym;labtab[lx]:=cx;lx:=lx+1;gen(jmp,0,0);code[cx2].a:=cxendelse error(23)endelse error(24){colon}end;if sym=elsesym thenbegingetsym;statement([endsym]+fsys);lx:=lx-1;while lx>=0 dobegin code[labtab[lx]].a:=cx;lx:=lx-1endend;if sym=endsym then getsymelse error(36)endelse error(17)endend;procedure compound;begingetsym; statement([semicolon,endsym]+fsys);while sym in ([semicolon]+statbegsys) dobeginif sym=semicolon then getsym else error(23);statement([semicolon,endsym]+fsys)end;if sym=endsym then getsym else error(36)end; {compound}procedure whilestatement;var x:item;begingetsym;labtab[lx]:=cx;lx:=lx+1;cx1:=cx; expression([dosym]+fsys,x);if x.typ <> bool then error(34);cx2:=cx; gen(jpc,0,0);if sym=dosym then getsym else error(37);statement(fsys); gen(jmp,0,cx1); code[cx2].a:=cx;labtab[lx]:=cx;lx:=lx+1end;procedure repeatstatement;{repeat}var x:item;begingetsym;cx1:=cx; labtab[lx]:=cx;lx:=lx+1;statement([untilsym]+fsys);if sym<>semicolon then error(23);getsym;while (not (sym in ([untilsym]))) dobeginstatement([untilsym]+fsys);if sym<>semicolon then error(23);getsymend;if sym=untilsym thenbegingetsym;expression([endsym]+fsys,x);if x.typ <> bool then error(34);gen(jpc,0,cx1);labtab[lx]:=cx;lx:=lx+1endend;procedure forstatement;{for}var x,ini,fin:item;begingetsym;if sym=ident thenbegini:=position(id);getsym;if i=0 then error(10)elseif nametab[i].kind<>variable thenbeginerror(30);i:=0endelsebeginx.typ:=nametab[i].typ;x.ref:=nametab[i].ref;if nametab[i].normalthen gen(loda,nametab[i].lev,nametab[i].adr)else gen(lod,nametab[i].lev,nametab[i].adr)end;if sym=becomes thenbegingetsym;expression([tosym]+fsys,ini);if ini.typ<>ints then error(12)else begingen(sto,0,0);if sym=tosym thenbegingetsym;cx1:=cx;labtab[lx]:=cx;lx:=lx+1;gen(loda,nametab[i].lev,nametab[i].adr);gen(lodt,0,0);expression([dosym]+fsys,fin);if sym=dosym thenbegingen(le,0,0);cx2:=cx;labtab[lx]:=cx;lx:=lx+1;gen(jpc,0,0);getsym;statement(fsys);if nametab[i].normal thenbegingen(loda,nametab[i].lev,nametab[i].adr);gen(loda,nametab[i].lev,nametab[i].adr);gen(lodt,0,0)endelse gen(lod,nametab[i].lev,nametab[i].adr);gen(lit,0,1);gen(add,0,0);gen(sto,0,0);gen(jmp,0,cx1);code[cx2].a:=cxendendendendendelse error(33)end;procedure call;var x: item;lastp,cp,i,j,k:integer;procedure stanproc(i:integer);var n:integer;beginif i =6 thenbegin { read }getsym;if sym=lparen thenbeginrepeatgetsym;if sym=ident thenbeginn:=position(id); getsym;if n=0 then error(10)elseif nametab[n].kind<>variable thenbegin error(30); n:=0 endelsebeginx.typ:=nametab[n].typ;x.ref:=nametab[n].ref;if nametab[n].normalthen gen(loda,nametab[n].lev,nametab[n].adr)else gen(lod,nametab[n].lev,nametab[n].adr);if sym = lbrackthen arrayelement(fsys+[comma],x);if x.typ = intsthen gen(red,0,0)else if x.typ = charsthen gen(red,0,1)else error(43)endendelse error(22)until sym<>comma;if sym<>rparen then error(25)else getsymendelse error(32)endelseif i = 7 thenbegin { write }getsym;if sym=lparen thenbeginrepeatgetsym;expression([rparen,comma]+fsys,x);if x.typ = intsthen gen(wrt,0,0)else if x.typ = charsthen gen(wrt,0,1)else error(43)until sym<>comma;if sym<>rparen then error(25);getsymendelse error(32)endend; { standproc }begin { call }getsym;if sym = ident thenbegini:=position(id);if nametab[i].kind = prosedure thenbeginif nametab[i].lev = 0 then stanproc(i)else begingetsym;gen(opac,0,0); {open active record}lastp :=btab[nametab[i].ref].lastpar;cp :=i;if sym=lparenthen begin {actual parameter list}repeatgetsym;if cp>=lastpthen error(29)else begincp :=cp+1;if nametab[cp].normal thenbegin {value parameter}expression(fsys+[comma,colon,rparen],x);if x.typ = nametab[cp].typ thenbeginif x.ref <> nametab[cp].refthen error(31)else if x.typ = arraysthen gen(lodb,0,atab[x.ref].size)endelse error(31)end else begin {variable parameter}if sym <> identthen error(22)else begink:=position(id);getsym;if k<>0then beginif nametab[k].kind<>variable then error (30);x.typ :=nametab[k].typ;x.ref :=nametab[k].ref;if nametab[k].normalthen gen(loda,nametab[k].lev,nametab[k].adr)else gen(lod,nametab[k].lev,nametab[k].adr);if sym = lbrackthen arrayelement(fsys+[comma,rparen],x);if (nametab[cp].typ<>x.typ)or (nametab[cp].ref<>x.ref)then error(31);endendend {variable parameter}end;test([comma,rparen],fsys,13)until sym <> comma;if sym=rparen then getsym else error(25)end;if cp < lastp then error(39);{too few actual parameters}gen(cal,nametab[i].lev,nametab[i].adr);if nametab[i].lev<level then gen(udis,nametab[i].lev,level)endend else error(51)end else error(22);test(fsys+[ident],[],13)end {call};begin { statement }test(statbegsys+[ident],fsys,13);if sym=ident then assignmentelse if sym=callsym then callelse if sym=ifsym then ifstatementelse if sym=casesym then casestatementelse if sym=repeatsym then repeatstatementelse if sym=forsym then forstatementelse if sym=beginsym then compoundelse if sym=whilesym then whilestatement;test(fsys+[elsesym],[],13)end; { statement }begin { block }prt:=tx;dx:=3; tx0:=tx; nametab[tx].adr:=cx;if level > levmax then error(4);enterblock ;prb:=bx; display[level]:=bx;nametab[prt].typ:=notyp; nametab[prt].ref:=prb;if(sym=lparen) and (level>1)thenbeginparamenterlist;if sym=semicolon then getsymelse error(23)endelse if level>1 thenif sym=semicolon then getsymelse error(23);btab[prb].lastpar:=tx;btab[prb].psize:=dx;gen(jmp,0,0); { jump from declaration part to statement part }repeatif sym=constsym thenbegingetsym;repeatconstdeclaration;until sym<>identend;if sym=typesym thenbegingetsym;repeattypedeclaration;until sym<>identend;if sym=varsym thenbegingetsym;repeatvardeclaration;until sym<>ident;end;while sym=procsym do procdeclaration;test(statbegsys+[ident],declbegsys,13)until not (sym in declbegsys);code[nametab[tx0].adr].a:=cx; {back enter statement code's start adr. }labtab[lx]:=cx;lx:=lx+1;with nametab[tx0] dobeginadr:=cx; {code's start address }end;cx0:=cx;gen(entp,level,dx); { block entry }statement([semicolon,endsym]+fsys);if level>1 then gen(retp,0,0) {return}else gen(endp,0,0); { end prograam }test(fsys,[],13);listcode;end; { block }{************************************************************************}begin { main }writeln('Please input source program file name:');readln(sfilename);assign(sfile,sfilename);reset(sfile);fsplit(sfilename,dir, name,ext);listfilename:=dir +name+'.LST';assign(listfile,listfilename);rewrite(listfile);initial;enterpreid;getsym;if sym = programsym thenbegingetsym;if sym = ident thenbegingetsym;if sym = semicolon then getsymelse error(23)endelse error(22)endelse error(15);test(declbegsys+[beginsym],[],13);block([period]+declbegsys+statbegsys,1);if sym<>period then error(38);if err=0 thenbeginwrite('SUCCESS');assign(fcode,dir+name+'.pld');rewrite(fcode);for i:=0 to cx dowrite(fcode,code[i]);close(fcode);assign(labfile,dir+name+'.lab');rewrite(labfile);for i:=0 to lx dowrite(labfile,labtab[i]);close(labfile)endelse write(err,'ERRORS IN PROGRAM');writeln;close(sfile);close(listfile)end. { of whole program }
program fsj;var n:integer;a:char;beginn:=2;a:='f';case a of1: call write(1);'f': call write(n);else call write(2)endend.
program fsj;var n:integer;beginn:=1;repeatn:=n+1;until n=5;call write(n)end.
program fsj;var i,sum:integer;beginsum:=0;for i:=3 to 7 dosum:=sum+i*2;call write(sum)end.