编译原理课程设计一个简单编译器的设计与分析.docx
《编译原理课程设计一个简单编译器的设计与分析.docx》由会员分享,可在线阅读,更多相关《编译原理课程设计一个简单编译器的设计与分析.docx(34页珍藏版)》请在冰豆网上搜索。
![编译原理课程设计一个简单编译器的设计与分析.docx](https://file1.bdocx.com/fileroot1/2023-7/14/9f129cbd-2a90-4ceb-b65b-41c843bc5512/9f129cbd-2a90-4ceb-b65b-41c843bc55121.gif)
编译原理课程设计一个简单编译器的设计与分析
摘要
使用过现代计算机的人都知道,多数用户是应用高级语言来实现他们所需要的计算的。
现在计算机系统一般都含有不只一个的高级语言的编译程序,对有些高级语言甚至配置了几个不同性能的编译程序,供用户按不同需要进行选择。
高级语言编译程序是计算机系统软件最主要的组成部分之一,也是用户最直接关系的工具之一。
计算机上执行一个高级语言程序一般分为两步:
第一,用一个编译程序把高级语言翻译成机器语言程序;第二,运行所得的机器语言程序求得计算结果。
通常说的翻译程序是指能够把某一种语言程序转换成另一种语言程序(目标语言程序)。
如果源语言诸如Fortran,Pascal,C,Ada或java这样的高级语言,而目标程序是诸如汇编语言或者机器语言这类的低级语言,这样的一个翻译程序就是称为编译程序。
一个编译程序的工作过程一般可以划分为五个阶段:
词法分析、语法分析、语义分析与中间代码生成、优化、目标代码生成。
每个阶段都是从上一个阶段得到结果,对他进行分析,并且根据一些外部环境(例如符号表等)得到最终的输出结果。
要构造一个编译程序,可以按照这样的阶段来分别构造,最后来连调。
现在人们已经建立了多种编制部分编译程序或整个编译程序的有效工具。
有些能用于自动生成扫描器(如LEX),有些可以用于自动产生语法分析器(如YACC),有些甚至可以用来自动产生整个的编译程序。
这些构造编译程序的工具成为编译程序-编译程序、编译程序产生器或翻译程序书写系统,他们是按照编译程序和目标语言的形式描述而自动产生编译程序的。
编译程序是一极其庞大而又复杂的系统,掌握它比较苦难。
但是一旦对其掌握,对以后的程序语言设计,系统软件分析,系统软件设计,形式语言研究等方面都是非常有好处的。
关键字:
C语言、、编译、扫描器、语法分析
一、需求分析
给出类C语言(C语言的子集)的词法和语法定义,并根据对应的语法定义写出一些属性文法和语法制导。
根据词法和语法的定义,构造一个编译程序,它主要可以完成如下功能:
1、读入某个已经编辑好的类C源程序文件,通过词法分析器,生成二元组,同时检查词法错误;
2、语法分析器将产生的二元组作为输入,进行语法分析,同时检查语法错误;
3、在语法分析同时,利用属性文法和语法制导技术,产生具体的语意动作,并对符号表进行操作;
4、根据语义动作产生整个源程序的四元式序列;
5、将产生的四元式序列连同符号表一起输出,作为编译程序的最终输出结果;
6、对最后的代码优化和目标代码生成要有所考虑,必须留有一定的接口供以后扩展;
7、增大程序的可移植性,努力做到整个系统方便移植。
二、详细算法设计
词法分析程序语法分析程序语义分析程序编译器。
三、流程图
图I主函数示意图
图II递归下降分析程序示意图
图III语句块分析示意图
图IV语句串分析示意图
图V语句分析示意图
四、相关函数说明
voidscanner();//扫描
voidlrparser();
voidstaBlock(int*nChain);//语句块
voidstaString(int*nChain);//语句串
voidsta(int*nChain);//语句
voidfuzhi();//赋值语句
voidtiaojian(int*nChain);//条件语句
voidxunhuan();//循环语句
char*E();//Expresiion表达式
char*T();//Term项
char*F();//Factor因子
char*newTemp();//自动生成临时变量
voidbackpatch(intp,intt);//回填
intmerge(intp1,intp2);//合并p1和p2
voidemit(char*res,char*num1,char*op,char*num2);//生成四元式
五.运行结果
图VI赋值语句的分析
图VII条件语句的分析
图VIII循环语句的分析
图IX综合
六.编译器使用说明
程序提示用户输入字符串“Pleaseinputyoursourcestring:
”,用户输入字符串并以“#”号结束。
回车后,程序显示运行结果。
七.程序清单
#include
#include
#include
#include
charprog[80];/*存放所有输入字符*/
chartoken[8];/*存放词组*/
charch;/*单个字符*/
intsyn,p,m,n,i;/*syn:
种别编码*/
doublesum;
intcount;
intisSignal;/*是否带正负号(0不带,1负号,2正号)*/
intisError;
intisDecimal;/*是否是小数*/
doubledecimal;/*小数*/
intisExp;/*是否是指数*/
intindex;/*指数幂*/
intisNegative;/*是否带负号*/
doubletemp;
inttemp2;
intrepeat;/*是否连续出现+,-*/
intnextq;
intkk;/*临时变量的标号*/
intntc,nfc,nnc,nnb,nna;
char*rwtab[9]={"main","int","float","double","char","if","else","do","while"};
struct{
charresult[10];/*字符串(字符数组)*/
chararg1[10];
charopera[10];
chararg2[10];
}fourCom[20];/*结构体数组*/
voidscanner();/*扫描*/
voidlrparser();
voidstaBlock(int*nChain);/*语句块*/
voidstaString(int*nChain);/*语句串*/
voidsta(int*nChain);/*语句*/
voidfuzhi();/*赋值语句*/
voidtiaojian(int*nChain);/*条件语句*/
voidxunhuan();/*循环语句*/
char*E();/*Expresiion表达式*/
char*T();/*Term项*/
char*F();/*Factor因子*/
char*newTemp();/*自动生成临时变量*/
voidbackpatch(intp,intt);/*回填*/
intmerge(intp1,intp2);/*合并p1和p2*/
voidemit(char*res,char*num1,char*op,char*num2);/*生成四元式*/
voidmain()
{p=0;
count=0;
isDecimal=0;
index=0;
repeat=0;
kk=0;
printf("\nPleaseinputyoursourcestring:
\n");
do{ch=getchar();
prog[p++]=ch;
}while(ch!
='#');
p=0;
isError=0;
scanner();
lrparser();
for(i=1;i{printf("\n%d\t",i);
printf("(%5s%5s%5s\t%5s)\n",fourCom[i].arg1,fourCom[i].opera,fourCom[i].arg2,fourCom[i].result);
}
}
voidlrparser()
{
intnChain;
nfc=ntc=1;
nextq=1;
if(syn==1)/*main*/
{
scanner();
if(syn==26)/*(*/
{scanner();
if(syn==27)/*)*/
{scanner();
staBlock(&nChain);
}
else
printf("缺少右括号\n");
}
else
printf("缺少左括号\n");
}
else
printf("缺少main\n");
}/*<语句块>:
:
='{'<语句串>'}'*/
voidstaBlock(int*nChain)/*语句块*/
{if(syn==28)/*{*/
{
scanner();
staString(nChain);
/*backpatch(*nChain,nextq);*/
if(syn==29)/*}*/
scanner();/*读下一个*/
else
printf("缺少}号\n");
}
else
printf("缺少{号\n");
}
/*<语句串>:
:
=<语句>{;<语句>};*/
voidstaString(int*nChain)/*语句串*/
{
sta(nChain);
backpatch(*nChain,nextq);
while(syn==31)/*;*/
{
scanner();
sta(nChain);
}
/*backpatch(*nChain,nextq-1);*/
}
voidsta(int*nChain)/*语句*/
{
if(syn==10)
{
fuzhi();
/**nChain=0;*/
}
elseif(syn==6)/*if*/
{
tiaojian(nChain);
}
elseif(syn==8)/*do*/
xunhuan();
}
/*<条件语句>->if(<条件>)<语句块>*/
voidtiaojian(int*nChain)
{
charres[10],num1[10],num2[10],op[10];
intnChainTemp;
/*<条件>-><表达式><关系运算符><表达式>*/
if(syn==6)/*if*/
{
scanner();
/*strcpy(num1,E());*/
if(syn==26)/*(*/
{
scanner();
strcpy(num1,E());
if((syn<=37)&&(syn>=32))
{
switch(syn)
{
case32:
strcpy(op,">");
break;
case33:
strcpy(op,">=");
break;
case34:
strcpy(op,"<");
break;
case35:
strcpy(op,"<=");
break;
case36:
strcpy(op,"==");
break;
case37:
strcpy(op,"!
=");
break;
default:
printf("error");
}
}
scanner();
strcpy(num2,E());
strcat(num1,op);
strcat(num1,num2);
/*nfc=nextq+1;*/
ntc=nextq;/*记住if语句位置*/
emit("0","if",num1,"goto");
nfc=nextq;/*if中表达式为假*/
emit("0","","","goto");
/*第一个0已回填*/
backpatch(ntc,nextq);/*ntc链接的所有四元式都回填nextq*/
}
if(syn==27)/*)*/
scanner();
staBlock(&nChainTemp);/*语句块*/
*nChain=merge(nChainTemp,nfc);
}
}
/*<循环语句>:
:
=do<语句块>while<条件>*/
voidxunhuan()
{
charres[10],num1[10],num2[10],op[10];
intnChainTemp;
if(syn==8)/*do*/
{
nnc=nextq;/*记住if语句位置,emit之后nextq就变了*/
/*emit("0","if",num1,"goto");*/
scanner();
staBlock(&nChainTemp);/*语句块*/
if(syn==9)/*while*/
{
scanner();
if(syn==26)/*(*/
{
scanner();
strcpy(num1,E());
if((syn<=37)&&(syn>=32))
{
switch(syn)
{
case32:
strcpy(op,">");
break;
case33:
strcpy(op,">=");
break;
case34:
strcpy(op,"<");
break;
case35:
strcpy(op,"<=");
break;
case36:
strcpy(op,"==");
break;
case37:
strcpy(op,"!
=");
break;
default:
printf("error");
}
}
scanner();
strcpy(num2,E());
strcat(num1,op);
strcat(num1,num2);
nnb=nextq;
emit("0","if",num1,"goto");
backpatch(nnb,nnc);
nna=nextq;
emit("0","","","goto");
backpatch(nna,nextq);
}
if(syn==27)/*)*/
scanner();
}
}
}
voidfuzhi()/*赋值语句只有1个操作数*/
{
charres[10],num[10];/*num操作数*/
if(syn==10)/*字符串*/
{
strcpy(res,token);/*结果*/
scanner();
if(syn==21)/*=*/
{
scanner();
strcpy(num,E());
emit(res,num,"=","");
}
else
{
printf("缺少=号\n");
}
}
}
char*E()/*Expression表达式*/
{
char*res,*num1,*op,*num2;
res=(char*)malloc(10);
num1=(char*)malloc(10);
op=(char*)malloc(10);
num2=(char*)malloc(10);
strcpy(num1,T());
while((syn==22)||(syn==23))/*+-*/
{
if(syn==22)/*+*/
strcpy(op,"+");
else
strcpy(op,"-");
scanner();
strcpy(num2,T());
strcpy(res,newTemp());
emit(res,num1,op,num2);
strcpy(num1,res);
}
returnnum1;
}
char*T()/*Term项*/
{
char*res,*num1,*op,*num2;
res=(char*)malloc(10);
num1=(char*)malloc(10);
op=(char*)malloc(10);
num2=(char*)malloc(10);
strcpy(num1,F());
while((syn==24)||(syn==25))/**/*/
{
if(syn==24)
strcpy(op,"*");
else
strcpy(op,"/");
scanner();
strcpy(num2,F());
strcpy(res,newTemp());
emit(res,num1,op,num2);
strcpy(num1,res);
}
returnnum1;
}
char*F()/*Factor因子*/
{
char*res;
res=(char*)malloc(10);
if(syn==10)/*字符串*/
{
strcpy(res,token);
scanner();
}
elseif(syn==20)/*二进制数*/
{
itoa((int)sum,res,10);/*整数转换为字符串*/
scanner();
}
elseif(syn==26)/*(*/
{
scanner();
res=E();
if(syn==27)/*)*/
{
scanner();
}
elseisError=1;
}
else
isError=1;
returnres;
}
char*newTemp()
{
char*p;
charvarTemp[10];
p=(char*)malloc(10);
kk++;
itoa(kk,varTemp,10);
strcpy(p+1,varTemp);
p[0]='T';
returnp;
}
/*将p所链接的每个四元式的第四个分量都回填t*/
voidbackpatch(intp,intt)
{
intw,circle=p;
while(circle)/*circle不为0的时候*/
{
w=atoi(fourCom[circle].result);/*四元式circle第四分量内容*/
/*strcpy(fourCom[circle].result,t);//把t填进四元式circle的第四分量*/
sprintf(fourCom[circle].result,"%d",t);
circle=w;/*w记录的是链条上下一个四元式,移动!
*/
}return;
}
intmerge(intp1,intp2)/*合并p1和p2*/
{
charcircle,nResult;
if(p2==0)
nResult=p1;
else
{
nResult=circle=p2;
while(atoi(fourCom[circle].result))/*四元式第四个分量不为0*/
{
circle=atoi(fourCom[circle].result);
/*strcpy(fourCom[circle].result,p1);*/
sprintf(fourCom[circle].result,"%s",p1);
}/*目的是用p1的值覆盖0*/
}
returnnResult;/*p2是头,p1覆盖0,接在p2后边*/
}
voidemit(char*res,char*num1,char*op,char*num2)
{
strcpy(fourCom[nextq].result,res);
strcpy(fourCom[nextq].arg1,num1);
strcpy(fourCom[nextq].opera,op);
strcpy(fourCom[nextq].arg2,num2);
nextq++;
}
voidscanner()
{
sum=0;
decimal=0;
m=0;
for(n=0;n<8;n++)
token[n]=NULL;
ch=prog[p++];/*从prog中读出一个字符到ch中*/
while(ch==''||ch=='\n')/*跳过空字符(无效输入)*/
ch=prog[p++];
if(((ch>='a')&&(ch<='z'))||((ch>='A')&&(ch<='Z')))/*ch是字母字符*/
{
while(((ch>='a')&&(ch<='z'))||((ch>='A')&&(ch<='Z'))||((ch>='0')&&(ch<='9')))
{
token[m++]=ch;/*ch=>token*/
ch=prog[p++];/*读下一个字符*/
}
token[m++]='\0';
p--;/*回退一格*/
syn=10;/*标识符*/
/*如果是"begin","if","then","while","do","end"标识符中的一个*/
for(n=0;n<9;n++)
if(strcmp(token,rwtab[n])==0)
{
syn=n+1;
break;
}
}
elseif((ch>='0')&&(ch<='9'))
{
IsNum:
if(isSignal==1)
{
/*token[m++]='-';*/
}
while((ch>='0')&&(ch<='9'))
{
sum=sum*10+ch-'0';/*ch中数字本身是当做字符存放的*/
ch=prog[p++];
}
if(ch=='.')
{
isDecimal=1;
ch=prog[p++];
count=0;/*之前忘了清零,123.123+123.123#两个浮点数就无法识别*/
while((ch>='0')&&(ch<='9'))
{
/*pow(x,y)计算x的y次幂*/
temp=(ch-'0')*pow