📄 cifa.c
字号:
void statement(struct node *fsys,int plev)
{//语句处理
int i,cx1,cx2,m=0,n=0;
char *tempset1[]={"rparen","comma",NULL};
char *tempset2[]={"thensym","dosym",NULL};
char *tempset3[]={"semicolon","endsym",NULL};
char *tempset4[]={"semicolon",NULL};
char *tempset5[]={"dosym",NULL};
char *tempset6[]={NULL};
struct node *temp1,*temp2,*temp3,*temp4,*temp5,*temp6;
temp1=(struct node *)malloc(sizeof(struct node));
temp2=(struct node *)malloc(sizeof(struct node));
temp3=(struct node *)malloc(sizeof(struct node));
temp4=(struct node *)malloc(sizeof(struct node));
temp5=(struct node *)malloc(sizeof(struct node));
temp6=(struct node *)malloc(sizeof(struct node));
while(tempset1[m]!=NULL)
{
temp1->pa[n++]=tempset1[m++];
}
temp1->pa[n]=NULL;
m=0;n=0;
while(tempset2[m]!=NULL)
{
temp2->pa[n++]=tempset2[m++];
}
temp2->pa[n]=NULL;
m=0;n=0;
while(tempset3[m]!=NULL)
{
temp3->pa[n++]=tempset3[m++];
}
temp3->pa[n]=NULL;
m=0;n=0;
while(tempset4[m]!=NULL)
{
temp4->pa[n++]=tempset4[m++];
}
temp4->pa[n]=NULL;
m=0;n=0;
while(tempset5[m]!=NULL)
{
temp5->pa[n++]=tempset5[m++];
}
temp5->pa[n]=NULL;
m=0;n=0;
while(tempset6[m]!=NULL)
{
temp6->pa[n++]=tempset6[m++];
}
temp6->pa[n]=NULL;
m=0;n=0;
if(strcmp(sym,"ident")==0)
{
i=position(id);
if(i==0)
{
error(11);
}
else
{
if(table[i].kind!=variable)//赋值号左部标识符的属性不是变量
{
error(12);
i=0;
}
}
getsym();
if(strcmp(sym,"becomes")==0)
{
getsym();
}
else //赋值号左部标识符的后继符号不是':='
{
error(13);
}
expression(fsys);
if(i!=0)
{
gen(sto,plev-table[i].level,table[i].adr);
}
}
else if(strcmp(sym,"readsym")==0)
{
getsym();
if(strcmp(sym,"lparen")!=0)
{
error(24);
}
else
{
do
{
getsym();
if(strcmp(sym,"ident")==0)
{
i=position(id);
}
else
{
i=0;
}
if(i==0)
{
error(35);
}
else
{
gen(opr,0,16);
gen(sto,plev-table[i].level,table[i].adr);
}
getsym();
}
while(strcmp(sym,"comma")==0);
}
if(strcmp(sym,"rparen")!=0)
{
error(22);
while(in(sym,fsys)==0)
{
getsym();
}
}
else
{
getsym();
}
}
else if(strcmp(sym,"writesym")==0)
{
getsym();
if(strcmp(sym,"lparen")==0)
{
do
{
getsym();
expression(add(temp1,fsys));
gen(opr,0,14);
}
while(strcmp(sym,"comma")==0);
if(strcmp(sym,"rparen")!=0)
{
error(33);
}
else
{
getsym();
}
}
gen(opr,0,15);
}
else if(strcmp(sym,"callsym")==0)
{
getsym();
if(strcmp(sym,"ident")!=0)
{
error(14);
}
else
{
i=position(id);
if(i==0)
{
error(11);
}
else
{
if(table[i].kind==procedur)
{
gen(cal,plev-table[i].level,table[i].adr);
}
else
{
error(15);
}
}
getsym();
}
}
else if(strcmp(sym,"ifsym")==0)
{
getsym();
condition(add(temp2,fsys));
if(strcmp(sym,"thensym")==0)getsym();
else error(16);
cx1=cx;
gen(jpc,0,0);
statement(fsys,plev);
code[cx1].a=cx;
}
else if(strcmp(sym,"beginsym")==0)
{
getsym();
statement(add(temp3,fsys),plev);
while(in(sym,add(temp4,statbegsys))==1)
{
if(strcmp(sym,"semicolon")==0)
{
getsym();
}
else
{
error(10);
}
statement(add(temp3,fsys),plev);
}
if(strcmp(sym,"endsym")==0)
{
getsym();
}
else
{
error(17);
}
}
else
{
if(strcmp(sym,"whilesym")==0)
{
cx1=cx;
getsym();
condition(add(temp5,fsys));
cx2=cx;
gen(jpc,0,0);
if(strcmp(sym,"dosym")==0)
{
getsym();
}
else
{
error(18);
}
statement(fsys,plev);
gen(jmp,0,cx1);
code[cx2].a=cx;
}
}
test(fsys,temp6,19);
}
//语法分析
void block(int plev,struct node *fsys)
{
int m=0,n=0;
int dx=3;
int tx0;//起始标识符的小标
static int cx0=0;//起始代码下标
char *tempset1[]={"semicolon","endsym",NULL};
char *tempset2[]={"ident","procsym",NULL};
char *tempset3[]={"semicolon",NULL};
char *tempset4[]={"ident",NULL};
char *tempset5[]={NULL};
struct node *temp1,*temp2,*temp3,*temp4,*temp5;
temp1=(struct node *)malloc(sizeof(struct node ));
temp2=(struct node *)malloc(sizeof(struct node ));
temp3=(struct node *)malloc(sizeof(struct node ));
temp4=(struct node *)malloc(sizeof(struct node ));
temp5=(struct node *)malloc(sizeof(struct node ));
while(tempset1[m]!=NULL)
{
temp1->pa[n++]=tempset1[m++];
}
temp1->pa[n]=NULL;
m=0;n=0;
while(tempset2[m]!=NULL)
{
temp2->pa[n++]=tempset2[m++];
}
temp2->pa[n]=NULL;
m=0;n=0;
while(tempset3[m]!=NULL)
{
temp3->pa[n++]=tempset3[m++];
}
temp3->pa[n]=NULL;
m=0;n=0;
while(tempset4[m]!=NULL)
{
temp4->pa[n++]=tempset4[m++];
}
temp4->pa[n]=NULL;
m=0;n=0;
while(tempset5[m]!=NULL)
{
temp5->pa[n++]=tempset5[m++];
}
temp5->pa[n]=NULL;
m=0;n=0;
lev=plev;
dx=3;
tx0=tx;
table[tx].adr=cx;
gen(jmp,0,1);
if(plev>LEVMAX)
{
error(32);
}
do
{
if(strcmp(sym,"constsym")==0)
{
getsym();
do
{
constdeclaration();
while(strcmp(sym,"comma")==0)
{
getsym();
constdeclaration();
}
if(strcmp(sym,"semicolon")==0)
{
getsym();
}
else
{
error(5);
}
}
while(strcmp(sym,"ident")==0);
}
if(strcmp(sym,"varsym")==0)
{
getsym();
do
{
vardeclaration();
while(strcmp(sym,"comma")==0)
{
getsym();
vardeclaration();
}
if(strcmp(sym,"semicolon")==0)
{
getsym();
}
else
{
error(5);
}
}
while(strcmp(sym,"ident")==0);
}
while(strcmp(sym,"procsym")==0)
{
getsym();
if(strcmp(sym,"ident")==0)
{
enter(procedur);
getsym();
}
else error(4);
if(strcmp(sym,"semicolon")==0)
{
getsym();
}
else
{
error(5);
}
block(plev+1,add(temp3,fsys));
lev=lev-1;
if(strcmp(sym,"semicolon")==0)
{
getsym();
test(add(statbegsys,temp2),fsys,6);
}
else
{
error(5);
}
}
test(add(statbegsys,temp4),declbegsys,7);
}
while(in(sym,declbegsys)==1);
code[table[tx0].adr].a=cx;
table[tx0].adr=cx;
table[tx0].size=dx;
gen(ini,0,dx);
statement(add(temp1,fsys),plev);
gen(opr,0,0);
test(fsys,temp5,8);
listcode(&cx0);
cx0=cx;
}
//返回基地址,提供计算静态链表信息
int base(int l,int *b,int s[STACKSIZE])
{
int b1;
b1=*b;
//顺静态链求层差为L的层的基地址
while(l>0)
{
b1=s[b1];
l=l-1;
}
return b1;
}
//解释执行
void interpret()
{
int p=0;
int b=1;
int t=0;
struct instruction i;
int s[STACKSIZE];
printf("开始执行 PL0……\n\n");
s[0]=0;
s[1]=0;
s[2]=0;
s[3]=0;
do
{
i=code[p];
p=p+1;
switch(i.f)
{
case lit://入栈
t=t+1;
s[t]=i.a;
break;
case opr:
switch(i.a)
{
case 0://跳转控制
t=b-1;
p=s[t+3];
b=s[t+2];
break;
case 1://取反
s[t]=-s[t];
break;
case 2://加法
t=t-1;
s[t]=s[t]+s[t+1];
break;
case 3://减法
t=t-1;
s[t]=s[t]-s[t+1];
break;
case 4://乘法
t=t-1;
s[t]=s[t]*s[t+1];
break;
case 5://除法
t=t-1;
s[t]=s[t]/s[t+1];
break;
case 6://奇偶判断
if(s[t]%2==0)
{
s[t]=0;
}
else
{
s[t]=1;
}
break;
case 8://关系运算符==
t=t-1;
if(s[t]==s[t+1])
{
s[t]=1;
}
else
{
s[t]=0;
}
break;
case 9://关系运算符!=
t=t-1;
if(s[t]==s[t+1])
{
s[t]=0;
}
else
{
s[t]=1;
}
break;
case 10://关系运算符<
t=t-1;
if(s[t]<s[t+1])
{
s[t]=1;
}
else
{
s[t]=0;
}
break;
case 11://关系运算符>=
t=t-1;
if(s[t]>=s[t+1])
{
s[t]=1;
}
else
{
s[t]=0;
}
break;
case 12://关系运算符>
t=t-1;
if(s[t]>s[t+1])
{
s[t]=1;
}
else
{
s[t]=0;
}
break;
case 13://关系运算符<=
t=t-1;
if(s[t]<=s[t+1])
{
s[t]=1;
}
else
{
s[t]=0;
}
break;
case 14://write
printf("Result: %d\n",s[t]);
fprintf(fa2,"Result: %d\n",s[t]);
t=t-1;
break;
case 15://换行
//printf("\n");
//fprintf(fa2,"\n");
break;
case 16://read
t=t+1;
printf("请输入源程序所需的整数:\n");
fprintf(fa2,"执行程序所用的整数为:\t");
//scanf("%d",&s[t]);
//cin>>s[t];
char mychar;
cin>>mychar;
while(!isdigit(mychar))
{
cout<<"非数字,请重新输入:"<<endl;
cin>>mychar;
}
s[t]=mychar-48;
cout<<endl;
fprintf(fa2,"%d\n\n",s[t]);
break;
}
break;
case lod://取变量(相对地址为a,层次差为l)放到数据栈的栈顶
t=t+1;
s[t]=s[base(i.l,&b,s)+i.a];
break;
case sto://将数据栈栈顶的内容存人变量
s[base(i.l,&b,s)+i.a]=s[t];
t=t-1;
break;
case cal://调用过程(入口地址为a,层次差为l)
s[t+1]=base(i.l,&b,s);
s[t+2]=b;
s[t+3]=p;
b=t+1;
p=i.a;
break;
case ini://数据栈栈顶指针增加a
t=t+i.a;
break;
case jmp://无条件转移到地址为a的指令
p=i.a;
break;
case jpc://条件转移到地址为a的指令
if(s[t]==0)
{
p=i.a;
}
t=t-1;
break;
}
}
while(p!=0);
cout<<endl<<"PL0 执行结束!"<<endl<<endl;
fclose(fa2);
}
void main()
{
int m=0,n=0;
char *declbeg[]={"constsym","varsym","procsym",NULL};
char *statbeg[]={"beginsym","callsym","ifsym","whilesym",NULL};
char *facbeg[]={"ident","number","lparen",NULL};
char *tempset[]={"period","constsym","varsym","procsym",NULL};
declbegsys=(struct node *)malloc(sizeof(struct node));
statbegsys=(struct node *)malloc(sizeof(struct node));
facbegsys=(struct node *)malloc(sizeof(struct node));
tempsetsys=(struct node *)malloc(sizeof(struct node));
while(declbeg[m]!=NULL)
{
declbegsys->pa[n++]=declbeg[m++];
}
declbegsys->pa[n]=NULL;
m=0;
n=0;
while(statbeg[m]!=NULL)
{
statbegsys->pa[n++]=statbeg[m++];
}
statbegsys->pa[n]=NULL;
m=0;n=0;
while(facbeg[m]!=NULL)
{
facbegsys->pa[n++]=facbeg[m++];
}
facbegsys->pa[n]=NULL;
m=0;n=0;
while(tempset[m]!=NULL)
{
tempsetsys->pa[n++]=tempset[m++];
}
tempsetsys->pa[n]=NULL;
if((fa1=fopen("Analyse.txt","w"))==NULL)
{
printf("程序不能打开存放分析过程信息的文件(“Analyse.txt”)!\n");
exit(0);
}
//打开PASCAL源文件
printf("请输入要编译的PASCAL源程序所在文件名:\n");
scanf("%s",fname);
while((fin=fopen(fname,"r"))==NULL)
{
printf("打开该文件失败!\n是否重试?(Y/N)\n");
char mychar;
cin>>mychar;
if(mychar=='Y'||mychar=='y')
{
system("cls");//清屏
printf("请输入要编译的PASCAL源程序所在文件名:\n");
scanf("%s",fname);
}
else
{
exit(0);
}
}
fprintf(fa1,"对PASCAL源程序的分析为: \n(源程序来自:%s)\n\n",fname);
printf("是否列出伪代码?(Y/N)\n");
scanf("%s",fname);
if(fname[0]=='y'||fname[0]=='Y')
{
listswitch=tru;
printf("\n伪代码如下:\n\n");
}
else
{
listswitch=fals;
printf("\n源程序如下:\n\n");
}
err=0;
cc=1;
cx=0;
ll=0;
ch=' ';
kk=AL;
getsym();
if((fa=fopen("ObjectCode.txt","w"))==NULL)
{
printf("打开存放伪代码文件(“ObjectCode.txt”)失败!\n");
exit(0);
}
else
{
fprintf(fa,"伪代码如下:\n\n");
}
if((fa2=fopen("Result.txt","w"))==NULL)
{
printf("打开程序执行结果文件(“Result.txt”)失败!\n");
exit(0);
}
block(0,add(statbegsys,tempsetsys));
fclose(fa);
if(strcmp(sym,"period")!=0)
{
error(9);
}
if(err==0)
{
fprintf(fa1,"\n\n在该程序中未发现语法错误!\n");
interpret();
}
else
{
printf("\n\n%d 个错误在该PASCAL源程序中!\n请修改并重新编译!\n\n",err);
}
fclose(fa1);
fclose(fin);
}
例子:Top
1、输入文件(*.txt):
var b,c,d;
begin
b:=10;
d:=10;
read(c);
read(d);
b:=c;
b:=c+d;
write(b)
end.
2、输出文件(ObjectCode.txt):
伪代码如下:
0 jmp 0 1
1 ini 0 3
2 lit 0 10
3 sto 0 0
4 lit 0 10
5 sto 0 2
6 opr 0 16
7 sto 0 1
8 opr 0 16
9 sto 0 2
10 lod 0 1
11 sto 0 0
12 lod 0 1
13 lod 0 2
14 opr 0 2
15 sto 0 0
16 lod 0 0
17 opr 0 14
18 opr 0 15
19 opr 0 0
3、输入:
该段pascal程序需要有两个输入:
随意输入:0到9的一个数,如果一次输入2位数会被认为是一次输入两个数。
会输出两个输入数的和。
--------------------------------------------------------------------------------
Top
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -