南昌大学实验报告一学生姓名:学号:专业班级:网络工程091 实验类型:□验证█综合□设计□创新实验日期:2012-4-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)(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)*运算符和界符+ - * / > < = <= >= ( ) ;{ }关键字main if then else while do int (可根据需要添加)2、根据状态图,设计词法分析函数int scan( ),完成以下功能:1)从文本文件中读入测试源代码,根据状态转换图,分析出一个单词,2)以二元式形式输出单词<单词种类,单词属性>其中单词种类用整数表示:0:标识符1:十进制整数2:八进制整数3:十六进制整数运算符和界符,关键字采用一字一符,不编码其中单词属性表示如下:标识符,整数由于采用一类一符,属性用单词表示运算符和界符,关键字采用一字一符,属性为空3、编写测试程序,反复调用函数scan( ),输出单词种别和属性。
四、实验环境PC微机DOS操作系统或Windows 操作系统Turbo C 程序集成环境或Visual C++ 程序集成环境五、实验步骤1、根据正规式,画出状态转换图;2、根据状态图,设计词法分析算法;3、采用C或C++语言,设计函数scan( ),实现该算法;4、编制测试程序(主函数main);5、调试程序:读入文本文件program.txt,运行程序得到输出结果result.txt,并检查输出结果是否正确。
六、测试数据输入数据:编辑一个文本文件program.txt,在文件中输入一段程序代码,如:result.txt文件中,输出格式如下:将输出结果存放在C++源程序:#include <iostream>#include<string>using namespace std;#define MAX 5char ch =' ';string key[5]={"if","then","else","while","do"};int Iskey(string c){ //关键字判断int i;for(i=0;i<MAX;i++) {if(key[i].compare(c)==0) return 1;}return 0;}int IsLetter(char c) { //判断是否为字母if(((c<='z')&&(c>='a'))||((c<='Z')&&(c>='A'))) return 1;else return 0;}int IsLetter1(char c) { //判断是否为a~f字母if(((c<='f')&&(c>='a'))||((c<='F')&&(c>='A'))) return 1;else return 0;}int IsDigit(char c){ //判断是否为数字if(c>='0'&&c<='9') return 1;else return 0;}void scan(FILE *fpin){string arr="";while((ch=fgetc(fpin))!=EOF){arr="";if(ch==' '||ch=='\t'||ch=='\n'){}else if(IsLetter(ch)||ch=='_'){arr=arr+ch;ch=fgetc(fpin);while(IsLetter(ch)||IsDigit(ch)){if((ch<='Z')&&(ch>='A')) ch=ch+32;arr=arr+ch;ch=fgetc(fpin);}fseek(fpin,-1L,SEEK_CUR);if (Iskey(arr)){cout<<arr<<"\t$关键字"<<endl;}else cout<<arr<<"\t$普通标识符"<<endl;}else if(IsDigit(ch)){int flag=0;if(ch=='0'){arr=arr+ch;ch=fgetc(fpin);if(ch>='0'&&ch<='7'){while(ch>='0'&&ch<='7'){flag=1;arr=arr+ch;ch=fgetc(fpin);}}else if(ch=='x'||ch=='X'){flag=2;arr=arr+ch;ch=fgetc(fpin);while(IsDigit(ch)||IsLetter1(ch)){arr=arr+ch;ch=fgetc(fpin);}}else if(ch==' '||ch==','||ch==';' ){cout<<arr<<"\t$整数0"<<endl;}fseek(fpin,-1L,SEEK_CUR);if(flag==1) cout<<arr<<"\t$八进制整数"<<endl;else if(flag==2) cout<<arr<<"\t$十六进制整数"<<endl;}else{arr=arr+ch;ch=fgetc(fpin);while(IsDigit(ch)){arr=arr+ch;ch=fgetc(fpin);}fseek(fpin,-1L,SEEK_CUR);cout<<arr<<"\t$十进制整数"<<endl;}}else switch(ch){case'+':case'-' :case'*' :case'=' :case'/' :cout<<ch<<"\t$运算符"<<endl;break;case'(' :case')' :case'[' :case']' :case';' :case'.' :case',' :case'{' :case'}' :cout<<ch<<"\t$界符"<<endl;break;case':' :{ch=fgetc(fpin);if(ch=='=') cout<<":="<<"\t$运算符"<<endl;else {cout<<"::"<<"\t$界符"<<endl;;fseek(fpin,-1L,SEEK_CUR);}}break;case'>' :{ch=fgetc(fpin);if(ch=='=') cout<<">="<<"\t$运算符"<<endl;if(ch=='>')cout<<">>"<<"\t$输入控制符"<<endl;else {cout<<">"<<"\t$运算符"<<endl;fseek(fpin,-1L,SEEK_CUR);}}break;case'<' :{ch=fgetc(fpin);if(ch=='=')cout<<"<="<<"\t$运算符"<<endl;else if(ch=='<')cout<<"<<"<<"\t$输出控制符"<<endl;else if(ch=='>') cout<<"<>"<<"\t$运算符"<<endl;else{cout<<"<"<<"\t$运算符"<<endl;fseek(fpin,-1L,SEEK_CUR);}}break;default : cout<<ch<<"\t$无法识别字符"<<endl;}}}void main(){char in_fn[30];FILE * fpin;cout<<"请输入源文件名(包括路径和后缀名):";for(;;){cin>>in_fn;if((fpin=fopen(in_fn,"r"))!=NULL) break;else cout<<"文件路径错误!请输入源文件名(包括路径和后缀名):";}cout<<"\n********************分析如下*********************"<<endl;scan(fpin);fclose(fpin);}运行结果:七、思考题1、词法分析能否采用空格来区分单词?答:不能,在词法分析中,处理不光有标识符还有连接符,而连接符和其他的标识符是可以连在一起出现的。