📄 symtab.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 + -