Spaces:
Sleeping
Sleeping
| 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 = { | |
| "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.") | |