一.
语义分析和代码生成程序的功能和目的
主义分析的功能
:
语义分析主要借助符号表记录的信息来实现语义分析动作
.
在语法分析中,严格按照文法来检查语句的语法是否正确,但有些语句,单看语法结构并没有错误,但和该语句所处的上下文联系考虑就有错误,那么,把这种错误就称为语义错误。语义分析就是处理这种语义错误
.
代码生成程序的功能和目的
:
中间代码是在编译程序将高级语言程序翻译为汇编语言或机器代码的过程中产生的,在编译过程中起着桥梁的作用
.
二.
所实现的语义分析和代码生成程序能处理什么语句
(1).
简单变量的声明语句
(2).
表达式语句
(3).if
语句
.
(4)while
语句
(5)for
语句
(6)write
语句
(7)read
语句
(8)do
语句
.
(9)
处理过程调用和返回
三
.
语义分析代码生成程序生的目标代码及好处
语义分析代码生成程序生成一种作为源程序中间形式的抽象机的代码。而该抽象机的指令应当尽可能模仿所编译的源语言的结构,且具备下列两个特点:可移植性和可适应性。这种代码的好处是提高可读性和简化代码生成过程,开发出可移植又适用的编译程序。同时降低移植的开销,使得程序很容易进行修改,满足不同用户和系统的需求
.
四
.
该程序的错误处理方法
为了简化起见,在
TEST
编译程序中没有进行复杂的错误处理。在语法和语义分析中,一旦遇到语法或语义错误,则停止编译,立即返回,并报告发生的错误。
五
.
实验过程
一
.
首先用
VC++
编辑、编译和运行教材
P231~245
的语义及代码生成程序。步骤如下:先编辑主程序文件
TESTmain.c(P244)
、词法分析程序
TESTscan.c(P218-220)
和语法、语义及代码生成程序
TESTparse.c
(
P231-245
)这三个文件,然后新建一个工程
,
接下来,将上述三个文件加入到该工程中,编译后运行即可。
二
.
下一步为了能使程序分析
do
语句
,
修改词法分析程序
TESTscan.c
和语法语
,
义及代码生成程序
TESTparse.c
这二个文件
,
使该程序能分析
do
语句
.(
其实这一步在第二次实验时就已经修改了词法分析程序
,
在这次实验中我们首先分析在没有
do
语句时程序运行会出什么错误
,
在对词法分析程序添加
do
关键字
,
进行分析带有
do
的源程序
.)
首先起先上面第一步的语义分析
,
在这里编写一个
{
int i;
int j;
if(i<10)
i=9;
else
i=11;
if(j>10)
j=12;
else
j=8;
}
文件,以文件名A.T保存在D盘中.然后用语义分析程序进行语义分析,如图:
至此,语义分析成功!
B.T文件中的内容如下:
{
{
int
int
ID
i
;
;
int
int
ID
j
;
;
if
if
(
(
ID
i
<
<
NUM
10
)
)
ID
i
=
=
NUM
9
;
;
else else
ID
i
=
=
NUM
11
;
;
if
if
(
(
ID
j
>
>
NUM
10
)
)
ID
j
=
=
NUM
12
;
;
else else
ID
j
=
=
NUM
8
;
;
}
}
C.T文件内容如下:
LOAD0
LAODI10
LES
BRF LABLE0
LAODI9
STO0
BR LABLE1
LABEL0:
LAODI11
STO0
LABLE1:
LOAD1
LAODI10
GT
BRF LABLE2
LAODI12
STO1
BR LABLE3
LABEL2:
LAODI8
STO1
LABLE3:
STOP
至于第二步关于添加
do
语句时的运行情况这里就不再详细介绍了
.
七
.
实验体会
这次实验让我学到了更多的编译知识
,
从对词法
,
到语义分析上有了理深一步了解
,
实验中
,
也遇到了不少问题
,
比如输入程序就是个很大的问题了
.
但总体上对实验的理解还是能了解实验要我们完成的目的
.
日后还要花时间慢慢体会编译原理这一门课程
.
附件
:(
只提供两个源代码
)
//
主程序
TESTmain
#include <stdio.h>
#include <ctype.h>
extern int TESTscan();
extern int TESTparse();
char Scanin[300],Scanout[300],Errorfile[300],Codeout[300];
FILE *fin,*fout;
void main(){
int es=0;
es=TESTscan();
if(es>0) printf("
词法分析有错,编译停止!
");
else printf("
词法分析成功!
/n");
if(es==0){
es=TESTparse();
if(es==0) printf("
语法、语义分析并生成代码成功!
/n");
else printf("
语法、语义分析并生成代码失败!
/n");
}
}
//TESTparse
#include<stdio.h>
#include<ctype.h>
#include<conio.h>
#define maxvartablep 500
int TESTparse();
int program();
int compound_stat();
int statement();
int expression_stat();
int expression();
int bool_expr();
int additive_expr();
int term();
int factor();
int if_stat();
int while_stat();
int for_stat();
int do_stat();
int write_stat();
int read_stat();
int declaration_stat();
int declaration_list();
int statement_list();
int compound_stat();
int name_def(char * name);
char token[20],token1[40];
extern char Scanout[300],Codeout[300];
FILE *fp,* fout;
struct{
char name[8];
int address;
}vartable[maxvartablep];
int vartablep=0,lablep=0,datap=0;
int name_def(char * name)
{
int i ,es=0;
if(vartablep>=maxvartablep) return(21);
for(i=vartablep-1;i==0;i--)
{
if(strcmp(vartable[i].name,name)==0)
{es=22;
break;
}
}
if(es>0) return(es);
strcpy(vartable[vartablep].name,name);
vartable[vartablep].address=datap;
datap++;
vartablep++;
return(es);
}
int lookup(char *name,int *paddress)
{
int i, es=0;
for(i=0;i<vartablep;i++)
{
if(strcmp(vartable[i].name,name)==0)
{
*paddress=vartable[i].address;
return(es);
}
}
es=23;
return(es);
}
int TESTparse()
{
int es=0;
if((fp=fopen(Scanout,"r"))==NULL)
{
printf("/n 打开%错误!/n",Scanout);
es=10;
return(es);
}
printf("请输入目标文件名(包括路径):");
scanf("%s",Codeout);
if((fout=fopen(Codeout,"w"))==NULL)
{
printf("/n创建%错误!/n",Codeout);
es=10;
return(es);
}
if(es==0) es=program();
printf("==语法、语义分析及代码生成程序结果==/n");
switch(es){
case 0 :printf("语法、语义分析成功并抽象机汇编生成代码!/n");break;
case 10 :printf("打开文件%失败!/n",Scanout);break;
case 1 :printf("缺少{!/n");break;
case 2 :printf("缺少}!/n");break;
case 3 :printf("缺少标识符!/n");break;
case 4:printf("缺少分号!/n");break;
case 5 :printf("缺少(!/n");break;
case 6 :printf("缺少)!/n");break;
case 7 :printf("缺少操作数!/n");break;
case 21 :printf("符号表溢出!/n");break;
case 22 :printf("变量重复定义!/n");break;
case 23 :printf("变量未声明!/n");break;
}
fclose(fp);
fclose(fout);
return(es);
}
int program()
{
int es=0,i;
fscanf(fp,"%s%s/n",token,token1);
printf("%s%s/n",token,token1);
if(strcmp(token,"{"))
{
es=1;
return(es);
}
fscanf(fp,"%s%s/n",&token,&token1);
printf("%s%s/n",token,token1);
es=declaration_list();
if(es>0) return(es);
printf(" 符号表/n");
printf(" 名字
地址/n");
for(i=0;i<vartablep;i++)
printf(" %s %d/n",vartable[i].name,vartable[i].address);
es=statement_list();
if(es>0) return(es);
if(strcmp(token,"}"))
{es=2;
return(es);
}
fprintf(fout," STOP/n");
return(es);
}
int declaration_list()
{
int es=0;
while(strcmp(token,"int")==0)
{
es=declaration_stat();
if(es>0)return(es);
}
return(es);
}
int declaration_stat()
{
int es=0;
fscanf(fp,"%s%s/n",&token,&token1); printf("%s%s/n",token,token1);
if(strcmp(token,"ID")) return(es=3);
es=name_def(token1);
if(es>0)return(es);
fscanf(fp,"%s%s",&token,&token1); printf("%s%s/n",token,token1);
if(strcmp(token,";")) return(es=4);
fscanf(fp,"%s%s/n",&token,&token1); printf("%s%s/n",token,token1);
return(es);
}
int statement_list()
{
int es=0;
while(strcmp(token,"}"))
{
es=statement();
if(es>0)return(es);
}
return(es);
}
int statement()
{
int es=0;
if(es==0&&strcmp(token,"if")==0)es=if_stat();
if(es==0&&strcmp(token,"while")==0)es=while_stat();
if(es==0&&strcmp(token,"for")==0)es=for_stat();
if(es==0&&strcmp(token,"do")==0)es=do_stat();
if(es==0&&strcmp(token,"read")==0)es=read_stat();
if(es==0&&strcmp(token,"write")==0)es=write_stat();
if(es==0&&strcmp(token,"{")==0)es=compound_stat();
if(es==0&&(strcmp(token,"ID")==0||strcmp(token,"NUM")==0))es=expression_stat();
return(es);
}
int if_stat()
{
int es=0,lable1,lable2;
fscanf(fp,"%s%s/n",&token,&token1);
printf("%s%s/n",token,token1);
if(strcmp(token,"(")) return(es=5);
fscanf(fp,"%s%s/n",&token,&token1);
printf("%s%s/n",token,token1);
es=expression();
if(es>0) return(es);
if(strcmp(token,")")) return(es=6);
lable1=lablep++;
fprintf(fout," BRF LABLE%d/n",lable1);
fscanf(fp,"%s%s/n",&token,&token1);
printf("%s%s/n",token,token1);
es=statement();
if(es>0)return(es);
lable2=lablep++;
fprintf(fout," BR LABLE%d/n",lable2);
fprintf(fout,"LABEL%d:/n",lable1);
if(strcmp(token,"else")==0)
{
fscanf(fp,"%s%s/n",&token,&token1);
printf("%s%s/n",token,token1);
es=statement();
if(es>0)return(es);
}
fprintf(fout,"LABLE%d:/n",lable2);
return(es);
}
int while_stat()
{
int es=0,lable1,lable2;
lable1=lablep++;
fprintf(fout,"LABLE%d:/n",lable1);
fscanf(fp,"%s%s/n",&token,&token1);
printf("%s%s/n",token,token1);
if(strcmp(token,"(")) return(es=5);
fscanf(fp,"%s%s/n",&token,&token1);
printf("%s%s/n",token,token1);
es=expression();
if(es>0)return(es);
if(strcmp(token,")")) return(es=6);
lable2=lablep++;
fprintf(fout," BRF LABLE%d/n",lable2);
fscanf(fp,"%s%s/n",&token,&token1);
printf("%s%s/n",token,token1);
es=statement();
if(es>0)return(es);
fprintf(fout," BR LABLE%d/n",lable1);
fprintf(fout,"LABEL%d:/n",lable2);
return(es);
}
int do_stat()
{
int es=0,lable1,lable2;
fscanf(fp,"%s%s/n",&token,&token1);
printf("%s%s/n",token,token1);
if(strcmp(token,"(")) return(es=5);
fscanf(fp,"%s%s/n",&token,&token1);
printf("%s%s/n",token,token1);
es=expression();
if(es>0) return(es);
if(strcmp(token,")")) return(es=6);
lable1=lablep++;
fprintf(fout," BRF LABLE%d/n",lable2);
fscanf(fp,"%s%s/n",&token,&token1);
printf("%s%s/n",token,token1);
es=statement();
if(es>0)return(es);
fprintf(fout,"LABEL%d:/n",lable1);
if(strcmp(token,"while")==0)
{
fscanf(fp,"%s%s/n",&token,&token1);
printf("%s%s/n",token,token1);
es=statement();
if(es>0)return(es);
}
fprintf(fout,"LABLE%d:/n",lable2);
return(es);
}
int for_stat()
{
int es=0,lable1,lable2,lable3,lable4;
fscanf(fp,"%s%s/n",&token,&token1);
printf("%s%s/n",token,token1);
if(strcmp(token,"(")) return(es=5);
fscanf(fp,"%s%s/n",&token,&token1);
printf("%s%s/n",token,token1);
es=expression();
if(es>0)return(es);
if(strcmp(token,";"))return(es=4);
lable1=lablep++;
fprintf(fout,"LABLE%d:/n",lable1);
fscanf(fp,"%s%s/n",&token,&token1);
printf("%s%s/n",token,token1);
es=expression();
if(es>0)return(es);
lable2=lablep++;
fprintf(fout," BRF LABLE%d/n",lable2);
lable3=lablep++;
fprintf(fout," BR LABLE%d/n",lable3);
if(strcmp(token,";"))return(es=4);
lable4=lablep++;
fprintf(fout,"LABLE%d:/n",lable4);
fscanf(fp,"%s%s/n",&token,&token1);
printf("%s%s/n",token,token1);
es=expression();
if(es>0)return(es);
fprintf(fout," BR LABLE%d/n",lable1);
if(strcmp(token,")")) return(es=6);
fprintf(fout,"LABLE%d:/n",lable3);
fscanf(fp,"%s%s/n",&token,&token1);
printf("%s%s/n",token,token1);
es=statement();
if(es>0)return(es);
fprintf(fout," BR LABLE%d/n",lable4);
fprintf(fout,"LABLE%d:/n",lable2);
return(es);
}
int write_stat()
{
int es=0;
fscanf(fp,"%s%s/n",&token,&token1);
printf("%s%s/n",token,token1);
es=expression();
if(es>0)return(es);
if(strcmp(token,";"))return(es=4);
fprintf(fout," OUT/n");
fscanf(fp,"%s%s/n",&token,&token1);
printf("%s%s/n",token,token1);
return(es);
}
int read_stat()
{
int es=0,address;
fscanf(fp,"%s%s/n",&token,&token1);
printf("%s%s/n",token,token1);
if(strcmp(token,"ID"))return(es=3);
es=lookup(token1,&address);
if(es>0)return(es);
fprintf(fout," IN %d/n",address);
fscanf(fp,"%s%s/n",&token,&token1);
printf("%s%s/n",token,token1);
if(strcmp(token,";"))return(es=4);
fscanf(fp,"%s%s/n",&token,&token1);
printf("%s%s/n",token,token1);
return(es);
}
int compound_stat()
{
int es=0;
fscanf(fp,"%s%s/n",&token,&token1);
printf("%s%s/n",token,token1);
es=statement_list();
return(es);
}
int
expression_stat()
{
int es=0;
if(strcmp(token,";")==0)
{
fscanf(fp,"%s%s/n",&token,&token1);
printf("%s%s/n",token,token1);
return(es);
}
es=expression();
if(es>0)return(es);
if(strcmp(token,";")==0)
{
fscanf(fp,"%s%s/n",&token,&token1);
printf("%s%s/n",token,token1);
return(es);
}else
{
es=4;
return(es);
}
}
int expression()
{
int es=0,fileadd;
char token2[20],token3[40];
if(strcmp(token,"ID")==0)
{
fileadd=ftell(fp);
fscanf(fp,"%s%s/n",&token2,&token3);
printf("%s%s/n",token2,token3);
if(strcmp(token2,"=")==0)
{
int address;
es=lookup(token1,&address);
if(es>0)return(es);
fscanf(fp,"%s%s/n",&token,&token1);
printf("%s%s/n",token,token1);
es=bool_expr();
if(es>0)return(es);
fprintf(fout," STO%d/n",address);
}else
{
fseek(fp,fileadd,0);
printf("%s%s/n",token,token1);
es=bool_expr();
if(es>0)return(es);
}
}
return(es);
}
int bool_expr()
{
int es=0;
es=additive_expr();
if(es>0)return(es);
if(strcmp(token,">")==0||strcmp(token,">=")==0
||strcmp(token,"<")==0||strcmp(token,"<=")==0
||strcmp(token,"==")==0||strcmp(token,"!=")==0)
{
char token2[20];
strcpy(token2,token);
fscanf(fp,"%s%s/n",&token,&token1);
printf("%s%s/n",token,token1);
es=additive_expr();
if(es>0)return(es);
if(strcmp(token2,">")==0) fprintf(fout ," GT /n");
if(strcmp(token2,">=")==0) fprintf(fout ," GE /n");
if(strcmp(token2,"<")==0) fprintf(fout ," LES/n");
if(strcmp(token2,"<=")==0) fprintf(fout ," LE/n");
if(strcmp(token2,"==")==0) fprintf(fout ," EQ/n");
if(strcmp(token2,"!=")==0) fprintf(fout ," NOTEQ /n");
}
return(es);
}
int additive_expr()
{
int es=0;
es=term();
if(es>0)return(es);
while(strcmp(token,"+")==0||strcmp(token,"-")==0)
{
char token2[20];
strcpy(token2,token);
fscanf(fp,"%s%s/n",&token,&token1);
printf("%s%s/n",token,token1);
es=term();
if(es>0) return(es);
if(strcmp(token2,"+")==0)fprintf(fout," ADD/n");
if(strcmp(token2,"-")==0)fprintf(fout," SUB/n");
}
return(es);
}
int term()
{
int es=0;
es=factor();
if(es>0)return(es);
while(strcmp(token,"*")==0||strcmp(token,"/")==0)
{
char token2[20];
strcpy(token2,token);
fscanf(fp,"%s%s/n",&token,&token1);
printf("%s%s/n",token,token1);
es=factor();
if(es>0)return(es);
if(strcmp(token2,"*")==0)fprintf(fout," NULT/n");
if(strcmp(token2,"/")==0)fprintf(fout," DIV/n");
}
return(es);
}
int factor()
{
int es=0;
if(strcmp(token,"(")==0)
{
fscanf(fp,"%s%s/n",&token,&token1);
printf("%s%s/n",token,token1);
es=expression();
if(es>0)return(es);
if(strcmp(token,")")) return(es=6);
fscanf(fp,"%s%s/n",&token,&token1);
printf("%s%s/n",token,token1);
}else
{
if(strcmp(token,"ID")==0)
{
int address;
es=lookup(token1,&address);
if(es>0)return(es);
fprintf(fout," LOAD%d/n",address);
fscanf(fp,"%s%s/n",&token,&token1);
printf("%s%s/n",token,token1);
return(es);
}
if(strcmp(token,"NUM")==0)
{
fprintf(fout," LAODI%s/n",token1);
fscanf(fp,"%s%s/n",&token,&token1);
printf("%s%s/n",token,token1);
return(es);
}else
{
es=7;
return(es);
}
}return(es);
}