⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lexeme2.c

📁 编译原理课程实验
💻 C
字号:
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define N 512    /*内存缓冲区大小*/
#define M 9      /*标识符的最大长度*/
#define X 1000   /*符号表的最大符号数目*/

#define KEY    0
#define ID     1
#define DIGIT  2
#define CALU   3
#define DIV    4
#define LETTER 5
#define UNDERLINE 6
#define INTERP  7
#define DONE 8 
int next=0;   /*指向内存缓冲区下一未读的字符*/
int tokenp=0;  /*指向字符串数组可放字符位置*/
int length=0;   /*符号表中下一存放单词的位置*/
FILE *fp;

char str[N];   /*内存缓冲区*/
char StrToken[M]={'\0'}; /*当前识别的单词*/
int row=1;  /*记录行号*/
int tag=0;  /*记录该行是否缺少分号*/

struct symbol
{
 int classno;
 char value[M];
 int num;
 int bin[16];
};
struct symbol Table[X];    /*符号表结构体数组*/

struct MatchStack     /*匹配括号的堆栈结构体*/
{
  char ch;
  int row;
};
struct MatchStack S[N];
int top=-1;

struct error_information  /*检错结构体*/
{
 int row;
 char info[30];
};
struct error_information error[50];
int errop=0;

int id_keyword(char ch);    /*比较关键字表,若单词是关键字返回classno=0,否则返回classno=1*/
void output();              /*输出子程序*/
int identify(char ch);   /*当前单词是标识符或关键字*/
int is_id();    /*判断是否为标识符里的关键字函数*/
int caculate(char ch);
int divide(char ch);
int interp(char ch);
int num_bin(char ch);

int identify(char ch)             /*判断当前单词是标识符*/
{   StrToken[tokenp]=ch;
    tokenp++;
    ch=str[next];
    next++;
    while((str[next]!='\0')&&(((ch>='a')&&(ch<='z'))||((ch>='A')&&(ch<='Z'))||(ch=='_')||((ch>='0')&&(ch<='9')))&&(tokenp<M))
    {  StrToken[tokenp]=ch;  
       tokenp++;
       ch=str[next];
       next++;
    }

   if(str[next]!='\0')  
    {if(tokenp==M)   tokenp--;
     next--;
     StrToken[tokenp]='\0';
     }
    else  StrToken[tokenp]='\0';
    return(ID);

}

int id_keyword(char ch)  /*判断当前单词是标识符或关键字*/
{int state=0; 
 StrToken[tokenp]=ch; 
 tokenp++;
 ch=str[next]; 
 next++;
 while((str[next]!='\0')&&(((ch>='a')&&(ch<='z'))||((ch>='A')&&(ch<='Z')))&&(tokenp<M))        /*若读入的是字母并且数组未满,则读入数组*/
 {StrToken[tokenp]=ch;         
  tokenp++;
  ch=str[next];
  next++;
 }
  if(((ch>='0')&&(ch<='9'))||(ch=='_'))    state=identify(ch);      /*若读到数字或下划线则表明该字符串为标识符*/
  if(ch=='\n')       
  { 
   if(tag>1)
   {strcpy(error[errop].info,"extra ;\n");         
    error[errop].row=row;
	errop++;
   }
	row++;
	tag=0;
    ch=str[next];
	next++;
  }
  if((state==0)&&(str[next]!='\0'))
   {if(tokenp==M)   tokenp--;
    next--;
    StrToken[tokenp]='\0';
    state=is_id();          /*判断由字母组成的串是关键字还是标识符*/
    }
 return state;
}
                                                   
 int is_id()  /*判断是否为标识符里的关键字函数*/
 {int i=31;
  char keyword[32][9]={"break","anto","case","char","const","continue","default","do","double","else","enum","extern","float","for","goto","if","int","long","register","return","short","signed","sizeof","static","struct","switch","typedef","union","unsigned","void","volatile","while"};
  while((i>=0)&&(strcmp(StrToken,keyword[i])))   i--; /*将读入的字符与关键字数组里的各关键字进行比较,进行判断*/
  if(i>=0)  return(KEY);  /*若相同,则返回值为关键字*/
  else return(ID);     /*若不同,则返回值为标识符*/
  }

int caculate(char ch)   /*识别算符的函数*/
{
  char c;
  StrToken[tokenp]=ch;
  tokenp++;
  if(str[next]!='\0')
  {
   c=str[next];             /*next小于内存缓冲区大小N*/
   if((ch=='-')&&((c=='>')||(c=='-')||(c=='=')))    /*识别“--、->、-=”*/
   {StrToken[tokenp]=ch;tokenp++;next++;}
   if((ch=='+')&&((c=='+')||(c=='=')))              /*识别”++、+=“*/ 
   {StrToken[tokenp]=ch;tokenp++;next++;}
   if((ch=='<')&&((c=='<')||(c=='=')))              /*识别“<<、<=”*/
    {StrToken[tokenp]=ch;tokenp++;next++;}
   if((ch=='>')&&((c=='>')||(c=='=')))              /*识别“>>、>=”*/
    {StrToken[tokenp]=ch;tokenp++;next++;}
   if(((ch=='!')||(ch=='=')||(ch=='&')||(ch=='^'))&&(c=='='))/*识别“!、=、&、^、=”*/
    {StrToken[tokenp]=ch;tokenp++;next++;}
   if(((ch=='|')||(ch=='/'))&&(c=='='))              /*识别”/、=、|“*/
    {StrToken[tokenp]=ch;tokenp++;next++;}
   if(((ch=='*')||(ch=='%'))&&(c=='='))              /*识别“*、%、=”*/ 
    {StrToken[tokenp]=ch;tokenp++;next++;}
   if((ch=='|')&&(c=='|'))                           /*识别 “||”*/
    {StrToken[tokenp]=ch;tokenp++;next++;}
   if((ch=='&')&&(c=='&'))                           /*识别“&&”*/ 
    {StrToken[tokenp]=ch;tokenp++;next++;}
   }
   StrToken[tokenp]='\0';
   return(CALU);
}


/*识别界符*/
 int divide(char ch)
 {char c;
  if(ch=='('||(ch=='[')||(ch=='{'))
  { top++;
   S[top].ch=ch;     /*入栈*/
   S[top].row=row;
  }
  if((ch==')')||(ch==']')||(ch=='}'))
  {c=S[top].ch;
   if(((ch==')')&&(c=='('))||((ch==']')&&(c=='['))||((ch=='}')&&(c=='{')))  {top--;next++;}   /*左右界符匹配*/
   else
   {strcpy(error[errop].info,"right division extra\n");         
    error[errop].row=row;
	errop++;
   }
  }
  if(ch==';')  tag++;
  StrToken[0]=ch;
  StrToken[1]='\0';
  return(DIV);
 }

int interp(char ch)    /*消除注释*/
 { ch=str[next];
   next++;
  if(ch!='*')  return(CALU);
   top++;
   S[top].ch='/';
   S[top].row=row;
   top++;
   S[top].ch='*';
   S[top].row=row;
   ch=str[next];
   next++;
  while((ch!='\0')&&(ch!='*'))
  { 
    while((ch!='*')&&(ch!='\0'))
    {ch=str[next];
     next++;
     }
  }
    if((ch!='\0')&&(str[next]=='/'))
       {next++;
	    top=top-2;
        }
   return(DONE);
 }

 int num_bin(char ch)      /*识别常数并转化成二进制*/ 
 {
    int num=0,i;
    while((ch!='\0')&&(ch>='0')&&(ch<='9'))  
   {
    ch=ch-'0';
    num=num*10+ch;
    ch=str[next];
    next++;   
	} 
	next--;
    Table[length].num=num;
    for(i=0;i<16;i++)  { Table[length].bin[i]=0;}
    i=15;
    while((num!=0)&&(i>=0))
    {
     Table[length].bin[i]=num%2;
     num=num/2;                 
     i--;  
    }
    return(DIGIT);
 }
 
 void output()     /*输出函数*/
 {FILE *fp1,*fp2;
  int temp=0,i;
  fp1=fopen("d:\\gao\\symbol.txt","wt");
  fp2=fopen("d:\\gao\\const.txt","wt");
   if(fp1==NULL)   printf("write symbol_table error!\n"); 
   if(fp1==NULL)   printf("write const_table error!\n");  
 
  printf("CLASSNO               VALUE            LOCATION      BINARY\n");
  fprintf(fp1,"CLASSNO          VALUE\n");
  fprintf(fp2,"NUM              BINARY\n");
  while(temp<length)
  {
   switch(Table[temp].classno)
    {
     case KEY  : printf("keyword                %s\n",Table[temp].value);break;
     case ID   : printf("ID                     %s              %d\n",Table[temp].value,temp);break;
     case DIGIT: printf("DIGIT                  %d                  %d          ",Table[temp].num,temp);
                 for(i=0;i<16;i++)     printf("%d",Table[temp].bin[i]);
                 printf("\n");
                 break;
	 case CALU : printf("caculate                   %s\n",Table[temp].value);break;
	 case DIV  : printf("division               %s\n",Table[temp].value);break;
     default   : break;
    }
    if(Table[temp].classno!=DIGIT)    fprintf(fp1,"%d                 %s\n",Table[temp].classno,Table[temp].value);
	else     {
		      fprintf(fp2,"%d      ",Table[temp].num);
	          for(i=0;i<16;i++)     fprintf(fp2,"%d",Table[temp].bin[i]);
			  fprintf(fp2,"\n");
	}
   temp++;
  }
  fclose(fp1);
  fclose(fp2);
   while(top!=-1)            /*左界符多余*/
   {strcpy(error[errop].info,"left division extra\n");         
    error[errop].row=S[top].row;
	top--;
	errop++;
   }
    if(errop>0)    /*若无错误信息,则errop为零*/
    {printf("ERROR INFORMATION:\n");
     temp=0;
     while(temp<errop)
     {
      printf("line:%d     ",error[temp].row);
      printf("%s\n",error[temp].info);
	  temp++;
     }
    }
 }

int main(int argc,char *argv[])
 {char ch;
  int initstate,classno,i;
  fp=fopen(argv[1],"rt");
  if(fp==NULL)
	{printf("不能打开此文件!");
 
    }
   while(!feof(fp))
	{fread(str,N,1,fp); 
	  puts(str);
	}
  
  ch=str[next];
  next++;
  while(ch!='\0')
  {if(ch=='\n')       
  { 
   if(tag>1)
   {strcpy(error[errop].info,"extra ;\n");         
    error[errop].row=row;
	errop++;
   }
	row++;
	tag=0;
    ch=str[next];
	next++;
    classno=DONE;
	initstate=10;
  }
  if(ch==' ')        
  {ch=str[next];
   next++;
   classno=DONE;
   initstate=10;
  }
  if(((ch>='a')&&(ch<='z'))||((ch>='A')&&(ch<='Z')))    initstate=LETTER;  /*以字母开头的字符串,开始识别标识符或关键字*/
  if(ch=='_')        initstate=UNDERLINE;  /*以下划线开头的字符串,开始识别标识符*/
  if((ch=='-')||(ch=='.')||(ch=='!')||(ch=='~')||(ch=='+')||(ch=='*')||(ch=='&')||(ch=='/')||(ch=='%')||(ch=='<')||(ch=='>')||(ch=='^')||(ch=='|')||(ch=='=')||(ch=='?')||(ch=='='))  initstate=CALU;
  if((ch=='[')||(ch=='(')||(ch==')')||(ch=='{')||(ch=='}')||(ch==']')||(ch==',')||(ch==';')||(ch=='"'))   initstate=DIV;
  if(ch=='/')                  initstate=INTERP;
  if((ch>='0')&&(ch<='9'))     initstate=DIGIT;
  switch(initstate)
  {case LETTER: classno=id_keyword(ch); break;
   case UNDERLINE: classno=identify(ch); break;
   case CALU: classno=caculate(ch); break;
   case DIV: classno=divide(ch); break;
   case INTERP: classno=interp(ch); break;
   case DIGIT: classno=num_bin(ch); break;
   default : break;
  }
  if(classno!=DONE)
  {Table[length].classno=classno;  /*把识别出的标识符或关键字放入符号表*/
   if(classno!=DIGIT)
   {strcpy(Table[length].value,StrToken);
   for(i=0;i<M;i++)   StrToken[i]='\0';
   tokenp=0;
   }
   length++;
  }
  ch=str[next];
   next++;
 }
  fclose(fp);
  output();
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -