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

📄 张文萍词法分析器.cpp

📁 这是我做的编译原理词法分析器
💻 CPP
字号:
#include <iostream.h>
#include <stdio.h>
#include <string.h>
#include <fstream.h>

#define NULL 0
#define MAX_KEY_NUM  15  
#define MAX_UNI_NUM 17
#define MAX_DOU_NUM 11  

FILE *sfile;//源文件指针
FILE *dfile;//目标文件指针
int count=0;//记录错误个数
int line=0;//记录行数
char sfilename[20],dfilename[20];
   
char *key[MAX_KEY_NUM]={"int","char","float","void","const","for","if","else","then","while","switch","break","begin","end","main"};
char *unifort[MAX_UNI_NUM]={",",";","{","}","(",")","[","]","+","-","*","/","%","!","<",">","="};
char *doublet[MAX_DOU_NUM]={"/=","+=","-=","*=","%=","||","&&","<=","==",">=","!="};
char consts[100][20];  //定义常数表
char label[100][20];   //定义标识符表
int connum=0;                //数字数组的下标
int labnum=0;                //标识符数组的下标
//====函数定义=========
int Initscanner();
void Scanner();
void Lexscan(char);
void Isalpha(char[]);
void Isnumber(char[]);
void Isanotation(char[]);
void Isother(char[]);
void Output();
void error(int);
void close();
//===================主函数============================
void main()
{
	cout<<"=============欢迎您使用由张文萍编写的词法分析器================"<<endl;
    Initscanner();
	cout<<endl;
	cout<<"开始编译"<<endl;
	cout<<endl;
	Scanner();
	cout<<endl;
    cout<<"编译完成"<<endl; 
	cout<<endl;
    close();

	char choice;
	cout<<"是否输出编译成功的结果?(Y or N)"<<endl;
	cin>>choice;
	if(choice=='Y'||choice=='y')
	{       
            Output();     
	}
	else
		cout<<"感谢您使用此编译系统!"<<endl;
           

}
//==================初始化函数===================
int Initscanner()
{
  
   
    cout<<"请输入您要编译的源文件名:"<<endl;
	cin>>sfilename;
	sfile=fopen(sfilename,"r");
	if(sfile==NULL)
	{
		cout<<"文件不存在!"<<endl;	
	}

	cout<<"请输入目标文件名:"<<endl;
    cin>>dfilename;
	dfile=fopen(dfilename,"w");
	if(dfile==NULL)
	{
		cout<<"无法打开文件!"<<endl;
        return -1;
	}
	return 1;
}
//===================浏览函数==========================
void Scanner()
{
	char s;
	s=fgetc(sfile);
	line++;
    while(s!=EOF)
	{
		if(s=='\n')line++;
	    while(s==' '||s=='\n')
	   {
		   s = fgetc(sfile);
           if(s=='\n')line++;
	   } 
	  Lexscan(s);
        s=fgetc(sfile);
	}
	return;
}
//======================Lexscan函数=========================
void Lexscan(char byte)
{
    char wordty[20]; 
		//数组中第一个字符是数字,转向Isnumber函数处理
	if((byte>='0')&&(byte<='9'))
	{
		wordty[0]=byte;
	     int k=1;
	     char s;
		 s=fgetc(sfile);
		 if(s=='\n')line++;
		 if(s!=EOF&&s!=' '&&s!='\n')
		 {
			 if(s>='0'&&s<='9')
             {wordty[k++]=s;
             s=fgetc(sfile);}//再读入下一个字符
             if(s=='\n')line++;
             while(s>='0'&&s<='9')
			 {
				 wordty[k++]=s;
				 s=fgetc(sfile);
				 if(s=='\n')line++;
			}
			 if(s!='.')//如果当前读入的符号不为小数点,则常数读完毕,输出此常数
			   wordty[k++]='\0';
             else//当前字符为小数点则继续向下读入
                { wordty[k++]=s;
                 s=fgetc(sfile);
				 if(s=='\n')line++;
                while(s>='0'&&s<='9')
				{
                  wordty[k++]=s;
                  s=fgetc(sfile);
				  if(s=='\n')line++;
				 }
                 wordty[k++]='\0';
			 }
		 }
	   fseek(sfile,-1,SEEK_CUR);
       Isnumber(wordty);
	 }
    else
	       //数组中第一个字符是字母,则转向Isalpha函数处理
			 if (byte>='A'&&byte<='Z'||byte>='a'&&byte<='z'||byte=='_')
			 {
				 wordty[0]=byte;
	           int n=1;
	           char s;
			   s=fgetc(sfile);
			   if(s=='\n')line++;
               if(s!=EOF&&s!=' '&&s!='\n')
			   {
				   wordty[n++]=s;
                   s=fgetc(sfile);//再读入下一个字符
				   if(s=='\n')line++;
                  while((s>='0'&&s<='9')||(s>='a'&&s<='z')||(s>='A'&&s<='Z'))
				  {
                     wordty[n++]=s;
                     s=fgetc(sfile);
					 if(s=='\n')line++;
				  }
				   wordty[n]='\0';
			   }
			   fseek(sfile,-1,SEEK_CUR);
			   Isalpha(wordty);

			   return;
			 }
               else
				   if(byte!=EOF&&byte!=' '&&byte!='\n') 
				   {//第一个字符是符号,则调用Isother函数
				      if(byte=='/')
					  {
					   wordty[0]=byte;
					   Isanotation(wordty);
					  }
				      else
					  {
					   wordty[0]=byte;
					   int m=1;
					   char s;
			            s=fgetc(sfile);
						if(s==' ')
							wordty[m]='\0'; 
						else
			               if(s=='\n')
						   {
							   line++;
						    wordty[m]='\0'; 
						   }
						else
                        {
							if(s!=EOF)
							{
				               if(s=='='||s=='&'||s=='|')
							   {wordty[m++]=s;
					             wordty[m]='\0';}
							   else
							   { wordty[m]='\0'; 
							   fseek(sfile,-1,SEEK_CUR);}
							}
							else
						       wordty[m]='\0';
						}
						Isother(wordty);
				   return;
				   }
				   }		  
}

//=====================Isalpha函数==========================
void Isalpha(char wordty[])
{
	for (int m=0;m<MAX_KEY_NUM;m++)
	{
              if (strcmp(key[m],wordty)==0)
			  { 
				fprintf(dfile,"(%s,-) ",wordty);
                return;
			  }
	}
    if(labnum!=0)
	{ 
		int j=0;
		while(j<labnum)
		 {
			if(strcmp(label[j],wordty)==0)
		     break;
		    else j++;
		}
		if(j>=labnum)//"标识符表未定义"
		{
			strcpy(label[labnum],wordty);   
			fprintf(dfile,"(%s,%d) ","id",labnum);
			labnum++;
			return;
		}
		else 
		{
		    fprintf(dfile,"(%s,%d) ","id",j);
			return;
		}
	}
    else
	{  
		strcpy(label[labnum],wordty);
	    fprintf(dfile,"(%s,%d) ","id",labnum);
	    labnum++;
        return;
	} 
}

//==================Isnumber函数=============================
void Isnumber(char wordty[])
{
	if(connum!=0)
	{
		int j=0;
		while(j<connum)
		{
			if(strcmp(consts[j],wordty)==0)
				break;
			else
				j++;
		 }
	   if(j>=connum)//"数字表未定义"
	   {  
			strcpy(consts[connum],wordty);   
			fprintf(dfile,"(%s,%d) ","num",connum);
					connum++;
		}
		else //定义输出位置
		{
			fprintf(dfile,"(%s,%d) ","num",j);
		}
	}
	else
	{
		strcpy(consts[connum],wordty);
		fprintf(dfile,"(%s,%d) ","num",connum);
	      connum++;
	}	

}
//=====================符号处理函数=============================
void Isother(char wordty[])
{
	if(strlen(wordty)==2)
	{
		
		for (int i=0;i<MAX_DOU_NUM;i++)
		if (strcmp(doublet[i],wordty)==0)
			{ 
				 if((strcmp(wordty,"<=")==0)||(strcmp(wordty,">=")==0)||(strcmp(wordty,"!=")==0)||(strcmp(wordty,"==")==0))
				 {fprintf(dfile,"(rlop,-) ");}                                
				 else 
					 if(strcmp(wordty,"&&")==0)
					 {fprintf(dfile,"(%s,-) ","and");}
			         else 
						 if(strcmp(wordty,"||")==0)
						 {fprintf(dfile,"(%s,-) ","or");}
			              else
						  {fprintf(dfile,"(%s,-) ",wordty);}						 
				
			}
	}
	else
		if(strlen(wordty)==1)
		{
		int flag=0;
		    int j=0;
			while(j<MAX_UNI_NUM)
			{
				if (strcmp(unifort[j],wordty)==0)
				{ 
					 flag=1;
					 if((strcmp(wordty,"<")==0)||(strcmp(wordty,">")==0))
					 {fprintf(dfile,"(rlop,-) ");break;}
				     else
					     if(strcmp(wordty,"!")==0)
						 {fprintf(dfile,"(%s,-) ","not");break;}
                           else
						   {fprintf(dfile,"(%s,-) ",wordty);break;}
				}
			   else j++;
			}
		if(!flag)
		{cout<<wordty;error(1);}
		}
}
//==========================处理/号函数============================
void Isanotation(char wordty[])
{  
	char s;
	s=fgetc(sfile);
	if(s=='\n')line++;
		else   
		{
			switch(s)
			{
			 case '=':
				 { fprintf(dfile,"(/=,-) ");
				 break;}
			 case '*':	//查找/*错误
				 {for(;;)
					{
						s=fgetc(sfile);
						if(s=='\n')line++;
						if(s==EOF){error(2);break;}
						if(s=='*')
						{
							s=fgetc(sfile);
							if(s=='/')
							{
								return;
							}
						}
				 }
				 break;}
			 case '/'://"//"之后为注释内容				     
				     s=fgetc(sfile);
					 if(s=='\n')line++;
					 else
						 while(s!='\n')
						 {
							 s=fgetc(sfile);
							 if(s=='\n')line++;
						 }cout<<"第"<<line-1<<"行//后为注释内容"<<endl;
                      break;
            default: /*不是注释,当作除号处理*/
				{fprintf(dfile,"(/,-) ");
				break;}	
			}
		}	
}
//==================输出函数========================
void Output()
{
        dfile=fopen(dfilename,"r");
		char ch;
		ch=fgetc(dfile);
        cout<<ch;
		while(ch!=EOF)
		{ch=fgetc(dfile);
		cout<<ch;
		}
}
//======================报错函数=========================
void error(int a)
{
	 count++;
	switch(a)
	{
	        case 1: cout<<"错误"<<count<<":第"<<line<<"行此字符非法!"<<endl;break;
			case 2: cout<<"错误"<<count<<":第"<<line-1<<"行没有匹配的*/"<<endl;break;
			default:break;
	}

}
//======================关闭文件===============================
void close()
{
	fclose(sfile);//关闭原文件
	fclose(dfile);//关闭目标文件
}

⌨️ 快捷键说明

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