编译原理课程设计C语言编译器的实现.docx
《编译原理课程设计C语言编译器的实现.docx》由会员分享,可在线阅读,更多相关《编译原理课程设计C语言编译器的实现.docx(49页珍藏版)》请在冰豆网上搜索。
编译原理课程设计C语言编译器的实现
南华大学
编译原理课程设计名:
编译代生成器设计
专业计算机科学与技术
学生姓名熊浩斌
班级计算机01班
学号***********
指导老师陈星
实验地点8栋2-209
完成日期:
2013.6.2
一、课程设计的目的
编译原理课程兼有很强的理论性和实践性,是计算机专业的一门非常重要的专业基础课程,它在系统软件中占有十分重要的地位,是计算机专业学生的一门主修课。
为了让学生能够更好地掌握编译原理的基本理论和编译程序构造的基本方法和技巧,融会贯通本课程所学专业理论知识,提高他们的软件设计能力,特设定该课程的课程设计,通过设计一个简单的PASCAL语言(EL语言)的编译程序,提高学生设计程序的能力,加深对编译理论知识的理解与应用。
二、课程设计的要求
1、明确课程设计任务,复习编译理论知识,查阅复印相关的编译资料。
2、按要求完成课程设计内容,课程设计报告要求文字和图表工整、思路清晰、算法正确。
3、写出完整的算法框架。
4、编写完整的编译程序。
三、课程设计的内容
课程设计是一项综合性实践环节,是对平时实验的一个补充,课程设计内容包括课程的主要理论知识,但由于编译的知识量较复杂而且综合性较强,因而对一个完整的编译程序不适合平时实验。
通过课程设计可以达到综合设计编译程序的目的。
本课程的课程设计要求学生编写一个完整的编译程序,包括词法分析器、语法分析器以及实现对简单程序设计语言中的逻辑运算表达式、算术运算表达式、赋值语句、IF语句、While语句以及do…while语句进行编译,并生成中间代码和直接生汇编指令的代码生成器。
四、总体设计方案及详细设计
总体设计方案:
1.总体模块
2.
表2.1各种单词符号对应的种别码
单词符号
种别码
单词符号
种别码
bgin
1
:
17
If
2
:
=
18
Then
3
<
20
wile
4
<>
21
do
5
<=
22
end
6
>
23
lettet(letter|digit)*
10
>=
24
dightdight*
11
=
25
+
13
;
26
—
14
(
27
*
15
)
28
/
16
#
0
详细设计:
4.1界面导入设计
(1)一共三个选项:
①choice1--------cifafenxi
②choice2--------yufafenxi
③choice3--------zhongjiandaima
(2)界面演示
图一
图二
图三
4.2词法分析程序
(1)流程图设计
(2)具体功能的具体设计
1、cifafenxi()
首先设置prog[n]来接收输入的语句,以‘#’来结束;
调用扫描子程序scaner1(),每一次得到一个类型码;
用switch判别相应输出;
直到syn1=0为止。
2、扫描子程序scaner1()-----------------扫描输入的语句
首先设置3个变量:
①token1用来存放构成单词符号的字符串;
②sum1用来存放整型单词;
③syn1用来存放单词符号的类型码。
有关scaner1()中关键点解析:
①
while((ch=='')||(ch=='\n'))ch=prog[p++];;忽略空格
②
if(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A')))
{while(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A'))||((ch>='0')&&(ch<='9')))
{token[m++]=ch;
ch=prog[p++];
};判别标识符
③
for(n=0;n<6;n++)
if(strcmp(token,rwtab[n])==0)
{syn=n+1;
break;
};标识符是否是关键字
④
if((ch>='0')&&(ch<='9'))
{while((ch>='0')&&(ch<='9'))
{sum=sum*10+ch-'0';
ch=prog[p++];
}}
;判别整数
(3)词法分析的运行结果
输入
beginx:
=1;y:
=1+2;end#
输出
4.3语法分析程序
(1)具体功能的具体设计
1.yufafenxi()---------------分析程序
给出算术表达式文法,进行适当的文法变换
输入——表达式;输出——表达式语法是否正确。
2.子程序的功能描述
(3)语法分析的运行结果
分析成功图
分析失败图
4.4中间代码生成程序
(1)总体描述
采用递归下降(自上而下)的语法制导翻译法。
在前两次试验的基础上改进。
词法分析程序à语法分析程序à语义分析程序à编译器。
不断完善,
不断改进。
渐变的过程。
单词符号及种别表
单词符号
种别编码
单词值
main
1
int
2
float
3
double
4
char
5
if
6
else
7
do
8
while
9
l(l|d)*
10
内部字符串
(+|-|ε)d*(.dd*|ε)(e(+|-|ε)dd*|ε)
20
二进制数值表示
=
21
+
22
-
23
*
24
/
25
(
26
)
27
{
28
}
29
30
;
31
>
32
>=
33
<
34
<=
35
==
36
!
=
37
(2)程序结构描述
(3)程序的功能描述
从文件中读入表达式,输出其四元式的结果序列
递归下降示意图
(4)详细功能描述
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);//生成四元式
voidemit(char*res,char*num1,char*op,char*num2)
该函数的功能是生成一个三地址语句送到四式表中
char*newTemp()
该函数的功能是会动一个新的临时变量,临时变量名产生的顺序是T1,T2,T3,….
intmerge(intp1,intp2)
该函数的功能是将以P1,P2为链首的两条链合并成一条链,返回时的函数值作为合并后的链首。
voidbackpatch(intp,intt)
该函数的功能是把P所链接的每个四元式的第四区段(result段)都回填t。
voidfuzhi()
该函数的功能是对赋值语句进行分析。
voidtiaojian(int*nChain)
该函数的功能是对条件语句进行分析。
voidxunhuan()
该函数的功能是对循环语句进行分析。
(4)结果演示
图一简单语句生成四元式
图二if语句的四元式生成
图三循环语句四元式生成
(5)汇编生成
if(strcmp(fourCom[i].opera,"=")==0)
{
printf("MoveAX,%1s\n",fourCom[i].arg1);
printf("Move%5s,Ax\n",fourCom[i].result);
}
if(strcmp(fourCom[i].opera,"+")==0)
{
printf("MovAX,%1s\n",fourCom[i].arg1);
printf("ADDAx,%1s\n",fourCom[i].arg2);
printf("Mov%1s,Ax\n",fourCom[i].result);
}
if(strcmp(fourCom[i].opera,"-")==0)
{
printf("MovAX,%1s\n",fourCom[i].arg1);
printf("SUBAx,%1s\n",fourCom[i].arg2);
printf("Mov%1s,Ax\n",fourCom[i].result);
}
if(strcmp(fourCom[i].opera,"*")==0)
{
printf("MovAL,%1s\n",fourCom[i].arg1);
printf("MUL%1s\n",fourCom[i].arg2);
printf("Mov%1s,Ax\n",fourCom[i].result);
}
if(strcmp(fourCom[i].opera,"/")==0)
{
printf("MovAX,%1s\n",fourCom[i].arg1);
printf("DIv%1s\n",fourCom[i].arg2);
printf("Mov%1s,AL\n",fourCom[i].result);
}
if(strcmp(fourCom[i].opera,"goto")==0)
{
printf("jmpL%1s\n",i);
}
结果演示
五、课程设计的体会与总结
经过一个星期的编译原理课程设计,本人在陈宏建老师的指导下,顺利完成该课程设计。
通过该课程设计,收获颇多。
词法分析的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。
通过本试验的完成,更加加深了对词法分析原理的理解。
通过本次试验,了解了语法分析的运行过程,主程序大致流程为:
“置初值”à调用scaner函数读下一个单词符号à调用IrParseà结束。
递归下降分析的大致流程为:
“先判断是否为begin”à不是则“出错处理”,若是则“调用scaner函数”à调用语句串分析函数à“判断是否为end”à不是则“出错处理”,若是则调用scaner函数à“判断syn=0&&kk=0是否成立”成立则说明分析成功打印出来。
不成立则“出错处理”。
一、对实验原理有更深的理解
通过该课程设计,掌握了什么是编译程序,编译程序工作的基本过程及其各阶段的基本任务,熟悉了编译程序总流程框图,了解了编译程序的生成过程、构造工具及其相关的技术对课本上的知识有了更深的理解,课本上的知识师机械的,表面的。
通过把该算法的内容,算法的执行顺序在计算机上实现,把原来以为很深奥的书本知识变的更为简单,对实验原理有更深的理解。
二、对该理论在实践中的应用有深刻的理解
通过把该算法的内容,算法的执行顺序在计算机上实现,知道和理解了该理论在计算机中是怎样执行的,对该理论在实践中的应用有深刻的理解。
三、激发了学习的积极性
通过该课程设计,全面系统的理解了编译原理程序构造的一般原理和基本实现方法。
把死板的课本知识变得生动有趣,激发了学习的积极性。
把学过的计算机编译原理的知识强化,能够把课堂上学的知识通过自己设计的程序表示出来,加深了对理论知识的理解。
以前对与计算机操
在这次课程设计中,我就是按照实验指导的思想来完成。
加深了理解文件系统的内部功能及内部实现,培养实践动手能力和程序开发能力的目的。
附录-----程序清单
#include
#include
#include
#include
usingnamespacestd;
#defineMAX100
charinputstream[50];//存储输入句子
inttemp1=0;//数组下标
intright1;//判断输出信息
intm2=0,sum2=0;//sum用于计算运算符的个数
//m用于标记输入表达式中字符的个数
charJG='A';
charstr[MAX];//用于存输入表达式
inttokene=0;//左括号的标志
charprog1[80],token1[8],ch1;
intsyn1,p1,m1,n1,sum1;
char*rwtab1[6]={"begin","if","then","while","do","end"};
intr1;
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];//结构体数组
cifafenxi();
yufafenxi();
zhongjiandaima();
scaner1();
voide();
voide1();
voidt();
voidt1();
voidf();
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);//生成四元式
voidscanner();//扫描
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());