FUNCIONES_VALIDAS = { "ACTIVATE_ALARM": "Activa la alarma del robot", "ACTIVATE_SENSOR": "Activa el sensor del robot", "BREAK": "Interrumpe el ciclo actual", "CHARGE_BATTERY": "Inicia la carga de batería del robot", "CHECK_BATTERY": "Verifica el nivel de batería", "CLOSE_DOOR": "Cierra la puerta del robot", "CONTINUE": "Continúa al siguiente ciclo", "DEACTIVATE_ALARM": "Desactiva la alarma", "DEACTIVATE_SENSOR": "Desactiva el sensor", "DECREASE_SPEED": "Disminuye la velocidad actual", "DOWNLOAD": "Inicia la descarga de datos", "REBOOT": "Reinicia el sistema del robot", "READ_SENSOR": "Lee un sensor", "RESET": "Reinicia las configuraciones", "RESUME": "Reanuda la ejecución previa", "REVERSE": "Invierte el sentido de movimiento", "SHUTDOWN": "Apaga el sistema del robot", "SHUT_OFF": "Desconecta inmediatamente", "START": "Inicia el programa principal", "STOP": "Detiene el movimiento actual", "STOP_IMMEDIATELY": "Frena inmediatamente", "TOGGLE_LIGHT": "Cambia el estado de la luz", "TURN_DOWN": "Inclina hacia abajo", "TURN_LEFT": "Gira a la izquierda", "TURN_RIGHT": "Gira a la derecha", "TURN_UP": "Inclina hacia arriba", "UNLOCK": "Desbloquea el acceso", "LOG": "Registra una entrada en el log", "INIT": "Inicializa el sistema", "LOCK": "Bloquea el acceso", "LOW_BATTERY": "Indica batería baja", "OPEN_DOOR": "Abre la puerta", "PAUSE": "Pausa temporal del programa", "CALIBRATE": "Calibra un sensor o componente", "COPY_FILE": "Copia un archivo en el sistema", "DELETE_FILE": "Elimina un archivo del sistema", "MOVE_BACKWARD": "El robot se moverá hacia atrás", "MOVE_FORWARD": "El robot se moverá hacia adelante", "MOVE_TO": "El robot se moverá a una posición específica", "PRINT": "Imprime un mensaje en pantalla", "RENAME_FILE": "Cambia el nombre de un archivo", "ROTATE": "Gira en su eje cierto número de grados", "SAVE_FILE": "Guarda información en un archivo", "SCAN": "Escanea el entorno", "SET": "Establece una variable o configuración", "SET_SPEED": "Establece una nueva velocidad", "UPLOAD": "Sube información al servidor", "UPLOAD_FILE": "Sube un archivo al servidor", "WAIT": "Hace una pausa durante X tiempo" } class AnalizadorSemantico: def __init__(self, ast): self.ast = ast self.tabla_simbolos = {} self.errores = [] self.anotaciones = [] def analizar(self): for nodo in self.ast: self.analizar_instruccion(nodo) return { "variables_declaradas": self.tabla_simbolos, "errores_semanticos": self.errores, "anotaciones": self.anotaciones } 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): if nombre not in FUNCIONES_VALIDAS: self.errores.append(f"Función '{nombre}' no reconocida.") return descripcion = FUNCIONES_VALIDAS[nombre] self.anotaciones.append(f"{nombre}: {descripcion}") funciones_sin_argumento = { "ACTIVATE_ALARM", "ACTIVATE_SENSOR", "BREAK", "CHARGE_BATTERY", "CHECK_BATTERY", "CLOSE_DOOR", "CONTINUE", "DEACTIVATE_ALARM", "DEACTIVATE_SENSOR", "DECREASE_SPEED", "DOWNLOAD", "REBOOT", "READ_SENSOR", "RESET", "RESUME", "REVERSE", "SHUTDOWN", "SHUT_OFF", "START", "STOP", "STOP_IMMEDIATELY", "TOGGLE_LIGHT", "TURN_DOWN", "TURN_LEFT", "TURN_RIGHT", "TURN_UP", "UNLOCK", "LOG", "INIT", "LOCK", "LOW_BATTERY", "OPEN_DOOR", "PAUSE" } funciones_con_argumento = { "CALIBRATE", "COPY_FILE", "DELETE_FILE", "MOVE_BACKWARD", "MOVE_FORWARD", "MOVE_TO", "PRINT", "RENAME_FILE", "ROTATE", "SAVE_FILE", "SCAN", "SET", "SET_SPEED", "UPLOAD", "UPLOAD_FILE", "WAIT" } 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.")