class AnalizadorSemantico: def __init__(self, ast): self.ast = ast self.tabla_simbolos = {} self.errores = [] def analizar(self): for nodo in self.ast: self.analizar_instruccion(nodo) return { "variables_declaradas": self.tabla_simbolos, "errores_semanticos": self.errores } def analizar_instruccion(self, nodo): tipo = nodo["type"] if tipo == "declaration": var = nodo["var"] dtype = nodo["datatype"] if var in self.tabla_simbolos: self.errores.append(f"Variable '{var}' ya fue declarada.") else: self.tabla_simbolos[var] = dtype elif tipo == "assign": if nodo["var"] not in self.tabla_simbolos: self.errores.append(f"Variable '{nodo['var']}' usada sin declarar.") return tipo_valor = self.analizar_expresion(nodo["value"]) tipo_var = self.tabla_simbolos[nodo["var"]] if tipo_valor != tipo_var and tipo_valor != "error": self.errores.append(f"Tipo incompatible en asignación a '{nodo['var']}': {tipo_var} = {tipo_valor}") elif tipo in ("if", "while"): tipo_cond = self.analizar_expresion(nodo["condition"]) if tipo_cond != "boolean": self.errores.append( f"La condición de '{tipo}' debe ser tipo boolean, no '{tipo_cond}'" ) for instr in nodo["body"]: self.analizar_instruccion(instr) elif tipo == "function": self.validar_funcion(nodo["name"], nodo["arg"]) else: self.errores.append(f"Instrucción no reconocida: {nodo}") def analizar_expresion(self, expr): tipo = expr["type"] if tipo == "num": return "float" if "." in expr["value"] else "int" elif tipo == "var": nombre = expr["value"] if nombre not in self.tabla_simbolos: self.errores.append(f"Variable '{nombre}' usada sin declarar.") return "error" return self.tabla_simbolos[nombre] elif tipo == "binop": tipo_izq = self.analizar_expresion(expr["left"]) tipo_der = self.analizar_expresion(expr["right"]) if tipo_izq != tipo_der: self.errores.append(f"Tipos incompatibles: {tipo_izq} y {tipo_der}") return "error" if expr["op"] in ("EQUAL", "NOT_EQUAL", "GREATER", "LESS"): return "boolean" return tipo_izq elif tipo == "bool": return "boolean" elif tipo == "string": return "string" else: self.errores.append(f"Expresión no válida: {expr}") return "error" def validar_funcion(self, nombre, arg): funciones_sin_argumento = { "START", "REBOOT", "SHUTDOWN" } funciones_con_argumento = { "MOVE_FORWARD", "MOVE_BACKWARD", "PRINT", "SET", "TOGGLE_LIGHT", "CALIBRATE", "ROTATE", "WAIT", "TURN_LEFT", "TURN_RIGHT", "ACTIVATE_SENSOR", "DEACTIVATE_SENSOR" } if nombre in funciones_sin_argumento: if arg is not None: self.errores.append(f"La función '{nombre}' no debe tener argumentos.") elif nombre in funciones_con_argumento: if arg is None: self.errores.append(f"La función '{nombre}' requiere un argumento.") else: self.analizar_expresion(arg) else: self.errores.append(f"Función '{nombre}' no reconocida.")