¿Te resulta más fácil leer con fondo crema, un tono de color, más contraste o un texto más grande? Elige tus colores y tu texto una sola vez, para todas las páginas.

Lección gratuita

Partir el código en tokens (análisis léxico)

Después de esta lección: Puedo convertir el texto de un programa en tokens.

Lección de 50 min11 comandosLaboratorio de compiladores y arquitectura: gcc, flex, bison y RISC-V en una VM

Una coma que nadie esperaba

Una tienda online guarda sus descuentos en un archivo de reglas. Alguien escribe price * 0,95, con coma, como se escribe en España. El programa rechaza la regla.

Nadie miró aún si la regla tiene sentido. Falló antes: al agrupar los caracteres en palabras. Esa primera parte de un compilador es pequeña y rápida, y es fácil equivocarse en ella.

Al final de esta lección

Nota

Puedo convertir el texto de un programa en tokens.

Palabras clave

PalabraQué significaEjemplo
Tokenuna palabra del programa, con su tipoNUMBER 50
Analizador léxicola parte del compilador que crea los tokens
Patrónla regla de cómo es un tipo de token[0-9]+
Coincidencia más largatomar todos los caracteres que el patrón admita
Palabra reservadauna palabra que el lenguaje guarda para síif
Generador léxicouna herramienta que escribe el analizador desde patronesflex

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Un token es un tipo y un texto

El analizador léxico es la primera parte del compilador propiamente dicho. Lee los caracteres de izquierda a derecha y entrega tokens.

Cada token tiene un tipo, como NUMBER o NAME, y el texto del que salió. Los espacios y los comentarios no crean tokens. Solo marcan dónde acaba uno y empieza el siguiente.

Ejemplo: if total >= 50

CaracteresTipoTexto
i fKEYWORDif
t o t a lNAMEtotal
> =OP>=
5 0NUMBER50
Los tres espaciosNingún tokenSe saltan

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Un analizador léxico en Python

Código: python
# Un analizador léxico mínimo: números con punto, nombres y signos.
text = "price * 1.21"
tokens = []
i = 0
while i < len(text):
    ch = text[i]
    if ch == " ":
        i = i + 1
    elif ch.isdigit():
        start = i
        # Sigue mientras haya cifras o un punto: la coincidencia más larga.
        while i < len(text) and (text[i].isdigit() or text[i] == "."):
            i = i + 1
        tokens.append(["NUMBER", text[start:i]])
    elif ch.isalpha():
        start = i
        while i < len(text) and text[i].isalpha():
            i = i + 1
        tokens.append(["NAME", text[start:i]])
    elif ch in "+-*/":
        tokens.append(["OP", ch])
        i = i + 1
    else:
        tokens.append(["ERROR", ch])
        i = i + 1
print(tokens)
# Cambia text por "price * 1,21" y vuelve a ejecutar.

flex escribe el analizador por ti

Escribir a mano el analizador de un lenguaje real es lento. Un generador léxico como flex lo escribe a partir de una lista de patrones.

En calc.l, cada línea une un patrón con lo que hay que hacer si encaja. [0-9]+ significa una o más cifras. Su acción convierte el texto en un número y entrega el token NUMBER al analizador sintáctico. Los Runs leen las reglas y reconstruyen la calculadora desde cero.

Entra en la carpeta del compilador

Comando
cd ~/compiler

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Las reglas que entregan un token

Comando
grep -n "return" calc.l

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

¿Cuántas líneas tiene calc.l?

Comando
grep -c "" calc.l

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Borra todo lo que hizo make

Comando
make clean

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Construye otra vez la calculadora

Comando
make

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

¿Cuánto mide lo que escribió flex?

Comando
wc -l lex.yy.c

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Caracteres que el analizador conoce y que no

Cada Run pasa una línea a la calculadora. Fíjate en qué mensajes vienen del analizador léxico y cuáles del sintáctico.

La última regla de calc.l, un punto solo, encaja con cualquier carácter que las demás no quisieron. Escribe unexpected character y no crea token. El analizador sintáctico ve después lo que queda.

Un decimal con coma

Comando
echo "3,5 + 1" | ./calc

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Un decimal con punto

Comando
echo "3.5 + 1" | ./calc

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Sin ningún espacio

Comando
echo "250+50" | ./calc

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Ceros a la izquierda

Comando
echo "007 + 1" | ./calc

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Un precio con su símbolo

Comando
echo "20 €" | ./calc

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Un error frecuente

Advertencia

Mucha gente cree que un analizador léxico crea un token por carácter, así que 007 serían tres números. El analizador toma la coincidencia más larga: sigue leyendo mientras el patrón encaje. Por eso 007 es un solo NUMBER, e iffy es un NAME, no la palabra if seguida de fy.

Para ir más lejos

Amplía tu analizador con textos entre comillas dobles. "oferta de verano" es un solo token STRING, sin las comillas. Una comilla que nunca se cierra es un token ERROR con el resto del texto.

Escribe primero tres pruebas tuyas. Después explica por qué un # dentro de las comillas no debe empezar un comentario.

Sobre este laboratorio y su código: Laboratorio de compiladores y arquitectura: gcc, flex, bison y RISC-V en una VM

¿Enseñas a una clase? Asigna este módulo a tus alumnos con guía del profesor, tareas con corrección automática y un laboratorio para cada alumno.