词法分析实验报告
实验一、词法分析实验
专业:商业软件工程 姓名:杨晓玲 学号:201506110193
一、 实验目的
1、编制一个词法分析程序
2、理解词法分析在编译程序中的作用,
3、加深对词法分析原理的理解
4、掌握词法分析程序实现的技术和方法
二、 实验内容和要求
输入:源程序字符串
输出:二元组(种别,单词符号本身)
三、 实验方法、步骤及结果测试
- 源程序名:压缩包文件(rar或zip)中源程序名:词法分析.c
可执行程序名:词法分析.exe
- 原理分析及流程图
对字符串表示的源程序从左到有进行扫描和分解,根据词法规则识别出一个一个具有独立意义的单词符号
2、主要程序段及其解释:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
void analyse(FILE *fp,char ch) { int m,j,i=0,n,flag=0; FILE *fp1,*fp2; /*定义两个文件*/ char s; chargjz[34][20]={"short","if","do","while","end","auto","double","int","struct" ,"break","”,"","else","long","switch","case","enum","register","typedef","char","extern","union","const","float","unsigned","continue","signed","for","default", "void","goto","sizeof","volatile","static"}; /*用数组存储32个关键字*/ char num[5]; /*定义数组用来存储源程序中的数字*/ char bsf[10]; /*定义数组用来存储源程序中的标识符*/ char alp[15]; /*定义数组用来存储扫描过程中的字母*/ while(!feof(fp)) /*用文件存放源程序,当源程序字符串未到末尾时,进行单词识别*/ { m=0,j=0; i=0; /*m,i,j为计数变量*/ if(ch=='+') printf("%c\t%d\n",ch,35); else if(ch=='-') printf("%c\t%d\n",ch,36); else if(ch=='*') printf("%c\t%d\n",ch,37); /*运算符的个数有限,直接把它们列出*/ else if(ch=='/') printf("%c\t%d\n",ch,38); else if(ch=='=') printf("%c\t%d\n",ch,39); else if(ch=='#') printf("%c\t%d\n",ch,40); else if(ch=='>') /*当出现>符号时,判断后面是否为=*/ { s=fgetc(fp); /*用fgetc从文件中读取一个字符存到s中*/ if(s=='=') printf("%c=\t%d\n",ch,43); /*如果后一个字符为=,则为运算符>=*/ else { printf("%c\t%d\n",ch,41); /*如果后一个字符不为=,则为运算符>*/ analyse(fp,s); /*调用analyse函数自身对s进行分析判断*/ } } else if(ch=='<') { s=fgetc(fp); if(s=='=') printf("%c=\t%d\n",ch,44); else /*同上判断运算符是<=还是<*/ { printf("%c\t%d\n",ch,42); analyse(fp,s); } } else if(ch=='.') printf("%c\t%d\n",ch,53); else if(ch==':') { s=fgetc(fp); /*同上判断运算符:=,==*/ if(s=='=') printf("%c=\t%d\n",ch,45); else { printf("%c\t%d\n",ch,46); analyse(fp,s); } } else if(ch=='(') printf("%c\t%d\n",ch,47); else if(ch==')') printf("%c\t%d\n",ch,48); else if(ch==';') printf("%c\t%d\n",ch,54); /*分隔符的个数也为有限个,将它们一一列出*/ else if(ch==',') printf("%c\t%d\n",ch,49); else if(ch=='{') printf("%c\t%d\n",ch,50); else if(ch=='}') printf("%c\t%d\n",ch,51); else if(ch=='"') { printf("%c\t%d\n",ch,52); } else if(ch>='a'&&ch<='z'||ch>='A'&&ch<='Z') /*当ch为字母时/* { if((fp1=fopen("data.txt","w"))==NULL) { printf("Fileure to open data.txt!\n"); } do { fputc(ch,fp1); /*把ch用fputc函数写入文件*/ i++; /*记录写入文件的字母个数*/ ch=fgetc(fp); /*从源程序读入下一个字符,不断循环直到后面接的不是字母或数字*/ }while(ch>='a'&&ch<='z'||ch>='A'&&ch<='Z'||ch>='0'&&ch<='9'); fclose(fp1); if((fp1=fopen("data.txt","r"))==NULL) { /*以只读方式打开文件fp1*/ printf("Fileure to open data.txt!\n"); } fgets(alp,i+1,fp1); /*用fgets从fp1中读取i个字母组成的字符串到数组alp中*/ for(j=0;j<34;j++) { if(j==10) /*用for循环和strcmp函数对alp数组中的字符串 j=j+2; 与gjz数组中的字符串做比较,判断单词是关键字还是 if(strcmp(alp,gjz[j])==0) 标识符*/ { printf("%s\t%d\n",gjz[j],j); /*如果是则输出单词自身和关键字种别*/ flag=1; break; } } if(flag==0) printf("%s\t%d\n",alp,t); /*否则输出单词自身和标识符种别*/ fclose(fp1); analyse(fp,ch); /*继续对ch进行分析*/ } else if(ch>='0'&&ch<='9') { if((fp2=fopen("data2.txt","w"))==NULL) { printf("Fileure to open data2.txt!\n"); } do { fputc(ch,fp2); /*与判断字母一样,当字符为数字时,把数字写入文件, m++; 用fgetc从源程序中读取下一个字符*/ ch=fgetc(fp); } while(ch>='0'&&ch<='9'); fclose(fp2); if((fp2=fopen("data2.txt","r"))==NULL) { printf("Fileure to open data2.txt!\n"); } fgets(num,m+1,fp2); /*把fp2中读取m个字符到数组alp中*/ printf("%s\t%d\n",num,num2); fclose(fp2); analyse(fp,ch); /*继续对ch进行分析*/ } else printf("\r"); ch=fgetc(fp); }
3、运行结果及分析
四、 实验总结
主要问题:一开始不知道怎么把一个个字符组成一个字符串,后面想了用文件,当字符为字母或数字时,先把字符用fgetc()写入文件,再用fgets写入数组,感觉用文件存储这个方法有点麻烦,但我觉得这个方法比较不容易出错。再运行过程中,当单词为标识符、关键字或数字时,在输出的时候,有些字符输不出来,检查了程序,发现,当分析程序中对标识符和数字循环判断结束后,没有对当前的ch字符进行分析,而是直接从源文件中读取下一个字符。这个问题可以用递归调用analyse函数自身,对当前ch进行分析。
心得:由于自己知识掌握的还不够多,也不够扎实,感觉自己在编写程序时用的方法都是比较笨拙的,这个程序应该还存在很多问题,今后不断学习研究,再慢慢改进。