首页 编译原理_简单编译器课程设计报告

编译原理_简单编译器课程设计报告

举报
开通vip

编译原理_简单编译器课程设计报告课 程 设 计 信息科学与工程学院课程设计任务书 题目: 姓 名: 学 号: 专业班级: 课 程: 指导教师: 职称: 完成时间: 2011年 12 月----2011年 12 月 枣庄学院信息科学与工程学院制 2011年12 月20日 课程设计任务书及成绩评定 课程设计的任务和具体要求 在理解编译原理相关理论的基础上,要求用C或C++语言描述及上机调试,实现一个小编译器(包括符号表的构造,词法分析,语法分析,语义分析,目标代码生成等重要子程序,其中词法分析、语法分析及语义分析功能必须完成),使学生将理论与实际应用...

编译原理_简单编译器课程设计报告
课 程 设 计 信息科学与工程学院课程设计任务书 题目: 姓 名: 学 号: 专业班级: 课 程: 指导教师: 职称: 完成时间: 2011年 12 月----2011年 12 月 枣庄学院信息科学与工程学院制 2011年12 月20日 课程设计任务书及成绩评定 课程设计的任务和具体要求 在理解编译原理相关理论的基础上,要求用C或C++语言描述及上机调试,实现一个小编译器(包括符号表的构造,词法分析,语法分析,语义分析,目标代码生成等重要子程序,其中词法分析、语法分析及语义分析功能必须完成),使学生将理论与实际应用结合起来,受到软件设计等开发过程的全面训练,从而提高学生软件开发的能力。 指导教师签字: _______ 日期: 指导教师评语 成绩:____________ 指导教师签字: 日期: 课程设计所需软件、硬件等 硬件环境:WindowsXP/Win7操作系统 软件环境:Microsoft visual C++6.0 课程设计进度计划 起至日期 工作内容 备注 2011-12-01—05 2011-12-06—10 2011-12-11—16 查找资料 理清思路,编写程序 完善程序,编辑文档 参考文献、资料索引 序号 文献、资料名称 编著者 出版单位 【1】​ 程序设计语言编译原理 陈火旺 李春林 国防工业出版社 【2】​ 数据结构 严蔚敏 清华大学出版社 【3】​ C++程序设计 吴乃林 况迎辉 高等教育出版社 【4】​ C语言程序设计 谭浩强 清华大学出版社 【5】​ 程序设计语言编译原理 陈火旺、刘春林等 国防工业出版社 目录 一、摘要………………………………………………………………………1 二、总体 设计方案 关于薪酬设计方案通用技术作品设计方案停车场设计方案多媒体教室设计方案农贸市场设计方案 及主要设计原理…………………………………………2 1、单词符号及种别表…………………………………………………2 2、语法结构定义………………………………………………………3 3、主要算法……………………………………………………………3 (1)词法分析主要算法…………………………………………3 (2)语法分析主要思想…………………………………………3 (3)语义分析主要算法…………………………………………3 三、源程序代码………………………………………………………………4 四、测试及分析………………………………………………………………20 五、心得体会…………………………………………………………………22 一、摘要 编译程序的工作过程一般可以分为五个阶段:词法分析、语法分析、语义分析与中间代码产生、优化、目标代码生成。每一个阶段在功能上是相对独立的,它一方面从上一个阶段获取分析的结果来进行分析,另一方面由将结果传递给下一个阶段。由编译程序的五个阶段就对应了编译系统的结构。 其中词法分析器利用超前搜索、状态转换等方法,将源程序转化成为一个一个的单词符号二元式。一般程序语言的单词符号包括关键字、运算符、常数、标识符和界符。语法分析器将这些单词符号作为输入,对它进行语法分析。语法分析分为两种方法:自上而下分析法和自下而上分析法。针对不同程序语言的语法规则可以采取不同的分析方法,当然两种方法也可以同时使用。语法分析器把语法单元作为输入供语义分析器使用。一般的语义分析器主要采用的是语法制导方法,即在语法分析的同时进行语法分析,并产生一定的语义动作,来生成中间代码。上面三个过程可以与硬件无关,而接下来的优化器和目标代码生成器是针对某一种处理器而言的。代码优化是将语义分析生成的中间代码进行优化,产生执行效率更高的代码。目标代码生成器最终生成可以在某种机器上运行的机器语言或者汇编语言。在整个编译过程中还包括对 表格 关于规范使用各类表格的通知入职表格免费下载关于主播时间做一个表格详细英语字母大小写表格下载简历表格模板下载 的操作和对错误的处理,这些也都是非常重要的环节。 下图给出了编译系统的结构框图 二、总体设计 方案 气瓶 现场处置方案 .pdf气瓶 现场处置方案 .doc见习基地管理方案.doc关于群访事件的化解方案建筑工地扬尘治理专项方案下载 及主要设计原理 2.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.2、语法结构定义 <程序> ::= main()<语句块> <语句块> ::= ‘{‘<语句串>’}’ //程序用括号括起来 <语句串>::=<语句>{;<语句>}; <语句>::=<赋值语句>|<条件语句>|<循环语句> <赋值语句>::=ID=<表达式> //赋值语句用”=”号 <条件语句>::=if<条件><语句块> //条件怎么没有括号,囧(自己加1个) <循环语句>::=do <语句块>while <条件> <条件>::=<表达式><关系运算符><表达式> <表达式> ::= <项>{ +<项>|-<项>} <项> ::= <因子>{*<因子>|/<因子>} <因子> ::=ID|num|(<表达式>) num::= ( +|-|ε ) 数字*(.数字数字* | ε)( e ( +|-|ε ) 数字数字*|ε) ID::=字母(字母|d数字)* 字母::=a|b|c…|z|A|B|C…|Z 数字::=0|1|2…|9 <关系运算符> ::= <|<=|>|>=|==|!= 2.3、主要算法 2.3.1、词法分析主要算法 这部分对源文件进行分析,允许/* */注释。从源文件依次读取字符,对字符进行分析,组成字符串、数字、关系符等固定含义的token符,并把它们添加到token链中,如果遇到非法字符报错并退出程序。 2.3.2、语法分析主要思想 这部分对Token链进行分析,利用自底向上的分析方法,构建SLR(1)分析表的过程是手工完成的。语法分析的同时构建语法树,移进时创建叶子,规约时创建节点。 2.3.3、语义分析主要分析 这部分对语法树从左到右进行遍历,节点记录了规约式的编号,遍历到节点时就进行相应处理。语义分析主要检查变量、函数是否被定义或重定义,同时产生四元式。 三、源程序代码 #include #include #include #include char prog[80]; //存放所有输入字符 char token[8]; //存放词组 char ch; //单个字符 int syn,p,m,n,i; //syn:种别编码 double sum; int count; int isSignal; //是否带正负号(0不带,1负号,2正号) int isError; int isDecimal; //是否是小数 double decimal; //小数 int isExp; //是否是指数 int index; //指数幂 int isNegative; //是否带负号 double temp; int temp2; int repeat; //是否连续出现+,- int nextq; int kk; //临时变量的标号 int ntc,nfc,nnc,nnb,nna; char *rwtab[9]={"main","int","float","double","char","if","else","do","while"}; struct{ char result[10]; //字符串(字符数组) char arg1[10]; char opera[10]; char arg2[10]; }fourCom[20]; //结构体数组 void scanner(); //扫描 void lrparser(); void staBlock(int *nChain); //语句块 void staString(int *nChain); //语句串 void sta(int *nChain); //语句 void fuzhi(); //赋值语句 void tiaojian(int *nChain); //条件语句 void xunhuan(); //循环语句 char* E(); //Expresiion表达式 char* T(); //Term项 char* F(); //Factor因子 char *newTemp(); //自动生成临时变量 void backpatch(int p,int t); //回填 int merge(int p1,int p2); //合并p1和p2 void emit(char *res,char *num1,char *op,char *num2); //生成四元式 void main() { p=0; count=0; isDecimal=0; index=0; repeat=0; kk=0; printf("\nPlease input your source string:\n"); do{ ch=getchar(); prog[p++]=ch; }while(ch!='#'); p=0; isError=0; scanner(); lrparser(); for(i=1;i ::= '{'<语句串>'}' void staBlock(int *nChain) //语句块 { if(syn==28) //{ { scanner(); staString(nChain); //backpatch(*nChain,nextq); if(syn==29) //} scanner(); //读下一个 else printf("缺少}号\n"); } else printf("缺少{号\n"); } //<语句串>::=<语句>{;<语句>}; void staString(int *nChain) //语句串 { sta(nChain); backpatch(*nChain,nextq); while(syn==31) //; { scanner(); sta(nChain); } //backpatch(*nChain,nextq-1); } void sta(int *nChain) //语句 { if(syn==10) { fuzhi(); //*nChain=0; } else if(syn==6) //if { tiaojian(nChain); } else if(syn==8) //do xunhuan(); } //<条件语句>->if(<条件>)<语句块> void tiaojian(int *nChain) { char res[10],num1[10],num2[10],op[10]; int nChainTemp; //<条件>-><表达式><关系运算符><表达式> if(syn==6) //if { scanner(); //strcpy(num1,E()); if(syn==26) //( { scanner(); strcpy(num1,E()); if((syn<=37)&&(syn>=32)) { switch(syn) { case 32: strcpy(op,">"); break; case 33: strcpy(op,">="); break; case 34: strcpy(op,"<"); break; case 35: strcpy(op,"<="); break; case 36: strcpy(op,"=="); break; case 37: 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 <条件> void xunhuan() { char res[10],num1[10],num2[10],op[10]; int nChainTemp; 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) { case 32: strcpy(op,">"); break; case 33: strcpy(op,">="); break; case 34: strcpy(op,"<"); break; case 35: strcpy(op,"<="); break; case 36: strcpy(op,"=="); break; case 37: 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(); } } } void fuzhi() //赋值语句只有1个操作数 { char res[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); } return num1; } 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); } return num1; } char* F() //Factor因子 { char *res; res=(char *)malloc(10); if(syn==10) //字符串 { strcpy(res,token); scanner(); } else if(syn==20) //二进制数 { itoa((int)sum,res,10); //整数转换为字符串 scanner(); } else if(syn==26) //( { scanner(); res=E(); if(syn==27) //) { scanner(); } else isError=1; } else isError=1; return res; } char *newTemp() { char *p; char varTemp[10]; p=(char *)malloc(10); kk++; itoa(kk,varTemp,10); strcpy(p+1,varTemp); p[0]='T'; return p; } //将p所链接的每个四元式的第四个分量都回填t void backpatch(int p,int t) { int w,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; } int merge(int p1,int p2) //合并p1和p2 { char circle,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 } return nResult; //p2是头,p1覆盖0,接在p2后边 } void emit(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++; } void scanner() { 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; } } else if((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(0.1,++count); decimal=decimal+temp; //AddToDec(); ch=prog[p++]; } sum=sum+decimal; } if(ch=='e'||ch=='E') { isExp=1; ch=prog[p++]; if(ch=='-') { isNegative=1; ch=prog[p++]; } while((ch>='0')&&(ch<='9')) { //指数 index=index*10+ch-'0'; ch=prog[p++]; } //10的幂 //123e3代表123*10(3) //sum=sum*pow(10,index);是错误的 if(isNegative) sum=sum*pow(0.1,index); else sum=sum*pow(10,index); } if(isSignal==1) { sum=-sum; isSignal=0; } p--; syn=20; } else switch(ch) { case '<': m=0; token[m++]=ch; ch=prog[p++]; if(ch=='=') { syn=35; token[m++]=ch; } else { syn=34; p--; } break; case '>': m=0; token[m++]=ch; ch=prog[p++]; if(ch=='=') { syn=33; token[m++]=ch; } else { syn=32; p--; } break; case '=': m=0; token[m++]=ch; ch=prog[p++]; if(ch=='=') { syn=36; token[m++]=ch; } else { syn=21; p--; } break; case '+': temp2=prog[p]; token[m++]=ch; if((temp2>='0')&&(temp2<='9')&&(repeat==1)) { isSignal=2; ch=prog[p++]; repeat=0; goto IsNum; } if(((temp2=='+')||(temp2=='-'))&&(repeat==0)) //如果重复出现符号,才将后边的+,-视为正负号 { repeat=1; //ch=prog[p++]; } syn=22; break; case '-': temp2=prog[p]; token[m++]=ch; if((temp2>='0')&&(temp2<='9')&&(repeat==1)) { isSignal=1; ch=prog[p++]; //读“-”下一个字符 repeat=0; goto IsNum; //转到数字的识别 } if(((temp2=='+')||(temp2=='-'))&&(repeat==0)) //如果重复出现符号,才将后边的+,-视为正负号 { repeat=1; //预言会重复 //ch=prog[p++]; //读下一个字符 } syn=23; break; case '*': temp2=prog[p]; token[m++]=ch; if(temp2=='+') { isSignal=2; repeat=1; } else if(temp2=='-') { isSignal=1; repeat=1; } syn=24; break; case '/': syn=25; token[m++]=ch; break; case '(': temp2=prog[p]; token[m++]=ch; if(temp2=='+') { isSignal=2; repeat=1; } else if(temp2=='-') { isSignal=1; repeat=1; } syn=26; break; case ')': syn=27; token[m++]=ch; break; case '{': syn=28; token[m++]=ch; break; case '}': syn=29; token[m++]=ch; break; case ',': syn=30; token[m++]=ch; break; case ';': syn=31; token[m++]=ch; break; case'#': syn=0; token[m++]=ch; break; default: syn=-1; } } 四、测试及分析 运行程序,结果如下: 先输入正确的程序 再输入错误的程序 五、心得体会 本次编译原理词法分析器的系统开发使我对词法分析有了进一步的认识,也对编译原理这门课程的了解更加深入,要想学好它重在实践。通过此次手动构造词法分析,我认识到做程序设计并不是只掌握词法分析的思想和方法就够的,一定得自己动手,这样才能充分认识到自己的不足,以提高自己的设计能力。 通过实践,我发现自身还有许多不足之处,我深刻认识到要学好计算机必须重视实践,所以在以后的学习过程中,我会更加注视上机操作,使自己更好地学好专业知识。回顾此次编译原理课程设计,可以说得是苦多于甜,但是我在巩固了以前所学过知识的同时,也学到了很多在已开设课程中未学到的知识。只有把所学的理论知识与实践相结合起来,从理论中得出结论,才能真正提高自己的实际动手能力和独立思考的能力。
本文档为【编译原理_简单编译器课程设计报告】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_016449
暂无简介~
格式:doc
大小:240KB
软件:Word
页数:28
分类:互联网
上传时间:2013-12-12
浏览量:60