(********************* 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.
文章整理:西部数码--专业提供域名注册、虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!
PL0编译器TurboPascal版再现
来源:互联网
作者:西部数码
时间:2008-04-09
西部数码-全国虚拟主机10强!40余项虚拟主机管理功能,全国领先!双线多线虚拟主机南北访问畅通无阻!免费赠送企业邮局,.CN域名,自助建站480元起,免费试用7天,满意再付款! P4主机租用799元/月.月付免压金!
热点关注
- AnsiString?PChar?赋值
- Report Machine 3.0 (报表
- MapX v5.02.25 破解文件
- WDBOX v1.0 多选下拉列表
- 用Delphi开发视频聊天软件
- Delphi客户服务器应用开发
- AES 加密算法函数包及演示
- ACCESS/SQL 数据库存取图
- 熊猫烧香核心源码(Delphi
- 把整个网页保存成JPG图片(
- 高级计算器 V1.0 (含代码)
- Delphi版模仿熊猫烧香病毒
- 精确定位打印程序 (含源代
- Delphi文件管理(六)
- 将数字四舍五入保留两位小
- 绝地程序编辑器 v1.0.1.4
- 关于自定义界面的方案(Eas
- Delphi 对象链接与嵌入(
- 用HTML页面做程序界面演示
- Delphi模拟最小化恢复关闭
- 用Delphi实现24位真彩色图
- 限制客户机运行程序 (有关
- Delphi中用API实现在MSN的
- DELPHI数据库应用程序的开
- Delphi 动态链接库编程(
- QQ号码自动申请器及源代码
- Win9x 下调整系统时钟控件
- delphi中的XML解析控件TXM
- 几个游戏内存修改器代码
- TT8 DevExpress 最新系列
- Tnt Delphi Unicode Contr
- DelphiTwain 2004-1-20 (
- Delphi中数据的自动录入
- 经验技巧:分享两条Delphi
- Delphi中Hash表的使用方法
IDC资讯
虚拟主机
域名注册
托管租用
vps主机
智能建站
网站运营 建站经验 策划盈利 搜索优化 网站推广 免费资源
网站联盟 联盟新闻 联盟介绍 联盟点评 网赚技巧
行业资讯 业界动态 搜索引擎 网络游戏 门户动态 电子商务 广告传媒
网络编程 Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术 Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷 Internet Explorer
网页制作 FrontPages Dreamweaver Javascript css photoshop fireworks Flash
程序设计 Java技术 C/C++ VB delphi
网络知识 网络协议 网络安全 网络管理 组网方案 Cisco技术
操作系统 Win2000 WinXP Win2003 Mac OS Linux FreeBSD
网站运营 建站经验 策划盈利 搜索优化 网站推广 免费资源
网站联盟 联盟新闻 联盟介绍 联盟点评 网赚技巧
行业资讯 业界动态 搜索引擎 网络游戏 门户动态 电子商务 广告传媒
网络编程 Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术 Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷 Internet Explorer
网页制作 FrontPages Dreamweaver Javascript css photoshop fireworks Flash
程序设计 Java技术 C/C++ VB delphi
网络知识 网络协议 网络安全 网络管理 组网方案 Cisco技术
操作系统 Win2000 WinXP Win2003 Mac OS Linux FreeBSD



