今天实现的是符号表,符号表用于把脚本中的符号和值对应起来,在脚本运行过程中,解释器会对符号表进行添加,查询和修改
在数字电路中,我们暂时认为一个变量就是一根线或者是它上边的节点,这个变量的值就代表了电平,可以简单的定义为三种情况:H,L,和未定义也就是高阻
为了方便查询,我们设定一个查询接口,只要输入一个变量名称就会得到对应的值,至于怎么得到的,对于外部是不可见的
设计一个修改接口,当输入变量名和数值时,就会修改或者创建对应的变量符号
类的设计如下:
//src/SyntacticAnalyzer/SymbolList.h
#ifndef SYMBOLLIST_H
#define SYMBOLLIST_H
#include "../../public/ErrorDefine.h"
#include <string>
using namespace std;
class SymbolInfo{
public:
SymbolInfo(){Next=NULL;};
string SymbolName; //符号名称
int Value; //符号值
SymbolInfo *Next; //下一个节点指针,如果为NULL表示链表结束
private:
};
class SymbolList{ //符号表,使用链表形式处理数据
public:
SymbolList(){FirstSymbol=NULL;};//初始化
~SymbolList(); //用析构函数删除子链
int AddSymbol(string _SymbolName,int _Value=0x2); //添加符号
int UpdSymbol(string _SymbolName,int _Value); //修改数据
int GetSymbol(string _SymbolName,int& _Value); //取得符号对应的数值
private:
SymbolInfo *FirstSymbol; //指向符号表第一个元素
};
#endif
来分析一下这个实现过程:
符号表同样是通过链表来实现,链表元素是SymbolInfo,SymbolList存储了链表元素的开头指针,SymbolList的析构函数负责释放链表空间
AddSymbol函数有个默认的0x2这个是未定义的默认值,表示为不确定值,也就是高阻态
所有的函数返回值都是错误值,取得的变量值需要用_Value来接收
//src/SyntacticAnalyzer/SymbolList.cpp
#include "SymbolList.h"
SymbolList::~SymbolList(){ //使用析构函数释放空间
SymbolInfo *_FirstSymbol;
while(0!=FirstSymbol){
_FirstSymbol=FirstSymbol->Next;
try{
delete FirstSymbol;
}
catch(int ErrorID){
throw ERROR_DELETE;
}
FirstSymbol=_FirstSymbol;
}
}
int SymbolList::AddSymbol(string _SymbolName,int _Value){ //_Value有默认值3,表示未定义
SymbolInfo *_FirstSymbol;
_FirstSymbol=FirstSymbol;
int _Value_tmp;
if(GetSymbol(_SymbolName,_Value_tmp)==0){ //返回不等于3则表示存在元素
return ERROR_SYMBOLEXIST;
}
try{
FirstSymbol=new SymbolInfo;
}
catch(int ErrorID){
return ERROR_NEW;
}
FirstSymbol->Next =_FirstSymbol;
FirstSymbol->SymbolName=_SymbolName;
if(_Value<0 || _Value>2){
_Value=2; //如果赋予的值无效,就将值写成未定义
}
FirstSymbol->Value=_Value;
return 0;
}
int SymbolList::GetSymbol(string _SymbolName,int& _Value){ //返回符号对应的数值
SymbolInfo *_SymbolPointer;
_SymbolPointer=FirstSymbol;
while(_SymbolPointer!=0){
if(_SymbolPointer->SymbolName==_SymbolName){
_Value=_SymbolPointer->Value;
return 0;
}
_SymbolPointer=_SymbolPointer->Next;
}
return ERROR_SYMBOLNOTEXIST;
}
int SymbolList::UpdSymbol(string _SymbolName,int _Value){
int _Return=0;
int _Valuex=0;
if(ERROR_SYMBOLNOTEXIST==GetSymbol(_SymbolName,_Valuex)){ //如果不存在符号就添加一个
if(_Return=AddSymbol(_SymbolName,_Value)){
return _Return;
}
return 0;
}
SymbolInfo *_SymbolPointer;
_SymbolPointer=FirstSymbol;
while(_SymbolPointer!=0){
if(_SymbolPointer->SymbolName==_SymbolName){
_SymbolPointer->Value=_Value;
return 0;
}
_SymbolPointer=_SymbolPointer->Next;
}
return ERROR_NOTDEFINE; //这里实际上是多余的返回
}
实现的方法就是从开头开始依次进行查询函数名,若函数名相同就进行对应的操作
需要注意的是,调用UpdSymbol时,如果符号不存在,就会自己创建一个
这个表的实现和数据栈实现很相似,只是接口和功能不同
对应的错误编号在(零)中说明了
接下来是对代码进行测试:
//main.cpp
#include <iostream>
#include <string>
using namespace std;
int main(){
SymbolList _Symbol_List; //创建一个对象
_Symbol_List.UpdSymbol("Var1",1);
_Symbol_List.AddSymbol("Var2",2);
int _Value=0;
_Symbol_List.GetSymbol("Var1",_Value);
cout << "Var1=" << _Value;
_Symbol_List.GetSymbol("Var2",_Value);
cout << "Var2=" << _Value;
return 0;
}
可以看到打印出了对应的值,初步认为通过测试了。