分享
 
 
 

PL0编译器TurboPascal版再现

王朝delphi·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

(********************* PL0 编译程序Turbo Pascal代码 *********************)

program pl0(fa,fa1,fa2);

(* PL0 compile with code generation *)

label 99;

(* Turbo Pascal do not support goto between different

blocks so, the 'goto' command in getch are replaced

by procedure exitp !! in another way, 'label 99' do

not work !! Lin Wei 2001 *)

const norw=13; (* of reserved words *)

txmax=100; (* length of identifier table *)

nmax=14; (* max number of digits in numbers *)

al=10; (* length of identifiers *)

amax=2047; (* maximum address *)

levmax=3; (* max depth of block nesting *)

cxmax=200; (* size of code array *)

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);

(* wirth used the word "procedure"and"object" there, which won't work! *)

symset=set of symbol;

fct=(lit,opr,lod,sto,cal,int,jmp,jpc);

instruction=packed record

f:fct; (* function code *)

l:0..levmax; (* level *)

a:0..amax; (* displacement addr *)

end;

(* lit 0,a load constant a

opr 0,a execute opr a

lod 1,a load variable 1,a

sto 1,a store variable 1,a

cal 1,a call procedure at level 1

int 0,a increment t -register by a

jmp 0,a jump to a

jpc 0,a jump conditional to a *)

var fa:text;

fa1,fa2:text;

listswitch:boolean; (* true set list object code *)

ch:char; (* last char read *)

sym:symbol; (* last symbol read *)

id:alfa; (* last identifier read *)

num:integer; (* last number read *)

cc:integer; (* character count *)

ll:integer; (* line length *)

kk:integer;

cx:integer; (* code allocation index *)

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[' '..'^'] of symbol;

(* wirth uses "array[char]" here *)

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)

(* "size" lacking in original. I think it belongs here *)

end;

fin,fout:text;

fname:string;

err:integer;

endf:boolean;

procedure error(n:integer);

begin

writeln('****','':cc-1,'!',n:2);

writeln(fa1,'****','':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:4,' ');

write(fa1,cx:4,' ');

while not eoln(fin) do begin

ll:=ll+1;

read(fin,ch);

write(ch);

write(fa1,ch);

line[ll]:=ch;

end;

writeln;

ll:=ll+1;

(* read(fin,line[ll]); repleaced by two lines below *)

line[ll]:=' ';

readln(fin);

writeln(fa1);

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 (* number *)

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; (* data allocation index *)

tx0:integer; (* inital table index *)

cx0:integer; (* inital code index *)

procedure enter(k:objects);

begin (* enter object into table *)

tx:=tx+1;

with table[tx] do begin

name:=id;

kind:=k;

case k of

constant: begin

if num>amax then begin error(31); 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 (* find identifier in table *)

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

if listswitch then 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;

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

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

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; (* program base topstack registers *)

i:instruction;

s:array[1..stacksize] of integer; (* datastore *)

function base(l:integer):integer;

var bl:integer;

begin

bl:=b; (* find base 1 level down *)

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(fa2,s[t]); t:=t-1; end;

15:begin writeln; writeln(fa2); end;

16:begin t:=t+1; write('?'); write(fa2,'?'); readln(s[t]);

writeln(fa2,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 (* generat new block mark *) 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(fa2);

end; (* interpret *)

begin (* main *)

for ch:=' ' to '!' do ssym[ch]:=nul;

(* changed bacause of different character set

note the typos below in the original where

the alfas were not given the correct space *)

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 ';

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(fa1,'PL0.txt');

rewrite(fa1);

write('input file? ');

write(fa1,'input file?');

readln(fname);

writeln(fa1,fname);

(* openf(fin,fname,'r'); ==> *)

assign(fin,fname); reset(fin);

write('list object code ?');

readln(fname);

write(fa1,'list object code ?');

listswitch:=(fname[1]='y');

err:=0;

cc:=0; cx:=0; ll:=0;

ch:=' '; kk:=al;

getsym;

assign(fa,'PL0-1.txt');

assign(fa2,'PL0-2.txt');

rewrite(fa);

rewrite(fa2);

block(0,0,[period]+declbegsys+statbegsys);

close(fa);

close(fa1);

if sym<>period then error(9);

if err=0 then interpret else write('error in pl/0 program');

99: (* this line is not work in turbo pascal so replace by

procedure exitp: see the memo at the top *)

close(fin);

writeln;

end.

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有