if (x > 5 { // Erro: Falta fechar parênteses
print("Maior que 5");
}
int x = "texto"; // Erro: Tipo incompatível
y = 10; // Erro: Variável não declarada
int x = 10;
x = "texto"; // Erro detectado na compilação
x = 10
x = "texto" # Permitido, tipo mudou dinamicamente
int a = 5;
boolean b = true;
int c = a + b; // Erro: Não pode somar int e boolean
int x = 10;
y = x + 5; // Erro: 'y' não foi declarada
void func(int x, String y) { ... }
func("texto", 10); // Erro: ordem de tipos invertida
int contador = 0;
String contador = "abc"; // Erro: redeclaração
class TabelaSimbolos:
def __init__(self, pai=None):
self.tabela = {}
self.pai = pai # Tabela do escopo pai (externo)
def inserir(self, nome, tipo, categoria="variavel"):
self.tabela[nome] = {
'tipo': tipo,
'categoria': categoria,
}
def buscar(self, nome):
# Busca primeiro na tabela atual
if nome in self.tabela:
return self.tabela[nome]
# Se não encontrar e tiver tabela pai, busca lá
elif self.pai:
return self.pai.buscar(nome)
# Não encontrou em nenhum lugar
return None
def novo_escopo(self):
# Cria nova tabela com esta como pai
return TabelaSimbolos(self)
int i = 5;
double d = i; // Coerção int → double
// Com tipo explícito
int x = 10;
// Com inferência de tipo
var x = 10; // O compilador infere que x é int
int a = 5;
double b = 3.14;
double c = a + b; // OK: int + double → double
String s1 = "Olá";
String s2 = "Mundo";
String s3 = s1 + s2; // OK: concatenação
if (a > 3) { // OK: comparação int com int
a = a * 2;
}
int x = 10;
boolean y = true;
int z = x + y; // ERRO: int + boolean
String s = "texto";
if (s) { // ERRO: string em contexto booleano
// ...
}
int valor = calcular(); // ERRO: função não declarada
class Simbolo:
def __init__(self, nome, tipo, categoria, escopo):
self.nome = nome
self.tipo = tipo
self.categoria = categoria # 'variavel', 'funcao', etc.
self.escopo = escopo
self.parametros = [] # para funções
class TabelaSimbolos:
def __init__(self):
self.escopos = [{}] # Pilha de escopos, começa com escopo global
def entrar_escopo(self):
self.escopos.append({}) # Adiciona novo escopo
def sair_escopo(self):
if len(self.escopos) > 1:
self.escopos.pop() # Remove escopo atual
def inserir(self, simbolo):
self.escopos[-1][simbolo.nome] = simbolo
def buscar(self, nome):
# Busca do escopo mais interno para o mais externo
for escopo in reversed(self.escopos):
if nome in escopo:
return escopo[nome]
return None # Símbolo não encontrado
def verificar_expressao(no, tabela_simbolos):
"""Verifica tipos em uma expressão e retorna seu tipo."""
if no.tipo_no == "LITERAL":
# Retorna o tipo do literal (int, float, string, etc.)
return inferir_tipo_literal(no.valor)
elif no.tipo_no == "ID":
# Busca o símbolo na tabela
simbolo = tabela_simbolos.buscar(no.nome)
if simbolo is None:
erro(f"Variável {no.nome} não declarada")
return "erro"
return simbolo.tipo
elif no.tipo_no == "OPERACAO_BINARIA":
# Verifica o tipo de cada operando
tipo_esq = verificar_expressao(no.esquerda, tabela_simbolos)
tipo_dir = verificar_expressao(no.direita, tabela_simbolos)
# Verifica compatibilidade dos tipos com o operador
return verificar_compatibilidade(
tipo_esq, tipo_dir, no.operador)
def verificar_compatibilidade(tipo1, tipo2, operador):
"""Verifica se os tipos são compatíveis com o operador."""
if "erro" in (tipo1, tipo2):
return "erro" # Propaga erros anteriores
if operador in ("+", "-", "*", "/"):
if tipo1 == "int" and tipo2 == "int":
return "int"
elif tipo1 in ("int", "float") and tipo2 in ("int", "float"):
return "float"
else:
erro(f"Operador {operador} incompatível com {tipo1} e {tipo2}")
return "erro"
elif operador in (">", "<", ">=", "<=", "==", "!="):
if tipo1 == tipo2:
return "boolean"
elif tipo1 in ("int", "float") and tipo2 in ("int", "float"):
return "boolean"
else:
erro(f"Comparação incompatível entre {tipo1} e {tipo2}")
return "erro"
# AST para a expressão
{
"tipo_no": "OPERACAO_BINARIA",
"operador": "+",
"esquerda": {
"tipo_no": "ID",
"nome": "a"
},
"direita": {
"tipo_no": "OPERACAO_BINARIA",
"operador": "*",
"esquerda": {
"tipo_no": "ID",
"nome": "b"
},
"direita": {
"tipo_no": "OPERACAO_BINARIA",
"operador": "-",
"esquerda": {
"tipo_no": "ID",
"nome": "c"
},
"direita": {
"tipo_no": "LITERAL",
"valor": 5
}
}
}
}
def processar_declaracao(no, tabela):
"""Processa uma declaração e insere o símbolo na tabela."""
if no.tipo_no == "DECLARACAO_VARIAVEL":
nome = no.nome
tipo = no.tipo
# Verificar se já existe no escopo atual
if tabela.buscar_escopo_atual(nome):
erro(f"Variável '{nome}' já declarada neste escopo")
return False
# Criar e inserir o símbolo
simbolo = Simbolo(nome, tipo, "variavel", len(tabela.escopos) - 1)
tabela.inserir(simbolo)
# Se tiver inicialização, verificar compatibilidade
if no.inicializacao:
tipo_expr = verificar_expressao(no.inicializacao, tabela)
if not tipos_compativeis(tipo, tipo_expr):
erro(f"Tipo incompatível na inicialização de '{nome}'")
return False
return True
int main() {
int x = 10;
boolean flag = true;
// Erro semântico: tipos incompatíveis
int resultado = x + flag;
return 0;
}
Erro semântico na linha 5:
Operador '+' incompatível entre tipos 'int' e 'boolean'
void exemplo() {
int a = 5;
int b = 10;
float c = a / b;
if (a > b) {
string mensagem = "a é maior";
print(mensagem);
} else {
int a = 20; // Redeclaração de 'a'
print(a + b);
}
print(mensagem); // Erro: fora de escopo
}
def verificar_atribuicao(no, tabela):
"""
Verifica se uma atribuição é válida semanticamente.
no: Nó da árvore que representa a atribuição
(contém campos 'variavel' e 'expressao')
tabela: Tabela de símbolos atual
Retorna True se válido, False caso contrário
"""
# Seu código aqui
# 1. Verificar se a variável existe
# 2. Obter seu tipo
# 3. Verificar o tipo da expressão à direita
# 4. Verificar compatibilidade
# 5. Retornar resultado