04070010张悦编译原理实验报告04070010张悦指导老师:蒋宗礼完成日期:2007-6-20104070010张悦一.实验目的基本掌握计算机语言的词法分析程序的开发方法。以及掌握计算机语言的语法分析程序设计与属性文法应用的实现方法。锻炼自己的编程能力和逻辑思维能力,体会计算机编译器的奥妙之处二.实验内容1.编制一个能够分析三种整数、标识符、主要运算符和主要关键字的词法分析程序。2.用二维预约分析表,编制一个能够进行语法分析并生成派生的产生式序列的编译程序。3.用递归子程序法,编制一个能够进行语法分析并生成三地址代码的微型编译程序。三.实验要求1.编制正规式以及正规文法,画出状态图;2.根据状态图,设计词法分析函数intscan(),完成以下功能:1)2)3)从键盘读入数据,分析出一个单词。返回单词种别(用整数表示),返回单词属性(不同的属性可以放在不同的全局变量中)。3.编写测试程序,反复调用函数scan(),输出单词种别和属性。4.改写文法,构造语法分析程序,要求按照最左派生的顺序输出派生的产生式序列;5.改写语法分析程序,构造三地址代码生成程序。6.处理的源程序存放在文件中,它可以包含多个语句;四.系统设计完成整个系统,实现本个实验的要求,需要两个比较大的模块:词法分析器和语法分析器。词法分析器的功能是将输入的程序串分解成一个一个独立的单词,并且记录下每个单词的类型以及数值。这里词法分析器的实现有两种方法:调用一次词法分析器,返回一个词的类型以及数值,以此类推;还有一种方法是条用一次词法分析器将程序串的所有单词都分解出来并保存到一个地方(比如线形表)以便将来使用。我采用的是前者,因为这样只需要对整个程序访问一遍语法分析器的功能是将已经分解好的单词按照一定的规范(产生式)组合起来,由此来确定输入程序的意思。我的设计是“语法分析器调用词法分析器”,当语法分析其分析进行不下去的时候调用词法分析器获取一个单词,继续进行分析。而语义功能是镶嵌在语法分析其当中的,当语法分析器分析出用什么产生式的时候作相应的语义处理。五.系统实现(一)词法分析器的实现一词法的正规式描述标识符:字母|(字母|数字字符)*(ε|_|.)(字母|数字字符)*十进制数:(0|(1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)*)(ε|.)(0|1|2|3|4|5|6|7|8|9)204070010张悦(0|1|2|3|4|5|6|7|8|9)*八进制数:0(0|(1|2|3|4|5|6|7)(0|1|2|3|4|5|6|7)*)(ε|.)(0|1|2|3|4|5|6|7)(0|1|2|3|4|5|6|7)*十六进制数:0x(0(|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)*)(ε|.)(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)*运算符和分隔符:+-*/=();关键字:ifthenelsewhiledo二、改变后的正规文法标识符-字母temptemp2temp十进制整数-数字字符temp3数字字符八进制整数-0temp4temp3temp4十六进制整数-0xtemp5temp3temp5运算符和分隔符-+|-|*|/|||=|(|)|;关键字-if|then|else|while|do字母-a|b|c|d|e|f|g|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z数字字符-0|1|2|3|4|5|6|7|8|9temp-(字母|数字字符)temp|εtemp2-(ε|_|.)temp3-(ε|.)temp4-(0|1|2|3|4|5|6|7)temp4|εtemp5-(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)temp5|ε将状态合起来,得:(0)-1~9(1)|0(4)|字母(12)|运算符和分隔符(17)(1)-0~9(1)|.(2)(2)-0~9(3)(3)-0~9(3)(4)-.(2)|1~7(5)|0(13)|x(8)|X(8)(5)-0~7(5)|.(6)(6)-0~7(7)(7)-0~7(7)(8)-1~9(9)|a~f(9)|0(14)(9)-0~9(9)|a~f(9)|.(10)(10)-0~9(11)|a~f(11)(11)-0~9(11)|a~f(11)(12)-0~9(12)|a~z(12)|A~Z(12)|.(15)|_(15)(13)-.(6)(14)-.(10)(15)-0~9(16)|a~z(16)|A~Z(16)(16)-0~9(16)|a~z(16)|A~Z(16)三、状态图:304070010张悦四、数据结构:char*arrBao[5]={if,then,else,do,while};//保留字表typedefstruct{chartype[TYPE_MAX];charvalue[VALUE_MAX];}CNode;//词法分析的节点,保留分析出的token的种类和值五、算法(伪码):boolMyScan(FILE*fp,CNode*&node){chartemp;//当前读取的字符chars[100];//保留字符串intsi=0;//对于控制s的下标intstate=0;//当前状态号//返回的节点node=newCNode;while(1){读取一个字符到temp;if(temp=='#'){strcpy(node-type,#);strcpy(node-value,_);returnfalse;//表示文件结束}4字母或数字17字母或数字1615字母或数字.|_.140分隔符12110~f10.91~f8字母0~f0~fx|X13.04001~70~7.765.1~90~70~70~932.10~90~904070010张悦switch(state){case0://状态0if(temp为0)if(temp为1到9)if(temp为字母)if(temp为分隔符)添加当前字符;continue;添加当前字符;continue;添加当前字符;continue;state=4;state=1;state=12;保存相应的分隔符到node;returntrue;if(temp为空格或回车或tab)continue;//忽略多个空格和回车和制表符else出错处理;returnfalse;case1://状态1if(temp为数字)state=4;添加当前字符;continue;添加当前字符;continue;if(temp为小数点)if(temp为分隔符)state=2;保存为INT10;returntrue;else出错处理;returnfalse;case2://状态2if(temp为数字)state=3;else出错处理;returnfalse;case3://状态3if(temp为数字)state=3;添加当前字符;continue;添加当前字符;continue;if(temp为分隔符)保存为REAL10;returntrue;else出错处理;returnfalse;case4://状态4if(temp为小数点)添加当前字符;continue;添加当前字符;continue;添加当前字符;continue;添加当前字符;continue;state=2;if(temp为1~7)if(temp为0)state=5;state=13;if(temp为x或X)if(temp为分隔符)state=8;保存为INT10;returntrue;else出错处理;returnfalse;case5://状态5if(temp为小数点)添加当前字符;continue;添加当前字符;continue;state=6;if(temp为0~7)state=5;if(temp为分隔符)保存为INT8;returntrue;else出错处理;returnfalse;case6://状态6if(temp为0~7)state=7;else出错处理;returnfalse;case7://状态7if(temp为0~7)state=7;添加当前字符;continue;添加当前字符;continue;if(temp为分隔符)保存为INT8;returntrue;else出错处理;returnfalse;case8://状态8if(temp为十六进制数)continue;if(temp为0)添加当前字符state=9;;state=14;添加当前字符;504070010张悦continue;else出错处理;returnfalse;case9://状态9if(temp为十六进制数)state=9;continue;添加当前字符;if(temp为小数点)continue;if(temp为分隔符)state=10;添加当前字符;保存为INT16;returntrue;else出错处理;returnfalse;//状态10case10:if(temp为十六进制数)state=11;continue;else出错处理;returnfalse;添加当前字符;case11://状态11if(temp为十六进制数)state=11;添加当前字符;continue;if(temp为分隔符)保存为INT16;returntrue;else出错处理;returnfalse;case12://状态12if(temp为数字或者字母)添加当前字符;state=12;continue;if(temp为_或者.)continue;if(temp为分隔符)if(为保留字)保存为保留字;returntrue;添加当前字符;state=15;else保存为IDN;returntrue;else出错处理;returnfalse;//状态13case13:if(temp为.)state=6;if(temp为分隔符)添加当前字符;continue;保存为INT8;returntrue;else出错处理;returnfalse;//状态14case14:if(temp为.)state=10;添加当前字符;continue;if(temp为分隔符)保存为INT16;returntrue;else出错处理;returnfalse;case15://状态15if(temp为数字或者字母)添加当前字符;state=16;continue;if(temp为分隔符)if(为保留字)保存为保留字;returntrue;else保存为IDN;returntrue;else出错处理;returnfalse;//状态16case16:if(temp为数字或者字母)state=16;添加当前字符;604070010张悦continue;if(temp为分隔符)if(为保留字)保存为保留字;returntrue;else保存为IDN;returntrue;else出错处理;returnfalse;}//switch}//while}//主函数源程序intmain(){FILE*fp;fp=fopen(code1.txt,r);CNode*node;while(MyScan(fp,node)){if(node!=NULL){//分析成功printf(%s\t%s\n,node-type,node-value