先决条件:符号表
符号表是编译器使用的数据结构,程序源代码中的每个标识符都与它的声明相关联的信息一起存储在该表中。它存储标识符及其相关属性,例如范围,类型,出现的行号等。
可以使用各种数据结构来实现符号表,例如:
- 链表
- 哈希表
- 树
用于实现符号表的常见数据结构是HashTable。
符号表的操作–符号表上定义的基本操作包括:
考虑以下C++函数:
// Define a global function
int add(int a, int b)
{
int sum = 0;
sum = a + b;
return sum;
}
上面代码的符号表:
Name | Type | Scope | ||||||
---|---|---|---|---|---|---|---|---|
add | function | global | ||||||
a | int | function parameter | b | int | function parameter | sum | int | local |
以下是使用带有单独链接的散列概念的Symbol Table的C++实现:
// C++ program to implement Symbol Table
#include
using namespace std;
const int MAX = 100;
class Node {
string identifier, scope, type;
int lineNo;
Node* next;
public:
Node()
{
next = NULL;
}
Node(string key, string value, string type, int lineNo)
{
this->identifier = key;
this->scope = value;
this->type = type;
this->lineNo = lineNo;
next = NULL;
}
void print()
{
cout << "Identifier's Name:" << identifier
<< "\nType:" << type
<< "\nScope: " << scope
<< "\nLine Number: " << lineNo << endl;
}
friend class SymbolTable;
};
class SymbolTable {
Node* head[MAX];
public:
SymbolTable()
{
for (int i = 0; i < MAX; i++)
head[i] = NULL;
}
int hashf(string id); // hash function
bool insert(string id, string scope,
string Type, int lineno);
string find(string id);
bool deleteRecord(string id);
bool modify(string id, string scope,
string Type, int lineno);
};
// Function to modify an identifier
bool SymbolTable::modify(string id, string s,
string t, int l)
{
int index = hashf(id);
Node* start = head[index];
if (start == NULL)
return "-1";
while (start != NULL) {
if (start->identifier == id) {
start->scope = s;
start->type = t;
start->lineNo = l;
return true;
}
start = start->next;
}
return false; // id not found
}
// Function to delete an identifier
bool SymbolTable::deleteRecord(string id)
{
int index = hashf(id);
Node* tmp = head[index];
Node* par = head[index];
// no identifier is present at that index
if (tmp == NULL) {
return false;
}
// only one identifier is present
if (tmp->identifier == id && tmp->next == NULL) {
tmp->next = NULL;
delete tmp;
return true;
}
while (tmp->identifier != id && tmp->next != NULL) {
par = tmp;
tmp = tmp->next;
}
if (tmp->identifier == id && tmp->next != NULL) {
par->next = tmp->next;
tmp->next = NULL;
delete tmp;
return true;
}
// delete at the end
else {
par->next = NULL;
tmp->next = NULL;
delete tmp;
return true;
}
return false;
}
// Function to find an identifier
string SymbolTable::find(string id)
{
int index = hashf(id);
Node* start = head[index];
if (start == NULL)
return "-1";
while (start != NULL) {
if (start->identifier == id) {
start->print();
return start->scope;
}
start = start->next;
}
return "-1"; // not found
}
// Function to insert an identifier
bool SymbolTable::insert(string id, string scope,
string Type, int lineno)
{
int index = hashf(id);
Node* p = new Node(id, scope, Type, lineno);
if (head[index] == NULL) {
head[index] = p;
cout << "\n"
<< id << " inserted";
return true;
}
else {
Node* start = head[index];
while (start->next != NULL)
start = start->next;
start->next = p;
cout << "\n"
<< id << " inserted";
return true;
}
return false;
}
int SymbolTable::hashf(string id)
{
int asciiSum = 0;
for (int i = 0; i < id.length(); i++) {
asciiSum = asciiSum + id[i];
}
return (asciiSum % 100);
}
// Driver code
int main()
{
SymbolTable st;
string check;
cout << "**** SYMBOL_TABLE ****\n";
// insert 'if'
if (st.insert("if", "local", "keyword", 4))
cout << " -successfully";
else
cout << "\nFailed to insert.\n";
// insert 'number'
if (st.insert("number", "global", "variable", 2))
cout << " -successfully\n\n";
else
cout << "\nFailed to insert\n";
// find 'if'
check = st.find("if");
if (check != "-1")
cout << "Identifier Is present\n";
else
cout << "\nIdentifier Not Present\n";
// delete 'if'
if (st.deleteRecord("if"))
cout << "if Identifier is deleted\n";
else
cout << "\nFailed to delete\n";
// modify 'number'
if (st.modify("number", "global", "variable", 3))
cout << "\nNumber Identifier updated\n";
// find and print 'number'
check = st.find("number");
if (check != "-1")
cout << "Identifier Is present\n";
else
cout << "\nIdentifier Not Present";
return 0;
}
输出:
**** SYMBOL_TABLE ****
if inserted -successfully
number inserted -successfully
Identifier's Name:if
Type:keyword
Scope: local
Line Number: 4
Identifier Is present
if Identifier is deleted
number Identifier updated
Identifier's Name:number
Type:variable
Scope: global
Line Number: 3
Identifier Is present