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

No tienes acceso a esta clase

隆Contin煤a aprendiendo! 脷nete y comienza a potenciar tu carrera

Parseo de let statements

16/58
Recursos

Aportes 8

Preguntas 1

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad?

Muy bien, mi soluci贸n es poco eficiente comparada con la del profesor, pero antes de ponerla, explicar茅 un par de cosas importantes (tuve que ver la soluci贸n del profesor porque no entend铆a qu茅 pasaba xD)
.
Mi idea era que, en program.statements estaban guardados cada uno de los statements, por lo que bas谩ndome en la clase LetStatement, deber铆a tener un nombre disponible, as铆 que mi idea era hacer esto:

self.assertEqual(program.statements[0].name, "x")
self.assertEqual(program.statements[1].name, "y")
self.assertEqual(program.statements[2].name, "foo")

Sin embargo, me sal铆a un error de que name no exist铆a en el statement y yo estaba de 鈥溌÷緾贸mo as铆 que noe existe?! No tas viendo que ah铆 est谩 definido dentro de la clase?鈥
.
Quer铆a hacer prints desde los tests para debuguear, pero no pod铆a usar la funci贸n print() desde los tests, no se imprim铆a nada, de ahi descubr铆 que si quieres usar prints en los tests tienes que correr este comando:

mypy . && nosetests -s

As铆 se imprime lo que quiera debuguear, gracias a esto descrubr铆 que cada statement era un string, y por eso no estaba definida la propiedad name鈥 隆Pues claro!, LetStatement tiene el dunder method __str__ que hace que cada vez que se consulte una instancia de statement esta devuelva un string鈥 revisando el c贸digo del profesor v铆 que el estaba usando una funci贸n llamada cast(), no s茅 exactamente lo que hace pero intuyo que esa funci贸n convierte ese string generado por el dunder method a una instancia de LetStatement, as铆 que aplic谩ndolo, llegue a esta conclusi贸n:

self.assertEqual(cast(LetStatement, program.statements[0]).name, "x")
self.assertEqual(cast(LetStatement, program.statements[1]).name, "y")
self.assertEqual(cast(LetStatement, program.statements[2]).name, "foo")

Todo bien pero鈥 en el atributo name se guarda una instancia de Identifier, as铆 que ten铆a que acceder a su value (propiedad de la clase Identifier).

self.assertEqual(cast(LetStatement, program.statements[0]).name.value, "x")
self.assertEqual(cast(LetStatement, program.statements[1]).name.value, "y")
self.assertEqual(cast(LetStatement, program.statements[2]).name.value, "foo")

Pero soprresa, Identifier tambi茅n tiene un dunder method xD As铆 que al final mi soluci贸n qued贸 as铆 jaja:

self.assertEqual(cast(Identifier, cast(LetStatement, program.statements[0]).name).value, "x")
self.assertEqual(cast(Identifier, cast(LetStatement, program.statements[1]).name).value, "y")
self.assertEqual(cast(Identifier, cast(LetStatement, program.statements[2]).name).value, "foo")

Y solo hay que importar los m贸dulos requeridos:

from typing import (
    cast
)

from lpp.ast import (
    Identifier,
    LetStatement,
    Program,
)

Despu茅s vi el c贸digo del profesor y el lo hizo con listas y bah! xD Al menos lo logr茅 jaja, una hora para lograrlo:'D

Tal y como funciona el programa actualmente, si al quien prepare la prueba automatizada o al usuario que escriba el c贸digo, se le olvida escribir el punto y coma al final del 煤ltimo statement, el programa quedar谩 en un loop infinito de todas maneras.

Para solucionar esto basta con cambiar la l铆nea del archivo parse.py que tiene esto:

while self._current_token.token_type != TokenType.SEMICOLON:

y sustituirlo por esto

while self._current_token.token_type != TokenType.SEMICOLON and self._current_token.token_type != TokenType.EOF:

Mi solucion usando la funcion zip de python.

El archivo de parser_test.py es:

    def test_identifiers(self) -> None:
        source: str = """
            variable x =  5;
            variable y = 10;
            variable foo = 20;
        """
        lexer: Lexer = Lexer(source)
        parser: Parser = Parser(lexer)

        program: Program = parser.parse_program()
        
        self.assertEqual(len(program.statements), 3)

        nombres = ['x','y','foo']
        for statement, nombre in zip(program.statements, nombres):
            self.assertEqual(statement.name.value,nombre)

Aqui les dejo el reto.

        self.assertEqual(cast(Identifier, cast(LetStatement, program.statements[0]).name).value ,'x')
        self.assertEqual(cast(Identifier, cast(LetStatement, program.statements[1]).name).value ,'y')
        self.assertEqual(cast(Identifier, cast(LetStatement, program.statements[2]).name).value ,'foo')

Por lo que entendi segun la documentacion:
https://mypy.readthedocs.io/en/stable/casts.html

La funcion cast(1, 2), basicamente lo que hace es decirle a mypy que trate al valor 2 como si fuera un tipo de valor 1.
En nuestro caso, ocupabamos que tratara a nuestro Statement, como un tipo de valor LetStatament, ya que al momento de declarar la lista de statements en program,

 def __init__(self, statements: List[Statement]) -> None:

le estamos diciendo que la lista va a contener valores de tipo Statement, pero la lista a la cual le estamos haciendo el test, contiene valores de tipo LetStatement, por lo que, cuando intentamos acceder a el name.value de el elemento de la lista, mypy nos dice " creo que eso no se va a poder", ya que el elemento de la lista se supone que tiene valores de tipo Statement, y este no tiene la propiedad .name. Por lo que aqui es donde entra cast, el cual de dice a mypy, "Trata a ese elemento de la lista que se supone que es un Statement, como un LetStatement y trata a su prop .name como un Identifier.

Eso fue lo que entend铆 de la documentaci贸n, si es que alguien se da cuenta que estoy incorrecto, porfavor dime jajaja.

Resoluci贸n del reto dentro del test_let_statements

letStatement = cast(LetStatement,program.statements[0])
        identifier = cast(Identifier, letStatement.name) 
        self.assertEqual(identifier.value,'x')
        letStatement = cast(LetStatement, program.statements[1])
        identifier = cast(Identifier, letStatement.name)
        self.assertEqual(identifier.value, 'y')
        letStatement = cast(LetStatement, program.statements[2])
        identifier = cast(Identifier, letStatement.name)
        self.assertEqual(identifier.value, 'foo')

Inicializaci贸n de current y peek tokens

En caso de que a alguien m谩s le suceda, yo mov铆 mi carpeta de trabajo a otra carpeta en otra ubicaci贸n y perd铆 nose, despu茅s de estar buscando pude volver a instalarlo en el entorno virtual usando

sudo pip3 install nose

Implementaci贸n de _expected_token y _advance_token