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

📄 symtab.cpp

📁 内含源代码和编译实验报告
💻 CPP
字号:
/******************************************************************
** 文件名: symtab.cpp
** 描  述: 这是一个完整的符号表,供语义分析器使用。
******************************************************************/
#include	"globals.h"
#include	"ExternGla"
#include	"scan.h"
#include	"symtab.h"
#include	"myexception.h"
#include	<iomanip>

/*******************************************
**构造函数,将符号表初始化为空。
*******************************************/
Csymboltab::Csymboltab(){
	for(int i=0;i<SIZE;i++)
		hashTable[i]=NULL;
}

/*******************************************
**以下三个函数共同完成符号表的销毁。
**主要采用递归算法。
*******************************************/
Csymboltab::~Csymboltab(){
	for(int i=0;i<SIZE;i++)
		Deletesybtab(hashTable[i]);
}

void Csymboltab::Deletesybtab(struct CBucketListRes* pa_tab){
	if(pa_tab!=NULL){
		Deletesybtab(pa_tab->m_Cnext);
		Deletesybtab2(pa_tab->m_Clines->m_Cnext);
		delete pa_tab;}
}

void Csymboltab::Deletesybtab2(struct CLineListRes* pa_tab2){
	if(pa_tab2!=NULL){
		Deletesybtab2(pa_tab2->m_Cnext);
		delete pa_tab2;}
}

/*****************************************
**给定一个具体的变量,根据变量名在哈希表中找
**到相应的位置。
******************************************/
int Csymboltab::hash(const char * pa_strkey){
	int temp=0;
	int i=0;
	while(pa_strkey[i] != '\0'){
		temp=((temp<<SHIFT)+pa_strkey[i])%SIZE;		//根据符号名执行的一个查找算法。
		i++;}
	return temp;
}

/*******************************************************************
**  向符号表中插入一个变量(或函数名),如果第一次插入该变量,则新建一个哈希表
**    中的结点,否则连在已有结点的后面。
**    变量包括的信息有:变量名,所在行数,是查到的第几个变量,作用域。
**********************************************************************/
void Csymboltab::st_insert(char* pa_strname, char* pa_strScope, TokenType pa_type,
											int pa_ilineno, int pa_iloc){
	try{
		int h=hash(pa_strname);						//为符号在表中找一个位置。
		struct CBucketListRes* l=hashTable[h];
		while((l!=NULL) && (strcmp(pa_strname, l->m_strName)!=0
								|| strcmp(pa_strScope,l->m_strScope)!=0))
			l=l->m_Cnext;							//在该位置查找这个符号。
		if(l==NULL){								//若还没有出现过这个符号,则新建结点。
			l= new CBucketListRes;
			strcpy(l->m_strName,pa_strname);
			l->m_Entype=pa_type;
			l->m_Clines= new CLineListRes;
			l->m_Clines->m_ilineno=pa_ilineno;
			strcpy(l->m_strScope,pa_strScope);
			l->m_Clines->m_Cnext=NULL;
			l->m_imemloc=pa_iloc;
			l->m_Cnext=hashTable[h];				//将新建结点插入链表头。
			hashTable[h]=l;}
		else{										//若已出现过这个符号,则增加计数即可。
			struct CLineListRes *t=l->m_Clines;
			while(t->m_Cnext!=NULL) t=t->m_Cnext;
			t->m_Cnext= new CLineListRes;
			t->m_Cnext->m_ilineno=pa_ilineno;
			t->m_Cnext->m_Cnext=NULL;}
	}
	catch (bad_alloc){										//处理堆分配异常。
		cout<<"Can't be allocated in heap, the programme must be terminated."<<endl;
		exit(1);}
}

/*******************************************************************
**  为goto语句单独实现的重载。
**********************************************************************/
void Csymboltab::st_insert(char* pa_strname, TokenType pa_type,
											int pa_ilineno, int pa_iloc){
	try{
		int h=hash(pa_strname);						//为符号在表中找一个位置。
		struct CBucketListRes* l=hashTable[h];
		while((l!=NULL) && strcmp(pa_strname, l->m_strName)!=0)
			l=l->m_Cnext;							//在该位置查找这个符号。
		if(l==NULL){								//若还没有出现过这个符号,则新建结点。
			l= new CBucketListRes;
			strcpy(l->m_strName,pa_strname);
			l->m_Entype=pa_type;
			l->m_Clines= new CLineListRes;
			l->m_Clines->m_ilineno=pa_ilineno;
			l->m_Clines->m_Cnext=NULL;
			l->m_imemloc=pa_iloc;
			l->m_Cnext=hashTable[h];				//将新建结点插入链表头。
			hashTable[h]=l;}
		else{										//若已出现过这个符号,则增加计数即可。
			struct CLineListRes *t=l->m_Clines;
			while(t->m_Cnext!=NULL) t=t->m_Cnext;
			t->m_Cnext= new CLineListRes;
			t->m_Cnext->m_ilineno=pa_ilineno;
			t->m_Cnext->m_Cnext=NULL;}
	}
	catch (bad_alloc){										//处理堆分配异常。
		cout<<"Can't be allocated in heap, the programme must be terminated."<<endl;
		exit(1);}
}

/******************************************************
**   在符号表中查找一个符号,并返回符号的"内存位置"
*******************************************************/
int Csymboltab::st_lookup(char* pa_strname, char* pa_strScope){
	int h=hash(pa_strname);
	struct CBucketListRes* l=hashTable[h];
	while((l != NULL) && (strcmp(pa_strname, l->m_strName)!=0
								|| strcmp(pa_strScope,l->m_strScope)!=0))
		l=l->m_Cnext;
	if(l==NULL) return -1;
	else return l->m_imemloc;
}
/***************************************************
**为goto语句单独实现的重载。
***************************************************/
int Csymboltab::st_lookup(char* pa_strname){
	int h=hash(pa_strname);
	struct CBucketListRes* l=hashTable[h];
	while((l != NULL) && strcmp(pa_strname, l->m_strName)!=0)
		l=l->m_Cnext;
	if(l==NULL) return -1;
	else return l->m_imemloc;
}

/********************************************************
**  在符号表中查找一个变量,并返回变量的类型。
*********************************************************/
TokenType Csymboltab::st_lookuptype(char* pa_strname,char* pa_strScope){
	int h=hash(pa_strname);
	struct CBucketListRes* l=hashTable[h];
	while((l != NULL) && (strcmp(pa_strname, l->m_strName)!=0
								|| strcmp(pa_strScope,l->m_strScope)!=0)){
		l=l->m_Cnext;}
	if(l==NULL) return ERROR;
	return l->m_Entype;				//返回变量类型。
}

/******************************************************
**  打印符号表。
*****************************************************/
void Csymboltab::printSymtab(void){
	int i;
	cout<<"    Variable Name      Location        Line Numbers"<<endl;
	cout<<"    _____________      ________        ____________"<<endl;
	for(i=0;i<SIZE;++i){
		if(hashTable[i] != NULL){
			struct CBucketListRes* l=hashTable[i];
			while(l != NULL){
				struct CLineListRes *t=l->m_Clines;
				cout<<setw(10)<<right<<l->m_strScope<<"::";
				cout<<setw(15)<<left<<l->m_strName;
				cout<<setw(15)<<left<<l->m_imemloc;
				while(t != NULL){
					cout<<t->m_ilineno<<" ";
					t=t->m_Cnext;}
				cout<<endl;
				l=l->m_Cnext;}
		}
	}
}

⌨️ 快捷键说明

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