📄 pl0.c
字号:
#include <stdio.h>
#include <string.h>
#include "pl0.h"
int getch()
{
if(cc==ll) //如果一行缓存取完
{
if(feof(fin))
{
printf("Program incomplete!");
return -1;
}
cc=0; //当前行取词位置初始化
ll=0; //当前行取词总数初始化
ch=' ';
while(ch!=10&&ll<=81)
{
ch=fgetc(fin);
if(feof(fin))
{
ch=0;
break;
}
line[ll]=ch;
printf("%c",ch);
fprintf(fa1,"%c",ch);
ll++;
}
}
ch=line[cc];
cc++;
return 0;
}
int getsym()
{
while(ch==10||ch==32||ch==9)
{
if(getch()==-1)
return -1;
}
if(ch>='a'&&ch<='z') //字母开头可能是标识符或关键字
{
int k=0;
do{
if(k<WMAX) //最多读入WMAX个字符
tmp[k]=ch;
if(getch()==-1)
return -1;
k++;
}while(ch>='a'&&ch<='z'||ch>='0'&&ch<='9');
tmp[k]=0;
strcpy(id,tmp);
for(k=0;k<NKEY;k++)
{
if(strcmp(id,word[k])==0)
{
sym=wsym[k];
break;
}
}
if(k>=NKEY)
sym=ident;
}
else if(ch>='0'&&ch<='9') //开头为数字,当作常数
{
int k=0;
num=0;
sym=number;
do{
num=num*10+ch-'0';
k++;
if(getch()==-1)
return -1;
}while(ch>='0'&&ch<='9');
if(k>NMAX)
error(0);
}
else //剩下的是单双字符符号
{
if(ch==':')
{
if(getch()==-1)
return -1;
if(ch=='=')
{
sym=becomes;
if(getch()==-1)
return -1;
}
else
sym=nul;
}
else if(ch=='>')
{
if(getch()==-1)
return -1;
if(ch=='=')
{
sym=geq;
if(getch()==-1)
return -1;
}
else
sym=gtr;
}
else if(ch=='<')
{
if(getch()==-1)
return -1;
if(ch=='=')
{
sym=leq;
if(getch()==-1)
return -1;
}
else
sym=lss;
}
else
{
sym=ssym[ch];
if(sym!=period) //当且仅当当前符号是句号时,
{ //不再读入一个符号
if(getch()==-1)
return -1;
}
}
}
return 0;
}
int inset(int e,int *s)
{
return s[e];
}
int addset(int *sr,int *s1,int *s2,int n)
{
int i;
for(i=0;i<n;i++)
sr[i]=s1[i]||s2[i];
return 0;
}
int subset(int *sr,int *s1,int *s2,int n)
{
int i;
for(i=0;i<n;i++)
sr[i]=s1[i]&&(!s2[i]);
return 0;
}
int mulset(int *sr,int *s1,int *s2,int n)
{
int i;
for(i=0;i<n;i++)
sr[i]=s1[i]&&s2[i];
return 0;
}
void init()
{
int i;
for(i=0;i<256;i++)
ssym[i]=nul;
ssym['=']=eql;
ssym[',']=comma;
ssym['.']=period;
ssym['#']=neq;
ssym[';']=semicolon;
ssym['(']=lparen;
ssym[')']=rparen;
ssym['+']=plus;
ssym['-']=minus;
ssym['*']=times;
ssym['/']=slash;
strcpy(word[0],"begin");
strcpy(word[1],"call");
strcpy(word[2],"const");
strcpy(word[3],"do");
strcpy(word[4],"end");
strcpy(word[5],"if");
strcpy(word[6],"odd");
strcpy(word[7],"procedure");
strcpy(word[8],"read");
strcpy(word[9],"then");
strcpy(word[10],"var");
strcpy(word[11],"while");
strcpy(word[12],"write");
strcpy(mc[0],"lit");
strcpy(mc[1],"opr");
strcpy(mc[2],"lod");
strcpy(mc[3],"sto");
strcpy(mc[4],"cal");
strcpy(mc[5],"inte");
strcpy(mc[6],"jmp");
strcpy(mc[7],"jpc");
wsym[0]=beginsym;
wsym[1]=callsym;
wsym[2]=constsym;
wsym[3]=dosym;
wsym[4]=endsym;
wsym[5]=ifsym;
wsym[6]=oddsym;
wsym[7]=procsym;
wsym[8]=readsym;
wsym[9]=thensym;
wsym[10]=varsym;
wsym[11]=whilesym;
wsym[12]=writesym;
for(i=0;i<SYMNUM;i++)
{
dcbsys[i]=0;
stbsys[i]=0;
fcbsys[i]=0;
}
dcbsys[constsym]=1;
dcbsys[varsym]=1;
dcbsys[procsym]=1;
stbsys[beginsym]=1;
stbsys[callsym]=1;
stbsys[ifsym]=1;
stbsys[whilesym]=1;
fcbsys[ident]=1;
fcbsys[number]=1;
fcbsys[lparen]=1;
}
void error(int n)
{
char space[81];
memset(space,32,81);
space[cc-2]=0;
printf("%s%c%s\n",space,24,errinfo[n]); //24为向上箭头符号,指使出错位置
fprintf(fa1,"%s%c%s\n",space,24,errinfo[n]);
err++;
}
int mb(int lev,int tx,int *s)
{
int ts[SYMNUM]; //看作布尔集合数组传给子程序
int tx0=tx;
int dx=3;
tb[tx].adr=cx;
if(gen(jmp,0,0)==-1)
return -1;
if(lev>LVMAX)
error(1);
do //声明部分
{
if(sym==constsym)
{
if(getsym()==-1)
return -1;
constdc(&tx,lev,&dx);
while(sym==comma)
{
if(getsym()==-1)
return -1;
constdc(&tx,lev,&dx);
}
if(sym!=semicolon)
error(2);
else
{
if(getsym()==-1)
return -1;
}
}
if(sym==varsym)
{
if(getsym()==-1)
return -1;
vardc(&tx,lev,&dx);
while(sym==comma)
{
if(getsym()==-1)
return -1;
vardc(&tx,lev,&dx);
}
if(sym!=semicolon)
error(3);
else
{
if(getsym()==-1)
return -1;
}
}
while(sym==procsym)
{
if(getsym()==-1)
return -1;
if(sym==ident)
{
record(procedure,&tx,lev,&dx);
if(getsym()==-1)
return -1;
if(sym!=semicolon)
error(4);
else
{
if(getsym()==-1)
return -1;
}
}
else
error(5);
memcpy(ts,s,sizeof(int)*SYMNUM);
ts[semicolon]=1;
if(mb(lev+1,tx,ts)==-1)
return -1;
if(sym==semicolon)
{
if(getsym()==-1)
return -1;
memcpy(ts,stbsys,sizeof(int)*SYMNUM);
ts[procsym]=1;
ts[ident]=1;
if(test(ts,s,8)==-1)
return -1;
}
else
error(6);
}
memcpy(ts,stbsys,sizeof(int)*SYMNUM);
ts[period]=1;
ts[ident]=1;
if(test(ts,s,9)==-1)
return -1;
}while(inset(sym,dcbsys));
code[tb[tx0].adr].a=cx;
tb[tx0].size=dx;
tb[tx0].adr=cx;
if(gen(inte,0,dx)==-1) //分配存储语句
return -1;
memcpy(ts,s,sizeof(int)*SYMNUM); //语句部分
ts[semicolon]=1;
ts[endsym]=1;
if(stat(&tx,ts,lev)==-1)
return -1;
if(gen(opr,0,0)==-1)
return -1;
memset(ts,0,sizeof(int)*SYMNUM);
if(test(s,ts,10)==-1)
return -1;
return 0;
}
int test(int *s1,int *s2,int n)
{
if(!inset(sym,s1))
{
error(n);
while(!inset(sym,s1)&&!inset(sym,s2))
{
if(getsym()==-1)
return -1;
}
}
return 0;
}
int constdc(int *ptx,int lev,int *pdx)
{
if(sym==ident)
{
if(getsym()==-1)
return -1;
if(sym==becomes)
error(11);
else if(sym==eql)
{
if(getsym()==-1)
return -1;
if(sym==number)
{
record(constant,ptx,lev,pdx);
if(getsym()==-1)
return -1;
}
else
error(12);
}
else
error(13);
}
else
error(14);
return 0;
}
int vardc(int *ptx,int lev,int *pdx)
{
if(sym==ident)
{
record(variable,ptx,lev,pdx);
if(getsym()==-1)
return -1;
}
else
error(15);
return 0;
}
void record(enum obj k,int *ptx,int lv,int *pdx)
{
(*ptx)++;
tb[*ptx].kind=k;
strcpy(tb[*ptx].name,id);
if(k==constant)
{
if(num>AMAX)
{
error(7); //数越界
num=0;
}
tb[*ptx].val=num;
}
else if(k==variable)
{
tb[*ptx].adr=*pdx;
tb[*ptx].lev=lv;
(*pdx)++;
}
else if(k==procedure)
tb[*ptx].lev=lv;
}
int gen(enum fct x,int y,int z)
{
if(cx==1000)
printf("%s",id);
if(cx>CXMAX)
{
printf("Program too long!\n");
return -1;
}
code[cx].f=x;
code[cx].l=y;
code[cx].a=z;
cx++;
return 0;
}
int extable(char *idt,int tx)
{
int j;
for(j=tx;j>0;j--)
{
if(strcmp(tb[j].name,idt)==0)
return j;
}
return 0;
}
int stat(int *ptx,int *s,int lev)
{
int p;
int ts[SYMNUM];
if(sym==ident)
{
p=extable(id,*ptx);
if(p==0)
error(16);
else
{
if(tb[p].kind!=variable)
{
error(17);
p=0;
}
else
{
if(getsym()==-1)
return -1;
if(sym==becomes)
{
if(getsym()==-1)
return -1;
memcpy(ts,s,sizeof(int)*SYMNUM);
if(exp(ptx,ts,lev)==-1)
return -1;
}
else
{
error(18);
p=0;
}
}
}
if(p!=0)
{
if(gen(sto,lev-tb[p].lev,tb[p].adr)==-1)
return -1;
}
}
else if(sym==callsym)
{
if(getsym()==-1)
return -1;
if(sym==ident)
{
p=extable(id,*ptx);
if(p==0)
error(25);
else
{
if(tb[p].kind!=procedure)
{
error(26);
p=0;
}
else
{
if(getsym()==-1)
return -1;
}
}
}
else
{
error(27);
p=0;
}
if(p!=0)
{
if(gen(cal,lev-tb[p].lev,tb[p].adr)==-1)
return -1;
}
}
else if(sym==beginsym)
{
if(getsym()==-1)
return -1;
memcpy(ts,s,sizeof(int)*SYMNUM);
ts[semicolon]=1;
ts[endsym]=1;
if(stat(ptx,ts,lev)==-1)
return -1;
while(inset(sym,stbsys)||sym==semicolon)
{
if(sym==semicolon)
{
if(getsym()==-1)
return -1;
}
else
error(29);
if(stat(ptx,ts,lev)==-1)
return -1;
}
if(sym!=endsym)
error(30);
else
{
if(getsym()==-1)
return -1;
}
}
else if(sym==ifsym)
{
int cx1;
if(getsym()==-1)
return -1;
memcpy(ts,s,sizeof(int)*SYMNUM);
ts[thensym]=1;
ts[dosym]=1;
if(con(ptx,ts,lev)==-1)
return -1;
cx1=cx;
if(gen(jpc,0,0)==-1)
return -1;
if(sym!=thensym)
error(28);
else
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -