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

📄 wordanalyser.c

📁 1.1 引言 1.1.1 设计目的 本次课程设计是在完成一个学期的编译原理课程之后
💻 C
字号:
/******************************************************************************
*模块名:词法分析器
*
*功能:从源程序文件中(文本文件)识别出单词符号,以二元组保存输出
*       
*开始时间:2004.10.8       
*
*修改时间:2004.10.10, 10.12, 10.15, 10.17, 10.29, 11.18
*     
*完成时间:2004.10.17
*
*作者: 邸晓峰,胡彬,宋如强      
*      
*       

*******************************************************************************/

#include "complier.h"

//全局常量
int KEYINDEX[16]={4,14,10,8,5,11,6,3,1,15,12,7,13,2,9,16};		//关键字编码表
char* KEYWORD[16]={"begin","call","do","else","end","for","if","procedure","program","read","step"
						,"then","until","var","while","write"}; //关键字表

//全局变量
char buffer[50];				//预输入缓冲区
char readchar;					//分析时存放读入的新字符
char strToken[21];				//分析时存放构成的单词符号串
								//用户自定义标识符最多20个字符,否则只取前20个
int linenum;					//行数
int searchpoint;				//搜索指示器
FILE* sfp;						//源文件指针
FILE* dfp;						//目的文件指针
DuaDualist Dualist;				//二元式链表

//////////////////////////////////////////////////////////////////////////////////////////////
//此函数初始化各公共变量
void initilize(){
	linenum=1;
	searchpoint=0;
	readchar='\0';
	Dualist.head=(Duatype*)malloc(sizeof(Duatype));		//带头结点
	Dualist.head->index=0;
	Dualist.head->value=NULL;
	Dualist.head->next=NULL;
	Dualist.tail=Dualist.head;
}

//////////////////////////////////////////////////////////////////////////////////////////////
//此函数判断源程序文件是否存在
//存在函数返回true,不存在函数返回false
int isFile(){
	char fname[20];				//源程序文件名
	printf("Please input the name of the source file:");
	scanf("%s",fname);
	sfp=fopen(fname,"r");
	if(sfp==NULL){
		printf("This file does not exit!Please input the name of the source file again!");
		return false;
	}
	else{
		printf("Success!");
		printf("\n");
		return true;
	}
}

////////////////////////////////////////////////////////////////////////////////////////////
//此函数判断readchar读入字符是否为字母
//若是字母,则返回true;否则返回false
int isLetter(char readchar){
	if(readchar>='a' && readchar<='z')
		return true;
	else
		return false;
}

////////////////////////////////////////////////////////////////////////////////////////////
//此函数判断readchar读入字符是否为数字
//若是数字,则返回true;否则返回false
int isDigit(char readchar){
	if(readchar>='0' && readchar<='9')
		return true;
	else
		return false;
}

////////////////////////////////////////////////////////////////////////////////////////////
//此函数清空指定字符缓冲区中已有字符
//参数为缓冲区首地址和缓冲区长度
void Clear(char* strBuffer,int lengthBuffer){
	int i;
	for(i=0;i<lengthBuffer;i++)				//清空strBuffer,以备下次使用
			strBuffer[i]='\0';
}


///////////////////////////////////////////////////////////////////////////////////////////////
//此函数从源程序文件中预输入到缓冲区buffer50
//参数为缓冲区首地址,若源文件读完返回true;未读完而缓冲区满返回false
int BeforehandInput(char* buffer){
	int i=0;
	readchar=fgetc(sfp);
	while(readchar!=EOF && i<50){
		if(readchar>='A' && readchar<='Z'){
			readchar=readchar+32;			//大写字母转化成小写,便于后续处理,源程序中不区分大小写
			buffer[i]=readchar;
			i++;
			readchar=getc(sfp);
		}
		else if(readchar==' ' || readchar=='\t'){	//连续空格只保留一个
			if(buffer[i-1]==' ' || buffer[i-1]=='\n')
				readchar=getc(sfp);
			else{
				buffer[i]=' ';	//制表符转化程空格,便于后续处理
				i++;
				readchar=getc(sfp);
			}
		}
		else{
			buffer[i]=readchar;
			i++;
			readchar=getc(sfp);
		}
	}
	if(i>=50){
		fseek(sfp,-1,SEEK_CUR);
		if(readchar==EOF)	return true;
		else	return false;
	}
	else{
		buffer[i]='\0';			//把EOF转化为'/0'放入缓冲区,作为源文件输入结束的标志
		fclose(sfp);
		return true;
	}
}

//////////////////////////////////////////////////////////////////////////////////////////////
//此函数相当于哈希函数,辅助查询关键字表
//参数为需识别标识符strtoken首字符,返回值为以此字母开头的关键字在关键字表中的起始位置(下标值)
int LocinKEYWORD(char fc){
	switch(fc){
	case 'b':
		return 0;
		break;
	case 'c':
		return 1;
		break;
	case 'd':
		return 2;
		break;
	case 'e':
		return 3;
		break;
	case 'f':
		return 5;
		break;
	case 'g':
	case 'h':
	case 'i':
		return 6;
		break;
	case 'j':
	case 'k':
	case 'l':
	case 'm':
	case 'n':
	case 'o':
	case 'p':
		return 7;
		break;
	case 'q':
	case 'r':
		return 9;
		break;
	case 's':
		return 10;
		break;
	case 't':
		return 11;
		break;
	case 'u':
		return 12;
		break;
	case 'v':
		return 13;
		break;
	case 'w':
		return 14;
		break;
	default:
		return 16;
		break;
	}
}

///////////////////////////////////////////////////////////////////////////////////////////////
//此函数把从缓冲区读入的字符readchar和strToken中字串相拼接
void Concat(){
	char temp[2]={readchar,'\0'};
	strcat(strToken,temp);
}

///////////////////////////////////////////////////////////////////////////////////////////////
//此函数对strToken中字串查找关键字表
//返回值为关键字编码;若不是关键字,返回17
int SearchKey(){
	int start,end,i;
	start=LocinKEYWORD(strToken[0]);
	end=LocinKEYWORD(strToken[0]+1);
	if(start==16)	
		return 17;					//非关键字;
	else
		for(i=start;i<end;i++){				//根据首字符索引查找关键字,提高效率,返回相应编码
			if((strcmp(strToken,KEYWORD[i]))==0)
				return KEYINDEX[i];
		}
	return 17;						//关键表中查不到
}



///////////////////////////////////////////////////////////////////////////////////////////////
//此函数对分析出的单词符号生成二元式结点并插入二元式链表
void Insert(){
	Duatype* temp;
	temp=(Duatype*)malloc(sizeof(Duatype));
	temp->value=(char*)malloc((strlen(strToken)+1)*sizeof(char));
	strcpy(temp->value,strToken);
	temp->next=NULL;
	Dualist.tail->next=temp;
	Dualist.tail=temp;
}

///////////////////////////////////////////////////////////////////////////////////////////////
//此函数清查上一个缓冲区中剩余的字符串或数字串
void CheckLeft(){
	if(isalpha(strToken[0])){
		Insert();
		Dualist.tail->index=SearchKey();
		Clear(strToken,21);
	}
	else if(isdigit(strToken[0])){
		Insert();
		Clear(strToken,21);
		Dualist.tail->index=18;
	}
}

///////////////////////////////////////////////////////////////////////////////////////////////
//此函数为词法分析过程
//参数为缓冲区首地址,生成二元式链表
void WordAnalyse(char* buffer){
	searchpoint=0;
	while(searchpoint<50){
		readchar=buffer[searchpoint];
		searchpoint++;
		if(isLetter(readchar)){
			do{
				if(strlen(strToken)<20)			//用户标识符最多20个字符,多余的略过不读
					Concat();
				if(searchpoint>=50)
					break;
				readchar=buffer[searchpoint];
				searchpoint++;
			}while(isLetter(readchar) || isDigit(readchar));
			if(isLetter(readchar) || isDigit(readchar))
					break;
			searchpoint--;
			Insert();
			Dualist.tail->index=SearchKey();
			Clear(strToken,21);
			
			continue;
		}
		else if(isDigit(readchar)){
			do{
				if(strlen(strToken)<20)			//用户标识符最多20个字符,多余的略过不读
					Concat();
				if(searchpoint>=50)
					break;
				readchar=buffer[searchpoint];
				searchpoint++;
			}while(isDigit(readchar));
			if(isDigit(readchar))
					break;
			searchpoint--;
			Insert();
			Clear(strToken,21);
			Dualist.tail->index=18;
			continue;
		}
		else if(readchar==' '){
			if(searchpoint>=50)
					break;
			else if(isLetter(strToken[0])){
				Insert();
				Dualist.tail->index=SearchKey();
				Clear(strToken,21);
			}
			else if(isDigit(strToken[0])){
				Insert();
				Dualist.tail->index=18;
				Clear(strToken,21);
			}
			else
				continue;					//空格跳过
		}
		else if(readchar=='+'){
			CheckLeft();
			Concat();
			Insert();
			Clear(strToken,21);
			Dualist.tail->index=19;
			if(searchpoint>=50)
					break;
		}
		else if(readchar=='-'){
			CheckLeft();
			Concat();
			Insert();
			Clear(strToken,21);
			Dualist.tail->index=20;
			if(searchpoint>=50)
					break;
		}
		else if(readchar=='*'){
			CheckLeft();
			Concat();
			Insert();
			Clear(strToken,21);
			Dualist.tail->index=21;
			if(searchpoint>=50)
					break;
		}
		else if(readchar=='/'){
			CheckLeft();
			Concat();
			Insert();
			Clear(strToken,21);
			Dualist.tail->index=22;
			if(searchpoint>=50)
					break;
		}
		else if(readchar==':'){
			CheckLeft();
			Concat();
			if(searchpoint>=50)
					break;
			readchar=buffer[searchpoint];
			searchpoint++;
			if(readchar=='='){
				Concat();
				Insert();
				Clear(strToken,21);
				Dualist.tail->index=23;
				if(searchpoint>=50)
					break;
			}
			else{    
				searchpoint--;
			}
		}
		else if(readchar=='='){
			CheckLeft();
			Concat();
			Insert();
			if(strlen(strToken)==2){			//":="
				if(strToken[0]==':')
					Dualist.tail->index=23;
				else if(strToken[0]=='<')		//"<="
					Dualist.tail->index=29;
				else if(strToken[0]=='>')		//">="
					Dualist.tail->index=27;
			}
			else
				Dualist.tail->index=24;			//"="
			Clear(strToken,21);
			if(searchpoint>=50)
					break;
		}
		else if(readchar=='<'){
			CheckLeft();
			Concat();
			if(searchpoint>=50)
					break;
			readchar=buffer[searchpoint];
			searchpoint++;
			if(readchar=='='){					//"<="
				Concat();
				Insert();
				Clear(strToken,21);
				Dualist.tail->index=29;
				if(searchpoint>=50)
					break;
			}
			else if(readchar=='>'){				//"<>"
				Concat();
				Insert();
				Clear(strToken,21);
				Dualist.tail->index=25;
				if(searchpoint>=50)
					break;
			}
			else{								//"<"
				searchpoint--;
				Insert();
				Clear(strToken,21);
				Dualist.tail->index=28;
				if(searchpoint>=50)
					break;
			}
		}
		else if(readchar=='>'){
			CheckLeft();
			Concat();
			if(searchpoint>=50)
					break;
			readchar=buffer[searchpoint];
			searchpoint++;
			if(readchar=='='){						//">="
				Concat();
				Insert();
				Clear(strToken,21);
				Dualist.tail->index=27;
				if(searchpoint>=50)
					break;
			}
			else{   
				searchpoint--;
				Insert();
				if(strlen(strToken)==2)
					Dualist.tail->index=25;			//"<>"
				else
					Dualist.tail->index=26;			//">"
				Clear(strToken,21);
				if(searchpoint>=50)
					break;
			}
		}
		else if(readchar=='('){
			CheckLeft();
			Concat();
			Insert();
			Clear(strToken,21);
			Dualist.tail->index=30;
			if(searchpoint>=50)
					break;
		}
		else if(readchar==')'){
			CheckLeft();
			Concat();
			Insert();
			Clear(strToken,21);
			Dualist.tail->index=31;
			if(searchpoint>=50)
					break;
		}
		else if(readchar==','){
			CheckLeft();
			Concat();
			Insert();
			Clear(strToken,21);
			Dualist.tail->index=32;
			if(searchpoint>=50)
					break;
		}
		else if(readchar==';'){
			CheckLeft();
			Concat();
			Insert();
			Clear(strToken,21);
			Dualist.tail->index=33;
			if(searchpoint>=50)
					break;
		}
		else if(readchar=='.'){
			CheckLeft();
			Concat();
			Insert();
			Clear(strToken,21);
			Dualist.tail->index=34;
			if(searchpoint>=50)
					break;
		}
		else if(readchar=='\n'){
			linenum++;
			CheckLeft();
			strcat(strToken,"newline");
			Insert();
			Clear(strToken,21);
			Dualist.tail->index=35;
			if(searchpoint>=50)
				break;
		}
		else if(readchar=='\0')			//源文件结束标志,结束词法分析
			break;
		else							//非法字符
			printf("Line %d: unknown word.",linenum);
		
	}
}
		
///////////////////////////////////////////////////////////////////////////////////////////////
//此函数为词法分析器
void WordAnalyser(){
	int index=1;
	int flagbuffer=false;			//判断源文件是否读完标志
	char strIndex[10];
	Duatype* p;
	initilize();
	while(!isFile());				//直到正确打开文件 
	while(!flagbuffer){
		flagbuffer=BeforehandInput(buffer);
		WordAnalyse(buffer);
	}
	dfp=fopen("duality.txt","w");
	for(p=Dualist.head->next;p!=NULL;p=p->next){
		itoa(p->index,strIndex,10);
		putc('(',dfp);
		fputs(p->value,dfp);
		putc(',',dfp);
		fputs(strIndex,dfp);
		putc(')',dfp);
		putc('\n',dfp);
	}
	fclose(dfp);
}
		

main()
{
WordAnalyser();
return;
}

⌨️ 快捷键说明

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