?? 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 + -