Compiler Design and ConstructionUnit 69 min read
Symbol Tables & Storage Management: Structures, Operations & Runtime Allocation
Unit 6 of Compiler Design and Construction covers symbol tables—how they store identifiers, types, and scopes—and runtime storage management techniques (static/dynamic allocation, activation records). Learn data structures (hash tables, BSTs), operations (insertion, lookup), and real-world applications in compilers lik
Core Concepts
1. What is a Symbol Table?
A symbol table is a data structure that stores information about program identifiers (variables, functions, types, etc.) during compilation. It acts as a dictionary mapping names to their attributes (e.g., type, scope, memory address).
Why is a Symbol Table Necessary?
- Compiler Phase Interaction: Used in lexical analysis (storing tokens), syntax analysis (resolving declarations), semantic analysis (type checking), and code generation (memory allocation).
- Error Detection: Detects undeclared variables, duplicate declarations, or type mismatches.
- Optimization: Helps in dead code elimination and constant propagation.
Typical Entries in a Symbol Table
| Field | Description | Example |
|---|---|---|
| Name | Identifier name (e.g., variable/function name) | student_age |
| Type | Data type (int, float, array, struct) | int |
| Scope | Block/level where the symbol is valid (global, local, function-scoped) | global or function scope |
| Address | Memory location (if allocated) | 0x1000 |
| Attributes | Additional info (e.g., const, static, volatile) |
const, mutable |
| Value (if constant) | Initial value (for constants) | 25 (for const int age = 25;) |
2. Data Structures for Symbol Tables
Three common implementations, each with trade-offs:
A. Linear List (Array/Linked List)
- Structure: Simple list where entries are stored sequentially.
- Operations:
- Insertion: (must search entire list).
- Lookup: (linear search).
- Pros: Easy to implement.
- Cons: Inefficient for large tables.
B. Hash Table
- Structure: Uses a hash function to map keys (symbol names) to indices in an array.
- Operations:
- Insertion: average case (with good hash function).
- Lookup: average case.
- Pros: Fast access, scalable.
- Cons: Collisions require chaining/open addressing; memory overhead.
C. Binary Search Tree (BST)
- Structure: Nodes store symbols, ordered by name (lexicographical).
- Operations:
- Insertion: average case (balanced tree).
- Lookup: average case.
- Pros: No collisions, ordered traversal useful for debugging.
- Cons: Slower than hash tables for large datasets; if unbalanced.
Comparison Table
| Data Structure | Insertion | Lookup | Best For | Worst Case |
|---|---|---|---|---|
| Linear List | Small tables | |||
| Hash Table | * | * | Large tables, frequent access | (collisions) |
| BST | Ordered traversal needed | (unbalanced) |
*Assuming good hash function and no collisions.
3. Operations on Symbol Tables
A. Insertion
- Process:
- Check if the symbol already exists (avoid duplicates).
- If not, add the symbol with its attributes.
- Update scope/address if needed.
B. Lookup
- Process:
- Search for the symbol using its name.
- Return its attributes (e.g., type, address).
C. Deletion
- Process:
- Remove the symbol from the table (used in scope exit, e.g., end of a block).
D. Traversal
- Used for debugging or optimization (e.g., printing all variables in scope).
In the Real World
eSewa (Nepal):
- Symbol Table Use: When you book a bill payment, eSewa’s backend compiler/interpreter uses a symbol table to track user sessions, transaction IDs, and payment statuses. Each "user" is a scope, and transactions are symbols with attributes like
amount,status, andtimestamp. - Storage Management: Dynamic allocation ensures temporary variables (e.g.,
temp_total) are freed after use.
- Symbol Table Use: When you book a bill payment, eSewa’s backend compiler/interpreter uses a symbol table to track user sessions, transaction IDs, and payment statuses. Each "user" is a scope, and transactions are symbols with attributes like
Khalti’s Payment Gateway:
- Symbol Table: Stores merchant IDs, API keys, and transaction logs. For example, the symbol
merchant_123might have attributes:{ "name": "merchant_123", "api_key": "sk_abc123", "balance": 50000, "scope": "global" } - Hash Table: Used for lookup of merchant details during payment processing.
- Symbol Table: Stores merchant IDs, API keys, and transaction logs. For example, the symbol
Ncell’s Billing System:
- Activation Records: When a user logs in, a new activation record is created for their session. The symbol table tracks:
user_id,plan_type,remaining_data,expiry_date.
- Dynamic Allocation: Temporary variables (e.g.,
current_usage) are allocated on the stack and freed when the session ends.
- Activation Records: When a user logs in, a new activation record is created for their session. The symbol table tracks:
Worked Example: Symbol Table for a C Program
Consider this C code snippet:
#include <stdio.h>
int global_var = 10; // Global scope
void func1() {
int local_var = 20; // Local to func1
printf("%d", global_var);
}
int main() {
int main_var = 30; // Local to main
func1();
return 0;
}
Symbol Table After Compilation
| Name | Type | Scope | Address | Value |
|---|---|---|---|---|
global_var |
int |
global |
0x1000 |
10 |
local_var |
int |
func1 |
0x2000 |
20 |
main_var |
int |
main |
0x3000 |
30 |
Visualization: Scope Hierarchy
graph TD
A["Global Scope"] --> B["func1 Scope"]
A --> C["main Scope"]
B --> D["local_var"]
C --> E["main_var"]
A --> F["global_var"]Storage Management Techniques
Compilers manage memory for variables using two main approaches:
1. Static Storage Allocation
- Definition: Memory is allocated before program execution (e.g., global variables).
- Example: In C,
int x;is statically allocated. - Pros: Fast access, no runtime overhead.
- Cons: Wastes memory if variables are unused.
2. Dynamic Storage Allocation
- Definition: Memory is allocated during runtime (e.g., local variables, heap allocation).
- Types:
- Stack Allocation: Used for function parameters and local variables (LIFO order).
- Heap Allocation: Used for dynamic memory (e.g.,
mallocin C).
- Pros: Efficient memory usage.
- Cons: Slower access; risk of memory leaks.
Activation Records (Runtime Stack)
- Definition: A data structure that stores information about a function call (e.g., parameters, return address, local variables).
- Example: When
func1()is called in the earlier C program, an activation record is pushed onto the stack:
Activation Tree
- Definition: Represents the nested call hierarchy of functions.
- Example:
Exam Tip
Symbol Table Questions:
- Always draw a table for symbol entries (name, type, scope, address).
- Compare hash tables vs. BSTs in terms of time complexity.
- Explain scope rules (e.g., how
global_varis accessible in all functions).
Storage Management:
- Differentiate static vs. dynamic allocation with examples.
- Draw an activation record for a function call (include parameters, return address, local variables).
- Mention stack vs. heap allocation (e.g., local variables use stack;
mallocuses heap).
Common Pitfalls:
- Don’t confuse symbol table with intermediate code (e.g., three-address code).
- Remember that hash tables can degrade to if collisions are high.
- For activation records, always show the LIFO order in the stack.
Practice Question with Solution
Question:
For the following C code, draw the symbol table and activation tree after func2() is called:
int x = 10;
void func1() {
int y = 20;
func2();
}
void func2() {
int z = 30;
}
Solution:
Symbol Table
| Name | Type | Scope | Address | Value |
|---|---|---|---|---|
x |
int |
global |
0x1000 |
10 |
y |
int |
func1 |
0x2000 |
20 |
z |
int |
func2 |
0x3000 |
30 |
Activation Tree
Stack After func2() Call
Based on the TU BSc CSIT syllabus for Compiler Design and Construction (CSC365), unit 6.
Discussion
Loading…