Qué es un Analizador Semántico y por qué es una pieza clave en el transpilador
En un transpilador o un compilador clásico, el analizador semántico es la fase encargada de comprobar que un programa, además de estar bien escrito desde el punto de vista sintáctico, tiene sentido.
En el proyecto ZX2SB, cuyo objetivo es convertir código ZX BASIC a otro lenguaje, en nuestro caso SuperBASIC del QL, el analizador semántico juega un papel fundamental: es el encargado de interpretar el significado real del programa.
Las fases de un transpilador
Antes de entrar en detalle, conviene situar el analizador semántico dentro del proceso completo:
Código fuente ZX BASIC
|
v
Analizador léxico (Lexer)
|
v
Analizador sintáctico (Parser)
|
v
Analizador semántico (Semantic)
|
v
Generador de código
|
v
Código destino (SuperBASIC)
Cada fase tiene una responsabilidad clara y bien delimitada.
- Lexer: convierte texto en tokens.
- Parser: verifica la estructura gramatical.
- Semantic: verifica el significado del programa.
- Generator: produce el código destino.
Qué hace exactamente el analizador semántico
El analizador semántico responde a preguntas como:
- ¿Se usa una variable antes de asignarle un valor?
- ¿Se asigna una cadena a una variable numérica?
- ¿Un
NEXTcorresponde a suFOR? - ¿Hay un
RETURNsinGOSUBprevio? - ¿Las instrucciones
READtienen datosDATAsuficientes?
En ZX BASIC muchas de estas situaciones están permitidas por el intérprete original, pero al convertir a otros lenguajes conviene detectarlas y, al menos, avisar.
Diseño del analizador semántico en ZX2SB
El analizador semántico de ZX2SB trabaja en dos pasadas sobre un formato intermedio (IR):
- Primera pasada: recolección de información.
- Segunda pasada: análisis semántico y generación del IR final.
Primera pasada: recolección
En esta fase no se genera código. Se recopila información global:
- Variables existentes y su tipo (numéricas o de cadena).
- Uso de instrucciones especiales (PRINT, READ, DATA, AT, etc.).
- Estructura del programa (FOR/NEXT, GOSUB/RETURN).
- Mapa de líneas para referencias posteriores.
Esta información se guarda en un contexto semántico que se utiliza en la segunda pasada.
Segunda pasada: análisis y emisión
En la segunda pasada se analiza cada sentencia individualmente:
- Se validan tipos.
- Se marcan variables como usadas o asignadas.
- Se detectan errores y avisos.
- Se emite el IR normalizado que usará el generador.
Errores y warnings: emisión inmediata
Inicialmente, el analizador semántico acumulaba errores y avisos en listas internas. Sin embargo, en ZX2SB se ha optado por un diseño más simple y coherente:
- Los errores y warnings se emiten en el momento en que se detectan.
- La decisión de continuar o abortar se basa en las opciones del usuario.
- Se eliminan listas auxiliares innecesarias.
Esto unifica el comportamiento con el Lexer, el Parser y el Generator.
Diagrama del flujo del analizador semántico
+-----------------------------+
| Inicializar contexto |
+-------------+---------------+
|
v
+-----------------------------+
| Primera pasada |
| - Variables |
| - DATA / READ |
| - Estructura |
+-------------+---------------+
|
v
+-----------------------------+
| Segunda pasada |
| - Analizar sentencias |
| - Emitir errores/warnings |
| - Generar IR normalizado |
+-------------+---------------+
|
v
+-----------------------------+
| Resultado semántico |
+-----------------------------+
Ejemplo de seudocódigo
El siguiente seudocódigo resume el funcionamiento básico:
function EjecutarSemantico():
inicializar_contexto()
primera_pasada()
if error_fatal:
salir
segunda_pasada()
emitir_warnings_variables()
Y el análisis de una sentencia concreta:
function AnalizarLET(sentencia):
comprobar_formato()
comprobar_variable()
comprobar_tipos()
marcar_asignación()
emitir_IR()
Por qué es importante esta fase
El analizador semántico es el lugar ideal para:
- Detectar errores lógicos tempranamente.
- Dar avisos útiles sin romper compatibilidad con ZX BASIC.
- Preparar el código para distintos lenguajes destino.
- Mantener el generador lo más simple posible.
Gracias a esta fase, ZX2SB puede crecer en el futuro hacia nuevos backends (solo cambiando el generador) manteniendo una base sólida.
Conclusión
El analizador semántico es mucho más que una comprobación adicional: es el puente entre la sintaxis y el significado.
En ZX2SB se ha diseñado de forma clara, estructurada y cercana al espíritu de los lenguajes clásicos, facilitando tanto el mantenimiento como la extensión del proyecto.
En próximas entradas profundizaremos en el generador de código y en cómo las decisiones semánticas influyen directamente en el resultado final.
No hay comentarios:
Publicar un comentario