-1-计算机科学与工程系编译原理课程设计实验报告姓名:__******__学号_*******__年级专业及班级___08计算机科学与技术成绩实验名称词法分析程序设计与实现完成日期2011/4/12指导教师*******实验目的:能够采用C编程语言实现简单的词法分析程序;设计、编制并调试一个词法分析程序,加深对词法分析原理的理解实验要求:1.对单词的构词规则有明确的定义;2.编写的分析程序能够正确识别源程序中的单词符号;3.识别出的单词以单词符号,种别码的形式保存在符号表中(链表);4.词法分析中源程序的输入以.c格式,分析后的符号表,将二元组保存在.txt文件中。实验内容:选择高级语言(C语言),编制它的词法分析程序。词法分析程序的实现可以采用任何一种编程工具实验原理:1、算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号;2、其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。实验分析:(1)关键字:ifelsewhiledocaseintbreak等所有的关键字都是小写。(2)运算符和界符:=+-*/===;()等(3)其他单词是标识符(ID)和整型常数(SUM),通过以下正规式定义:ID=_|letter(letter|digit)*NUM=digitdigit*(4)空格有空白、制表符和换行符组成。空格一般用来分隔ID、SUM、运算符、界符和关键字,词法分析阶段通常被忽略。(5)注释被忽略(6)各种单词符号对应的种别码(如下):单词符号种别码单词符号种别码auto1double2int3struct4break5else6-2-long7switch8case9enum10register11typedef12char13extern14return15union16const17float18short19unsigned20continue21for22signed23void24default25goto26sizeof27volatile28do29while30static31if32\a33\b34\f35\n36\t37\v38\\39\?40\’41\”42\043\ddd44\xhh45数字46标识符47#48(49)50-3-[51]52{53}54‘55*56:57~58%59^60+61?62=63|64&65!666768=69==7071!=7273&&74=75||76++77?=78-79--80-81“82%A(A可为d’s’c)83;84_85/868788899091其他类别99-4-实验流程图(由于流程图过大因此各部分分开写):整体:输入需要扫描的文件名输入扫描结果另存为的文件名判断文件是否为空预读一位ChCh是否为空格返回,结束程序否行计数器自加1Ch是否为字母或下划线跳转到扫描头文件单词及保留字Ch是否为数字或‘-’跳转到扫描数字Ch是否为‘/’Ch是否为引号跳转到扫描注释跳转到扫描引号是否是否否是是否否是跳转到扫描其他符号p处扫描注释:Ch为‘/’时预读下一位chch是否为回车行计数器自加1判断文件是否结束Ch是否为‘/’Ch是否为‘*’退出程序预读一位ch是否否是是否判断ch是否为回车否预读一位ch是Ch是否为‘*’ch是否为回车行计数器自加1是否否预读一位ch是ch是否为回车是Ch是否为‘/’否返回到p处是是-5-扫描数字:Ch为数字或‘-’Ch是否为‘-’预读ch是Ch是否为‘-’判别为自减符是Ch是否为数字Ch是否为‘’否判别为”-”是回退3否预读chCh是否为数字判别为减号是判别为负号预读ch预读chCh是否为数字或‘.’Ch1[i++]=ch是认为数字结束否以%s的形式输出ch1回退1位返回到p处否-6-扫描引号:-7-扫描单词:-8-扫描其他字符:实验环境:需要TC、VC++6.0等开发工具作为本次试验的环境。-9-实验步骤:1、准备:用TC、VC++等开发工具;2、对本实验的任务进行分析,确定实现功能的函数;3、写好程序,仔细修改函数;4、上机操作:输入源程序,修改、调试,运行。5、写好试验报告。实验调试过程及测试结果/*******************************源代码******************************/#includestdio.h#includestdlib.h#includectype.h#includestring.hvoidmain(){FILE*fp,*fp1;inthanjsq=1;//行计数器,保存行号intguanjz(charch1[]);//关键字和标识符判断charch,infile[15],outfile[15];//定义输入和输出文件名printf(*****************Entertheinfilename*******************\n);scanf(%s,infile);//输入需要扫描的文件名printf(*****************Entertheoutfilename******************\n);scanf(%s,outfile);//输入需要另存为的文件名if((fp=fopen(infile,r))==NULL)//打开需要扫描的文件{printf(cannotopenfile\n);exit(0);}if((fp1=fopen(outfile,w))==NULL)//打开需要存入的文件-10-{printf(cannotopenfile\n);exit(0);}printf(\n*********************************************************\n);printf(*》开始进行词法分析《*\n);printf(*********************************************************\n);printf(\n*********************************************************\n);printf(行号字符串种别码\n);printf(*********************************************************\n);fprintf(fp1,*********************************************************\n);fprintf(fp1,行号字符串种别码\n);fprintf(fp1,*********************************************************\n);while(!feof(fp)){ch=fgetc(fp);if(ch==10)hanjsq++;/**********************扫描头文件单词及保留字***********************/if(isalpha(ch)||ch=='_')//如果第一个字符为字母或下划线则判断为标识符{inti=0;charch1[30];//假定每个标识符最长为ch1[i++]=ch;//将ch保存到ch1[0]中并使i自加1while(!feof(fp)){ch=fgetc(fp);if(ch==10)hanjsq++;//如果ch为换行符,则行计数器自加1if(isalpha(ch)||isdigit(ch)||ch=='_')-11-{//如果ch为字母、数字或下划线就把ch放到ch1[i]中并使i自加1ch1[i++]=ch;}if(ch=='.')//如果ch为小数点则判断是否为头文件{if((ch=fgetc(fp))=='h')//如果小数点后一位为h则判定其为头文件{if(ch==10)hanjsq++;ch1[i++]='.';ch1[i++]='h';ch1[i]='\0';//把结束标志放到ch1[i]中作为单词结束标志printf(line%d:%s83\n,hanjsq,ch1);//以字符串形式输出ch1fprintf(fp1,line%d:%s83\n,hanjsq,ch1);break;}else//如果小数点后一位不是h则判定其为标识符{fseek(fp,-1,1);//fp回退1ch1[i]='\0';//把结束标志放到ch1[i]中作为单词结束标志printf(line%d:%s%d\n,hanjsq,ch1,guanjz(ch1));//以字符串形式输出ch1fprintf(fp1,line%d:%s%d\n,hanjsq,ch1,guanjz(ch1));break;}}if(!isalpha(ch)&&!isdigit(ch)&&ch!='_'&&ch!='.'){//如果ch不为字母、数字、下划线和点时判断其为标识符ch1[i]='\0';printf(line%d:%s%d\n,hanjsq,ch1,guanjz(ch1));fprintf(fp1,line%d:%s%d\n,hanjsq,ch1,guanjz(ch1));-12-break;}}}/************************扫描数字*************************/if(isdigit(ch)||ch=='-')//如果ch为数字或'-'{if(isdigit(ch))//如果ch为数字{printf(line%d:%c,hanjsq,ch);fprintf(fp1,line%d:%c,hanjsq,ch);while(!feof(fp)){ch=fgetc(fp);//预读一位如果ch为数字和点则循环输出if(isdigit(ch)||ch=='.'){printf(%c,ch);fprintf(fp1,%c,ch);}else//否则视为数字结束{printf(46\n);fprintf(fp1,46\n);fseek(fp,-1,1);//回退一位ch='0';//置ch为0,以免影响下面误判并顺利退出扫描数字break;}}}if(ch=='-')//如果ch为'-'-13-{ch=fgetc(fp);//预读一位if(ch=='-')//如果ch还是为'-'则判断为自减符'--'{printf(line%d:--80\n,hanjsq);fprintf(fp1,line%d:--80\n,hanjsq);}if(ch=='')//如果ch为'',则判断为结构体运算符'-'{printf(line%d:-81\n,hanjsq);fprintf(fp1,line%d:-81\n,hanjsq);}if(isdigit(ch))//如果ch为数字则可能为减号或负号{fseek(fp,-3,1);//回退3为判断ch=fgetc(fp);if(isdigit(ch))//如果ch为数字则判断'-'为减号{ch=fgetc(fp);printf(line%d:%c79\n,hanjsq,ch);fprintf(fp1,line%d:%c79\n,hanjsq,ch);}else//否则判断'-'为负号{ch=fgetc(fp);printf(line%d:%c,hanjsq,ch);fprintf(fp1,line%d:%c,hanjsq,ch);while(!feof(fp)){ch=fgetc(fp);//预读一位如果ch为数字和点则循环输出-14-if(isdigit(ch)||ch=='.'){printf(%c,ch);fprintf(fp1,%c,ch);}else//否则视为数字结束{printf(46\n);fprintf(fp1,46\n);fseek(fp,-1,1);//回退1break;}}}}}}/**************