A tabela de símbolos é uma estrutura de dados (hash table, árvore ou aninhamento dessas) usada pelo compilador para armazenar informações sobre cada identificador do programa:
Ela é criada no início da compilação e é consultada e atualizada em várias fases para:
| Fase | Ação sobre a Tabela de Símbolos |
|---|---|
| Análise Léxica | Insere novos tokens de identificador (variáveis, literais) |
| Análise Sintática | Recupera tokens, mas não altera a tabela; auxilia na construção da Árvore de Sintaxe (AST) |
| Análise Semântica | Atualiza atributos (tipo de dado, escopo), checa declarações repetidas ou usos não declarados |
| Geração de Código Intermediário | Consulta escopo e endereço para gerar temporários e instruções de referência a variáveis |
| Otimização | Usa informações de tipos e escopos para eliminar código morto, propagar constantes e outras otimizações |
| Geração de Código Final | Utiliza endereços e atributos para emitir instruções de máquina ou bytecode |
A seguir, um exemplo completo que simula a criação e o uso de tabelas de símbolos em diferentes escopos.
class Symbol:
"""Representa um identificador."""
def __init__(self, name, kind, data_type, scope_level):
self.name = name *# léxico*
self.kind = kind *# 'variable', 'function', 'constant'*
self.data_type = data_type *# 'int', 'float', etc.*
self.scope_level = scope_level
class SymbolTable:
"""Tabela de símbolos com encadeamento de escopos."""
def __init__(self, parent=None):
self.table = {} *# map name -> Symbol*
self.parent = parent *# escopo aninhado*
def insert(self, name, kind, data_type):
"""Insere novo símbolo no escopo atual."""
if name in self.table:
raise Exception(f"Símbolo '{name}' já declarado neste escopo.")
sym = Symbol(name, kind, data_type, self.scope_level())
self.table[name] = sym
return sym
def lookup(self, name):
"""Procura símbolo no escopo atual ou nos ancestrais."""
if name in self.table:
return self.table[name]
if self.parent:
return self.parent.lookup(name)
return None
def scope_level(self):
"""Retorna profundidade do escopo (0 = global)."""
level = 0
cur = self.parent
while cur:
level += 1
cur = cur.parent
return level
def enter_scope(self):
"""Cria e retorna um novo escopo aninhado."""
return SymbolTable(parent=self)
def exit_scope(self):
"""Retorna ao escopo pai."""
return self.parent
def __repr__(self):
syms = ', '.join(self.table.keys())
return f"<Scope level={self.scope_level()} symbols=[{syms}]>"
*# Exemplo de uso:*
if __name__ == "__main__":
*# Escopo global*
global_scope = SymbolTable()
global_scope.insert('x', 'variable', 'int')
global_scope.insert('pi', 'constant', 'float')
print(global_scope)
*# <Scope level=0 symbols=[x, pi]># Entrando em função foo*
foo_scope = global_scope.enter_scope()
foo_scope.insert('y', 'variable', 'int')
foo_scope.insert('x', 'variable', 'float') *# sombreia 'x' global*
print(foo_scope.lookup('x').data_type) *# float*
print(foo_scope.lookup('pi').kind) *# constant*
print(foo_scope)
*# <Scope level=1 symbols=[y, x]># Saindo para escopo global*
back = foo_scope.exit_scope()
print(back)
*# <Scope level=0 symbols=[x, pi]>*
Como funciona o código:
table e ponteiro parent para escopo externo.