Skip to content

Clase 2 — El Analizador Léxico — Fundamentos y Componentes

Resumen Ejecutivo

La clase introduce el analizador léxico como primera fase del módulo de análisis de un compilador, explicando su función de leer el código fuente y transformar secuencias de caracteres (lexemas) en componentes léxicos (tokens) que consume el analizador sintáctico. Se establece la relación productor-consumidor entre el léxico y el sintáctico, donde este último actúa como director del proceso. Se repasan los conceptos de lexema, token, patrón, tabla de símbolos y el papel de las expresiones regulares/autómatas finitos en el reconocimiento léxico.

Conceptos Clave

  • Analizador léxico: Módulo que lee el código fuente carácter a carácter, agrupa secuencias en lexemas y devuelve tokens al analizador sintáctico. Es el único módulo que lee directamente el código fuente. ⚠️ EXAMEN
  • Lexema: Secuencia de caracteres del código fuente cuya estructura se corresponde con el patrón de un componente léxico. No confundir con el significado lingüístico general (raíz de una palabra). ⚠️ EXAMEN
  • Token (componente léxico): Cualquier secuencia de caracteres con significado sintáctico propio. Es la unidad que el léxico pasa al sintáctico. ⚠️ EXAMEN
  • Patrón: Regla (expresión regular) que describe la forma de los lexemas correspondientes a un token.
  • Tabla de símbolos: Estructura compartida (recomendada como tabla hash) donde se almacenan los identificadores y su información asociada (tipo, ámbito, declaración...). ⚠️ EXAMEN
  • Algoritmo ambicioso (greedy/maximal munch): El léxico siempre intenta reconocer el lexema más largo posible. ⚠️ EXAMEN
  • Acción semántica: Código que se ejecuta cuando el autómata finito alcanza un estado final (p.ej., devolver el token al sintáctico, guardar en tabla de símbolos).

Desarrollo del Temario

1. Arquitectura del módulo de análisis

El compilador tiene tres fases de análisis: léxico → sintáctico → semántico. Aunque el diagrama sugiere un proceso secuencial, en la práctica el analizador sintáctico es el director: actúa como rutina principal y llama al léxico como subrutina cada vez que necesita el siguiente token. ⚠️ EXAMEN

Ejemplo (analogía lingüística): En el análisis sintáctico del español, la gramática dice "sujeto + verbo + predicado". Al sintáctico no le importa si el sujeto es "Ana" o "Pedro", solo que haya un nombre. De la misma forma, al sintáctico de un compilador no le importa si el identificador es x o num, solo que sea un identificador.

2. Relación léxico-sintáctico (productor-consumidor)

El proceso real funciona así: 1. El sintáctico solicita un componente léxico. 2. El léxico lee del código fuente, compara con un patrón y determina el tipo de token. 3. Devuelve al sintáctico: el token + opcionalmente una referencia a la tabla de símbolos. 4. El sintáctico, al completar una frase, realiza su análisis y vuelve a solicitar tokens.

Ventajas de esta separación: ⚠️ EXAMEN - El sintáctico es independiente del alfabeto del lenguaje; solo trabaja con tipos de palabras. - Mayor eficiencia: el léxico maneja palabras, el sintáctico maneja frases. - Se comunican mediante buffer, llamada a subrutina o retorno.

3. Lexemas, tokens y patrones — La transformación léxica

Dado el código: if x < 10 then x := x + y

Los lexemas reconocidos son: if, x, <, 10, then, x, :=, x, +, y

Lexema Token (componente léxico) Info adicional
if Palabra reservada IF
x Identificador Ref. tabla símbolos
< Operador menor
10 Literal entero Valor: 10
then Palabra reservada THEN
:= Operador asignación
+ Operador suma
y Identificador Ref. tabla símbolos

Relación lexema-token: ⚠️ EXAMEN - Palabras reservadas: relación 1 a 1 (private → token PRIVATE, class → token CLASS). - Identificadores: relación muchos a 1 (x, y, num, valor... → todos son token IDENTIFICADOR). - Cada lexema tiene un único componente léxico, pero un componente léxico puede tener muchos lexemas.

4. Tipos de componentes léxicos

En la mayoría de lenguajes se consideran tokens: ⚠️ EXAMEN - Palabras reservadas (if, then, class, private, new...) - Operadores: aritméticos (+), comparación (<), asignación (:=), lógicos - Identificadores (nombres de variables, funciones...) - Literales/constantes (enteros: 10, reales: 3.14, cadenas: "hola") - Signos de puntuación (;, (, ), {, }) - Marcas de bloque (si el lenguaje las tiene)

Los blancos, tabuladores y comentarios NO son tokens: solo sirven para delimitar palabras y se descartan. ⚠️ EXAMEN

Ejemplo (cadenas de caracteres): Los blancos dentro de comillas ("hola mundo") no se eliminan porque forman parte del valor del literal, no son separadores de palabras.

5. Palabras reservadas vs. identificadores

Las palabras reservadas (private, new, class) no pueden usarse como identificadores — están reservadas para posiciones específicas en la gramática.

Decisión de diseño sobre cómo manejar palabras reservadas: ⚠️ EXAMEN - Opción A: Un token específico por cada palabra reservada (TOKEN_IF, TOKEN_THEN...) → más eficiente en ejecución. - Opción B: Un token genérico "PALABRA_RESERVADA" + búsqueda en tabla → gramática más simple pero menos eficiente.

6. Tabla de símbolos

  • Se recomienda implementarla como tabla hash (indexación por cadenas, búsqueda e inserción rápidas). ⚠️ EXAMEN
  • Almacena los identificadores con información que se va enriqueciendo: tipo, si está declarado, ámbito, etc.
  • Los literales como 10 no necesitan tanta información asociada (basta con saber tipo y valor), por lo que no siempre se guardan en la tabla.
  • Es una estructura compartida entre las fases de análisis.

Ejemplo: Cuando el léxico reconoce x, la guarda en la posición 32 de la tabla de símbolos y devuelve al sintáctico: (IDENTIFICADOR, 32). El sintáctico sabe que hay un identificador y, cuando lo necesite, puede consultar la posición 32 para obtener más información.

7. El algoritmo ambicioso (Maximal Munch)

El léxico siempre intenta leer el lexema más largo posible antes de devolver un token. ⚠️ EXAMEN

Ejemplo: Si existe la palabra reservada private y alguien escribe el identificador privates, el léxico no se detiene al leer private. Sigue leyendo hasta encontrar el delimitador (blanco) y reconoce privates como identificador, no como palabra reservada.

8. Funciones secundarias del analizador léxico

  • Eliminar comentarios y espacios en blanco (blancos, tabuladores, saltos de línea).
  • Detectar errores léxicos/morfológicos: símbolos no permitidos, identificadores que exceden longitud máxima (típicamente 256 caracteres).
  • Mantener la posición actual (línea y carácter) en el archivo fuente → imprescindible para reportar errores con ubicación precisa.

Ejemplo (Python vs Java): En Python, el salto de línea actúa como delimitador de sentencias (no se usa ;), y la indentación delimita bloques. En Java se puede escribir todo en una línea si se respetan los ;. Son decisiones de diseño del lenguaje con consecuencias directas en el léxico.

9. Formalización: gramáticas regulares y autómatas finitos

  • Los patrones léxicos se formalizan como expresiones regulares. ⚠️ EXAMEN
  • Las expresiones regulares definen una gramática regular.
  • La gramática regular es reconocida por un autómata finito determinista (AFD).
  • Herramientas como JFlex construyen automáticamente el autómata a partir de las expresiones regulares.
Nivel de análisis Formalismo Reconocedor
Léxico Expresiones regulares / Gramática regular Autómata finito (determinista)
Sintáctico Gramática independiente del contexto Autómata con pila (pushdown)

Ejemplo de expresión regular para identificador básico (Pascal): \(\text{letra} \cdot (\text{letra} \mid \text{dígito})^*\) En Java se amplía a: \((\text{letra} \mid \$ \mid \_) \cdot (\text{letra} \mid \text{dígito} \mid \$ \mid \_)^*\)

Preguntas de Autoevaluación

  1. ¿Cuál es la diferencia entre un lexema y un token? Pon un ejemplo donde un mismo token tenga múltiples lexemas asociados.

  2. ¿Por qué se dice que el analizador sintáctico es el "director" del proceso de análisis? ¿Cómo interactúa con el léxico?

  3. ¿Qué información pasa el analizador léxico al sintáctico cuando reconoce: (a) una palabra reservada, (b) un identificador, (c) un literal entero, (d) un operador?

  4. ¿Por qué los blancos y comentarios no se consideran tokens? ¿Existe alguna excepción donde un carácter "blanco" sí tenga relevancia sintáctica?

  5. Explica el algoritmo ambicioso (maximal munch). ¿Qué problema resuelve? Pon un ejemplo donde no aplicarlo generaría un error.

  6. ¿Qué tipo de formalismo se usa para describir los patrones léxicos y qué tipo de autómata los reconoce? ¿En qué se diferencia del formalismo usado para la sintaxis?

  7. ¿Cuál es la función de la tabla de símbolos en el análisis léxico? ¿Por qué se recomienda implementarla como tabla hash?

  8. ¿Qué ventaja tiene crear un token específico para cada palabra reservada frente a usar un token genérico "PALABRA_RESERVADA" con tabla de búsqueda?

  9. Escribe la expresión regular para un identificador en un lenguaje que permita letras, dígitos, guion bajo y dólar, pero que deba comenzar por letra o guion bajo.

  10. ¿Qué funciones secundarias realiza el analizador léxico además de reconocer tokens?


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