简单编译器的实现课时设计.docx
《简单编译器的实现课时设计.docx》由会员分享,可在线阅读,更多相关《简单编译器的实现课时设计.docx(27页珍藏版)》请在冰豆网上搜索。
简单编译器的实现课时设计
成绩:
课程设计
题目:
简单编译器实现
学院:
专业:
班级:
组长:
小组成员:
指导教师:
2014
年
12
月
19
日
一、课程设计的目的
在学习《程序设计语言编译原理》课程过程中,结合各章节构造编译程序的基本理论分别完成词法分析器、语法分析器和语义分析器实验,在基本实验完成的基础上,逐步完成课程设计。
针对自己的理解和学习,实现一个小编译器括符号表的构造,词法分析,语法分析,目标代码生成等重要子程序,其中词法分析、语法分析及语义分析功能必须完成),并对其进行分析解释和总结,同时将理论与实际应用结合起来,接受软件设计等开发过程的全面训练,从而提高软件开发的能力。
二、课程设计的任务
(1)设计符号表
确定符号表的组织方式,一般应包括名字栏和信息栏,其中名字栏作为关键字。
要考虑能够存储有关名字的信息,并可以高效地完成如下操作:
a.查找:
根据给定的名字,在符号表中查找其信息。
如果该名字在符号表中不存在,则将其加入到符号表中,否则返回指向该名字的指针;
b.删除:
从符号表中删除给定名字的表项。
(2)设计词法分析器
设计各单词的状态转换图,并为不同的单词设计种别码。
将词法分析器设计成供语法分析器调用的子程序。
功能包括:
a.具备预处理功能。
将不翻译的注释等符号先滤掉,只保留要翻译的符号串,即要求设计一个供词法分析调用的预处理子程序;
b.能够拼出语言中的各个单词;
c.将拼出的标识符填入符号表;
d.返回(种别码,属性值)。
(3)语法分析器
要求用预测分析法、递归下降分析法、算符优先分析法、SLR分析法(几种方法任选),实现对表达式、各种说明语句、控制语句进行语法分析。
(4)目标代码生成器
能完成指定寄存器个数的情况下将一中间代码程序段翻译成汇编语言目标代码(汇编指令应包括加、减、乘、除),要求指令条数最少的情况下,尽量使用寄存器,尽量少访问内存,这样才能做到运行效率高。
三、课程设计要求
样本语言为C-语言,实现简单的编译器,其中基本的语句要求必须实现,其余部分可根据自己的实际情况选择实现。
对主要代码给予解释和理解注释,各函数和过程应有简要描述,有功能说明,有入口和出口参数说明。
四、简单编译器的实现流程图
主程序
=
词法分析程序语法分析程序中间代码生成程序
4.2词法分析程序
(1)设计词法分析器
设计思想:
要求:
1.对单词的构词规则有明确的定义;
2.编写的分析程序能够正确识别源程序中的单词符号;
3.识别出的单词以<种别码,值>的形式保存在符号表中;
4.词法分析中源程序的输入以.c格式,分析后的符号表保存在.txt文件中。
5.对于源程序中的词法错误,能够做出简单的错误处理,给出简单的错误提示,保证顺利完成整个源程序的词法分析;
6.输入:
由符合规定单词类别结构的各类单词组成的源程序。
实现方法:
根据加入语义过程的状态转换图直接编写词法分析程序。
根据每一组状态转换关系(标识符)组织程序结构,并将所有公共处理过程分别实现即可。
在扫描源程序字符串时,一旦识别出关键字、运算符、标识符、无符号常数中之一,即以二元式形式(类别编码,值)输出单词。
每次调用词法分析程序,它均能自动继续扫描下去,形成下一个单词。
实现过程及主要代码:
#include
#include
#include
#include
voidreading(char*prog);
charprog[800],token[80];
charch;
intsyn,p,m=0,n,row,sum=0;
//关键字存储
char*rwtab[20]={
"PROGRAM","VAR","PROCEDURE","BEGIN","END","IF",
"THEN","ELSE","REPEAT","UNTIL","READ","WRITE",
"WRITELN","FOR","DO","int","float","double","char","printf"};
voidscaner(){
for(n=0;n<8;n++)token[n]=NULL;
//过滤空格
ch=prog[p++];
while(ch==''){
ch=prog[p];
p++;
}
if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')){//可能是标示符或者变量名
m=0;//整形变量int
while((ch>='0'&&ch<='9')||(ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')){
token[m++]=ch;
ch=prog[p++];
}
//识别出一个标示符
token[m++]='\0';
//回退一位
p--;
syn=34;//单纯的标示符
for(n=0;n<20;n++)//将识别出来的字符和已定义的标示符作比较,
if(strcmp(token,rwtab[n])==0){
//字符串类别
syn=n+1;
break;
}
}elseif((ch>='0'&&ch<='9')){
sum=0;
while((ch>='0'&&ch<='9')){
sum=sum*10+ch-'0';
//读取下一个字符
ch=prog[p++];
}
//回退一下
p--;
syn=33;//33标示数值类型
//限制数组的大小范围
if(sum>999999999)
syn=-1;
}else
switch(ch){
case'<':
m=0;
token[m++]=ch;
//读取下一个字符
ch=prog[p++];
if(ch=='>'){
syn=30;
token[m++]=ch;
}elseif(ch=='='){
syn=31;
token[m++]=ch;
}else{
syn=32;
p--;
}
break;
case'>':
m=0;
m=0;
token[m++]=ch;
//读取下一个字符
ch=prog[p++];
if(ch=='='){
syn=28;
token[m++]=ch;
}else{
syn=29;
p--;
}
break;
case':
':
m=0;token[m++]=ch;
ch=prog[p++];
if(ch=='='){
syn=26;
token[m++]=ch;
}else{
syn=27;
p--;
}
break;
case'+':
syn=16;token[0]=ch;break;
case'-':
syn=17;token[0]=ch;break;
case'*':
syn=18;token[0]=ch;break;
case'/':
syn=19;token[0]=ch;break;
case'(':
syn=20;token[0]=ch;break;
case')':
syn=21;token[0]=ch;break;
case'=':
syn=22;token[0]=ch;break;
case',':
syn=23;token[0]=ch;break;
case'.':
syn=24;token[0]=ch;break;
case';':
syn=25;token[0]=ch;break;
case'#':
syn=0;token[0]=ch;break;
case'\n':
syn=-2;break;
default:
syn=-1;break;
}
}
voidmain(){
p=0;
row=1;
cout<<"Pleaseinputstring:
"<reading(prog);
p=0;
do{
scaner();
switch(syn){
case33:
cout<<"("<case-1:
cout<<"Errorinrow"<"<case-2:
row=row++;break;
default:
cout<<"("<}
}while(syn!
=0);//结束符号时停止执行
}
/*读取路径下的文件,将文件内容保存到prog中。
*/
voidreading(char*prog){
FILE*in;
printf("请输入文件路径:
\n");
charpath[100],ch;
scanf("%s",&path);
printf("%s\n",path);
if((in=fopen(path,"r"))==NULL){
printf("文件无法打开!
!
!
");
exit(0);
}
inti=0;
while(!
feof(in)){
ch=fgetc(in);
putchar(ch);
prog[i]=ch;
i++;
}
prog[--i]='#';
fclose(in);
}
词法分析的运行结果
4.3语法分析程序
设计思想:
要求:
1.对语法规则有明确的定义;
2.编写的分析程序能够对实验一的结果进行正确的语法分析;
3.编写的分析程序能够对实验二的结果进行正确的语义分析;
4.对于遇到的语法、语义错误,能够做出简单的错误处理,给出简单的错误提示,保证语义分析过程;
实现方法:
在词法分析识别出单词符号的基础上分析并规定程序的语法结构是否符合语法规则。
其工作本质就是按文法的产生式,识别输入符号串是否为一个句子。
首先定义语法规则,然后按照规则实现语法分析。
实现过程及主要代码:
1、代码
主程序
#include
#include
externintscan();
externintgrammar();
charScanin[300],Scanout[300];//用于接收输入输出文件名
FILE*fin,*fout;//用于指向输入输出文件的指针
voidmain(){
intes=0;
es=scan();//调词法分析
if(es>0)
printf("词法分析有错,编译停止!
");
else
printf("词法分析成功!
\n");
if(es==0){
es=grammar();//调语法分析
if(es==0)
printf("语法分析成功!
\n");
else
printf("语法分析错误!
\n");
}
}
词法分析代码
#include
#include
#definekeywordSum8
char*keyword[keywordSum]={"if","else","for","while","do","int","read","write"};
//下面定义纯单分界符,如需要可添加
charsingleword[50]="+-*(){};,:
";
//下面定义双分界符的首字符
chardoubleword[10]="><=!
";
externcharScanin[300],Scanout[300];//用于接收输入输出文件名,在TEST_main.c中定义
externFILE*fin,*fout;//用于指向输入输出文件的指针,在TEST_main.c中定义
intscan(){//词法分析函数
charch,token[40];//ch为每次读入的字符,token用于保存识别出的单词
intes=0,j,n;//es错误代码,0表示没有错误。
j,n为临时变量,控制组合单词时的下标等
printf("请输入源程序文件名(包括路径):
");
scanf("%s",Scanin);
printf("请输入词法分析输出文件名(包括路径):
");
scanf("%s",Scanout);
if((fin=fopen(Scanin,"r"))==NULL){//判断输入文件名是否正确
printf("\n打开词法分析输入文件出错!
\n");
return
(1);//输入文件出错返回错误代码1
}
if((fout=fopen(Scanout,"w"))==NULL){//判断输出文件名是否正确
printf("\n创建词法分析输出文件出错!
\n");
return
(2);//输出文件出错返回错误代码2
}
ch=getc(fin);
while(ch!
=EOF){
while(ch==''||ch=='\n'||ch=='\t')
ch=getc(fin);
if(isalpha(ch)){//如果是字母,则进行标识符处理
token[0]=ch;
j=1;
ch=getc(fin);
while(isalnum(ch)){//如果是字母数字则组合标识符;如果不是则标识符组合结束
token[j++]=ch;//组合的标识符保存在token中
ch=getc(fin);//读下一个字符
}
token[j]='\0';//标识符组合结束
//查保留字
n=0;
while((nn++;
if(n>=keywordSum)//不是保留字,输出标识符
fprintf(fout,"%s\t%s\n","ID",token);//输出标识符符号
else//是保留字,输出保留字
fprintf(fout,"%s\t%s\n",token,token);//输出保留字符号
}elseif(isdigit(ch)){//数字处理
token[0]=ch;j=1;
ch=getc(fin);//读下一个字符
while(isdigit(ch)){//如果是数字则组合整数;如果不是则整数组合结束
token[j++]=ch;//组合整数保存在token中
ch=getc(fin);//读下一个字符
}
token[j]='\0';//整数组合结束
fprintf(fout,"%s\t%s\n","NUM",token);//输出整数符号
}elseif(strchr(singleword,ch)>0){//单分符处理
token[0]=ch;
token[1]='\0';
ch=getc(fin);//读下一个符号以便识别下一个单词
fprintf(fout,"%s\t%s\n",token,token);//输出单分界符符号
}elseif(strchr(doubleword,ch)>0){//双分界符处理
token[0]=ch;
ch=getc(fin);//读下一个字符判断是否为双分界符
if(ch=='='){//如果是=,组合双分界符
token[1]=ch;
token[2]='\0';//组合双分界符结束
ch=getc(fin);//读下一个符号以便识别下一个单词
}else//不是=则为单分界符
token[1]='\0';
fprintf(fout,"%s\t%s\n",token,token);//输出单或双分界符符号
}elseif(ch=='/'){//注释处理
ch=getc(fin);//读下一个字符
if(ch=='*'){//如果是*,则开始处理注释
charch1;
ch1=getc(fin);//读下一个字符
do
{
ch=ch1;ch1=getc(fin);
}//删除注释
while((ch!
='*'||ch1!
='/')&&ch1!
=EOF);//直到遇到注释结束符*/或文件尾
ch=getc(fin);//读下一个符号以便识别下一个单词
}else{//不是*则处理单分界符/
token[0]='/';token[1]='\0';
fprintf(fout,"%s\t%s\n",token,token);//输出单分界符/
}
}else{//错误处理
token[0]=ch;
token[1]='\0';
ch=getc(fin);//读下一个符号以便识别下一个单词
es=3;//设置错误代码
fprintf(fout,"%s\t%s\n","ERROR",token);//输出错误符号
}
}
fclose(fin);//关闭输入输出文件
fclose(fout);
return(es);//返回主程序
}
语法分析代码
#include
#include
#include
chartoken[20],token1[40];//token保存单词符号,token1保存单词值
externcharScanout[300];//保存词法分析输出文件名
FILE*fp;//用于指向输入输出文件的指针
//语法分析程序
intgrammar(){
intes=0;
if((fp=fopen(Scanout,"r"))==NULL){
printf("\n打开%s错误!
\n",Scanout);
es=10;
}
if(es==0)
es=program();
printf("=====语法分析结果!
======\n");
switch(es){
case0:
printf("语法分析成功!
\n");break;
case10:
printf("打开文件%s失败!
\n",Scanout);break;
case1:
printf("缺少{!
\n");break;
case2:
printf("缺少}!
\n");break;
case3:
printf("缺少标识符!
\n");break;
case4:
printf("少分号!
\n");break;
case5:
printf("缺少(!
\n");break;
case6:
printf("缺少)!
\n");break;
case7:
printf("缺少操作数!
\n");break;
}
fclose(fp);
return(es);
}
//<程序>:
:
={<声明序列><语句序列>}
//program:
:
={}
intprogram(){
intes=0;
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);
es=statement_list();
if(es>0)
return(es);
if(strcmp(token,"}")){//判断是否'}'
es=2;
return(es);
}
return(es);
}
//<声明序列>:
:
=<声明序列><声明语句>|<声明语句>
//:
:
=
//|
//该成:
:
={}
intdeclaration_list(){
intes=0;
while(strcmp(token,"int")==0){
es=declaration_stat();
if(es>0)
return(es);
}
return(es);
}
//<声明语句>:
:
=int<变量>;
//:
:
=intID;
intdeclaration_stat(){
intes=0;
fscanf(fp,"%s%s\n",&token,&token1);
printf("%s%s\n",token,token1);
if(strcmp(token,"ID"))
return(es=3);//不是标识符
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
|