Desarrollo de un AST en Python: Creación de la Clase Programa
Clase 14 de 58 • Curso de Creación de Lenguajes de Programación: Intérpretes
Contenido del curso
- 3

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

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

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

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

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

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

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

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

Creación de un REPL en Python para Lenguaje de Programación
12:35
- 12

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

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

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

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

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

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

Parseo de Return Statements en Lenguaje Platzi
12:42 - 19
Técnicas de Parsing: Top-Down y Bottom-Up
01:46 - 20

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

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

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

Parseo de Expression Statements en Platzi Parser
16:34 - 24

Parseo de Enteros en Lenguaje Platzi
14:03 - 25

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

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

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

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

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

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

Parseo de Condicionales en Lenguaje Platzi
13:50 - 32

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

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

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

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

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

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

Implementación de REPL para Árbol de Sintaxis Abstracta
08:59
- 39

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

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

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

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

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

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

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

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

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

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

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

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

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

Implementación de Llamadas a Funciones en PlatziLang
23:55
¿Cómo crear un nodo principal para un AST?
La creación del Abstract Syntax Tree (AST) en programación es crucial para interpretar y transformar el código de una manera estructurada. El nodo principal que representa al AST es fundamental, ya que es él quien contiene todos los sub-nodos, ya sean expresiones o declaraciones. Vamos a desarrollar una clase de programa que será un nodo principal en el AST, junto con un test básico para verificar su implementación.
¿Cómo inicializar el nodo principal del AST?
Para establecer correctamente la base de nuestro AST, necesitamos crear una clase Programa, que será de tipo AST Node. Esto requerirá también del diseño de un test denominado test_parse_program, que nos indicará si el parser es capaz de devolver correctamente un objeto de tipo Programa. Para llegar a este punto, seguimos estos pasos:
-
Crear Archivos Necesarios:
- Se genera un archivo
parser.pyque contendrá la implementación del parser. - Se crea un archivo
parser_test.pydentro de una carpetatestpara los test unitarios.
- Se genera un archivo
-
Importar Dependencias:
- Utilizamos
unittest.TestCasepara estructurar nuestros tests. - Inicializamos una clase
ParserTestcomo subclase deTestCase.
- Utilizamos
-
Implementación del Test:
- Se inicia el test
test_parse_program, donde el enfoque es en las aserciones. - Se introduce una simple estructura de programa: "variable x es igual a 5".
- Se genera un lexer para convertir el código en tokens, y se crea un parser que usará esos tokens.
- Se inicia el test
¿Cómo crear el test inicial para el parser?
Al seguir la metodología Test Driven Development (TDD), es vital desarrollar los tests primero y luego el código necesario para que los tests pasen exitosamente. Aquí algunos pasos básicos:
-
Definir las Aserciones:
- Comprobar que el objeto generado no es
None. - Verificar que el objeto es de tipo
Programa.
- Comprobar que el objeto generado no es
-
Configurar el Parser:
- Se busca que el parser tome un lexer y devuelva un objeto de
Programausandoparse_program.
- Se busca que el parser tome un lexer y devuelva un objeto de
Veamos cómo se refleja esto en código:
from unittest import TestCase
class ParserTest(TestCase):
def test_parse_program(self):
program = "variable x = 5"
lexer = Lexer(program)
parser = Parser(lexer)
parsed_program = parser.parse_program()
self.assertIsNotNone(parsed_program)
self.assertIsInstance(parsed_program, Program)
¿Cómo definir la clase Programa?
La clase Programa debe estar bien estructurada para recibir los Statements que forman parte de nuestro AST. Esta clase requiere de un constructor y una implementación mínima de varios métodos:
-
Estructura de la Clase:
- Se define la clase
Programcomo una subclase deASTNode. - Su constructor debe recibir una lista de
Statements.
- Se define la clase
-
Implementar Métodos Requeridos:
token_literal: Devuelve el token literal del primer statement o una cadena vacía en caso de que no haya ninguno.__str__: Retornar una concatenación de todos los statements en forma de string.
Aquí un ejemplo simplificado de cómo se podría implementar la clase:
class Program(ASTNode):
def __init__(self, statements):
self.statements = statements
def token_literal(self):
if len(self.statements) > 0:
return self.statements[0].token_literal()
return ""
def __str__(self):
return "".join(str(statement) for statement in self.statements)
¿Cómo implementar un parser básico?
La implementación del parser es el siguiente paso después de confirmar que tenemos la clase Programa correctamente configurada. Un parser básico puede inicializarse de la siguiente manera:
-
Definir el Constructor del Parser:
- El constructor debe aceptar un lexer.
- Es necesario asignar el lexer a una variable interna para su uso posterior.
-
Implementar
parse_programBásico:- Inicializar un objeto
Programacon una lista vacía de statements. - Retornar el objeto
Programa.
- Inicializar un objeto
Aquí hay una representación básica del parser:
class Parser:
def __init__(self, lexer):
self.lexer = lexer
def parse_program(self):
return Program([])
Con cada componente correctamente implementado y testeado, podemos estar seguros de que nuestro nodo principal para el AST está listo para ampliaciones futuras. Esto incluye añadir más tipos de statements y seguir comprobando cada nueva adición con tests adicionales. Recuerda siempre acudir al sistema de comentarios ante cualquier duda o esclarecimiento necesario durante tu aprendizaje en programación.