Symbol Table In C++

In this article, you will learn about the symbol table in C++.

Compiler Design symbol table

In order to store information on the existence of different entities , such as variable and function names, objects and classes , etc., the compiler builds and maintains a data structure. Symbol tables are one class of data structure.

C++ code for symbol table entry:

Example:

Example

#include <iostream>
#include <unordered_map>
#include <vector>

class SymbolTableEntry {
public:
std::string name;
std::string dataType;
std::string scope;

SymbolTableEntry(const std::string& n, const std::string& dt, const std::string&sc)
        : name(n), dataType(dt), scope(sc) {}
};

class SymbolTable {
public:
    void insert(constSymbolTableEntry& entry) {
entries.push_back(entry);
    }

SymbolTableEntry* lookup(const std::string& name) {
        for (auto&entry : entries) {
            if (entry.name == name) {
                return &entry;
            }
        }
        return nullptr;
    }

private:
std::vector<SymbolTableEntry> entries;
};

int main() {
SymbolTablesymbolTable;

symbolTable.insert(SymbolTableEntry("A", "int", "P1"));
symbolTable.insert(SymbolTableEntry("B", "int", "P1"));
symbolTable.insert(SymbolTableEntry("C", "int", "P1 inner block"));
symbolTable.insert(SymbolTableEntry("D", "int", "P1 inner block"));
symbolTable.insert(SymbolTableEntry("E", "int", "P1"));
symbolTable.insert(SymbolTableEntry("F", "int", "P1 inner block"));
symbolTable.insert(SymbolTableEntry("G", "int", "P1 inner block"));
symbolTable.insert(SymbolTableEntry("H", "int", "P2"));
symbolTable.insert(SymbolTableEntry("I", "int", "P2"));
symbolTable.insert(SymbolTableEntry("J", "int", "P2 inner block"));
symbolTable.insert(SymbolTableEntry("K", "int", "P2 inner block"));
symbolTable.insert(SymbolTableEntry("L", "int", "P2"));

SymbolTableEntry* entryA = symbolTable.lookup("A");
    if (entryA) {
std::cout<< "Found symbol A in the symbol table." <<std::endl;
    } else {
std::cout<< "Symbol A not found in the symbol table." <<std::endl;
    }

SymbolTableEntry* entryX = symbolTable.lookup("X");
    if (entryX) {
std::cout<< "Found symbol X in the symbol table." <<std::endl;
    } else {
std::cout<< "Symbol X not found in the symbol table." <<std::endl;
    }

    return 0;
}

Output:

Output

Found symbol A in the symbol table.
Symbol X not found in the symbol table.

Symbol table operations

There are several symbol table operations in C++. Some main symbol table operations in C++ are as follows:

Operate on the Symbol table.

A symbol table can use the Allocate Operation to allocate a brand-new, empty symbol table.

Operation Insert on the Symbol table

A symbol table's Insert Operation can be used to insert a name and return a pointer to the entry.

Operation Set_attribute on the Symbol table

Set_attribute is a symbol table that can be operated on to associate an attribute with a specific entry.

Operation Get_attribute on the Symbol table

Get_attribute is a symbol table that can be operated on to obtain an attribute connected to a specific entry.

Operation of Lookup on the Symbol Table

Lookup An operation on a symbol table can be used to look for a name and return a pointer to its entry.

Free Operation on the Symbol table

A symbol table's storage can be freed up by performing a Free Operation to remove every entry. On the symbol table, additional actions can be carried out in a similar manner to remove operations.

Deployment of the Symbol table

It is possible to implement symbol tables using a variety of data structure methods. The following techniques are listed:

  • LinkedList
  • Hash Table
  • Tree

Implementation of symbol tables in C++ using hashing:

Example

// Symbol Table implementation in C++ 

#include <iostream>
using namespace std; 

const int MAXIMUM = 200; 

class Node { 

	string identifier, scope, type; 
	int Line_Number; 
	Node* next_Node; 

public: 
	Node() 
	{ 
		next_Node = NULL; 
	} 

	Node(string key, string value, string type, int Line_Number) 
	{ 
		this->identifier = key; 
		this->scope = value; 
		this->type = type; 
		this->Line_Number = Line_Number; 
		next_Node = NULL; 
	} 

	void print() 
	{ 
		cout<< "Identifier's Name:" << identifier 
			<< "\nType:" << type 
			<< "\nScope: " << scope 
			<< "\nLine Number: " <<Line_Number<<endl; 
	} 
	friend class SymbolTable; 
}; 

class SymbolTable { 
	Node* header[MAXIMUM]; 

public: 
	SymbolTable() 
	{ 
		for (int i = 0; i< MAXIMUM; i++) 
			header[i] = NULL; 
	} 

	int hashf(string id); // hash function 
	bool JavaCppTutorial_insertion(string id, string scope, 
				string Type, int Line_Number); 

	string JavaCppTutorial_search(string id); 

	bool deleteRecord(string id); 

	bool modify(string id, string scope, 
				string Type, int Line_Number); 
}; 

// Identifyer modification function 

bool SymbolTable::modify(string id, string s, 
						string t, int l) 
{ 
	int index = hashf(id); 
	Node* start = header[index]; 

	if (start == NULL) 
		return "-1"; 

	while (start != NULL) { 
		if (start->identifier == id) { 
			start->scope = s; 
			start->type = t; 
			start->Line_Number = l; 
			return true; 
		} 
		start = start->next_Node; 
	} 

	return false; // id not found 
} 

// Delete an identifier function

bool SymbolTable::deleteRecord(string id) 
{ 
	int index = hashf(id); 
	Node* JavaCppTutorial_Temporary_Variable = header[index]; 
	Node* par = header[index]; 

	// There is no identifier at that index. 

	if (JavaCppTutorial_Temporary_Variable == NULL) { 
		return false; 
	} 
	// There is only one identifier. 

	if (JavaCppTutorial_Temporary_Variable->identifier == id &&JavaCppTutorial_Temporary_Variable->next_Node == NULL) { 
		JavaCppTutorial_Temporary_Variable->next_Node = NULL; 
		delete JavaCppTutorial_Temporary_Variable; 
		return true; 
	} 

	while (JavaCppTutorial_Temporary_Variable->identifier != id &&JavaCppTutorial_Temporary_Variable->next_Node != NULL) { 
		par = JavaCppTutorial_Temporary_Variable; 
		JavaCppTutorial_Temporary_Variable = JavaCppTutorial_Temporary_Variable->next_Node; 
	} 
	if (JavaCppTutorial_Temporary_Variable->identifier == id &&JavaCppTutorial_Temporary_Variable->next_Node != NULL) { 
		par->next_Node = JavaCppTutorial_Temporary_Variable->next_Node; 
		JavaCppTutorial_Temporary_Variable->next_Node = NULL; 
		delete JavaCppTutorial_Temporary_Variable; 
		return true; 
	} 

	// remove the conclusion
	else { 
		par->next_Node = NULL; 
		JavaCppTutorial_Temporary_Variable->next_Node = NULL; 
		delete JavaCppTutorial_Temporary_Variable; 
		return true; 
	} 
	return false; 
} 

// JavaCppTutorial_search identifier function 

string SymbolTable::JavaCppTutorial_search(string id) 
{ 
	int index = hashf(id); 
	Node* start = header[index]; 

	if (start == NULL) 
		return "-1"; 

	while (start != NULL) { 

		if (start->identifier == id) { 
			start->print(); 
			return start->scope; 
		} 

		start = start->next_Node; 
	} 

	return "-1"; // not found 
} 

// JavaCppTutorial_insertion function for an identifier  
bool SymbolTable::JavaCppTutorial_insertion(string id, string scope, 
						string Type, int Line_Number) 
{ 
	int index = hashf(id); 
	Node* p = new Node(id, scope, Type, Line_Number); 

	if (header[index] == NULL) { 
		header[index] = p; 
		cout<< "\n"
			<< id << " insertion"; 

		return true; 
	} 

	else { 
		Node* start = header[index]; 
		while (start->next_Node != NULL) 
			start = start->next_Node; 

		start->next_Node = p; 
		cout<< "\n"
			<< id << " insertion"; 

		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); 
} 
int main() 
{ 
	SymbolTablest; 
	string check; 
	cout<< "**** SYMBOL_TABLE ****\n"; 

	if (st.JavaCppTutorial_insertion("if", "local", "keyword", 4)) 
		cout<< " -successfully"; 
	else
		cout<< "\nFailed to JavaCppTutorial_insertion.\n"; 

	if (st.JavaCppTutorial_insertion("number", "global", "variable", 2)) 
		cout<< " -successfully\n\n"; 
	else
		cout<< "\nFailed to JavaCppTutorial_insertion\n"; 

	check = st.JavaCppTutorial_search("if"); 
	if (check != "-1") 
		cout<< "Identifier Is present\n"; 
	else
		cout<< "\nIdentifier Not Present\n"; 

	if (st.deleteRecord("if")) 
		cout<< "if Identifier is deleted\n"; 
	else
		cout<< "\nFailed to delete\n"; 

	if (st.modify("number", "global", "variable", 3)) 
		cout<< "\nNumber Identifier updated\n"; 

	check = st.JavaCppTutorial_search("number"); 
	if (check != "-1") 
		cout<< "Identifier Is present\n"; 
	else
		cout<< "\nIdentifier Not Present"; 
	return 0; 
}

Output:

Output

**** SYMBOL_TABLE ****

if insertion -successfully
number insertion -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

Conclusion:

The symbol table is a crucial tool for language processing systems which provides the essential infrastructure to manage the complicated semantics and behavior of identifiers in C programs. It is essential to make sure the code is executed correctly and efficiently.

Input Required

This code uses input(). Please provide values below: