Contenido del curso
Construcción del lexer o tokenizador
- 3

Análisis Léxico: Construcción de un Léxer para Intérpretes
05:35 min - 4

Definición de Tokens en Lenguaje de Programación Platzi
11:53 min - 5

Desarrollo de un Lexer con Test-Driven Development
15:42 min - 6

Pruebas de Operadores, Delimitadores y Fin de Archivo en Lexer Python
10:01 min - 7

Lexer: Identificación de Keywords y Tokens Complejos
18:57 min - 8

Reconocimiento de Funciones en Lexer de Lenguaje de Programación
07:46 min - 9

Implementación de Operadores y Condicionales en Lexer de Platzi
12:38 min - 10

Implementación de Operadores de Dos Caracteres en Lexer
12:07 min - 11

Creación de un REPL en Python para Lenguaje de Programación
12:35 min
Construcción del parser o analizador sintáctico
- 12

Construcción de un Parser para el Lenguaje Platzi
05:22 min - 13

Definición de Nodos Abstractos para Árbol de Sintaxis (AST) en Python
09:14 min - 14

Desarrollo de un AST en Python: Creación de la Clase Programa
12:48 min - 15

Parseo de Let Statements en Lenguaje Platzi
20:21 min - 16

Implementación de funciones advanced y expected tokens
08:26 min - 17

Manejo de Errores en Parsers con Test Driven Development
11:06 min - 18

Parseo de Return Statements en Lenguaje Platzi
12:42 min - 19

Técnicas de Parsing: Top-Down y Bottom-Up
01:46 min - 20

Pruebas de AST para Let y Return Statements en Parsers
12:05 min - 21

Pratt Parsing: Implementación y Registro de Funciones en Python
11:47 min - 22

Parseo de Identificadores en Lenguajes de Programación
13:29 min - 23

Parseo de Expression Statements en Platzi Parser
Viendo ahora - 24

Parseo de Enteros en Lenguaje Platzi
14:03 min - 25

Implementación de Operadores Prefijo en Parsers
16:43 min - 26

Operadores InFix en Expresiones: Implementación y Pruebas
10:40 min - 27

Implementación de Operadores InFix en un Parser
20:20 min - 28

Expresiones Booleanas en el Lenguaje de Programación Platzi
13:00 min - 29

Evaluación de Precedencia y Testeo de Booleanos en Parsers
08:39 min - 30

Evaluación de Expresiones Agrupadas en un Parser
10:16 min - 31

Parseo de Condicionales en Lenguaje Platzi
13:50 min - 32

Implementación de Condicionales en Parser de Lenguaje
12:05 min - 33

Parsing de Funciones en Lenguaje Platzi: Creación de Nodos AST
15:51 min - 34

Construcción de nodos de función en un parser AST
15:43 min - 35

Llamadas a Funciones en Lenguajes de Programación
13:05 min - 36

Implementación de llamadas a funciones en un parser con AST
12:21 min - 37

Parseo de Expresiones en LET y RETURN Statements
07:58 min - 38

Implementación de REPL para Árbol de Sintaxis Abstracta
08:59 min
Evaluación o análisis semántico
- 39

Evaluación Semántica en Lenguajes de Programación
03:42 min - 40

Estrategias de Evaluación en Lenguajes de Programación
09:18 min - 41

Representación de Nodos AST y Objetos en Python
14:17 min - 42

Evaluación de Expresiones en JavaScript y Python
19:39 min - 43

Implementación del Patrón Singleton para Booleanos y Nulos
11:52 min - 44

Evaluación de Prefijos en Lenguaje de Programación Platzi
14:41 min - 45

Evaluación de Expresiones Infix en Lenguaje Platzi
18:07 min - 46

Evaluación de Condicionales en Lenguaje de Programación Platzi
13:50 min - 47

Evaluación y Uso del Return Statement en Programación
14:41 min - 48

Manejo de Errores Semánticos en Lenguaje Platzi
21:04 min - 49

Declaración y Gestión de Variables en Lenguajes de Programación
13:55 min - 50

Manejo de Ambientes y Variables en Lenguajes de Programación
11:56 min - 51

Declaración de Funciones en Lenguaje de Programación Platzi
12:26 min - 52

Implementación de Llamadas a Funciones en PlatziLang
23:55 min
Mejora del intérprete
Siguientes pasos
Parseo de Expression Statements en Platzi Parser
Resumen
Construir un parser capaz de reconocer expresiones es uno de los pasos más importantes al desarrollar un intérprete. Aquí se aborda cómo enseñarle al parser a reconocer expression statements e identificadores, conectando tokens con funciones específicas mediante la técnica conocida como Pratt Parser. Si ya sabes parsear let statements y return statements, este es el siguiente paso natural para que tu intérprete cobre vida.
¿Qué es un expression statement y cómo se parsea?
Dentro del lenguaje de programación que se está construyendo, toda instrucción es una de tres cosas: un let statement (declaración de variable), un return statement (retorno de valor) o un expression statement [01:00]. No hay otra opción. Cuando el parser encuentra algo que no es let ni return, automáticamente intenta parsearlo como un expression statement.
Para implementarlo, se modifica la función parse_statement. Donde antes se regresaba None cuando no se encontraba ni let ni return, ahora se llama a una nueva función: parse_expression_statement [01:12].
La función parse_expression_statement sigue estos pasos:
- Verifica que el
current_tokenno seaNone(programación defensiva). - Crea una nueva instancia de
ExpressionStatementpasándole el token actual. - Llama a
parse_expressioncon la precedencia más baja. - Si el siguiente token es un punto y coma (semicolon), avanza al siguiente token con
advance_tokens. - Regresa el expression statement construido.
La verificación de que current_token no sea None es fundamental. Si se omite, herramientas como mypy señalarán un error porque el parámetro token no acepta valores opcionales [02:28]. Esto es programación defensiva: trabajar con tipos garantiza que el programa sea correcto y falle de forma controlada si algo inesperado ocurre.
¿Cómo funcionan las precedencias en un intérprete?
La precedencia determina el orden en que se evalúan las operaciones. Se implementa como un IntEnum importado del módulo enum de Python [03:42]. A diferencia de un Enum regular donde se usa auto(), aquí el valor numérico importa porque define qué operación se ejecuta primero.
Las precedencias, de menor a mayor, son:
- Lowest (1): la precedencia más baja.
- Equals: comparaciones de igualdad.
- Less greater: comparaciones de menor o mayor.
- Sum: operaciones de suma.
- Product: multiplicación y división.
- Prefix: operadores como el signo menos o
not. - Call: llamadas a función, que tienen la precedencia más alta [04:40].
Este orden sigue la lógica matemática que puedes recordar con el acrónimo PEMDAS [03:20]. Por ejemplo, en 5 * 5 + 5, primero se ejecuta la multiplicación porque product tiene mayor precedencia que sum.
¿Cómo se registra y parsea un identificador en el Pratt Parser?
La función parse_expression recibe una precedencia y regresa opcionalmente una expresión [05:18]. Su lógica central consiste en buscar dentro del diccionario prefix_parse_functions una función asociada al token_type del token actual. Si no encuentra una función registrada, captura un KeyError y regresa None.
Para que el parser reconozca identificadores, se registra la función parse_identifier dentro de register_prefix_functions [07:05]:
python self._prefix_parse_functions[TokenType.IDENTIFIER] = self.parse_identifier
Nótese que no se hace la llamada a la función (sin paréntesis); solo se pasa una referencia. La función parse_identifier es extremadamente sencilla [07:22]:
python def parse_identifier(self) -> Identifier: assert self._current_token is not None return Identifier( token=self._current_token, value=self._current_token.literal )
Simplemente toma el token actual y usa su literal como valor del identificador.
¿Por qué refactorizar parse let statement?
Una vez que existe parse_identifier, tiene sentido usarla también dentro de parse_let_statement [08:20]. Antes, esa función construía el identificador manualmente. Ahora se reemplaza por una llamada a parse_identifier, logrando consistencia y un solo punto de fallo. Los tests confirman que el refactoring no rompió nada.
¿Qué hace especial al Pratt Parser?
El Pratt Parser se distingue porque liga tokens a funciones [09:00]. Cada tipo de token tiene asociada una función que sabe cómo parsearlo. Toda la infraestructura ya está lista: para parsear enteros, booleanos u otras expresiones en el futuro, solo hay que definir la función correspondiente y registrarla en el diccionario. Este patrón hace que el parser sea extensible y elegante.
El enfoque de test driven development también demuestra su valor aquí: al refactorizar, los tests existentes verifican de inmediato que todo sigue funcionando correctamente [09:15]. Si parse_identifier fallara en algún contexto, la suite de tests lo detectaría al instante.
Si estás construyendo tu propio intérprete, recuerda leer el código de arriba hacia abajo, de izquierda a derecha, siguiendo cómo cada función llama a la siguiente. Comparte tus avances y experiencias con la comunidad.