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

📄 test.cpp

📁 1.1 引言 1.1.1 设计目的 本次课程设计是在完成一个学期的编译原理课程之后
💻 CPP
📖 第 1 页 / 共 4 页
字号:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <stack>
#include <queue>
#include <ctype.h>
#include "RecurAnalyser.h"

using namespace std;

#define true	1
#define false	0

//全局常量
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* signCache[5];			//保留规约时从符号栈弹出的字符,以便语义分析时使用。

//全局变量

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

Quatype Qualist[100];		//四元式表,不得超过200条四元式
stack<Operand> place;		//变量栈
stack<int> chain;			//回填链栈
stack<int> quad;			//比较运算符栈
stack<int> spro;			//调用子过程时,将该子过程在过程表中的序号保存
queue<Operand> part;		//参数队列
int K;					//临时变量序号
int PC;					//四元式表指针

Duatype WORD;				//读入单词符号
vtable VariableTable;		//变量表
ptable ProcTable;			//过程名表
my_stack ProcStack;			//过程栈,用于查过程名表 
int level;					//当前分析所在过程深度
int	counter;					//变量相对个数
int errflag_prog;
char errtext[19][20];		//错误信息存储区

stack<int> clusterSta;		//状态栈
stack<char*> signSta;		//符号栈
bool isTrue;				//如果语法分析出现错误,则置为false,不再产生四元式。
//PL数组:下标表示产生式编号(为与讲义协调,数组第一个元素不使用),内容表示此产生式右部长度。
int PL[43]={1,2,1,2,3,3,2,2,2,3,5,2,4,4,3,3,3,1,3,3,4,3,1,1,3,1,1,1,3,3,3,3,2,
			3,1,1,3,1,1,1,1,1,1};
//AL数组:第一列表示产生式编号(为与讲义协调,数组第一个元素不使用),第二列存放此产生式左部符号名称。
char AL[43][5]={{'P','L','\0'},{'L','\0'},{'L','\0'},{'L','S','\0'},{'S','\0'},{'S','\0'},
				{'S','\0'},{'S','\0'},{'S','\0'},{'S','\0'},{'S','\0'},{'S','\0'},
				{'S','\0'},{'S','\0'},{'C','\0'},{'T','p','\0'},{'W','d','\0'},
				{'W','\0'},{'F','3','\0'},{'F','2','\0'},{'F','1','\0'},
				{'P','A','R','T','\0'},{'P','A','R','T','\0'},{'T','T','\0'},
				{'I','\0'},{'I','\0'},{'I','D','\0'},{'E','X','P','\0'},{'E','\0'},
				{'E','\0'},{'E','\0'},{'E','\0'},{'E','\0'},{'E','\0'},{'E','\0'},
				{'E','\0'},{'L','E','\0'},{'R','O','P','\0'},{'R','O','P','\0'},
				{'R','O','P','\0'},{'R','O','P','\0'},{'R','O','P','\0'},{'R','O','P','\0'}};
//以下四个数组用于存放LR分析表
///////////////////////////////////////////////////////////////////////////////////////////////
//SL数组与SA数组配合,存放了ACTION表中内容:
//SL数组:下标表示状态号,内容为对应下标所表示的状态在SA数组中从第几行开始。
int SL[85]={0,9,12,21,22,23,24,33,35,44,53,62,64,66,68,70,75,80,81,83,85,87,90,91,96,97,99,100,
		    101,102,111,112,114,119,120,121,124,125,130,131,133,136,137,138,139,141,142,144,147,
			148,150,151,158,163,164,166,167,172,173,178,179,181,186,187,188,189,190,191,192,193,
			198,203,208,209,210,215,220,225,230,233,236,237,238,239,245};
//SA数组:第一列存放单词编码,第二列存放动作。
int SA[246][2]={{4,6},{6,15},{9,17},{11,20},{14,12},{15,13},{16,14},{17,7},{0,0},{5,999},{33,4},
				{0,0},{4,6},{6,15},{9,17},{11,20},{14,12},{15,13},{16,14},{17,7},{0,0},
				{-1,-2},{-1,-3},{-1,-1},{4,6},{6,15},{9,17},{11,20},{14,12},{15,13},{16,14},{17,7},{0,0},
				{23,23},{0,0},{4,6},{6,15},{9,17},{11,20},{14,12},{15,13},{16,14},{17,7},{0,0},
				{4,6},{6,15},{9,17},{11,20},{14,12},{15,13},{16,14},{17,7},{0,0},
				{4,6},{6,15},{9,17},{11,20},{14,12},{15,13},{16,14},{17,7},{0,0},
				{10,29},{0,0},{17,31},{0,0},{30,39},{0,0},{30,46},{0,0},
				{17,72},{18,73},{20,70},{30,71},{0,0},{17,72},{18,73},{20,70},{30,71},{0,0},
				{-1,-17},{13,56},{0,0},{12,58},{0,0},{17,60},{0,0},{5,22},{33,4},{0,0},
				{-1,-4},{17,72},{18,73},{20,70},{30,71},{0,0},{-1,-5},{8,26},{-1,-6},{-1,-15},{-1,-7},
				{-1,-8},{4,6},{6,15},{9,17},{11,20},{14,12},{15,13},{16,14},{17,7},{0,0},
				{-1,-9},{30,32},{-1,-11},{17,72},{18,73},{20,70},{30,71},{0,0},{-1,-22},
				{-1,-23},{31,36},{32,37},{0,0},{-1,-10},{17,72},{18,73},{20,70},{30,71},{0,0},
				{-1,-21},{17,42},{0,0},{31,43},{32,44},{0,0},{-1,-25},{-1,-26},{-1,-12},{17,42},
				{0,0},{-1,-24},{17,42},{0,0},{31,48},{32,44},{0,0},{-1,-13},{7,50},{0,0},
				{-1,-14},{24,63},{25,64},{26,65},{27,66},{28,67},{29,68},{0,0},{17,72},{18,73},{20,70},{30,71},{0,0},
				{-1,-36},{10,55},{0,0},{-1,-16},{17,72},{18,73},{20,70},{30,71},{0,0},
				{-1,-18},{17,72},{18,73},{20,70},{30,71},{0,0},{-1,-19},{23,61},{0,0},
				{17,72},{18,73},{20,70},{30,71},{0,0},{-1,-20},{-1,-37},{-1,-38},{-1,-39},
				{-1,-40},{-1,-41},{-1,-42},{19,74},{20,75},{21,76},{22,77},{-1,-27},
				{17,72},{18,73},{20,70},{30,71},{0,0},{17,72},{18,73},{20,70},{30,71},{0,0},
				{-1,-34},{-1,-35},{17,72},{18,73},{20,70},{30,71},{0,0},{17,72},{18,73},{20,70},{30,71},{0,0},
				{17,72},{18,73},{20,70},{30,71},{0,0},{17,72},{18,73},{20,70},{30,71},{0,0},
				{21,76},{22,77},{-1,-28},{21,76},{22,77},{-1,-29},{-1,-30},{-1,-31},{-1,-32},
				{19,74},{20,75},{21,76},{22,77},{31,84},{0,0},{-1,-33}};
///////////////////////////////////////////////////////////////////////////////////////////////
//NL数组与GL数组配合,存放GOTO表中内容:
//NL数组:下标表示产生式编号(为与讲义协调,数组第一个元素不使用),内容表示此产生式左部非终结符
//		  在GOTO表中从GL数组的第几行开始。
int NL[43]={-1,0,0,2,3,3,3,3,3,3,3,3,3,3,9,10,11,12,13,14,15,16,16,17,19,19,21,23,31,31,31,
			31,31,31,31,31,38,40,40,40,40,40,40};
//GL数组:第一列存放原状态,第二列存放下一状态。
int GL[41][2]={{0,1},{-1,21},{-1,2},{2,5},{8,25},{9,27},{10,28},{29,30},{-1,3},{-1,8},{-1,9},
				{-1,10},{-1,16},{-1,11},{-1,18},{-1,19},{-1,35},{32,33},{-1,38},{39,40},{-1,47},
				{44,45},{-1,41},{23,24},{32,34},{37,34},{52,53},{56,57},{58,59},{61,62},{-1,51},
				{70,82},{71,83},{74,78},{75,79},{76,80},{77,81},{-1,69},{15,49},{-1,54},{-1,52}};
//////////////////////////////////////////////////////////////////////////////////////////////
//此函数初始化各公共变量
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;
}

//////////////////////////////////////////////////////////////////////////////////////////////
//此函数从二元式链表中读出一个单词符号,放入WORD中
void getWord(){
	Duatype* temp;
	if(Dualist.head->next==NULL){		//二元式链表读完,WORD.index=0作为标志
		WORD.index=0;
		Dualist.tail=Dualist.head;
	}
	else{
		temp=Dualist.head->next;
		Dualist.head->next=temp->next;		//从链表中删除已读二元式
		while(temp->index==35){
			linenum++;
			free(temp);
			temp=Dualist.head->next;
			if(temp==NULL)
				break;
			Dualist.head->next=temp->next;
		}
		if(temp==NULL){		//二元式链表读完,WORD.index=0作为标志
			WORD.index=0;
			Dualist.tail=Dualist.head;
		}
		else{
			WORD.value=(char*)malloc((strlen(temp->value)+1)*sizeof(char));
			strcpy(WORD.value,temp->value);			//读入单词所在二元式
			WORD.index=temp->index;
			free(temp);							//释放已读二元式空间
		}
	}
}
//////////////////////////////////////////////////////////////////////////////////////////////
//此函数判断源程序文件是否存在
//存在函数返回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!\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';
}


///////////////////////////////////////////////////////////////////////////////////////////////
//此函数从源程序文件中预输入到缓冲区buffer(buffer1和buffer2配合使用)
//参数为缓冲区首地址,若源文件读完返回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;

⌨️ 快捷键说明

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