?? 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 + -