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

📄 ls.c

📁 词法分析器
💻 C
字号:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <math.h>

#define max_line 100
#define max_word 31
#define num_keyword 32

static FILE *fkeyword,*fidentifier,*flexci,*fsr;//作为外部变量
int line=1;
enum {err_zero=0,err_one,err_notdefined};
int identi_value=0;
int num_add=0;

typedef struct IDEN
{
	int num;
	struct IDEN * next;
	char str[20];
}IDEN;
IDEN * head=NULL;

void Write_keyword(char **Reserve)//关键字写入文档
{
	int i;
	for(i=0;i<num_keyword;i++)
		fprintf(fkeyword,"%d  %s  \n",i+1,Reserve[i]);
}

void Write_oper(char *s,char **arr_oper)//运算符放入文件,返回地址
{
	int i;
	char str[]="OPERATOR";//将其填入词法分析所得的程序中
	for(i=0;i<13;i++)
		if(strcmp(s,arr_oper[i])==0)
			break;
	fprintf(flexci,"%s",s);
}

void Write_sep(char c)//分隔符
{	
	char s[]="SEP";
	if(c!=EOF&&c!='\n')
      fprintf(flexci,"%c",c);
}

void Write_identi_to_lex(char *s,char *str,int value)//标识符写入lex,入口地址
{
	char c='$';
	fprintf(flexci,"%c",c);
}

int Double_or_not(char c,char **arr_oper)//运算符的操作
{
	char next;
	char s[3];
	next=fgetc(fsr);
	if(next==c)//处理==,++,--
	{
		s[0]=s[1]=c;
		s[2]='\0';
		Write_oper(s,arr_oper);
	}
	else if((c=='<'||c=='>'||c=='!')&&next=='=')//处理三个特殊的运算符<=,>=,!=
	{
		s[0]=c;
		s[1]=next;
		s[3]='\0';
		Write_oper(s,arr_oper);
	}
	else
	{
		s[0]=c;
		s[1]='\0';
		Write_oper(s,arr_oper);
		ungetc(next,fsr);//将fp回退一个指针
	}
	return 0;
}

char * Addtoken(char c, char *s)//加字符
{
	int i=0;
	while(s[i]!='\0') i++;
	s[i]=c;
	s[i+1]='\0';
	return s;
}

int Seprator(char ch)//检查是否是界符
{
	if(ch==','||ch=='('||ch==')'||ch==';'||ch=='#'||ch=='{'||ch=='['||ch==']'||ch=='\"')
		return 1;
	else if(ch=='<'||ch=='>'||ch=='.'||ch==' '||ch=='}'||ch==EOF||ch=='\n'||ch=='\''||ch=='\\')
		return 1;
	else 
		return 0;
}

int Operator(char ch)//检查是否是运算符
{
	if(ch=='*'||ch=='/'||ch=='+'||ch=='-'||ch=='&'||ch=='^'||ch=='='||ch=='!'||ch=='%')
		return 1;
	else
		return 0;
}

void Error_msg(int type)//简单的错误信息处理
{
	switch(type)
	{
       case err_zero:printf("the file has not been opend!\n");break;//文件信息错误
       case err_one:printf("the identifier is not legal in %5d line\n",line);break;
       case err_notdefined:printf("undefined error int line %5d\n",line);break;//标识符不符合定义
       default:break;
	 }
}

int Tra_ch_int_write(char *token)//将字符串转换为整数
{
	FILE * fnum;
	int value=0;
	int i;
	fnum=fopen("num.txt","a+");
	if(fnum==NULL)
	{   
		Error_msg(err_zero);
		return 0;
	}
	for(i=0;token[i]!='\0';i++)//将字符串转换为整数
		value=10*value+(int)token[i]-'0';
	fprintf(fnum,"%2d %10d;\n",++num_add,value);
	fclose(fnum);
	return num_add;
}

int Tra_ch_float_write(char *token)//将字符串转换为浮点数
{
    FILE * fnum;
	float value=0;
	char *pc,*p;
	int val_int=0,i=-1;

	pc=token;//处理浮点数的整数部分
	while(*pc!='.')
		pc++;
	for(p=token;p<pc;p++)
        val_int=10*val_int+(int)*p-'0';
	p++;
	while(*p!='\0')//处理浮点数的小数部分
	{
		value=(float)pow(10,i--)*((int)*p-'0')+value;
		p++;
	}
    value+=val_int;
    fnum=fopen("num.txt","a+");
    if(fnum==NULL)
	{   
		Error_msg(err_zero);
		return 0;	
	}
    fprintf(fnum,"%2d %8.2f\n",++num_add,value);//将数据写入常数文档
    fclose(fnum);
	return num_add;
 }

void Digit(char c)//对数据处理
{
	char ch;
	char next;
	char token[max_word]={'\0'};
	int revalue=-1;

    Addtoken(c,token);
	next=fgetc(fsr);
	while(isdigit(next))//浮点数的情况处理,科学计数法
	{
		Addtoken(next,token);//需要写函数,没有写完
		next=fgetc(fsr);
	}
    
	if(next=='.')//浮点,读到小数点后所有数据形式
	{
		Addtoken(next,token);
	    next=fgetc(fsr);
	    while(isdigit(next))
		{
		 Addtoken(next,token);
		 next=fgetc(fsr);
		}
		revalue=Tra_ch_float_write(token);
	}
	else if(isalpha(next))//错误的标识符
	{
		Error_msg(err_one);//非数据出错处理
		while(1)//跳过一些项,直到下一个分隔符,继续处理
		{
			next=fgetc(fsr);
			if(Seprator(next))break;
		}
	}
	else if(Seprator(next)||Operator(next))//整数的情况
		revalue=Tra_ch_int_write(token);

	ungetc(next,fsr);
	ch='$';
    fprintf(flexci,"%c",ch);
}

int Check_iden(char *str)//检查是否是已有的标志符
{
	IDEN* pid;
	pid=head;
	for(;pid!=NULL;pid=pid->next )
		if(strcmp(str,pid->str )==0)
			break;
	if(pid!=NULL)
		return pid->num ;
	else return 0;
}

int Write_to_fidentifier(char *str)//写标识符
{
	int i=0;
	int checkvalue;
	IDEN * newp;

	checkvalue=Check_iden(str);
	if(checkvalue!=0)
		return checkvalue;
	else
	{
		newp=(IDEN *)malloc(sizeof(IDEN));
		newp->num =++identi_value;
		strcpy(newp->str,str);
		newp->next =head;
		head=newp;//将新增加的标识符加入链表中
	   
	    fprintf(fidentifier,"%4d %20s\n",identi_value,str);//写入标识符文件
	    return identi_value;
	}
}

int Lookup(char *s,char **reserword)//检查是否是关键字
{
	int i;
	for(i=0;i<max_word;i++)
		if(!strcmp(reserword[i],s))
			return i+1;
	return 0;
}

void Alpha(char c,char **reseword)//以字符打头的字母处理
{
	char next;
	char token[max_word]={'\0'};
	int i=1;
	int re_value,tag_re;
	
    Addtoken(c,token);
	next=fgetc(fsr);
	while(isalpha(next)||isdigit(next)||next=='_')//标识符的情况处理
	{
		i++;
		Addtoken(next,token);
		next=fgetc(fsr);
	}

	if(!Seprator(next)&&!Operator(next)&&next!=EOF)//对结构体的.->看作是分隔符(运算符和界符)
	{
        Error_msg(err_notdefined);//在LEX中报错,并显示忽略一些字符
		while(1)//忽视错误,继续处理
		{
			next=fgetc(fsr);
			if(Seprator(next))break;
		}

	}

    ungetc(next,fsr);
	tag_re=Lookup(token,reseword);//是否关键字
	if(tag_re!=0)
		Write_identi_to_lex(token,"KEYWORD",tag_re);
	else
	{
      re_value=Write_to_fidentifier(token);//返回地址入口,写入lex
	  Write_identi_to_lex(token,"IDENTIFIER",re_value);//写入词法分析程序
	}

}

void Write_oper_to_txt(char **arr_oper)//将运算符写入文档
{
	FILE *foper;
	int i;

	foper=fopen("operator.txt","w");
	if(!foper)
	{
		Error_msg(err_one);
		return ;
	}
	for(i=0;i<13;i++)
	{
		fprintf(foper,"%2d   %10s\n",i+1,arr_oper[i]);
	}
	fclose(foper);
}

void Last_work()//对文件和动态释放的内存进行释放,回收
{
	IDEN *pre;
	fclose(fsr);
	fclose(fidentifier);
	fclose(flexci);
	fclose(fkeyword);

	pre=head;
	while(head!=NULL)
	{
		head=head->next ;
		free(pre);
		pre=head;
	}
}

void Explain(char ch,char **arr_oper)//对注释的处理
{
	char next;
	char token[max_word]={'\0'};
	char after;
    next=fgetc(fsr);
	if(next=='*')//注释的情况,/* */的形式
	{
      next=fgetc(fsr);
	  after=fgetc(fsr);
	  while(next!='*'&&after!='/')
	  {
		if(next=='\n')
			line++;
		next=after;
		after=fgetc(fsr);

	  }
	}
    else if(next=='/')//单行注释的情况
	{
	  next=fgetc(fsr);
	  while(next!='\n')
		next=fgetc(fsr);
	 line++;
	}
	else//一般的运算
	{
		ungetc(next,fsr);
		token[0]=ch;
		token[1]='\0';
	    Write_oper(token,arr_oper);
	 }
}

void main()
{
	char *Reser_word[num_keyword]={"auto","break","case","char","const","continue","default",
		  "do","double","else","enum","extern","float","for","goto","if","int",
		  "long","register","return","short","sizeof","static","struct","switch",
		  "typedef","union","unsigned","void","volatile","while"};
	char ch,newc;
	char *arr_oper[13]={"+","-","*","/","^","++","--","&&","||","!=","==","<=",">="};

    Write_oper_to_txt(arr_oper);
    fsr=fopen("fsr.txt","r");
	fkeyword=fopen("fkeyword.txt","w");
	flexci=fopen("flexci.txt","w");
	fidentifier=fopen("fidentifier.txt","w");

	if(fsr==NULL||fkeyword==NULL||flexci==NULL||fidentifier==NULL)
	  {
		Error_msg(err_zero);
		return ;
	}

    Write_keyword(Reser_word);//关键字写入关键字文件,一字一行
	while(!feof(fsr))
	{
	  ch=fgetc(fsr);
	  if(ch==' '||ch=='\t')
		   continue;
	  else if(ch=='\n')
	  {    line++;
	       newc='\n';
	       fprintf(flexci,"%c",newc);
	       continue;
	  }
	  else if(Operator(ch)&&ch!='/')//运算符的情况,注释的情况另外处理
		    Double_or_not(ch,arr_oper);
	  else if(Seprator(ch)&&ch!=' ')//分隔符的情况
		    Write_sep(ch);
	  else if(isdigit(ch))//常数的情况
		    Digit(ch);
	  else if(isalpha(ch))//标识符的情况
		    Alpha(ch,Reser_word);
	  else if(ch=='/')//除号的情况特殊处理,有可能是注释或乘
	        Explain(ch,arr_oper);
	  else if(ch==EOF)
		  printf("at the end of the file!");
	  else
		  Error_msg(err_notdefined);//出错处理,对输出格式会报错%2d
	}
 
	Last_work();
}





	

	
    


⌨️ 快捷键说明

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