专业:计算机科学与技术学号:14101103姓名:傅开煤2016年11月编译原理实验报告14101103-傅开煤-编译原理实验报告-1-前言“编译原理”是一门研究设计和构造编译程序原理和方法的课程,是计算机各专业的一门重要专业基础课。编译原理这门课程蕴含着计算机学科中解决问题的思路、形式化问题和解决问题的方法,对应用软件和系统软件的设计与开发有一定的启发和指导作用。编译程序构造的原理和技术在软件工程、逆向工程、软件再工程、语言转换及其他领域中都有着广泛的应用。通过本课程的实验教学,使学生加深对编译系统的结构、工作流程及编译程序各组成部分设计原理的理解,使他们能够掌握和应用常用的编译技术和方法,为今后从事应用软件和系统软件的开发打下一定的理论和实践基础。编译原理实验指导书围绕着实验教学目标,详细阐述了各实验的原理和步骤。希望同学们能够充分利用实验条件,认真完成实验,从实验中得到应有的锻炼和培养。14101103-傅开煤-编译原理实验报告-2-实验要求为了顺利完成编译原理课程实验,学生应做到:(1)熟练掌握一种高级程序设计语言。(2)实验前,认真学习教材以及实验指导书的相关内容,提前做好实验准备。(3)每次实验先分析后编程,在实验报告中应写明自己的编程思路和设计流程。(4)实验结束一周后提交实验报告。实验报告内容应包括:实验目的、实验内容、设计思路和流程框图,源程序(含注释)清单、测试结果以及实验总结。(5)遵守机房纪律,服从辅导教师指挥,爱护实验设备。实验的验收将分为两个部分。第一部分是上机操作,随机抽查程序运行和即时提问;第二部分是提交书面的实验报告。此外杜绝抄袭现象,一经发现雷同,双方成绩均以0分计算。14101103-傅开煤-编译原理实验报告-3-目录实验一词法分析程序设计..............................................1实验二递归下降语法分析程序设计......................................514101103-傅开煤-编译原理实验报告-1-实验1词法分析程序设计【开发语言及实现平台或实验环境】C/C++/C#MicrosoftVisualStudio6.0/MicrosoftVisualStudio.NET2005-2008【实验目的】(1)理解词法分析在编译程序中的作用(2)加深对有穷自动机模型的理解(3)掌握词法分析程序的实现方法和技术【实验内容】对一个简单语言的子集编制一个一遍扫描的词法分析程序。【实验要求】(1)待分析的简单语言的词法1)关键字beginifthenwhiledoend2)运算符和界符:=+-*/===;()#3)其他单词是标识符(ID)和整形常数(NUM),通过以下正规式定义:ID=letter(letter|digit)*NUM=digitdigit*4)空格由空白、制表符和换行符组成。空格一般用来分隔ID、NUM、运算符、界符和关键字,词法分析阶段通常被忽略。(2)各种单词符号对应的种别编码单词符号种别码单词符号种别码begin1:17if2:=18then320while421do5=22end623letter(letter|digit)*10=24digitdigit*11=25+13;26-14(2714101103-傅开煤-编译原理实验报告-2-*15)28/16#0(3)词法分析程序的功能输入:所给文法的源程序字符串输出:二元组(syn,token或sum)构成的序列。syn为单词种别码;token为存放的单词自身字符串;sum为整形常数。例如:对源程序beginx:=9;ifx0thenx:=2*x+1/3;end#经词法分析后输出如下序列:(1,begin)(10,’x’)(18,:=)(11,9)(26,;)(2,if)……【实验步骤】(1)根据图1.1构建主程序框架图1.1词法分析主程序示意图主代码:voidmain(){p=0;row=1;coutPleaseinputstring:endl;do{cin.get(ch);prog[p++]=ch;}while(ch!='#');置初值调用扫描子程序输出串结束?输出单词二元组是否结束14101103-傅开煤-编译原理实验报告-3-p=0;do{scaner();switch(syn){case11:cout(syn,sum)endl;break;case-1:coutErrorinrowrow!endl;break;case-2:row=row++;break;default:cout(syn,token)endl;break;}}while(syn!=0);getchar();getchar();}(2)关键字表置初值关键字作为特殊标识符处理,把它们预先安排在一张表格中(关键字表),当扫描程序识别标识符时,查关键字表。如能查到匹配的单词,则为关键字,否则为一般标识符。(3)编写扫描子程序voidscaner(){for(n=0;n8;n++)token[n]=NULL;ch=prog[p++];//读下一个字符送入chwhile(ch=='')//如果为空格,读下一字符{ch=prog[p];p++;}if((ch='a'&&ch='z')||(ch='A'&&ch='Z'))//如果ch为字母{m=0;while((ch='a'&&ch='z')||(ch='A'&&ch='Z'))/*如果ch仍为字母(单词),将ch输入token*/{token[m++]=ch;//当前字符送入tokench=prog[p++];//读下一个字符送入ch}token[m++]='\0';//单词结束p--;14101103-傅开煤-编译原理实验报告-4-syn=10;for(n=0;n6;n++)//与关键字表进行比较,确定syn的值if(!strcmp(token,rwtab[n])){syn=n+1;break;}}elseif((ch='0'&&ch='9'))//如果ch为数字{{sum=0;while((ch='0'&&ch='9'))//如果ch仍为数字(一个数){sum=sum*10+ch-'0';//ch送入sum,并更新数字ch=prog[p++];//读下一个字符送入ch}}p--;syn=11;if(sum32767)syn=-1;//错误}elseswitch(ch)//其他字符情况{case'':m=0;token[m++]=ch;ch=prog[p++];if(ch==''){syn=21;token[m++]=ch;}elseif(ch=='='){syn=22;token[m++]=ch;}else{syn=23;p--;}break;case'':m=0;token[m++]=ch;14101103-傅开煤-编译原理实验报告-5-ch=prog[p++];if(ch=='='){syn=24;token[m++]=ch;}else{syn=20;p--;}break;case':':m=0;token[m++]=ch;ch=prog[p++];if(ch=='='){syn=18;token[m++]=ch;}else{syn=17;p--;}break;case'*':syn=13;token[0]=ch;break;case'/':syn=14;token[0]=ch;break;case'+':syn=15;token[0]=ch;break;case'-':syn=16;token[0]=ch;break;case'=':syn=25;token[0]=ch;break;case';':syn=26;token[0]=ch;break;case'(':syn=27;token[0]=ch;break;case')':syn=28;token[0]=ch;break;case'#':syn=0;token[0]=ch;break;case'\n':syn=-2;break;default:syn=-1;break;}}(4)调试程序,验证输出结果。源程序代码如下:#includestdio.h14101103-傅开煤-编译原理实验报告-6-#includestring.h#includeiostreamusingnamespacestd;charprog[80],token[8],ch;intsyn,p,m,n,sum,row;char*rwtab[6]={begin,if,then,while,do,end};voidmain(){p=0;row=1;coutPleaseinputstring:endl;do{cin.get(ch);prog[p++]=ch;}while(ch!='#');p=0;do{voidscaner();switch(syn){case11:cout(syn,sum)endl;break;case-1:coutErrorinrowrow!endl;break;case-2:row=row++;break;default:cout(syn,token)endl;break;}}while(syn!=0);getchar();getchar();}voidscaner(){for(n=0;n8;n++)token[n]=NULL;ch=prog[p++];//读下一个字符送入chwhile(ch=='')//如果为空格,读下一字符{ch=prog[p];p++;}if((ch='a'&&ch='z')||(ch='A'&&ch='Z'))//如果ch为字母{m=0;while((ch='a'&&ch='z')||(ch='A'&&ch='Z'))/*如果ch仍为字14101103-傅开煤-编译原理实验报告-7-母(单词),将ch输入token*/{token[m++]=ch;//当前字符送入tokench=prog[p++];//读下一个字符送入ch}token[m++]='\0';//单词结束p--;syn=10;for(n=0;n6;n++)//与关键字表进行比较,确定syn的值if(!strcmp(token,rwtab[n])){syn=n+1;break;}}elseif((ch='0'&&ch='9'))//如果ch为数字{{sum=0;while((ch='0'&&ch='9'))//如果ch仍为数字(一个数){sum=sum*10+ch-'0';//ch送入sum,并更新数字ch=prog[p++];//读下一个字符送入ch}}p--;syn=11;if(sum32767)syn=-1;//错误}elseswitch(ch)//其他字符情况{case'':m=0;token[m++]=ch;ch=prog[p++];if(ch==''){syn=21;token[m++]=ch;}elseif(ch=='='){syn=22;token[m++]=ch;}14101103-傅开煤-编译原理实验报告-8-else{syn=23;p--;}break;case'':m=0;token[m++]=ch;ch=prog[p++];if(ch=='='){syn=24;token[m++]=ch;}else{syn=20;p--;}break;case':':m=0;token[m++]=ch;ch=prog[p++];if(ch=='='){syn=18;token[m++]=ch;}else{syn=17;p--;}break;case'*':syn=13;token[0]=ch;break;case'/':syn