📄 pl0.c
字号:
/*扩充了++a,--a,a++,a--,+=,-=,else语句,error错误说明*/
#include<stdio.h>
#include<stdlib.h>
#include"pl0.h"
#include"string.h"
/*解释执行时使用的栈*/
#define stacksize 500
int main()
{
bool nxtlev[symnum];
system("cls");
printf("Input 1.txt to text 'else'\n");
printf("Input 2.txt to test '+= & -='\n");
printf("Input 3.txt to text '++'&'--'\n");
printf("Input 4.txt to text 'Error'\n");
printf("Input pl/0 file ?");
scanf("%s",fname); /*输入文件名*/
fin=fopen(fname,"r");
if(fin)
{
printf("List object code ?(Y/N)"); /*是否输出虚拟机代码*/
scanf("%s",fname);
listswitch=(fname[0]=='y'||fname[0]=='Y');
printf("List symbol table ? (Y/N)"); /*是否输出名字表*/
scanf("%s",fname);
tableswitch=(fname[0]=='y'||fname[0]=='Y');
fa1=fopen("fa1.tmp","w");
fprintf(fa1,"Iput pl/0 file ? ");
fprintf(fa1,"%s\n", fname);
init(); /*初始化*/
err=0;
cc=cx=ll=0;
ch=' ';
if(-1!=getsym())
{
fa=fopen("fa.tmp","w");
fas=fopen("fas.tmp","w");
addset(nxtlev,declbegsys,statbegsys,symnum);
nxtlev[period]=true;
if(-1==block(0,0,nxtlev)) /*调用编译程序*/
{
fclose(fa);
fclose(fa1);
fclose(fas);
fclose(fin);
printf("\n");
return 0;
}
fclose(fa);
fclose(fa1);
fclose(fas);
if(sym!=period)
{
error(9);
}
if(err==0)
{
fa2=fopen("fa2.tmp", "w");
interpret();
fclose(fa2);
}
else
{
printf("Errors in pl/0 program");
}
}
fclose(fin);
}
else
{
printf("Can't open file! \n");
}
printf("\n");
return 0;
}
/*
*初始化
*/
void init()
{
int i;
for(i=0;i<=255;i++)
{
ssym[i]=nul;
}
ssym['+']=plus; /* char 的ASCI 作为数组下标*/
ssym['-']=minus;
ssym['*']=times;
ssym['/']=slash;
ssym['(']=lparen;
ssym[')']=rparen;
ssym['=']=eql;
ssym[',']=comma;
ssym['.']=period;
//ssym['#']=neq;
ssym[';']=semicolon;
/*设置保留字名字,按照字母顺序,便于折半查找*/
strcpy(&(word[0][0]),"begin");
strcpy(&(word[1][0]),"call");
strcpy(&(word[2][0]),"const");
strcpy(&(word[3][0]),"do");
strcpy(&(word[5][0]),"else"); //扩
strcpy(&(word[6][0]),"end");
strcpy(&(word[8][0]),"if");
strcpy(&(word[9][0]),"odd");
strcpy(&(word[10][0]),"procedure");
strcpy(&(word[11][0]),"read");
strcpy(&(word[13][0]),"then");
strcpy(&(word[14][0]),"to");
strcpy(&(word[15][0]),"var");
strcpy(&(word[16][0]),"while");
strcpy(&(word[17][0]),"write");
/*设置保留字符号*/
wsym[0]=beginsym;
wsym[1]=callsym;
wsym[2]=constsym;
wsym[3]=dosym;
wsym[5]=elsesym; /* add else*/
wsym[6]=endsym;
wsym[8]=ifsym;
wsym[9]=oddsym;
wsym[10]=procsym;
wsym[11]=readsym;
wsym[13]=thensym;
wsym[14]=tosym; /*add tosym*/
wsym[15]=varsym;
wsym[16]=whilesym;
wsym[17]=writesym;
/*设置指令名称*/
strcpy(&(mnemonic[lit][0]),"lit");
strcpy(&(mnemonic[opr][0]),"opr");
strcpy(&(mnemonic[lod][0]),"lod");
strcpy(&(mnemonic[sto][0]),"sto");
strcpy(&(mnemonic[cal][0]),"cal");
strcpy(&(mnemonic[inte][0]),"int");
strcpy(&(mnemonic[jmp][0]),"jmp");
strcpy(&(mnemonic[jpc][0]),"jpc");
/*设置符号集*/
for(i=0;i<symnum;i++)
{
declbegsys[i]=false;
statbegsys[i]=false;
facbegsys[i]=false;
}
/*设置声明开始符号集*/
declbegsys[constsym]=true;
declbegsys[varsym]=true;
declbegsys[procsym]=true;
/*设置语句开始符号集*/
statbegsys[beginsym]=true;
statbegsys[callsym]=true;
statbegsys[ifsym]=true;
statbegsys[whilesym]=true;
/*设置因子开始符号集*/
facbegsys[ident]=true;
facbegsys[number]=true;
facbegsys[lparen]=true;
facbegsys[plusone]=true; // 添加前自加和前自减运算
facbegsys[minusone]=true;
}
/*
*用数组实现集合的集合运算
*/
int inset(int e,bool* s)
{
return s[e];
}
int addset(bool* sr,bool* s1,bool* s2,int n)
{
int i;
for(i=0;i<n;i++)
{
sr[i]=s1[i]||s2[i];
}
return 0;
}
int subset(bool* sr,bool* s1,bool* s2,int n)
{
int i;
for(i=0;i<n;i++)
{
sr[i]=s1[i]&&(!s2[i]);
}
return 0;
}
int mulset(bool* sr,bool* s1,bool* s2,int n)
{
int i;
for(i=0;i<n;i++)
{
sr[i]=s1[i]&&s2[i];
}
return 0;
}
/*
*出错处理,打印出错位置和错误编码
*/
void error(int n)
{
char space[81];
memset(space,32,81);
space[cc-1]=0;//出错时当前符号已经读完,所以cc-1
printf("****%s!%d\n",space,n);
switch(n)
{
case 1:
printf("常数说明中的“=”写成“:=”\n");
break;
case 2:
printf("常数说明中的“=”后应是数字\n");
break;
case 3:
printf("常数说明中的标识符应是“=”\n");
break;
case 4:
printf("const,var,procedure后应为标识符\n");
break;
case 5:
printf("漏掉了“,”或“;”\n");
break;
case 6:
printf("过程说明后的符号不正确\n");
break;
case 7:
printf("应是语句开始符\n");
break;
case 8:
printf("程序体内语句部分的后跟符不正确\n");
break;
case 9:
printf("程序结尾丢掉了“.”\n");
break;
case 10:
printf("语句之间漏掉了“;”\n");
break;
case 11:
printf("标识符未说明\n");
break;
case 12:
printf("赋值语句中,赋值号左部标识符属性应是变量\n");
break;
case 13:
printf("赋值语句标识符后应是赋值号“:=”\n");
break;
case 14:
printf("call后应为标识符\n");
break;
case 15:
printf("call后标识符属性应为过程\n");
break;
case 16:
printf("常数说明中的“=”写成“:=”\n");
break;
case 17:
printf("丢了“end”或“;”\n");
break;
case 18:
printf("while型循环语句中丢了do\n");
break;
case 19:
printf("语句后的符号不正确\n");
break;
case 20:
printf("应为关系运算符\n");
break;
case 21:
printf("表达式内标识符属性不能是过程\n");
break;
case 22:
printf("表达式中漏掉“)”\n");
break;
case 23:
printf("因子后的非法符号\n");
break;
case 24:
printf("表达式的开始符不能是此符号\n");
break;
case 31:
printf("数越界\n");
break;
case 32:
printf("read语句括号中的标识符不是变量\n");
break;
}
err++;
}
/*
* 漏掉空格,读取一个字符
*
* 每次读一行,存入line缓冲区,line被getsym取空后再读一行
*
* 被函数getsym调用
*/
int getch()
{
if(cc==ll)
{
if(feof(fin))
{
printf("program incomplete");
return -1;
}
ll=0;
cc=0;
printf("%d ",cx );
fprintf(fa1,"%d ",cx);
ch=' ';
while(ch!=10)
{
//fscanf(fin,"%c",&ch)
if(EOF==fscanf(fin,"%c",&ch))
{
line[ll]=0;
break;
}
printf("%c",ch);
fprintf(fa1,"%c",ch);
line[ll]=ch;
ll++;
}
printf("\n");
fprintf(fa1,"\n");
}
ch=line[cc];
cc++;
return 0;
}
/*词法分析,获取一个符号
*/
int getsym()
{
int i,j,k;
while( ch==' '||ch==10||ch==9)
{
getchdo; /* 宏定义 getch*/
}
if(ch>='a'&&ch<='z')
{
k=0;
do{
if(k<al)
{
a[k]=ch; /*字符数组a为临时符号*/
k++;
}
getchdo;
}while(ch>='a'&&ch<='z'||ch>='0'&&ch<='9');
a[k]=0;
strcpy(id,a);
i=0;
j=norw-1;
do{ /*折半查找保留字表*/
k=(i+j)/2;
if(strcmp(id,word[k])<=0)
{
j=k-1;
}
if(strcmp(id,word[k])>=0)
{
i=k+1;
}
}while(i<=j);
if(i-1>j) /* 找到,当前单词为保留字*/
{
sym=wsym[k];
}
else /* 没找到,为用户定义的标识符*/
{
sym=ident;
}
}
else
{
if(ch>='0'&&ch<='9')
{
k=0;
num=0;
sym=number;
do{
num=10*num+ch-'0';
k++;
getchdo;
}while(ch>='0'&&ch<='9'); /*获取数字的值*/
k--;
if(k>nmax)
{
error(30);
}
}
else
{
if(ch==':') /*检测赋值符号*/
{
getchdo;
if(ch=='=')
{
sym=becomes; //becomes为:=
getchdo;
}
else
{
sym=nul; /*不能识别的符号*/
}
}
else
{
if(ch=='<') /*检测小于或小于等于符号*/
{
getchdo;
if(ch=='=')
{
sym=leq; //leq为<=
getchdo;
}
else if(ch=='>') //add neq
{
sym=neq; //neq为<>
getchdo;
}
else
{
sym=lss; //lss为<
}
}
else// else 11 begin
{
if(ch=='>') /*检测大于或大于等于符号*/
{
getchdo;
if(ch=='=')
{
sym=geq; //geq为>=
getchdo;
}
else
{
sym=gtr; //gtr为>
}
}
else
{
if(ch=='+') /*检测+,+=,++符号*/
{
getchdo;
if(ch=='=')
{
sym=pluseq; //pluseq为+=
getchdo;
}
else if(ch=='+')
{
sym=plusone; //plusone为++
getchdo;
}
else
{
sym=plus; //plus为+
}
}
else
{
if(ch=='-') /*检测-,-=,--符号*/
{
getchdo;
if(ch=='=')
{
sym=minuseq; //minuseq为-=
getchdo;
}
else if(ch=='-')
{
sym=minusone; //minusone为--
getchdo;
}
else
{
sym=minus; //minus为-
}
}
else
{
sym=ssym[ch];/* 当符号不满足上述条件时,全部按照单字符号处理 包括“+”等*/
//getchdo;
//richard
if(sym!=period) /*检测是否为程序终结*/
{
getchdo;
}
//end richard
}
}
}
}//else 11 end
}
}
}
return 0;
}
/*
*生成虚拟机代码
*
*x:instruction.f;
*y:instruction.l;
*z:instruction.a;
*/
int gen(enum fct x,int y,int z)
{
if(cx>=cxmax)
{
printf("Program too long"); /*程序过长*/
return -1;
}
code[cx].f=x;
code[cx].l=y;
code[cx].a=z;
cx++;
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -