0Pricing
C Academy · Lección

Tokenizar la entrada

Convierta texto en tokens

Tokenizar la entrada es una lección gratuita de C Academy en CoddyKit. Esta es la lección 1 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de C Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de C Academy incluye 4 lecciones en total.

¿Qué es un tokenizador?

Un intérprete comienza convirtiendo el texto sin procesar en tokens: las unidades más pequeñas con significado. Para la cadena 3 + 4 * 2, el tokenizador (o analizador léxico) emite números y operadores.

Esta etapa elimina los espacios en blanco y clasifica cada grupo de caracteres, para que el analizador sintáctico nunca tenga que trabajar con bytes sin procesar.

Un tipo de token

Modelamos cada token con una etiqueta enum y una carga útil. Los números contienen un valor entero; los operadores y los paréntesis solo necesitan indicar su tipo.

Conservar el valor dentro de la estructura evita volver a explorar el código fuente más adelante.

typedef enum {
  TOK_NUM, TOK_PLUS, TOK_MINUS,
  TOK_STAR, TOK_SLASH,
  TOK_LPAREN, TOK_RPAREN, TOK_EOF
} TokKind;

typedef struct {
  TokKind kind;
  int value; /* used when kind == TOK_NUM */
} Token;

Posición de exploración

El analizador léxico recorre el código fuente con un puntero cursor. Una pequeña función auxiliar consulta el carácter actual sin consumirlo y devuelve '\0' al llegar al final.

La aritmética de punteros mantiene el analizador rápido y sencillo.

static const char *src;

static char peek(void) {
  return *src;
}

static char advance(void) {
  return *src++;
}

Omisión de espacios en blanco

Antes de leer un token, descartamos los espacios y las tabulaciones. La función estándar isspace de <ctype.h> gestiona todos los caracteres de espacio en blanco.

Aquí los saltos de línea cuentan como espacios en blanco, por lo que la expresión puede ocupar varias líneas.

#include <ctype.h>

static void skip_ws(void) {
  while (isspace((unsigned char)peek()))
    advance();
}

Análisis léxico de un número

Cuando el cursor se encuentra sobre un dígito, acumulamos los dígitos consecutivos en un entero. Multiplicar por diez y sumar cada dígito construye el valor de izquierda a derecha.

El bucle se detiene ante el primer carácter que no es un dígito, dejando el cursor listo para el siguiente token.

static int lex_number(void) {
  int n = 0;
  while (isdigit((unsigned char)peek())) {
    n = n * 10 + (advance() - '0');
  }
  return n;
}

La función next_token

La rutina principal omite los espacios en blanco y después decide según el carácter actual. Los dígitos se convierten en un TOK_NUM; cada operador se asigna a su propio tipo.

Al llegar al NUL terminador se obtiene TOK_EOF, la señal para detenerse.

static Token next_token(void) {
  skip_ws();
  char c = peek();
  if (c == '\0') return (Token){TOK_EOF, 0};
  if (isdigit((unsigned char)c))
    return (Token){TOK_NUM, lex_number()};
  advance();
  switch (c) {
    case '+': return (Token){TOK_PLUS, 0};
    case '-': return (Token){TOK_MINUS, 0};
    case '*': return (Token){TOK_STAR, 0};
    case '/': return (Token){TOK_SLASH, 0};
    case '(': return (Token){TOK_LPAREN, 0};
    case ')': return (Token){TOK_RPAREN, 0};
  }
  return (Token){TOK_EOF, 0};
}

Ejecución del analizador léxico

Aquí tiene un programa completo que analiza léxicamente una expresión y muestra el tipo de cada token. Los números también muestran su valor.

Observe que el bucle termina cuando lee TOK_EOF.

#include <stdio.h>
#include <ctype.h>

typedef enum { TOK_NUM, TOK_PLUS, TOK_STAR, TOK_EOF } TokKind;
typedef struct { TokKind kind; int value; } Token;

static const char *src;
static char peek(void){ return *src; }
static char advance(void){ return *src++; }

static Token next_token(void){
  while (isspace((unsigned char)peek())) advance();
  char c = peek();
  if (c=='\0') return (Token){TOK_EOF,0};
  if (isdigit((unsigned char)c)){
    int n=0; while(isdigit((unsigned char)peek())) n=n*10+(advance()-'0');
    return (Token){TOK_NUM,n};
  }
  advance();
  if (c=='+') return (Token){TOK_PLUS,0};
  return (Token){TOK_STAR,0};
}

int main(void){
  src = "12 + 3 * 4";
  Token t;
  do {
    t = next_token();
    if (t.kind==TOK_NUM) printf("NUM %d\n", t.value);
    else if (t.kind==TOK_PLUS) printf("PLUS\n");
    else if (t.kind==TOK_STAR) printf("STAR\n");
    else printf("EOF\n");
  } while (t.kind != TOK_EOF);
  return 0;
}

Un token de anticipación

Los analizadores sintácticos normalmente necesitan inspeccionar el token siguiente antes de consumirlo. Almacenamos un token en un current global y lo renovamos después de cada coincidencia.

Esta anticipación de un único token es suficiente para nuestra gramática LL(1).

static Token current;

static void init_lexer(const char *s) {
  src = s;
  current = next_token();
}

static Token cur(void) { return current; }

static void bump(void) { current = next_token(); }

Notificación de errores léxicos

Un carácter desconocido, como $ o @, no debe desaparecer silenciosamente. Un analizador léxico robusto informa del byte problemático y aborta.

Fallar rápidamente en el analizador léxico evita que las etapas posteriores reciban tokens basura.

#include <stdio.h>
#include <stdlib.h>

static void lex_error(char c) {
  fprintf(stderr, "lex error: unexpected '%c'\n", c);
  exit(1);
}

Operadores de varios caracteres

Los lenguajes reales tienen tokens como == o <=. Para analizarlos léxicamente, consultamos un carácter adicional después del primero.

Si el siguiente byte completa el operador, consumimos ambos; de lo contrario, emitimos la forma de un solo carácter.

/* fragment: distinguish '=' from '==' */
if (peek() == '=') {
  advance();
  if (peek() == '=') { advance(); /* TOK_EQ */ }
  else { /* TOK_ASSIGN */ }
}

Por qué importan los tokens

Al convertir los caracteres en tokens, el analizador sintáctico trabaja con un flujo limpio y tipado. La precedencia de operadores, la agrupación y los errores resultan más fáciles de analizar.

A continuación introduciremos estos tokens en un analizador sintáctico descendente recursivo.

Comprobación rápida

Piense en qué produce el analizador léxico para los símbolos de agrupación.

Resumen

Ha creado un analizador léxico: un tipo de token, un cursor de exploración, omisión de espacios en blanco, análisis léxico de números y un distribuidor next_token con anticipación de un token.

Estos tokens son la entrada del análisis sintáctico, que construye un árbol de sintaxis a partir de ellos.

Preguntas frecuentes

¿La lección «Tokenizar la entrada» es gratis?

Sí — el texto completo de «Tokenizar la entrada» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de C Academy, actualiza a CoddyKit PRO. El curso de C Academy incluye 4 lecciones en total.

¿Qué aprenderé en «Tokenizar la entrada»?

Convierta texto en tokens Practicas C Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar C Academy?

No se requiere experiencia previa. C Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 1 de 4.

¿Cuánto tiempo toma la lección «Tokenizar la entrada»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de C Academy?

Sí. Cada lección de C Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Tokenizar la entrada
  2. Analizar expresiones
  3. Evaluar el árbol
  4. Añadir variables
← Volver a C Academy