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

Estrategias de evaluación para intérpretes de software

40/58
Recursos

Aportes 2

Preguntas 0

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Depth First, o Primero en Profundidad.

Existen dos estrategias para recorrer una estructura de árbol:
Depth First o Primero en anchura:
Se recorren primero las hojas hermanas, luego las hojas hijas, nivel por nivel.

Breath First o Primero en profundidad:
Se recorren primero las hojas hijas, rama por rama, hasta la más lejana a la raíz primero.

Ambas estrategias tienen sus ventajas y desventajas, pero para este evaluador, la mejor es ir primero en profundidad.

¿Porqué?
Porque así respetamos el órden correcto de los operadores.
En este caso, las hojas “6” y “7” se multiplican primero. Y luego el resultado es asignado a “x”.

En mi caso me gustaría hablar del motor V8 de JavaScript, y esto es algo que ya he hablado en otras clases, pero ahora que entiendo más todo este proceso me gustaría profundizar más en ello:
.
Este es un esquema que tomé del Curso Profesional de JavaScript
.

.
Este es otro que tomé del Curso de JavaScript Engine (V8) y el Navegador
.

.
Son los mismos, pero pongo ambos para que tengan dos visiones diferentes.
.
Todo inicia en el Source Code, justamente ese archivo de texto plano que termina en extensión .js, en nuestro caso, nuestro source code del Lenguaje de Programación Platzi es todo el programa que pasamos, es decir, lo que escribimos en sintaxis de LPP.
.
Podemos ver que JavaScript lo pasa por un parser, para generar su propio AST. El LPP también usa un parser para generar nuestro LPP. Muy seguramente el parser de JavaScript usa un Lexer interno que también genera tokens (de ahí el error Unexpected token... de JavaScript)
.
Recordemos que las computadoras solo entienden machine code, no entienden nada de lo que escribimos dentro de ese archivo que terminan en .js:
.

.
Entonces, para que nuestra computadora pueda entenderlo, hacemos uso del JavaScript Engine, existen demasiados pero el más conocido es V8 que es justamente el que te mostré en las primeras imagenes, básicamente V8 es el intérprete de JavaScript, es su evaluador, es ese motor que traduce todo el código a algo que la computadora puede entender:
.

.
Como se mencionó en la clase, JavaScript usa Just In Time Compiler, es decir, genera código máquina y bytecode al mismo tiempo, y los genera dependiendo de cómo se comporte el código que le pasemos:
.

.
Esto se puede apreciar mejor en este diagrama (la segunda imagen que te puse al inicio):
.

.
El interpreter traduce todo esto a bytecode (este es un código de bajo nivel que es leído por una máquina virtual que lo ejecuta), también podemos ver como el profiler se mantiene vigilando al interpreter en busca de cosas que optimizar para luego tomar la decisión de pasarlo directamente por un compilador y generar código máquina que puede leer la computadora, que por lo general es código mejor optimiazado.
.
La forma en la que el profiler decide esto es, si hay un pedazo de código que se ejecuta mucho (por ejemplom las llamadas a una función), entonces mejor lo optimiza y lo manda directamente a machine code.
.
Sin embargo, cuando una llamada a una función que estaba optimizada cambia y produce un resultado diferente al que solía producri, JavaScript dice: “Uy, esto ya cambio, mejor vamos a deoptimizar esto y mandemoslo a la máquina virtual”, es ahí donde se produce el proceso de deoptimización (primera imagen):
.

.
Es por eso que debemos cuidar nuestra programación en JavaScript para que el lenguaje tenga la posibilidad de echarnos una manita optimizando nuestro código. 😄