PL0语言可看成是Pascal[1]语言的子集,它的编译程序是一个编译解释执行系统。
PL/0的目标程序为假象栈试计算机的汇编语言,与具体计算机无关。编译原理的课程作业,就是实现一个PL0的编译程序,分两个任务。第一个任务是生成中间代码以及输出运行过程的栈中数据,第二个任务在第一个任务的基础上实现PL0的read和write函数。
program pl0(input, output); {任务一的代码实现} label 99; const norw=11; {保留字个数} txmax=100; {标识符表长度} nmax=14; {数字允许的最长位数} al=10; {标识符表的长度} amax=2047; {最大地址} levmax=3; {程序体嵌套的最大深度} cxmax=200; {代码数组的大小} type symbol=(nul,ident,number,plus,minus,times,slash,oddsym, eql,neq,lss,leq,gtr,geq,lparen,rparen,comma, semicolon,period,becomes,beginsym,endsym,ifsym, thensym,whilesym,dosym,callsym, constsym,varsym,procsym); alfa=packed array[1..al] of char; objects=(constant,variable,procedur); {procedure和object在pascal中是关键字,所以分别使用procedur和object替代} symset=set of symbol; fct=(lit,opr,lod,sto,cal,int,jmp,jpc); instruction=packed record f:fct; {功能码} l:0..levmax; {层} a:0..amax; {相对地址} end; var fa:text; {文本文件fa用于列出中间程序} srccode,data:text; {文本文件srccode用于列出源代码、data用于记录运行数据} ch:char; {最近读到的字符} sym:symbol; {最近读到的符号} id:alfa; {最近读到的标识符} num:integer; {最近读到的数} cc:integer; {字符计数} ll:integer; {行长} kk:integer; cx:integer; {代码分配下标} line:array[1..81] of char; a:alfa; code:array[0..cxmax] of instruction; word:array[1..norw] of alfa; wsym:array[1..norw] of symbol; ssym:array[char] of symbol; mnemonic:array[fct] of packed array[1..5] of char; declbegsys, statbegsys, facbegsys:symset; table:array[0..txmax] of record name:alfa; case kind:objects of constant:(val:integer); variable,procedur:(level,adr,size:integer) end; fin,fout:text; fname:string; err:integer; endf:boolean; procedure error(n:integer); begin writeln('****',' ':cc-1,'!',n:2); writeln(srccode,'****','':cc-1,'!',n:2); err:=err+1; end; {error} procedure exitp; begin endf:=true; close(fin); writeln; exit; end; procedure getsym; var i,j,k:integer; procedure getch; begin if cc=ll then begin if eof(fin) then begin write('program incomplete'); close(fin); writeln; exitp; (* goto 99;*) end; ll:=0; cc:=0; write(cx:5,' '); write(srccode,cx:5,' '); while not eoln(fin) do begin ll:=ll+1; read(fin,ch); write(ch); write(srccode,ch); line[ll]:=ch; end; writeln; ll:=ll+1; line[ll]:=' '; readln(fin); writeln(srccode); end; cc:=cc+1; ch:=line[cc]; end; {getch} begin {getsym} while ch=' ' do getch; if ch in ['a'..'z'] then begin k:=0; repeat if k<al then begin k:=k+1; a[k]:=ch; end; getch; until not(ch in ['a'..'z','0'..'9']); if k>=kk then kk:=k else repeat a[kk]:=' '; kk:=kk-1; until kk=k; id:=a; i:=1; j:=norw; repeat k:=(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:=ident; end else if ch in ['0'..'9'] then begin k:=0; num:=0; sym:=number; repeat num:=10*num+(ord(ch)-ord('0')); k:=k+1; getch; until not(ch in['0'..'9']); if k>nmax then error(30); end else if ch=':' then begin getch; if ch='=' then begin sym:=becomes; getch; end else sym:=nul; end else if ch='<' then begin getch; if ch='=' then begin sym:=leq; getch; end else sym:=lss; end else if ch='>' then begin getch; if ch='=' then begin sym:=geq; getch; end else sym:=gtr; end else begin sym:=ssym[ch]; getch; end; end; {getsym} procedure gen(x:fct;y,z:integer); begin if cx>cxmax then begin write('program too long'); (* goto 99;*) end; with code[cx] do begin f:=x; l:=y; a:=z; end; cx:=cx+1; end; {gen} procedure test(s1,s2:symset;n:integer); begin if not(sym in s1) then begin error(n); s1:=s1+s2; while not(sym in s1) do getsym; end; end; {test} procedure block(lev,tx:integer;fsys:symset); var dx:integer; {数据分配下标} tx0:integer; {起始标识符表的下标} cx0:integer; {起始代码的下标} procedure enter(k:objects); begin {把objects填入标识符表中} tx:=tx+1; with table[tx] do begin name:=id; kind:=k; case k of constant: begin if num>amax then begin error(30); num:=0; end; val:=num; end; variable: begin level:=lev; adr:=dx; dx:=dx+1; end; procedur: level:=lev; end; end; end; {enter} function position(id:alfa):integer; var i:integer; begin {在标识符表中查标识符id} table[0].name:=id; i:=tx; while table[i].name<>id do i:=i-1; position:=i; end; {position} procedure constdeclaration; begin if sym=ident then begin getsym; if sym in [eql,becomes] then begin if sym=becomes then error(1); getsym; if sym=number then begin enter(constant); getsym; end else error(2); end else error(3); end else error(4); end; {constdeclaration} procedure vardeclaration; begin if sym=ident then begin enter(variable); getsym; end else error(4); end; {vardeclaration} procedure listcode; var i:integer; begin for i:=cx0 to cx-1 do with code[i] do begin writeln(i,mnemonic[f]:5,l:3,a:5); writeln(fa,i:4,mnemonic[f]:5,l:3,a:5); end; end; {listcode} procedure statement(fsys:symset); var i,cx1,cx2:integer; procedure expression(fsys:symset); var addop:symbol; procedure term(fsys:symset); var mulop:symbol; procedure factor(fsys:symset); var i:integer; begin test(facbegsys,fsys,24); while sym in facbegsys do begin if sym=ident then begin i:=position(id); if i=0 then error(11) else with table[i] do case kind of constant:gen(lit,0,val); variable:gen(lod,lev-level,adr); procedur:error(21); end; getsym; end else if sym=number then begin if num>amax then begin error(30); num:=0; end; gen(lit,0,num); getsym; end else if sym=lparen then begin getsym; expression([rparen]+fsys); if sym=rparen then getsym else error(22); end; test(fsys,facbegsys,23); end; end; {factor} begin {term} factor([times,slash]+fsys); while sym in [times,slash] do begin mulop:=sym; getsym; factor(fsys+[times,slash]); if mulop=times then gen(opr,0,4) else gen(opr,0,5) end; end; {term} begin {expression} if sym in [plus,minus] then begin addop:=sym; getsym; term(fsys+[plus,minus]); if addop=minus then gen(opr,0,1); end else term(fsys+[plus,minus]); while sym in [plus,minus] do begin addop:=sym; getsym; term(fsys+[plus,minus]); if addop=plus then gen(opr,0,2) else gen(opr,0,3); end; end; {expression} procedure condition(fsys:symset); var relop:symbol; begin if sym=oddsym then begin getsym; expression(fsys); gen(opr,0,6); end else begin expression([eql,neq,lss,leq,gtr,geq]+fsys); if not(sym in [eql,neq,lss,leq,gtr,geq]) then error(20) else begin relop:=sym; getsym; expression(fsys); case relop of eql:gen(opr,0,8); neq:gen(opr,0,9); lss:gen(opr,0,10); geq:gen(opr,0,11); gtr:gen(opr,0,12); leq:gen(opr,0,13); end; end; end; end; {condition} begin {statement} if sym=ident then begin i:=position(id); if i=0 then error(11) else if table[i].kind<>variable then begin error(12); i:=0; end; getsym; if sym=becomes then getsym else error(13); expression(fsys); if i<>0 then with table[i] do gen(sto,lev-level,adr); end else if sym=callsym then begin getsym; if sym<>ident then error(14) else begin i:=position(id); if i=0 then error(11) else with table[i] do if kind=procedur then gen(cal,lev-level,adr) else error(15); getsym; end; end else if sym=ifsym then begin getsym; condition([thensym,dosym]+fsys); if sym=thensym then getsym else error(16); cx1:=cx; gen(jpc,0,0); statement(fsys); code[cx1].a:=cx; end else if sym=beginsym then begin getsym; statement([semicolon,endsym]+fsys); while sym in [semicolon]+statbegsys do begin if sym=semicolon then getsym else error(10); statement([semicolon,endsym]+fsys); end; if sym=endsym then getsym else error(17); end else if sym=whilesym then begin cx1:=cx; getsym; condition([dosym]+fsys); cx2:=cx; gen(jpc,0,0); if sym=dosym then getsym else error(18); statement(fsys); gen(jmp,0,cx1); code[cx2].a:=cx; end; test(fsys,[],19); end; {statement} begin {block} dx:=3; tx0:=tx; table[tx].adr:=cx; gen(jmp,0,0); if lev>levmax then error(32); repeat if sym=constsym then begin getsym; repeat constdeclaration; while sym=comma do begin getsym; constdeclaration; end; if sym=semicolon then getsym else error(5); until sym<>ident; end; if sym=varsym then begin getsym; repeat; vardeclaration; while sym=comma do begin getsym; vardeclaration; end; if sym=semicolon then getsym else error(5); until sym<>ident; end; while sym=procsym do begin getsym; if sym=ident then begin enter(procedur); getsym; end else error(4); if sym=semicolon then getsym else error(5); block(lev+1,tx,[semicolon]+fsys); if sym=semicolon then begin getsym; test(statbegsys+[ident,procsym],fsys,6); end else error(5); end; test(statbegsys+[ident],declbegsys,7); until not(sym in declbegsys); code[table[tx0].adr].a:=cx; with table[tx0] do begin adr:=cx; size:= dx; end; cx0:=cx; gen(int,0,dx); statement([semicolon,endsym]+fsys); gen(opr,0,0); test(fsys,[],8); listcode; end; {block} procedure interpret; const stacksize=500; var p,b,t:integer; {程序地址寄存器,基地址寄存器,栈顶地址寄存器} i:instruction; {指令寄存器} s:array[1..stacksize] of integer; {数据存贮} function base(l:integer):integer; var bl:integer; begin bl:=b; {顺静态链求层差为l的层的基地址} while l>0 do begin bl:=s[bl]; l:=l-1; end; base:=bl; end; {base} begin writeln('start pl/0'); writeln(data,'start pl/0'); t:=0; b:=1; p:=0; s[1]:=0; s[2]:=0; s[3]:=0; repeat i:=code[p]; p:=p+1; with i do case f of lit: begin t:=t+1; s[t]:=a; end; opr: case a of {operator} 0: begin {return} t:=b-1; p:=s[t+3]; b:=s[t+2]; end; 1: s[t]:=-s[t]; 2: begin t:=t-1; s[t]:=s[t]+s[t+1]; end; 3: begin t:=t-1; s[t]:=s[t]-s[t+1]; end; 4: begin t:=t-1; s[t]:=s[t]*s[t+1]; end; 5: begin t:=t-1; s[t]:=s[t] div s[t+1]; end; 6: s[t]:=ord(odd(s[t])); 8: begin t:=t-1; s[t]:=ord(s[t]=s[t+1]); end; 9: begin t:=t-1; s[t]:=ord(s[t]<>s[t+1]); end; 10:begin t:=t-1; s[t]:=ord(s[t]<s[t+1]); end; 11:begin t:=t-1; s[t]:=ord(s[t]>=s[t+1]); end; 12:begin t:=t-1; s[t]:=ord(s[t]>s[t+1]); end; 13:begin t:=t-1; s[t]:=ord(s[t]<=s[t+1]); end; end; lod: begin t:=t+1; s[t]:=s[base(l)+a]; end; sto: begin s[base(l)+a]:=s[t]; writeln(s[t]); writeln(data,s[t]);t:=t-1; end; cal: begin s[t+1]:=base(l); s[t+2]:=b; s[t+3]:=p; b:=t+1; p:=a; end; int: t:=t+a; jmp: p:=a; jpc: begin if s[t]=0 then p:=a; t:=t-1; end; end; {with, case} until p=0; writeln('end pl/0'); writeln(data,'endpl/0'); close(data); end; {interpret} begin {main} for ch:=' ' to '!' do ssym[ch]:=nul; word[1]:='begin '; word[2]:='call '; word[3]:='const '; word[4]:='do '; word[5]:='end '; word[6]:='if '; word[7]:='odd '; word[8]:='procedure '; word[9]:='then '; word[10]:='var '; word[11]:='while '; wsym[1]:=beginsym; wsym[2]:=callsym; wsym[3]:=constsym; wsym[4]:=dosym; wsym[5]:=endsym; wsym[6]:=ifsym; wsym[7]:=oddsym; wsym[8]:=procsym; wsym[9]:=thensym; wsym[10]:=varsym; wsym[11]:=whilesym; ssym['+']:=plus; ssym['-']:=minus; ssym['*']:=times; ssym['/']:=slash; ssym['(']:=lparen; ssym[')']:=rparen; ssym['=']:=eql; ssym[',']:=comma; ssym['.']:=period; ssym['#']:=neq; ssym[';']:=semicolon; mnemonic[lit]:='lit '; mnemonic[opr]:='opr '; mnemonic[lod]:='lod '; mnemonic[sto]:='sto '; mnemonic[cal]:='cal '; mnemonic[int]:='int '; mnemonic[jmp]:='jmp '; mnemonic[jpc]:='jpc '; declbegsys:=[constsym,varsym,procsym]; statbegsys:=[beginsym,callsym,ifsym,whilesym]; facbegsys:=[ident,number,lparen]; (* page(output);*) endf:=false; assign(srccode,'SRCCODE.txt'); rewrite(srccode); assign(data,'STACK.txt'); rewrite(data); write('Enter the path of the file:'); write(srccode,'Enter the path of the file:'); readln(fname); writeln(srccode,fname); assign(fin,fname); reset(fin); err:=0; cc:=0; cx:=0; ll:=0; ch:=' '; kk:=al; getsym; assign(fa,'MIDCODE.txt'); rewrite(fa); block(0,0,[period]+declbegsys+statbegsys); close(fa); close(srccode); if sym<>period then error(9); if err=0 then interpret else write('ERRORS IN PL/0 PROGRAM'); 99: {这个标号原来是用于退出程序的,由于Turbo Pascal不支持跨过程的跳转,所以使用exip函数替代} close(fin); writeln; end.
program pl0(input, output); {任务二的代码实现} label 99; const norw=13; {保留字个数} txmax=100; {标识符表长度} nmax=14; {数字允许的最长位数} al=10; {标识符表的长度} amax=2047; {最大地址} levmax=3; {程序体嵌套的最大深度} cxmax=200; {代码数组的大小} type symbol=(nul,ident,number,plus,minus,times,slash,oddsym, eql,neq,lss,leq,gtr,geq,lparen,rparen,comma, semicolon,period,becomes,beginsym,endsym,ifsym, thensym,whilesym,writesym,readsym,dosym,callsym, constsym,varsym,procsym); alfa=packed array[1..al] of char; objects=(constant,variable,procedur); {procedure和object在pascal中是关键字,所以分别使用procedur和object替代} symset=set of symbol; fct=(lit,opr,lod,sto,cal,int,jmp,jpc); instruction=packed record f:fct;{功能码} l:0..levmax; {层} a:0..amax; {相对地址} end; var fa:text;{文本文件fa用于列出中间代码} srccode,iofile:text; ch:char; {最近读到的字符} sym:symbol; {最近读到的符号} id:alfa; {最近读到的标识符} num:integer; {最近读到的数} cc:integer; {字符计数} ll:integer; {行长} kk:integer; cx:integer; {代码分配下标} line:array[1..81] of char; a:alfa; code:array[0..cxmax] of instruction; word:array[1..norw] of alfa; wsym:array[1..norw] of symbol; ssym:array[char] of symbol; mnemonic:array[fct] of packed array[1..5] of char; declbegsys, statbegsys, facbegsys:symset; table:array[0..txmax] of record name:alfa; case kind:objects of constant:(val:integer); variable,procedur:(level,adr,size:integer) end; fin,fout:text; fname:string; err:integer; endf:boolean; procedure error(n:integer); begin writeln('****','':cc-1,'!',n:2); writeln(srccode,'****','':cc-1,'!',n:2); err:=err+1; end; {error} procedure exitp; begin endf:=true; close(fin); writeln; exit; end; procedure getsym; var i,j,k:integer; procedure getch; begin if cc=ll then begin if eof(fin) then begin write('program incomplete'); close(fin); writeln; exitp; (*goto 99;*) end; ll:=0; cc:=0; write(cx:5,' '); write(srccode,cx:5,' '); while not eoln(fin) do begin ll:=ll+1; read(fin,ch); write(ch); write(srccode,ch); line[ll]:=ch; end; writeln; ll:=ll+1; line[ll]:=' '; readln(fin); writeln(srccode); end; cc:=cc+1; ch:=line[cc]; end; {getch} begin {getsym} while ch=' ' do getch; if ch in ['a'..'z'] then begin k:=0; repeat if k<al then begin k:=k+1; a[k]:=ch; end; getch; until not(ch in ['a'..'z','0'..'9']); if k>=kk then kk:=k else repeat a[kk]:=' '; kk:=kk-1; until kk=k; id:=a; i:=1; j:=norw; repeat k:=(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:=ident; end else if ch in ['0'..'9'] then begin k:=0; num:=0; sym:=number; repeat num:=10*num+(ord(ch)-ord('0')); k:=k+1; getch; until not(ch in['0'..'9']); if k>nmax then error(30); end else if ch=':' then begin getch; if ch='=' then begin sym:=becomes; getch; end else sym:=nul; end else if ch='<' then begin getch; if ch='=' then begin sym:=leq; getch; end else sym:=lss; end else if ch='>' then begin getch; if ch='=' then begin sym:=geq; getch; end else sym:=gtr; end else begin sym:=ssym[ch]; getch; end; end; {getsym} procedure gen(x:fct;y,z:integer); begin if cx>cxmax then begin write('program too long'); (*goto 99;*) end; with code[cx] do begin f:=x; l:=y; a:=z; end; cx:=cx+1; end; {gen} procedure test(s1,s2:symset;n:integer); begin if not(sym in s1) then begin error(n); s1:=s1+s2; while not(sym in s1) do getsym; end; end; {test} procedure block(lev,tx:integer;fsys:symset); var dx:integer; {数据分配下标} tx0:integer; {起始标识符表的下标} cx0:integer; {起始代码的下标} procedure enter(k:objects); begin {把objects填入标识符表中} tx:=tx+1; with table[tx] do begin name:=id; kind:=k; case k of constant: begin if num>amax then begin error(30); num:=0; end; val:=num; end; variable: begin level:=lev; adr:=dx; dx:=dx+1; end; procedur: level:=lev; end; end; end; {enter} function position(id:alfa):integer; var i:integer; begin {在标识符表中查标识符id} table[0].name:=id; i:=tx; while table[i].name<>id do i:=i-1; position:=i; end; {position} procedure constdeclaration; begin if sym=ident then begin getsym; if sym in [eql,becomes] then begin if sym=becomes then error(1); getsym; if sym=number then begin enter(constant); getsym; end else error(2); end else error(3); end else error(4); end; {constdeclaration} procedure vardeclaration; begin if sym=ident then begin enter(variable); getsym; end else error(4); end; {vardeclaration} procedure listcode; var i:integer; begin for i:=cx0 to cx-1 do with code[i] do begin writeln(i,mnemonic[f]:5,l:3,a:5); writeln(fa,i:4,mnemonic[f]:5,l:3,a:5); end; end; {listcode} procedure statement(fsys:symset); var i,cx1,cx2:integer; procedure expression(fsys:symset); var addop:symbol; procedure term(fsys:symset); var mulop:symbol; procedure factor(fsys:symset); var i:integer; begin test(facbegsys,fsys,24); while sym in facbegsys do begin if sym=ident then begin i:=position(id); if i=0 then error(11) else with table[i] do case kind of constant:gen(lit,0,val); variable:gen(lod,lev-level,adr); procedur:error(21); end; getsym; end else if sym=number then begin if num>amax then begin error(31); num:=0; end; gen(lit,0,num); getsym; end else if sym=lparen then begin getsym; expression([rparen]+fsys); if sym=rparen then getsym else error(22); end; test(fsys,facbegsys,23); end; end; {factor} begin {term} factor([times,slash]+fsys); while sym in [times,slash] do begin mulop:=sym; getsym; factor(fsys+[times,slash]); if mulop=times then gen(opr,0,4) else gen(opr,0,5) end; end; {term} begin {expression} if sym in [plus,minus] then begin addop:=sym; getsym; term(fsys+[plus,minus]); if addop=minus then gen(opr,0,1); end else term(fsys+[plus,minus]); while sym in [plus,minus] do begin addop:=sym; getsym; term(fsys+[plus,minus]); if addop=plus then gen(opr,0,2) else gen(opr,0,3); end; end; {expression} procedure condition(fsys:symset); var relop:symbol; begin if sym=oddsym then begin getsym; expression(fsys); gen(opr,0,6); end else begin expression([eql,neq,lss,leq,gtr,geq]+fsys); if not(sym in [eql,neq,lss,leq,gtr,geq]) then error(20) else begin relop:=sym; getsym; expression(fsys); case relop of eql:gen(opr,0,8); neq:gen(opr,0,9); lss:gen(opr,0,10); geq:gen(opr,0,11); gtr:gen(opr,0,12); leq:gen(opr,0,13); end; end; end; end; {condition} begin {statement} if sym=ident then begin i:=position(id); if i=0 then error(11) else if table[i].kind<>variable then begin error(12); i:=0; end; getsym; if sym=becomes then getsym else error(13); expression(fsys); if i<>0 then with table[i] do gen(sto,lev-level,adr); end else if sym=readsym then begin {添加read语句执行功能} getsym; if sym<>lparen then error(34) else repeat getsym; if sym=ident then i:=position(id) else i:=0; if i=0 then error(35) else with table[i] do begin gen(opr,0,16); gen(sto,lev-level,adr); end; getsym; until sym<>comma; if sym<>rparen then begin error(33); while not(sym in fsys) do getsym; end else getsym; end else if sym=writesym then begin {添加write语句执行功能} getsym; if sym=lparen then begin repeat getsym; expression([rparen,comma]+fsys); gen(opr,0,14); until sym<>comma; if sym<>rparen then error(33) else getsym; end; gen(opr,0,15); end else if sym=callsym then begin getsym; if sym<>ident then error(14) else begin i:=position(id); if i=0 then error(11) else with table[i] do if kind=procedur then gen(cal,lev-level,adr) else error(15); getsym; end; end else if sym=ifsym then begin getsym; condition([thensym,dosym]+fsys); if sym=thensym then getsym else error(16); cx1:=cx; gen(jpc,0,0); statement(fsys); code[cx1].a:=cx; end else if sym=beginsym then begin getsym; statement([semicolon,endsym]+fsys); while sym in [semicolon]+statbegsys do begin if sym=semicolon then getsym else error(10); statement([semicolon,endsym]+fsys); end; if sym=endsym then getsym else error(17); end else if sym=whilesym then begin cx1:=cx; getsym; condition([dosym]+fsys); cx2:=cx; gen(jpc,0,0); if sym=dosym then getsym else error(18); statement(fsys); gen(jmp,0,cx1); code[cx2].a:=cx; end; test(fsys,[],19); end; {statement} begin {block} dx:=3; tx0:=tx; table[tx].adr:=cx; gen(jmp,0,0); if lev>levmax then error(32); repeat if sym=constsym then begin getsym; repeat constdeclaration; while sym=comma do begin getsym; constdeclaration; end; if sym=semicolon then getsym else error(5); until sym<>ident; end; if sym=varsym then begin getsym; repeat; vardeclaration; while sym=comma do begin getsym; vardeclaration; end; if sym=semicolon then getsym else error(5); until sym<>ident; end; while sym=procsym do begin getsym; if sym=ident then begin enter(procedur); getsym; end else error(4); if sym=semicolon then getsym else error(5); block(lev+1,tx,[semicolon]+fsys); if sym=semicolon then begin getsym; test(statbegsys+[ident,procsym],fsys,6); end else error(5); end; test(statbegsys+[ident],declbegsys,7); until not(sym in declbegsys); code[table[tx0].adr].a:=cx; with table[tx0] do begin adr:=cx; size:=dx; end; cx0:=cx; gen(int,0,dx); statement([semicolon,endsym]+fsys); gen(opr,0,0); test(fsys,[],8); listcode; end; {block} procedure interpret; const stacksize=500; var p,b,t:integer; {程序地址寄存器,基地址寄存器,栈顶地址寄存器} i:instruction; {指令寄存器} s:array[1..stacksize] of integer; {数据存贮} function base(l:integer):integer; var bl:integer; begin bl:=b; {顺静态链求层差为l的层的基地址} while l>0 do begin bl:=s[bl]; l:=l-1; end; base:=bl; end; {base} begin (* writeln('start pl0');*) t:=0; b:=1; p:=0; s[1]:=0; s[2]:=0; s[3]:=0; repeat i:=code[p]; p:=p+1; with i do case f of lit: begin t:=t+1; s[t]:=a; end; opr: case a of {operator} 0: begin {return} t:=b-1; p:=s[t+3]; b:=s[t+2]; end; 1: s[t]:=-s[t]; 2: begin t:=t-1; s[t]:=s[t]+s[t+1]; end; 3: begin t:=t-1; s[t]:=s[t]-s[t+1]; end; 4: begin t:=t-1; s[t]:=s[t]*s[t+1]; end; 5: begin t:=t-1; s[t]:=s[t] div s[t+1]; end; 6: s[t]:=ord(odd(s[t])); 8: begin t:=t-1; s[t]:=ord(s[t]=s[t+1]); end; 9: begin t:=t-1; s[t]:=ord(s[t]<>s[t+1]); end; 10:begin t:=t-1; s[t]:=ord(s[t]<s[t+1]); end; 11:begin t:=t-1; s[t]:=ord(s[t]>=s[t+1]); end; 12:begin t:=t-1; s[t]:=ord(s[t]>s[t+1]); end; 13:begin t:=t-1; s[t]:=ord(s[t]<=s[t+1]); end; 14:begin write(s[t]); write(iofile,s[t]); t:=t-1; end; 15:begin writeln; writeln(iofile); end; {输出换行操作} 16:begin t:=t+1; write(':'); write(iofile,':'); readln(s[t]); writeln(iofile,s[t]); end; {是接受键盘值输入} end; lod: begin t:=t+1; s[t]:=s[base(l)+a]; end; sto: begin s[base(l)+a]:=s[t]; (* writeln(s[t]) *) t:=t-1; end; cal: begin s[t+1]:=base(l); s[t+2]:=b; s[t+3]:=p; b:=t+1; p:=a; end; int: t:=t+a; jmp: p:=a; jpc: begin if s[t]=0 then p:=a; t:=t-1; end; end; {with, case} until p=0; close(iofile); end; {interpret} begin {main} for ch:=' ' to '!' do ssym[ch]:=nul; word[1]:='begin '; word[2]:='call '; word[3]:='const '; word[4]:='do '; word[5]:='end '; word[6]:='if '; word[7]:='odd '; word[8]:='procedure '; word[9]:='read '; word[10]:='then '; word[11]:='var '; word[12]:='while '; word[13]:='write '; {添加了保留字write和read} wsym[1]:=beginsym; wsym[2]:=callsym; wsym[3]:=constsym; wsym[4]:=dosym; wsym[5]:=endsym; wsym[6]:=ifsym; wsym[7]:=oddsym; wsym[8]:=procsym; wsym[9]:=readsym; wsym[10]:=thensym; wsym[11]:=varsym; wsym[12]:=whilesym; wsym[13]:=writesym; {添加符号列表} ssym['+']:=plus; ssym['-']:=minus; ssym['*']:=times; ssym['/']:=slash; ssym['(']:=lparen; ssym[')']:=rparen; ssym['=']:=eql; ssym[',']:=comma; ssym['.']:=period; ssym['#']:=neq; ssym[';']:=semicolon; {初始化符号列表} mnemonic[lit]:='lit '; mnemonic[opr]:='opr '; mnemonic[lod]:='lod '; mnemonic[sto]:='sto '; mnemonic[cal]:='cal '; mnemonic[int]:='int '; mnemonic[jmp]:='jmp '; mnemonic[jpc]:='jpc '; declbegsys:=[constsym,varsym,procsym]; statbegsys:=[beginsym,callsym,ifsym,whilesym]; facbegsys:=[ident,number,lparen]; (* page(output) *) endf:=false; assign(srccode,'SRCCODE.txt'); rewrite(srccode); write('Enter the path of the file:'); write(srccode,'Enter the path of the file:'); readln(fname); writeln(srccode,fname); assign(fin,fname); reset(fin); err:=0; cc:=0; cx:=0; ll:=0; ch:=' '; kk:=al; getsym; assign(fa,'MIDCODE.txt'); assign(iofile,'IO.txt'); rewrite(fa); rewrite(iofile); block(0,0,[period]+declbegsys+statbegsys); close(fa); close(srccode); if sym<>period then error(9); if err=0 then interpret else write('ERRORS IN PL/0 PROGRAM'); 99: {这个标号原来是用于退出程序的,由于Turbo Pascal不支持跨过程的跳转,所以使用exip函数替代} close(fin); writeln; end.