The symbol table is a critical data structure in the Expresiones compiler that tracks all declared variables, their types, and runtime values. It enables variable resolution, duplicate detection, and semantic analysis.
The Simbolo class represents a single symbol (variable) in the symbol table.From Visitor.py:4-8:
class Simbolo: def __init__(self, nombre, tipo, valor=None): self.nombre = nombre # Variable identifier self.tipo = tipo # Type: 'int', 'float', or 'bool' self.valor = valor # Runtime value (can be None)
Symbols are retrieved during variable references in visitVariable().From Visitor.py:83-88:
def visitVariable(self, ctx): nombre = ctx.ID().getText() if nombre in self.tabla_simbolos: val = self.tabla_simbolos[nombre].valor return val if val is not None else 0 return 0
Process:
1
Extract Variable Name
Get identifier from parse tree context.
2
Search Symbol Table
Check if symbol exists in tabla_simbolos dictionary.
3
Return Value
If found: Return symbol’s valor (or 0 if None)
If not found: Return 0 (masks undeclared variable error)
The current implementation returns 0 for undeclared variables instead of raising an error. This can mask bugs. Consider modifying to:
def visitVariable(self, ctx): nombre = ctx.ID().getText() if nombre not in self.tabla_simbolos: print(f"Error: Variable '{nombre}' no declarada.") return 0 val = self.tabla_simbolos[nombre].valor return val if val is not None else 0
Symbol values are updated during assignments in visitInstrAsig().From Visitor.py:33-42:
def visitInstrAsig(self, ctx): nombre = ctx.asignacion().ID().getText() valor = self.visit(ctx.asignacion().expr()) if nombre in self.tabla_simbolos: self.tabla_simbolos[nombre].valor = valor print(f"Asignación: {nombre} = {valor}") else: print(f"Error: Variable '{nombre}' no declarada.") return valor
Process:
1
Extract Assignment Information
Get variable name and evaluate right-hand expression.
2
Verify Declaration
Check if variable exists in symbol table.
3
Update Value
If variable exists, update its valor attribute.
4
Error Handling
If variable doesn’t exist, report error (but don’t crash).
Example:
int counter = 0;counter = 10;counter = counter + 5;
Goal: Support block-level and function-level scopes.Implementation:
class Visitor(ExpresionesVisitor): def __init__(self): self.scopes = [{}] # Stack of scopes, [0] is global def enterScope(self): self.scopes.append({}) def exitScope(self): self.scopes.pop() def lookup(self, nombre): # Search from innermost to outermost scope for scope in reversed(self.scopes): if nombre in scope: return scope[nombre] return None def declare(self, nombre, simbolo): # Add to current (innermost) scope self.scopes[-1][nombre] = simbolo
Usage:
def visitBloque(self, ctx): self.enterScope() result = self.visitChildren(ctx) self.exitScope() return result
2. Add Type Checking
Goal: Enforce type safety during assignments.Implementation:
def visitInstrAsig(self, ctx): nombre = ctx.asignacion().ID().getText() valor = self.visit(ctx.asignacion().expr()) if nombre not in self.tabla_simbolos: print(f"Error: Variable '{nombre}' no declarada.") return None simbolo = self.tabla_simbolos[nombre] # Type checking if simbolo.tipo == 'int' and not isinstance(valor, int): print(f"Error de Tipo: '{nombre}' es 'int', no se puede asignar {type(valor).__name__}") return None elif simbolo.tipo == 'float' and not isinstance(valor, (int, float)): print(f"Error de Tipo: '{nombre}' es 'float', no se puede asignar {type(valor).__name__}") return None elif simbolo.tipo == 'bool' and not isinstance(valor, bool): print(f"Error de Tipo: '{nombre}' es 'bool', no se puede asignar {type(valor).__name__}") return None simbolo.valor = valor print(f"Asignación: {nombre} = {valor}") return valor
3. Add Symbol Table Inspection
Goal: Provide debugging and inspection capabilities.Implementation:
class Visitor(ExpresionesVisitor): # ... existing code ... def printSymbolTable(self): print("\n=== SYMBOL TABLE ===") print(f"{'Variable':<15} {'Type':<10} {'Value':<15}") print("-" * 40) for nombre, simbolo in self.tabla_simbolos.items(): print(f"{nombre:<15} {simbolo.tipo:<10} {simbolo.valor!s:<15}") print("=" * 40 + "\n")
=== SYMBOL TABLE ===Variable Type Value ----------------------------------------x int 11 y int 10 pi float 3.14 ========================================