一个小语言的词法分析程序

  • 来源: 互联网 作者: rocket   2008-03-18/13:34
  • 前些天写了个小语言的词法分析程序,因为前些天在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 常数 2 if 3 then 4 else 5 program 6 begin 7 end 8 + 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 ==''\t'')//过滤掉空格和tab
    
    			;
    
    		else if( ch==''\n'')//回车换行符,为下面进行错误判断
    
    			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] =''\0'';//把数组里面的内容拷贝到连外一个数组里面,因为我定义的
    
    			//arr为255个字节,实际上写不到那么多,所以只拷贝实际上有数据的
    
    
    
    			j=0;//恢复初始状态,以备下次使用
    
    			fprintf(fpout,"%s\t\t%d\n",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] =''\0'';
    
    
    
    			i=0;
    
    			/*基本思想同处理数字的*/
    
    		
    
              if(FindOK(temp))//FindOK函数在关键字表中查找和temp字符串相同的,找到就返回类别编号
    
    		  {
    
    			 
    
    			 fprintf(fpout,"%s\t\t%d \n",temp,FindOK(temp));
    
    			 
    
    		  }
    
    		  else
    
    		  {
    
    			  fprintf(fpout,"%s\t\t%d\n",temp,1);//标示符号
    
    			  
    
    		  }
    
    		  free(temp);
    
    		}
    
    	
    
    		//以下为2字节的运算符号
    
    		else if( ch=='':'')//符号“:=”
    
    		{
    
    			fscanf(fpin,"%c",&ch);
    
    			if(ch==''='') 
    
    				fprintf(fpout,"%s\t\t%d\n",":=",20);
    
    			
    
    		else 	
    
    			fprintf(fpout,"error in compileing %d lines unknown character %c \n",lineno,ch);//出错了
    
    		}
    

    评论 {{userinfo.comments}}

    {{money}}

    {{question.question}}

    A {{question.A}}
    B {{question.B}}
    C {{question.C}}
    D {{question.D}}
    提交

    驱动号 更多