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

📄 scan.cpp

📁 本程序是实现C-的一个小型编译器
💻 CPP
字号:
#include"scan.h"

char ch,ch1;//从文件中读取一个字符
int row=1;//正在读取的字符的行号
int R=0;//括号匹配中用于记录栈顶位置
char parRight[20];//栈,用与括号匹配
FILE *sourceFile;//要分析的文件
FILE *inFile;//关键字和保留字的文档
FILE *keyFile;//关键字和保留字的文档
symble symbleList[30];//用与存储关键字和保留字的结构体数组
token currentToken;
int Token_Number=0;

/*如果输入的符号是左括号中的一种,则将其存入数组中,如果是右括号,则进行以下的判定:\
	1:数组中元素是否为空,为空,表明不匹配
	2:数组中的元素不为空,则数组中的最后一个元素和当前的元素是否为匹配的左右元素的关系,
	若是,则将数组的最后一个元素置为'\0*/
void kuahao(char ch1)
{
	int i;
	char ch=ch1;
	if((ch=='(')||(ch=='[')||(ch=='{'))//左向括号,进入数组
	{
		parRight[R++]=ch;
		printf("\n");
	}
	if(ch==')')
	{
		i=R-1;
		if((parRight[i]=='\0')||(parRight[i]!='('))
		{
			printf("此处括号是不匹配的!     \n");
		}
		if(parRight[i]=='(')
		{
			parRight[i]='\0';
			printf("\n");
			R--;
		}
	}
	if(ch==']')
	{
		i=R-1;
		if((parRight[i]=='\0')||(parRight[i]!='['))
		{
			printf("此处括号是不匹配的!     \n");
		}
		if(parRight[i]=='[')
		{
			parRight[i]='\0';
			printf("\n");
			R--; 
		}
	}
	if(ch=='}')
	{
		i=R-1;
		if((parRight[i]=='\0')||(parRight[i]!='{'))
		{
			printf("此处括号是不匹配的!     \n");
		}
		if(parRight[i]=='{')
		{
			parRight[i]='\0';
			printf("\n");
			R--;
		}
	}
}

/************************判定是否为数字****************************/
void IsNumber()
{
	int k=0;
	int flag=0;//用于记录是否有小数点出现
	
	while((ch>47)&&(ch<58))//判断当前的字符是否是数字
	{
		currentToken.name[k++]=ch;
		ch=fgetc(sourceFile);
		if(ch=='.')
		{
			flag=1;//出现了一个小数点,随后进行是否为小数的判断
			currentToken.name[k++]=ch;
			break;
		}
	}
	
	if(flag==1)
	{
		ch=fgetc(sourceFile);
		if((ch==',')||(ch==';'))//小数点后直接接了这两个符号是违法的
		{
			printf("第%d行 %s :   非法数字\n",row,currentToken.name);
			fprintf(inFile,"%d  %d  %s\n",currentToken.LineofPro=row,currentToken.code=0,currentToken.name);
			Token_Number++;
			return;
		}
		
		while((ch>47)&&(ch<58))//读入小数点后面的所有的字符
		{
			currentToken.name[k++]=ch;
			ch=fgetc(sourceFile);
		}
		if((ch==',')||(ch==';'))//正确的数字遇到间隔符,表明是正确的数字
		{
			printf("第%d行 %s :   实常数\n",row,currentToken.name);
			fprintf(inFile,"%d   %d   %s\n",currentToken.LineofPro=row,currentToken.code=28,currentToken.name);
			Token_Number++;
			return;
		}
		if(ch=='.')//出现两个小数点,后面紧接的所有符号作为违法的符号输出
		{
			currentToken.name[k++]=ch;
			while((ch!=' ')&&(ch!='\t')&&(ch!='\n')&&(ch!=';'))
			{
				ch=fgetc(sourceFile);
				currentToken.name[k++]=ch;
			}
			printf("第%d行 %s :   这个数字中出现了两个小数点!\n",row,currentToken.name);
			fprintf(inFile,"%d   %d   %s\n",currentToken.LineofPro=row,currentToken.code=0,currentToken.name);
			Token_Number++;
			return;
		}
		
		if(((ch>64)&&(ch<91))||((ch>96)&&(ch<123)))//数字后面接了字母也为非法的数字
		{
			currentToken.name[k++]=ch;
			ch=fgetc(sourceFile);
			while(((ch>47)&&(ch<58))||((ch>64)&&(ch<91))||((ch>96)&&(ch<123)))//读入所有的非法的字符
			{
				currentToken.name[k++]=ch;
				ch=fgetc(sourceFile);
			}
			printf("第%d行 %s :   非法字符\n",row,currentToken.name);
			fprintf(inFile,"%d   %s    %d\n",currentToken.LineofPro=row,currentToken.code=0,currentToken.name);
			Token_Number++;
			return;
		}
	}
	
	else//可能是整型数字
	{
		if(((ch>64)&&(ch<91))||((ch>96)&&(ch<123)))//数字后面跟了字母,属于非法错误
		{
			currentToken.name[k++]=ch;
			ch=fgetc(sourceFile);
			while(((ch>47)&&(ch<58))||((ch>64)&&(ch<91))||((ch>96)&&(ch<123)))//读入所有的非法的字母或数字
			{
				currentToken.name[k++]=ch;
				ch=fgetc(sourceFile);			
			}
			printf("第%d行 %s :   非法字符\n",row,currentToken.name);
			fprintf(inFile,"%d   %d   %s\n",currentToken.LineofPro=row,currentToken.code=0,currentToken.name);
			Token_Number++;
			return;	
		}
		else//整形数字
		{
			printf("第%d行 %s :   NUM\n",row,currentToken.name);
			fprintf(inFile,"%d   %d   %s\n",currentToken.LineofPro=row,currentToken.code=27,currentToken.name);
			Token_Number++;
		}
	}

}

/************************字符或字符串的处理*****************************/
void IsAlpha()
{
    int i=0,h=0;//h的作用与flag相似,用于判定读入的字符串是否为关键字
	while(((ch>64)&&(ch<91))||((ch>96)&&(ch<123)))//判定输入的字符是否是字母
	{
		currentToken.name[i++]=ch;
		ch=fgetc(sourceFile);
	}
	for(i=1;i<=6;i++)
	{
		h=strcmp(currentToken.name,symbleList[i].name);//与关键字进行比较
		if(!h)
		{
			printf("第%d行 %s :   关键字\n",row,currentToken.name);
			fprintf(inFile,"%d   %d   %s\n",currentToken.LineofPro=row,currentToken.code=i,currentToken.name);
			Token_Number++;
			break;
		}
	}
	if(h)
	{
		printf("第%d行 %s :   ID\n",row,currentToken.name);//关键字以外的字符串全部定义为标识符
		fprintf(inFile,"%d   %d   %s\n",currentToken.LineofPro=row,currentToken.code=26,currentToken.name);
		Token_Number++;
	}
}

/****************************判定是否为注释***********************/
//注释的情况:遇到/*就进行判定,遇到*后判定下一个字符是否为/,是则是注释,如果不是整个
//函数都将是错误的
void IsAnotation()
{
	char ch1;
	ch1=ch;
	ch=fgetc(sourceFile);
	if(ch=='*')
	{
		for(;;)
		{
			ch=fgetc(sourceFile);
			if(ch==EOF)
			{
				printf("第%d行 没有匹配的注释符!\n",row);
				break;
			}
			if(ch=='\n' )
			{
					row++; //行号加1	
					ch=fgetc(sourceFile);
			}	
			if(ch=='*')
			{
			    ch1=ch;
				ch=fgetc(sourceFile);
				if(ch=='/')
				{
					ch=fgetc(sourceFile);
					break;
				}
			}
		}
	}
	else
	{	
		printf("第%d行 %c :   保留符\n",row,ch1);
		currentToken.name[0]=ch1;
		fprintf(inFile,"%d   %d   %s\n",currentToken.LineofPro=row,currentToken.code=10,currentToken.name);
		Token_Number++;
	}
}

/***********************************判定是否为保留字***********************************/
void IsOther()
{
	char ch1;
	ch1=ch;
	int i;
	ch=fgetc(sourceFile);
	
	for(i=0;i<30;i++)
		currentToken.name[i]='\0';
	switch(ch1)
	{
		case '+':currentToken.code=7;
			     currentToken.name[0]='+';
				 printf("第%d行 %c :   保留符\n",row,currentToken.name[0]);
				 fprintf(inFile,"%d   %d   %c\n",currentToken.LineofPro=row,currentToken.code,currentToken.name[0]);
			   	 Token_Number++;
				 break;
		
		case '-':currentToken.code=8;
				 currentToken.name[0]='-';
				 printf("第%d行 %c :   保留符\n",row,currentToken.name[0]);
				 fprintf(inFile,"%d   %d   %c\n",currentToken.LineofPro=row,currentToken.code,currentToken.name[0]);
			   	 Token_Number++;
				 break;
		
		case '*':currentToken.code=9;
				 currentToken.name[0]='*';
				 printf("第%d行 %c :   保留符\n",row,currentToken.name[0]);
				 fprintf(inFile,"%d   %d   %c\n",currentToken.LineofPro=row,currentToken.code,currentToken.name[0]);
				 Token_Number++;
				 break;
		
		case '/':currentToken.code=10;
				 currentToken.name[0]='/';
				 printf("第%d行 %c :   保留符\n",row,currentToken.name[0]);
				 fprintf(inFile,"%d   %d   %c\n",currentToken.LineofPro=row,currentToken.code,currentToken.name[0]);
			 	 Token_Number++;
				 break;
        
		case ',':currentToken.code=19;
				 currentToken.name[0]=',';
				 printf("第%d行 %c :   保留符\n",row,currentToken.name[0]);
				 fprintf(inFile,"%d   %d   %c\n",currentToken.LineofPro=row,currentToken.code,currentToken.name[0]);
				 Token_Number++;
				 break;
		
		case ';':currentToken.code=18;
				 currentToken.name[0]=';';
				 printf("第%d行 %c :   保留符\n",row,currentToken.name[0]);
				 fprintf(inFile,"%d   %d   %c\n",currentToken.LineofPro=row,currentToken.code,currentToken.name[0]);
		    	 Token_Number++;		 
				 break;
        
		case '<':if(ch=='=')
				 {
					 currentToken.code=12;
					 currentToken.name[0]='<';
					 currentToken.name[1]='=';
					 ch=fgetc(sourceFile);
				 }
			     else
				 {
					 currentToken.code=11;
					 currentToken.name[0]='<';
				 }
				 printf("第%d行 %s :   保留符",row,currentToken.name);
				 fprintf(inFile,"%d   %d   %s\n",currentToken.LineofPro=row,currentToken.code,currentToken.name);
				 Token_Number++;
				 break;
		
		case '>':if(ch=='=')
				 {
					 currentToken.code=14;
					 currentToken.name[0]='>';
					 currentToken.name[1]='=';
					 ch=fgetc(sourceFile);
				 }
			     else
				 {
					 currentToken.code=11;
					 currentToken.name[0]='>';
				 }
				 printf("第%d行 %s :   保留符",row,currentToken.name);
		         fprintf(inFile,"%d   %d   %s\n",currentToken.LineofPro=row,currentToken.code,currentToken.name);
				 Token_Number++;
				 break;
		
		case '=':if(ch=='=')
				 {
					 currentToken.code=15;
					 currentToken.name[0]='=';
					 currentToken.name[1]='=';
					 ch=fgetc(sourceFile);		
				 }
			     else
				 {
					 currentToken.code=17;
					 currentToken.name[0]='=';
				 }
				 printf("第%d行 %s :   保留符\n",row,currentToken.name);
		         fprintf(inFile,"%d   %d   %s\n",currentToken.LineofPro=row,currentToken.code,currentToken.name);
				 Token_Number++;
				 break;

		case '!':if(ch=='=')
				 {
					 currentToken.code=16;
					 currentToken.name[0]='!';
					 currentToken.name[1]='=';
				   	 printf("第%d行 %c :   保留符\n",row,currentToken.name);
				     fprintf(inFile,"%d   %d   %s\n",currentToken.LineofPro=row,currentToken.code,currentToken.name);
					 Token_Number++;
					 ch=fgetc(sourceFile);
				 }
	        	else
				{
					printf("第%d行 此处为一个错误!\n",row);
					fprintf(inFile,"%d   %d   %s\n",currentToken.LineofPro=row,currentToken.code=0,currentToken.name);
					Token_Number++;
				}
				break;

		case '(':currentToken.code=20;
			     currentToken.name[0]='(';
				 printf("第%d行 %c :   保留符",row,currentToken.name[0]);
		         fprintf(inFile,"%d   %d   %c\n",currentToken.LineofPro=row,currentToken.code,currentToken.name[0]);
				 Token_Number++;
				 kuahao(ch1);
				 break;

		case ')':currentToken.code=21;
			     currentToken.name[0]=')';
				 printf("第%d行 %c :   保留符",row,currentToken.name[0]);
		         fprintf(inFile,"%d   %d   %c\n",currentToken.LineofPro=row,currentToken.code,currentToken.name[0]);
				 Token_Number++;				 
				 kuahao(ch1);
				 break;

		case '[':currentToken.code=22;
			     currentToken.name[0]='[';
				 printf("第%d行 %c :   保留符",row,currentToken.name[0]);
				 fprintf(inFile,"%d   %d   %c\n",currentToken.LineofPro=row,currentToken.code,currentToken.name[0]);
				 Token_Number++;
				 kuahao(ch1);
				 break;

		case ']':currentToken.code=23;
			     currentToken.name[0]=']';
				 printf("第%d行 %c :   保留符",row,currentToken.name[0]);
		         fprintf(inFile,"%d   %d   %c\n",currentToken.LineofPro=row,currentToken.code,currentToken.name[0]);
				 Token_Number++;
				 kuahao(ch1);
				 break;

		case '{':currentToken.code=24;
			     currentToken.name[0]='{';
				 printf("第%d行 %c :   保留符",row,currentToken.name[0]);
		         fprintf(inFile,"%d   %d   %c\n",currentToken.LineofPro=row,currentToken.code,currentToken.name[0]);
				 Token_Number++;
				 kuahao(ch1);
				 break;
	
		case '}':currentToken.code=25;
			     currentToken.name[0]='}';
				 printf("第%d行 %c :   保留符",row,currentToken.name[0]);
		         fprintf(inFile,"%d   %d   %c\n",currentToken.LineofPro=row,currentToken.code,currentToken.name[0]);
			   	 Token_Number++; 
				 kuahao(ch1);
				 break;
    }
}

/************************************ 主函数*******************************************/
void main()
{
	char filename[20];
	int i,flag=0;

	
	/**********************************初始化************************************/
	if((keyFile=fopen("symble.txt","r"))==NULL)//打开关键字和保留字的文件,把他读入到结构体数组中
	{
		printf("打不开文件symble.txt!\n");
		exit(0);
	}

	if((inFile=fopen("token.txt","w"))==NULL)
	{
		printf("打不开文件token.txt!\n");
		exit(0);
	}

	for(i=1;i<=29;i++)
		fscanf(keyFile,"%d%s",&symbleList[i].code,symbleList[i].name);
	
    
	printf("       *****************************************************************\n");
	printf("                               词法分析器\n");
	printf("       *****************************************************************\n");
   	while(flag==0)
	{ 
		printf("请输入您要分析的文件名称:");
		scanf("%s",filename);//sa.txt
		if((sourceFile=fopen(filename,"r"))==NULL)
		{
			printf("无法打开文件!\n");	
			printf("请输入正确的文件名!\n");
		}
		else
		{
			flag=1;
		}
	}
	ch=fgetc(sourceFile);
	for(i=0;i<20;i++)
		parRight[i]='\0';
	
	while(ch!=EOF)
	{
		if((ch==' ')||(ch=='\t'))
			ch=fgetc(sourceFile);
		if(ch=='\n')
		{
			ch=fgetc(sourceFile);
			row++;//行号加1
		}
		for(i=0;i<30;i++)
			currentToken.name[i]='\0';
		if((ch>47)&&(ch<58))//是否为数字的判定
			IsNumber();
		else 
			if(((ch>64)&&(ch<91))||((ch>96)&&(ch<123)))
				IsAlpha();//是否为字母或字符串的判定
			else
				if(ch=='/')//是否为注释的判定
					IsAnotation();
				else
					IsOther();//是否为保留字的判定
	}
	if(parRight[0]!='\0')//若所有程序都分析完成,数组中仍有括号没有完成匹配,则程序的括号也是不匹配的
	{
		printf("您的程序的括号是不匹配的,请改正错误后在进行词法分析!\n");
	}
	fclose(inFile);
	printf("%d",Token_Number);
}

⌨️ 快捷键说明

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