编译原理第三章词法分析班级:2009211311学号:姓名:schnee1目录1.实验题目和要求....................................................................................32.检测代码分析.......................................................................................33.源代码……………………………………………………………………..421.实验题目和要求题目:词法分析程序的设计与实现。实验内容:设计并实现C语言的词法分析程序,要求如下。(1)、可以识别出用C语言编写的源程序中的每个单词符号,并以记号的形式输出每个单词符号。(2)、可以识别并读取源程序中的注释。(3)、可以统计源程序汇总的语句行数、单词个数和字符个数,其中标点和空格不计算为单词,并输出统计结果(4)、检查源程序中存在的错误,并可以报告错误所在的行列位置。(5)、发现源程序中存在的错误后,进行适当的恢复,使词法分析可以继续进行,通过一次词法分析处理,可以检查并报告源程序中存在的所有错误。实验要求:方法1:采用C/C++作为实现语言,手工编写词法分析程序。方法2:通过编写LEX源程序,利用LEX软件工具自动生成词法分析程序。2.检测代码分析1、HelloWorld简单程序输入:2、较复杂程序输入:33.异常程序输入检测三,源代码#includecmath#includecctype#includestring4#includevector#includecstdio#includecstdlib#includecstring#includefstream#includeiostream#includealgorithmusingnamespacestd;constintFILENAME=105;constintMAXBUF=82;constintL_END=40;constintR_END=81;constintSTART=0;//开始指针vectorstringKey;//C保留的关键字表classfuntion//词法分析结构{public://变量声明charfilename[FILENAME];//需要词法分析的代码文件名ifstreamf_in;charbuffer[MAXBUF];//输入缓冲区intl_end,r_end,forward;//左半区终点,右半区终点,前进指针,booll_has,r_has;//辅助标记位,表示是否已经填充过缓冲区vectorstringId;//标识符表charC;//当前读入的字符intlinenum,wordnum,charnum;//行数,单词数,字符数stringcurword;//存放当前的字符串//函数声明voidget_char();//从输入缓冲区读一个字符,放入C中,forward指向下一个voidget_nbc();//检查当前字符是否为空字符,反复调用直到非空5voidretract();//向前指针后退一位voidinitial();//初始化要词法分析的文件voidfillBuffer(intpos);//填充缓冲区,0表示左,1表示右voidanalyzer();//词法分析voidtoken_table();//以记号的形式输出每个单词符号voidnote_print();//识别并读取源程序中的注释voidcount_number();//统计源程序汇总的语句行数、单词个数和字符个数voiderror_report();//检查并报告源程序中存在的所有错误voidsolve(char*file);//主调用函数};voidwelcome(){printf(\n*********************************************************\n);printf(**WelcometouseLexicalAnalyzer**\n);printf(**Byschnee@BUPTDate:2011/20/10**\n);printf(*********************************************************\n\n\n);}voidinitKey(){Key.clear();Key.push_back(auto);Key.push_back(break);Key.push_back(case);Key.push_back(char);Key.push_back(const);Key.push_back(continue);Key.push_back(default);Key.push_back(do);Key.push_back(double);Key.push_back(else);Key.push_back(enum);Key.push_back(extern);Key.push_back(float);Key.push_back(for);Key.push_back(goto);Key.push_back(if);Key.push_back(int);Key.push_back(long);Key.push_back(register);Key.push_back(return);Key.push_back(short);Key.push_back(signed);Key.push_back(static);Key.push_back(sizeof);Key.push_back(struct);Key.push_back(switch);Key.push_back(typedef);Key.push_back(union);Key.push_back(unsigned);Key.push_back(void);Key.push_back(volatile);Key.push_back(while);}voidfuntion::get_char(){C=buffer[forward];if(C==EOF)return;//结束6if(C=='\n')linenum++;//统计行数和字符数elseif(isalnum(C))charnum++;forward++;if(buffer[forward]==EOF){if(forward==l_end){fillBuffer(1);forward++;}elseif(forward==r_end){fillBuffer(0);forward=START;}}}voidfuntion::get_nbc(){while(C==''||C=='\n'||C=='\t'||C=='\0')get_char();}voidfuntion::initial(char*file){Id.clear();//清空标识符表l_end=L_END;r_end=R_END;//初始化缓冲区forward=0;l_has=r_has=false;buffer[l_end]=buffer[r_end]=EOF;fillBuffer(0);linenum=wordnum=charnum=0;//初始化行数,单词数,字符数}voidfuntion::fillBuffer(intpos)7{if(pos==0)//填充缓冲区的左半边{if(l_has==false){fin.read(buffer,l_end);if(fin.gcount()!=l_end)buffer[fin.gcount()]=EOF;}elsel_has=false;}else//填充缓冲区的右半边{if(r_has==false){fin.read(buffer+l_end+1,l_end);if(fin.gcount()!=l_end)buffer[fin.gcount()+l_end+1]=EOF;}elser_has=false;}}voidfuntion::retract(){if(forward==0){l_has=true;//表示已经读取过文件,避免下次再次读取forward=l_end-1;}else{forward--;if(forward==l_end){r_add=true;forward--;}8}}voidfuntion::analyzer(){FILE*token_file,*note_file,*count_file,*error_file;token_file=fopen(token_file.txt,w);note_file=fopen(note_file.txt,w);count_file=fopen(count_file.txt,w);error_file=fopen(error_file.txt,w);inti;curword.clear();get_char();get_nbc();if(C==EOF)returnfalse;if(isalpha(C)||C=='_')//关键字和标识符的处理,以字母或下划线开头{curword.clear();while(isalnum(C)||C=='_'){curword.push_back(C);get_char();}retract();wordnum++;Id.push_back(curword);for(i=0;iKey.size();i++)if(Key[i]==curword)break;//输出每一个单词的标识符if(iKey.size())//关键字fprintf(token_file,%8d----%20s%s\n,wordnum,KEYWORD,curword);else9fprintf(token_file,%8d----%20s%s\n,wordnum,Identifier,curword);}elseif(isdigit(C))//无符号数的处理{curword.clear();while(isdigit(C)){curword.push_back(C);get_char();}if(C=='.'||C=='E'||C=='e')//处理小数和指数形式{curword.push_back(C);get_char();while(isdigit()){curword.push_back(C);get_char();}}retract();wordnum++;Id.push_back(curword);fprintf(token_file,%8d----%20s%s\n,wordnum,UnsignedNumber,curword);}elseif(C=='#')//过滤掉以#开头的预处理{fprintf(note_file,preproccessLine%d:,linenum);get_char();fprintf(note_file,%c,C);while(C!='\n'){get_char();fprintf(note_file,%c,C);}fprintf(note_file,%c,C);10}elseif(C=='')//内的句子当成整个串保存起来{curword.clear();get_char();while(C!=''){curword.push_back(C);get_char();}fprintf(token_file,*****stringin----%s\n,curword);}elseif(C=='/'){get_char();if(C=='/')//过滤掉//开头的行注释{fprintf(note_file,single-linenoteLine%d:,linenum);get_char();curword.clear();while(C!='\