Skip to content

Clase 3 — Analizador Léxico (Parte 2) — Recuperación de errores, alternativas de implementación y JFlex

Resumen Ejecutivo

La clase abordó tres grandes bloques del analizador léxico: las técnicas de recuperación de errores léxicos (con énfasis en el modo pánico como única técnica fiable), las alternativas de implementación (manual vs. automática mediante herramientas como JFlex), y la estructura del archivo de especificación JFlex con sus tres secciones, directivas, macros y expresiones regulares. Se introdujo además el algoritmo ambicioso (longest match + prioridad por orden) como mecanismo clave de resolución de ambigüedades.

Conceptos Clave

  • Token / Componente léxico: Tipo de palabra reconocido por el analizador léxico (palabra reservada, identificador, operador, etc.)
  • Lexema: La cadena concreta de caracteres que se ajusta a un patrón (expresión regular)
  • Autómata Finito Determinista (AFD): Modelo computacional que subyace a todo analizador léxico; recorre estados hasta alcanzar un estado final de aceptación o detectar un error ⚠️ EXAMEN
  • Modo pánico: Técnica de recuperación de errores que avanza en la entrada hasta encontrar un punto seguro (delimitador) desde el cual continuar el análisis ⚠️ EXAMEN
  • Acción semántica: Código Java asociado a una expresión regular que se ejecuta cuando se produce una concordancia
  • Macro (JFlex): Nombre asignado a una subexpresión regular para simplificar y hacer más legible la especificación
  • Algoritmo ambicioso (longest match): El analizador siempre intenta reconocer la cadena más larga posible; a igualdad de longitud, prevalece la regla que aparece primero ⚠️ EXAMEN

Desarrollo del Temario

1. Implementación del analizador léxico mediante AFD

El analizador léxico se implementa internamente como un autómata finito determinista (AFD) que se construye a partir de las expresiones regulares que definen la morfología de cada tipo de palabra del lenguaje. ⚠️ EXAMEN

  • Las expresiones regulares definen la morfología (cómo se forman las palabras/lexemas).
  • El AFD es lo que realmente se ejecuta: parte de un estado inicial, transita entre estados según los caracteres leídos y llega (o no) a un estado final.
  • Las herramientas como JFlex automatizan la construcción del AFD; internamente suelen construir primero un AFND y luego lo convierten a AFD.

Ejemplo: Si defines la expresión regular para identificadores y para while, JFlex construye un AFD que integra ambas reglas y decide, al recorrer los estados, qué token devolver.

2. Recuperación de errores léxicos

El analizador léxico tiene capacidad limitada de detección de errores: solo detecta errores puramente léxicos (caracteres o combinaciones no permitidas por ninguna expresión regular).

Tipos de errores léxicos comunes: - Caracteres ilegales no pertenecientes al alfabeto del lenguaje (ñ, acentos en identificadores de C++) - Combinaciones de símbolos no válidas (:= en un lenguaje que usa = para asignación)

Evolución histórica de las estrategias: 1. Parada total sin información — el análisis se detenía sin indicar el error. 2. Parada con informe — se detenía pero informaba del error encontrado. 3. Continuación del análisis (actual) — informa del error y sigue leyendo para detectar más errores.

2.1 Modo pánico (panic mode) ⚠️ EXAMEN

Única técnica fiable de recuperación de errores en el analizador léxico:

  1. Se detecta un error (ninguna expresión regular reconoce la entrada).
  2. Se informa del error.
  3. Se avanza en la entrada ignorando caracteres hasta llegar a un punto seguro (delimitador): un blanco, un salto de línea o un operador.
  4. Se reanuda el análisis desde ese punto.

Ejemplo (analogía del profesor): Es como un incendio: corres presa del pánico hasta encontrar una puerta segura donde el fuego ya no te afecta. Si encuentras otro fuego más adelante, repites el proceso.

2.2 Técnicas de corrección (inserción, borrado, reemplazo) — NO fiables

Intentan corregir el error automáticamente (similar a un corrector ortográfico). Son peligrosas en el léxico porque carecen de contexto sintáctico:

Ejemplo: Si se lee BEGN, ¿se corrige a BEGIN (palabra reservada) o el programador realmente quería un identificador llamado BEGN? El léxico no puede saberlo.

El contexto necesario para estas correcciones lo proporciona el analizador sintáctico, que conoce la estructura de las frases y puede determinar qué tipo de token se esperaba en esa posición. ⚠️ EXAMEN

3. Alternativas de implementación del analizador léxico

Alternativa Descripción
Manual Se construyen las expresiones regulares, se diseña el AFD manualmente, se implementa como un bucle con switch-case recorriendo estados
Automática (herramientas) Se escribe un archivo de especificación con expresiones regulares + acciones; la herramienta genera el AFD y el código Java/C automáticamente

Herramientas: Lex (C), Flex (C/C++), JFlex (Java) — todas siguen el mismo principio. ⚠️ EXAMEN

4. JFlex: generador automático de analizadores léxicos

Flujo de trabajo: 1. El usuario escribe un archivo de especificación (.flex) con expresiones regulares + acciones semánticas. 2. JFlex lee el archivo y genera una clase Java (Yylex) que contiene el AFD. 3. La clase tiene un método yylex() que ejecuta el análisis carácter a carácter sobre el archivo de entrada. 4. Al constructor de Yylex se le pasa el archivo fuente (objeto Reader de Java).

4.1 Estructura del archivo de especificación JFlex ⚠️ EXAMEN

[Sección 1: Código de usuario]
%%
[Sección 2: Opciones y declaraciones]
%%
[Sección 3: Reglas léxicas (expresiones regulares + acciones)]

Las tres secciones se separan con %%.

Sección 1 — Código de usuario: - Se copia literalmente antes de la declaración de la clase Yylex. - Contenido típico: declaración de package, sentencias import.

Sección 2 — Opciones y declaraciones:

Directiva Función
%class NombreClase Cambia el nombre de la clase del analizador (por defecto Yylex)
%function nombre Cambia el nombre del método analizador (por defecto yylex)
%type Tipo Define el tipo de retorno del método yylex()
%line Activa el contador de líneas (yyline, tipo int, empieza en 0) ⚠️ EXAMEN
%column Activa el contador de columnas (yycolumn, tipo int)
%{ ... %} Bloque de código Java insertado dentro de la clase
  • yyline y yycolumn son atributos privados: se necesita definir un método getter para acceder a ellos desde fuera.
  • El contador de líneas se incrementa automáticamente cada vez que el analizador lee un salto de línea.

Macros: Se definen en la sección 2 como nombre = expresión_regular para simplificar las reglas.

Sección 3 — Reglas léxicas:

Formato de cada regla:

expresión_regular  { código_Java }

El código Java (acción semántica) se ejecuta cuando se reconoce una concordancia con la expresión regular. Se copia literalmente al archivo generado.

4.2 Expresiones regulares en JFlex ⚠️ EXAMEN

Símbolo Significado Ejemplo
. Cualquier carácter excepto \n . reconoce a, 1, @...
* 0 o más ocurrencias ab*a, ab, abb...
+ 1 o más ocurrencias [0-9]+ → uno o más dígitos
? 0 o 1 ocurrencia (opcional) -?[0-9]+ → entero con signo opcional
[xyz] Clase de caracteres (OR) [xyz]x, y o z
[a-z] Rango de caracteres [a-z] → cualquier minúscula
[^...] Negación de clase [^A-Z] → cualquier cosa que NO sea mayúscula
{n} Exactamente n repeticiones a{4}aaaa
{m,n} De m a n repeticiones x{1,3}x, xx, xxx
\| Alternativa (OR) ab\|cdab o cd
( ) Agrupación (ab\|cd)eabe o cde
"..." Literal (desactiva metacaracteres) "*" → reconoce el carácter * literal
\t Tabulador [ \t]+ → uno o más espacios/tabs

Ejemplo: La expresión [a-zA-Z][a-zA-Z0-9]* reconoce identificadores: primer carácter letra, seguido de cero o más letras o dígitos. Reconocería v1, miVar, x.

Cuidado con .*: reconoce toda la línea completa hasta \n. Usar con precaución.

4.3 Algoritmo ambicioso (Longest Match + Rule Priority) ⚠️ EXAMEN

Dos reglas fundamentales de resolución de ambigüedades:

  1. Longest match (concordancia más larga): Si una entrada puede ser reconocida por una expresión como cadena corta o larga, se elige la más larga.
  2. Prioridad por orden: Si dos expresiones regulares reconocen la misma cadena con la misma longitud, se aplica la que aparece primero en el archivo.

Ejemplo 1 (longest match): Si tenemos la regla para while (palabra reservada) y la regla [a-zA-Z][a-zA-Z0-9]* (identificador), la entrada whilem se reconoce como identificador (no para en while porque puede leer más).

Ejemplo 2 (prioridad por orden): La entrada while concordaría tanto con la regla de palabra reservada como con la de identificador. Si la regla de while está antes, se devuelve como palabra reservada. Si el identificador estuviera antes, se devolvería erróneamente como identificador.

Consecuencia práctica: Las palabras reservadas deben definirse antes que la regla de identificadores en el archivo de especificación. ⚠️ EXAMEN

5. Introducción a la Actividad 1: Analizador léxico para Pocket

  • Construir un analizador léxico en JFlex para el lenguaje Pocket.
  • Se parte de una gramática que describe el lenguaje.
  • Elementos léxicos a identificar: palabras reservadas (main, int, boolean, float), símbolos ({, }, ;, ,, [, ], (, ), &&), identificadores, números, etc.
  • Recomendación del profesor: Primero diseñar las expresiones regulares en papel, luego trasladarlas al archivo .flex.

Preguntas de Autoevaluación

  1. ¿Qué modelo computacional subyace a la implementación de un analizador léxico y por qué no se utiliza un autómata a pila?

  2. Explica en qué consiste la técnica de recuperación de errores en modo pánico y por qué se considera la única técnica fiable en el analizador léxico.

  3. ¿Por qué las técnicas de corrección automática (inserción, borrado, reemplazo de caracteres) no son adecuadas en el análisis léxico? ¿Qué fase del compilador podría realizar mejor estas correcciones y por qué?

  4. Dado un archivo JFlex con las reglas en este orden: (1) [a-zA-Z][a-zA-Z0-9]* y (2) while, ¿qué token devolvería para la entrada while? ¿Por qué? ¿Cómo se corrige?

  5. ¿Qué diferencia hay entre poner [abc] y abc en una expresión regular de JFlex?

  6. ¿Para qué sirven las directivas %line y %column en JFlex y qué atributos generan en la clase?

  7. Describe las tres secciones de un archivo de especificación JFlex y qué contiene cada una.

  8. ¿Qué reconoce la expresión regular -?[0-9]+? Pon tres ejemplos de cadenas aceptadas.

  9. Explica el algoritmo ambicioso con un ejemplo donde dos reglas podrían reconocer la misma entrada con distinta longitud.

  10. ¿Por qué es peligroso usar la expresión .* en una regla de JFlex?


Guía generada automáticamente a partir de transcripción con faster-whisper + Claude Sonnet.