目录一、课程设计的目的………………………………………………………………2二、课程设计的要求………………………………………………………………2三、课程设计报告内容……………………………………………………………2四、实验运行环境…………………………………………………………………2五、实验设计步骤…………………………………………………………………2六、变化后的正规文法………………………………………………………………2七、状态图………………………………………………………………3八、基本测试数据…………………………………………………………4九.词法分析程序的数据结构与算法………………………………………………4十、实验结果截图……………………………………………………………………12十一、设计结果及体会………………………………………………………………12十二、参考文献………………………………………………………………………12-1-一、课程设计的目的加深对词法分析器的工作过程的理解;加强对词法分析方法的掌握;能够采用一种编程语言实现简单的词法分析程序;能够使用自己编写的分析程序对简单的程序段进行词法分析。二、课程设计要求1.根据以下的正规式,编制正规文法,画出状态图;标识符字母(字母|数字字符)*十进制数(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)(0|1|2|3|4|5|6|7|8|9)*八进制数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)*运算符和分隔符+-*/=();关键字ifthenelsewhiledo2.根据状态图,设计词法分析函数intscan(),完成以下功能:1)从键盘读入数据,分析出一个单词。2)返回单词种别(用整数表示),3)返回单词属性(不同的属性可以放在不同的全局变量中)。3.编写测试程序,反复调用函数scan(),输出单词种别和属性。三、课程设计报告内容编制一个能够分析三种数、标识符、主要运算符和主要关键字的词法分析程序。四、实验运行环境PC微机DOS操作系统或Windows操作系统TurboC程序集成环境或VisualC++程序集成环境五、实验设计步骤1.根据状态图,设计词法分析算法2.采用C语言,设计函数scan(),实现该算法3.编制测试程序(主函数main)。4.调试程序:输入一组单词,检查输出结果。-2-0138101557134691114161217182六、变化后的正规文法:标识符-字母(字母|数字字符)*十进制数-数字字符temp数字字符八进制数-0temp1temptemp1十六进制数-0xtemp2temptemp2运算符和分隔符-+|-|*|/|||=|(|)|;关键字-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|9)数字字符|εtemp-(ε|.)temp1-(0|1|2|3|4|5|6|7)temp1|εtemp5-(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)temp5|ε七、状态图图-1-空白0-9/a-z/A-ZA-Z/a-z其它0-91-9其它0-9非数字0-700-7非0-7且…00-7x/X非0-71-9/A-F/a-f非(1-9/A-F/a-f)+1-1…1-3-00-9/A-F/a-fIf/while/非(1-9/A-F/a-f)then/else/do八、基本测试数据输入数据例:058+data0x2f00then;正确结果:这些单词的单词种别及其属性INT100INT1058+_IDNdata_INT1647INT80Then-;-九、词法分析程序的数据结构与算法词法分析的算法思想主要是根据状态图来实现,由前面的状态图来进行结构的设计,具体细节请参见“图1”的图示。主要的数据结构如下所示:unionchars{//联合,可存储字符串,整型和浮点型charpro_char[15];intpro_number;floatreal;};structdata{//将每个单元用一个结构来存储charkind[7];//类型即种别intid;//所属的具体类型即种别号unioncharspro;//属性值};种别与种别号的对应关系如下表所示:种别种别号INT101INT82INT163标识符4分隔符5关键字6出错7REAL108-4-REAL89REAL1610完整代码如下:#includestdio.h#includestring.hunionchars{//联合,可存储字符串,整型和浮点型charpro_char[15];intpro_number;floatreal;};structdata{//将每个单元用一个结构来存储,其内容包括:类型,所属的具体类型,以及属性值charkind[7];intid;unioncharspro;};intscan(char*a);//对每个用空格打断的单元进行进一步的分析,对其进行进一步的分类voidPrints(chara[15],intid,inta_long);//将分析后的每个token输出voidsave(char*a,intid,intx);//将分析后的结果保存到一个结构数组中charnowChar[15];//临时的存储单元,用来存储被空格打断以后单元charkinds[11][8]={,INT10,INT8,INT16,IDN,,,,REAL10,REAL8,REAL16};//单词的不同种别structdatalink[100];//用来存放词法分析以后的结果的结构数组intlink_long=0;//全局变量intscan(char*a){intid;inta_long=0;intdoc=0;while(*a!=NULL){nowChar[0]='\0';a_long=0;doc=0;//对数值的判断及处理if('0'=*a&&*a='9'){//如果第一个字符为数值nowChar[a_long]=*a;*a++;a_long++;//对十六进制的判断及处理-5-if(nowChar[0]=='0'&&(*a=='x'||*a=='X')){//如果第一个字符为0且第二个字符为x,则为十六进制数nowChar[a_long]=*a;*a++;a_long++;while(*a!=NULL&&(('0'=*a&&*a='9')||('a'=*a&&*a='f')||('A'=*a&&*a='F')||*a=='.')){nowChar[a_long]=*a;//一直将此十六进制数完全读入,若为浮点型的,则加以标记if(*a=='.')doc=1;*a++;a_long++;}nowChar[a_long]='\0';//判断输入的十六进制数是否合法if(a_long==2){//输入的只有0x,则输入错误Prints(nowChar,7,a_long);return0;}if(doc)//输入的十六进制数是浮点型的Prints(nowChar,10,a_long);//则将其具体的类型属性定为10else//输入的十六进制数是整型的Prints(nowChar,3,a_long);//则将其具体的类型属性定义为3continue;}//对八进制的判断及处理if(nowChar[0]=='0'&&'0'=*a&&*a='7'){//如果第一个字符为0且第二个字符为0~7,则为八进制数nowChar[a_long]=*a;*a++;a_long++;while(*a!=NULL&&(('0'=*a&&*a='7')||*a=='.')){nowChar[a_long]=*a;//一直将此八进制数完全读入,若为浮点型的,则加以标记if(*a=='.')doc=1;*a++;a_long++;}nowChar[a_long]='\0';if(doc)//输入的八进制数是浮点型的Prints(nowChar,9,a_long);//则将其具体的类型属性定为9else//输入的十六进制数是整型的Prints(nowChar,2,a_long);//则将其具体的类型属性定义为2continue;-6-}//对十进制数的判断及处理else{while(*a!=NULL&&(('0'=*a&&*a='9')||*a=='.')){nowChar[a_long]=*a;//一直将此十进制数完全读入,若为浮点型的,则加以标记if(*a=='.')doc=1;*a++;a_long++;}nowChar[a_long]='\0';if(doc)//输入的十进制数是浮点型的Prints(nowChar,8,a_long);//则将其具体的类型属性定为8else//输入的十进制数是整型的Prints(nowChar,1,a_long);//则将其具体的类型属性定义为1continue;}}//完成了对数值的判断及处理//对字符的判断及处理else{nowChar[a_long]=*a;*a++;a_long++;//判断输入的字符是否为运算符或其他的分隔符switch(nowChar[0]){case'+':case'-':case'*':case'/':case'':case'':case'(':case')':case'=':case';':nowChar[a_long]='\0';Prints(nowChar,5,a_long);//将其具体的类型属性定义为5continue;default:break;}//判断输入的第一个字符是否为字母if(('a'=nowChar[0]&&nowChar[0]='z')||('A'=nowChar[0]&&nowChar[0]='Z')){while(*a!=NULL&&(('a'=*a&&*a='z')||('A'=*a&&*a='Z')||('0'=*a&&*a='9')||(*a=='.')||(*a=='_'))){//一直将此字符串完全读入nowChar[a_long]=*a;*a++;a_long++;}nowChar[a_long]='\0';-7-//判断输入的字符串是否为特殊的标识符,若是,则将其具体类型值定义为6//判断输入的字符串是否为特殊的字符串ifif(a_long==2&&strcmp(nowChar,if)==0){Prints(nowChar,6,a_long);continue;}//判断输入的字符串是否为特殊的字符串thenif(a_long==4&&strcmp(nowChar,then)==0){Prints(nowChar,6,a_long);continue;}//判断输入的字符串是否为特殊的字符串elseif(a_long==4&&strcmp(nowChar,else)==0){Prints(nowChar,6,a_long);continue;}//判断输入的字符串是否为特殊的字符