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
16:33 min - 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
Viendo ahora - 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
Manejo de Ambientes y Variables en Lenguajes de Programación
Resumen
Lograr que un lenguaje de programación propio declare variables y las recuerde entre líneas es un hito importante. Aquí se explica cómo funciona el ambiente (el diccionario interno que almacena nombres y valores), cómo se implementan los nodos let statement e identifier en el evaluador, y cómo se modifica el REPL para soportar múltiples líneas.
¿Cómo funciona el ambiente en un lenguaje de programación?
El ambiente es un diccionario que guarda llaves (los nombres de las variables) y valores (el resultado de evaluar las expresiones asignadas). Así funcionan todos los lenguajes de programación internamente: mantienen una estructura donde puedes consultar el valor asociado a un nombre en cualquier punto del programa [0:12].
Este concepto se vuelve más interesante cuando existen múltiples ambientes. Las funciones generan su propio ambiente, y funciones dentro de funciones generan los suyos. Esto se conoce como closures [0:40]. Está directamente relacionado con los scopes: dependiendo del scope en el que te encuentres, tienes acceso a ciertos valores del ambiente. Ahora, al construir un intérprete, se comprende cómo opera esto de manera interna [0:52].
¿Cómo se implementa la declaración de variables con let statement?
El primer paso es crear un nuevo tipo de error llamado unknown identifier [1:38]. Este error se lanza cuando se intenta acceder a un identificador que no existe en el ambiente.
Después, se trabaja con dos nodos del AST:
¿Qué hace el nodo let statement?
Cuando el evaluador encuentra un nodo de tipo ast.LetStatement, realiza lo siguiente [1:56]:
- Hace un cast del nodo a
LetStatement. - Verifica que el valor interno no sea
None. - Evalúa recursivamente la expresión asignada, pasándole el ambiente.
- Guarda en el ambiente el nombre de la variable con el valor ya evaluado.
Esto permite evaluar expresiones complejas. Por ejemplo, si escribes variable a = 5 * 5 * 5, la expresión 5 * 5 * 5 se resuelve recursivamente y el resultado final se almacena en el ambiente con la llave a [2:44].
¿Cómo se resuelve un identifier en el evaluador?
Cuando el evaluador encuentra un nodo ast.Identifier, necesita obtener el valor previamente guardado en el ambiente [3:09]. La función evaluate_identifier es sencilla:
- Recibe el nodo y el ambiente.
- Intenta acceder al diccionario usando el nombre del identificador como llave.
- Si la llave no existe, se utiliza un enfoque pythónico: pedir perdón y no permiso. Se captura la excepción
KeyErrory se retorna un error con el mensaje unknown identifier [3:38].
python def evaluate_identifier(node: ast.Identifier, env: Environment) -> Object: try: return env[node.value] except KeyError: return new_error(UNKNOWN_IDENTIFIER, [node.value])
Con estas dos modificaciones, los tests comienzan a pasar correctamente [4:18].
¿Cómo hacer que el REPL soporte múltiples líneas?
Al probar el REPL, se puede declarar variable a = 5, variable b = 10, luego variable c = a + b y evaluar c, obteniendo 15 [4:38]. Sin embargo, cada línea genera un programa nuevo, por lo que al evaluar a en una línea separada, el intérprete dice que no encontró el identificador.
La solución es acumular todo lo escaneado en una lista llamada scant [5:10]:
- Cada input del usuario se agrega a esta lista.
- En lugar de pasar solo la línea actual al lexer, se unen todos los statements previos.
- Así el REPL recuerda las declaraciones anteriores.
Con esta modificación, el REPL funciona como se espera [5:30]:
variable a = 5.variable b = 10.a + bevalúa a 15.a * bevalúa a 50.- Se pueden guardar resultados en nuevas variables y seguir operando.
El lenguaje ya cuenta con variables, condicionales, operaciones aritméticas, comparaciones y booleanos. La siguiente pieza fundamental son las funciones, necesarias para reutilizar código en un lenguaje procedimental [6:15].
¿Ya lograste que tu intérprete declare variables? Comparte tu experiencia y cuéntanos cómo va tu implementación.