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
- Tokenizar la entrada
- Analizar expresiones
- Evaluar el árbol
- Añadir variables