Introducción al desarrollo de intérpretes y lenguajes de programación

1

Aprende a desarrollar lenguajes de programación con intérpretes

2

Desarrolla LPP o Lenguaje de Programación Platzi

Construcción del lexer o tokenizador

3

¿Qué es análisis léxico? Funcionamiento del lexer y tokens

4

Estructura y definición de tokens en Python

5

Lectura de caracteres y tokens

6

Tokens ilegales, operadores de un solo carácter y delimitadores

7

Reconocimiento y diferenciación entre letras y números

8

Declaración y ejecución de funciones

9

Extensión del lexer: condicionales, operaciones y booleanos

10

Operadores de dos caracteres

11

Primera versión del REPL con tokens

Construcción del parser o analizador sintáctico

12

¿Qué es un parser y AST?

13

Estructura y definición de nodos del AST en Python

14

Parseo del programa o nodo principal

15

Parseo de assignment statements

16

Parseo de let statements

17

Parseo de errores

18

Parseo del return statement

19

Técnicas de parsing y pratt parsing

20

Pruebas del AST

21

Implementación del pratt parser

22

Parseo de Identifiers: testing

23

Parseo de Identifiers: implementación

24

Parseo de enteros

25

Prefix operators: negación y negativos

26

Infix operators y orden de las operaciones: testing

27

Infix operators y orden de las operaciones: implementación

28

Parseo de booleanos

29

Desafío: testing de infix operators y booleanos

30

Parseo de expresiones agrupadas

31

Parseo de condicionales: testing y AST

32

Parseo de condicionales: implementación

33

Parseo de declaración de funciones: testing

34

Parseo de declaración de funciones: AST e implementación

35

Parseo de llamadas a funciones: testing y AST

36

Parseo de llamadas a funciones: implementación

37

Completando los TODOs o pendientes del lexer

38

Segunda versión del REPL con AST

Evaluación o análisis semántico

39

Significado de símbolos

40

Estrategias de evaluación para intérpretes de software

41

Representación de objetos

42

Evaluación de expresiones: enteros

43

Evaluación de expresiones: booleanos y nulos

44

Evaluación de expresiones: prefix

45

Evaluación de expresiones: infix

46

Evaluación de condicionales

47

Evaluación del return statement

48

Manejo de errores

49

Ambiente

50

Bindings

51

Evaluación de funciones

52

Llamadas a funciones

Mejora del intérprete

53

Implementación de strings

54

Operaciones con strings

55

Built-in functions: objeto y tests

56

Built-in functions: evaluación

Siguientes pasos

57

Retos para expandir tu intérprete

58

Continúa con el Curso de Creación de Compiladores de Software

Aún no tienes acceso a esta clase

Crea una cuenta y continúa viendo este curso

Manejo de errores

48/58
Recursos

Aportes 2

Preguntas 0

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.

Ahhhh!! reto conseguido
.
Logré añadir el número de línea a los errores que salen, pero debo decir que es un trabajo MUY pesado. Si tu quieres añadirlo puedes hacerlo pero te dejo la advertencia xD.
.
Otra cosa, te recomiendo que hagas este cambio en un branch nuevo, ya que esto implica modificar tanto el Lexer como el Parser como el Evaluador, por lo que si sigues el curso con estos cambios es posible que tengas que agregar cosas extra para adicionar la línea a los diferentes nodos.
.
Aquí una captura de uno de los mensajes de error:
.

.
Obviamente aquí simepre me va a decir que en la línea 1 porque solo hay una línea jaja, pero en los tests puse para hacer tests en otras líneas.
.
Como explicación general, lo que se tiene que hacer es:
.

  1. En el Lexer: Añadir a todos los tokens en qué línea se encuentra cada token, esto implica modificar la clase Token ubicada en lpp/token.py
  2. En el Parser: Modificar las clases del AST para que cada expresión tenga el atributo line específicando en dónde se encuentra la línea, y en cada cración de nodo dentro del parser, hay que pasar la línea: self._current_token.line
    3.- En el evaluador: Hay que modificar varios métodos para que acepten las líneas que contienen los nodos (en qué línea se encuentra dicho nodo) para así poder mandar el error, esto implica también modificar las clases de cada objeto.

.
Sí, es un trabajo muy pesado, tienes que modiciar casi todos los archivos, y el mayor problema es que MUCHOS tests van a fallar con cada modificación.
.
Para el conteo de líneas dentro del Lexer, simplemente hay que añadirle una propiedad llamada line y en cada llamada al método _read_character hay que comparar si el siguiente token es un salto de línea, es ahí cuando aumentamos en uno la línea.
.
Realmente explicar todos los cambios es muy largo xD Pero si quieren ver cómo lo hice yo, aquí les dejo el enlace a la comparación de los archivos nuevos (con el mensaje de en qué línea está el error incluído) versus los archivos antiguos (sin los mensajes):
.
Adicion de la linea en los errores (comparación de GitHub)
.
También les dejo el enlace hacia el explorador de archivos para que puedan ver los archivos en su estado final:
.
Adicion de la linea en los errores (explorador de archivos de GitHub)
.
La verdad es que me gustaría saber cómo lo hizo el profesor pero no encontré ningún commit/branch donde él lo haya hecho jaja

Así fue como me quedaron los mensajes de error. Me guié un poco con el código de RetaxMaster para conseguir que se imprima también el número de lineas