|
本文示例源代码下载
前些天写了个小语言的词法分析程序,因为前些天在VC知识库看到一个pascal词法分析的程序,觉得写得挺复杂的。其实词法分析程序的原理都是一样的,所以我想只要搞明白了简单的词法分析程序,再写复杂的就不难了,无非是多加几个关键字,多写几个条件判断语句而已。词法分析是编译程序的基础,也是最简单的。好,现在让我们看程序吧。 先让我们看看这个小语言的文法吧。 G[<程序>]: <程序>∷=<程序首部>;<分程序>. <程序首部>∷=program<标识符> <分程序>∷=<复合语句> <复合语句>∷=begin<语句序列>end <语句序列>∷=<语句>{;<语句>} <语句>∷=<赋值语句>|<复合语句>|<条件语句> <赋值语句>∷=<标识符>:=<表达式> <条件语句>∷=if <布尔表达式> then <语句> else <语句> <表达式>∷=<项>{(+|-)<项>} <项>∷=<因式>{(*|/)<因式>} <因式>∷=<标识符>|<无正负号常量>|’(’<表达式>’)’ <布尔表达式>∷=<表达式><关系运算符><表达式> <关系运算符>∷= =|<|<=|>|>=|<> <标识符>∷=<字母>{<字母>|<数字>} <无正负号常量>∷=<数字>{<数字>}[.<数字>{<数字>}] <字母>∷=a|b|c|d|e|f|g|……|u|v|w|x|y|z <数字>∷=0|1|2|3|4|5|6|7|8|9 根据此文法,构造一词法分析程序。输入以“#”为结束符 按照这个文法,找出该语言的关键字,如program,begin,end ,if,then,else,以及其他一些特殊符号,然后再构造一个分析表,如下表: 单词符号 类别编号标识符1常数2if3then4else5program6begin7end8+9-10*11/12(13)14>15>=16<17<=18<>19:=20;21.22,23 根据这个表来构造程序,程序的核心是下面的这个函数, /******************************************************************** 以下为主分析函数 从输入文件里面读,把分析结果写到输出文件中 参数:fpin :输入文件指针 fpout: 输出文件指针 ********************************************************************/ void parse(FILE* fpin,FILE* fpout) { char arr[MAXBUF];//读出的最长的字符串不超过MAXBUF,MAXBUF定义为255,够长了我想 int i=0;//分析含字母的字符串用 int j=0;//分析纯数字的字符串用 while(1) { fscanf(fpin,"%c",&ch);//从输入文件中读入一个字符 if( ch=='' ''|| ch =='' '')//过滤掉空格和tab ; else if( ch=='' '')//回车换行符,为下面进行错误判断 lineno++; else if( IsDigit(ch))//读入的是数字 { while(IsDigit(ch)) { arr[j] = ch; j++; fscanf(fpin,"%c",&ch); } fseek(fpin,-1L,SEEK_CUR);//文件指针后退一个字节 char* temp1 =(char*)malloc(j+1);/ memcpy(temp1,arr,j); temp1[j] ='''';//把数组里面的内容拷贝到连外一个数组里面,因为我定义的 //arr为255个字节,实际上写不到那么多,所以只拷贝实际上有数据的 j=0;//恢复初始状态,以备下次使用 fprintf(fpout,"%s %d ",temp1,2);//常数 free(temp1);//释放内存 } else if(IsAlpha(ch))//是字母开头的 { while(IsAlpha(ch) || IsDigit(ch)) { arr[i] =ch; i++; fscanf(fpin,"%c",&ch); } fseek(fpin,-1L,SEEK_CUR); char* temp = (char*)malloc(i+1) ; memcpy(temp,arr,i); temp[i] =''''; i=0; /*基本思想同处理数字的*/ if(FindOK(temp))//FindOK函数在关键字表中查找和temp字符串相同的,找到就返回类别编号 { fprintf(fpout,"%s %d ",temp,FindOK(temp)); } else { fprintf(fpout,"%s %d ",temp,1);//标示符号 } free(temp); } //以下为2字节的运算符号 else if( ch=='':'')//符号“:=” { fscanf(fpin,"%c",&ch); if(ch==''='') fprintf(fpout,"%s %d ",":=",20); else fprintf(fpout,"error in compileing %d lines unknown character %c ",lineno,ch);//出错了 } else if(ch==''>'')//符号 “> “ 和”>=” { fscanf(fpin,"%c",&ch); if(ch==''='') fprintf(fpout,"%s %d ",">=",16); else fprintf(fpout,"> 15 "); } else if( ch==''<'') //符号 “< “ 和”<=” { fscanf(fpin,"%c",&ch); if(ch==''='') {fprintf(fpout,"<= 18 ");} else if( ch==''>'') {fprintf(fpout,"<> 19");} else {fprintf(fpout,"< 19 ");} } else { //以下为一个字节的运算符号 if(ch==''-'') {fprintf(fpout,"%s %d ",''-'',10);continue;}//在文件中输出为“- 10” if(ch=='';'') {fprintf(fpout,"; 21 ");continue;} if(ch==''+'') {fprintf(fpout,"+ 9 ");continue;} if(ch==''*'') {fprintf(fpout,"* 11 ");continue;} if(ch==''/'') {fprintf(fpout,"/ 12 ");continue;} if(ch==''('') {fprintf(fpout,"( 13 ");continue;} if(ch=='')'') {fprintf(fpout,") 14 ");continue;} if(ch==''.'') {fprintf(fpout,". 22 ");continue;} if(ch=='','') {fprintf(fpout,", 23 ");continue;} if(ch==''#'') break;//分析结束 else fprintf(fpout,"error in compileing %d lines unknown character %c ",lineno,ch);//出错了,输出出错信息 } } }其他请看源代码,注释很详细,但是肯定有不足的地方,请大家吝赐教。有什么问题,可以给我发邮件。这是我第一次向VC知识库投稿,以后将会陆续写一些VC方面的程序来和大家共享。我的email:brilliant_zhang@21cn.com,QQ:110902663, 谢谢大家。
|