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

1

Construcción de Intérpretes de Software en Python 3.8

2

Creación de Compiladores e Intérpretes con Lenguaje Platzi

Construcción del lexer o tokenizador

3

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

4

Definición de Tokens en Lenguaje de Programación Platzi

5

Desarrollo de un Lexer con Test-Driven Development

6

Pruebas de Operadores, Delimitadores y Fin de Archivo en Lexer Python

7

Lexer: Identificación de Keywords y Tokens Complejos

8

Reconocimiento de Funciones en Lexer de Lenguaje de Programación

9

Implementación de Operadores y Condicionales en Lexer de Platzi

10

Implementación de Operadores de Dos Caracteres en Lexer

11

Creación de un REPL en Python para Lenguaje de Programación

Construcción del parser o analizador sintáctico

12

Construcción de un Parser para el Lenguaje Platzi

13

Definición de Nodos Abstractos para Árbol de Sintaxis (AST) en Python

14

Desarrollo de un AST en Python: Creación de la Clase Programa

15

Parseo de Let Statements en Lenguaje Platzi

16

Implementación de funciones advanced y expected tokens

17

Manejo de Errores en Parsers con Test Driven Development

18

Parseo de Return Statements en Lenguaje Platzi

19

Técnicas de Parsing: Top-Down y Bottom-Up

20

Pruebas de AST para Let y Return Statements en Parsers

21

Pratt Parsing: Implementación y Registro de Funciones en Python

22

Parseo de Identificadores en Lenguajes de Programación

23

Parseo de Expression Statements en Platzi Parser

24

Parseo de Enteros en Lenguaje Platzi

25

Implementación de Operadores Prefijo en Parsers

26

Operadores InFix en Expresiones: Implementación y Pruebas

27

Implementación de Operadores InFix en un Parser

28

Expresiones Booleanas en el Lenguaje de Programación Platzi

29

Evaluación de Precedencia y Testeo de Booleanos en Parsers

30

Evaluación de Expresiones Agrupadas en un Parser

31

Parseo de Condicionales en Lenguaje Platzi

32

Implementación de Condicionales en Parser de Lenguaje

33

Parsing de Funciones en Lenguaje Platzi: Creación de Nodos AST

34

Construcción de nodos de función en un parser AST

35

Llamadas a Funciones en Lenguajes de Programación

36

Implementación de llamadas a funciones en un parser con AST

37

Parseo de Expresiones en LET y RETURN Statements

38

Implementación de REPL para Árbol de Sintaxis Abstracta

Evaluación o análisis semántico

39

Evaluación Semántica en Lenguajes de Programación

40

Estrategias de Evaluación en Lenguajes de Programación

41

Representación de Nodos AST y Objetos en Python

42

Evaluación de Expresiones en JavaScript y Python

43

Implementación del Patrón Singleton para Booleanos y Nulos

44

Evaluación de Prefijos en Lenguaje de Programación Platzi

45

Evaluación de Expresiones Infix en Lenguaje Platzi

46

Evaluación de Condicionales en Lenguaje de Programación Platzi

47

Evaluación y Uso del Return Statement en Programación

48

Manejo de Errores Semánticos en Lenguaje Platzi

49

Declaración y Gestión de Variables en Lenguajes de Programación

50

Manejo de Ambientes y Variables en Lenguajes de Programación

51

Declaración de Funciones en Lenguaje de Programación Platzi

52

Implementación de Llamadas a Funciones en PlatziLang

Mejora del intérprete

53

Implementación de Strings en un Intérprete de Lenguaje de Programación

54

Operaciones de Concatenación y Comparación de Strings en Intérprete

55

Implementación de Funciones Built-in en Python

56

Implementación de Built-ins en el Lenguaje Platzi

Siguientes pasos

57

Desarrollo de Lenguaje de Programación y Estructuras de Datos en Python

58

Construcción de un Intérprete en Python desde Cero

No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Implementación de Operadores InFix en un Parser

27/58
Recursos

¿Cómo implementar InFix Operators en un parser?

Integrar InFix Operators en un parser puede parecer complicado al principio, pero una vez entendidas las bases, el proceso se torna más manejable. En este segmento vamos a ver cómo implementar estos operadores en el código de manera efectiva.

¿Qué es InFix y cómo lo implementamos?

Primero, es esencial comprender que InFix se refiere a operadores que están entre dos operandos, como + en 3 + 5. Para gestionarlos en un parser, requerimos registrar estos operadores y definir sus precedencias.

precedences = {
    token_type_equals: precedence_equals,
    token_type_not_equals: precedence_equals,
    token_type_less_than: precedence_less_greater,
    token_type_greater_than: precedence_less_greater,
    token_type_plus: precedence_sum,
    token_type_minus: precedence_sum,
    token_type_division: precedence_product,
    token_type_multiplication: precedence_product,
}

Con este diccionario de precedencias, nuestro parser sabe cómo evaluar las expresiones en el orden correcto.

¿Cómo registramos los operadores InFix?

Para que nuestro parser entienda y pueda procesar InFix Operators, debemos registrarlos específicamente. Dado que utilizan la misma estructura, podemos optimizar el proceso. Todos estos operadores terminan llamando a una misma función, parseInfixExpression, para su interpretación:

# Registro de operadores InFix
registerInfix(token_type_plus, parseInfixExpression)
registerInfix(token_type_minus, parseInfixExpression)
registerInfix(token_type_division, parseInfixExpression)

¿Cómo se implementa parseInfixExpression?

Esta función es el núcleo donde realmente interpretamos las expresiones InFix. Aquí se maneja el orden de operaciones y se evalúan las partes derecha e izquierda de la expresión:

def parseInfixExpression(left):
    token = self.current_token
    precedence = self.current_precedence()
    self.advance_tokens()
    right = self.parse_expression(precedence)
    return InFixExpression(token, left, right)

Esta pequeña función encapsula el manejo de precedencias y el avance temporal de tokens para asegurarse de que las expresiones se evalúen correctamente.

¿Cuál es el rol de las funciones current_precedence y peek_precedence?

Las funciones current_precedence y peek_precedence son auxiliares cruciales que facilitan el manejo de precedencias dependiendo del token actual o el siguiente en línea.

def current_precedence():
    try:
        return precedences[self.current_token.token_type]
    except KeyError:
        return precedence_lowest  

def peek_precedence():
    try:
        return precedences[self.peek_token.token_type]
    except KeyError:
        return precedence_lowest

¿Qué más necesitamos para completar el parser?

Un aspecto vital es prueba y error. Errores y test fallidos son excelentes indicadores de áreas para mejorar. Utilizando un sistema de pruebas puede ayudarnos a identificar y corregir fallos rápidamente, además de desarrollar una comprensión más profunda del funcionamiento del código.

La esencia de un parser exitoso radica en la experimentación y adaptación. Esto se realiza modificando, probando y consultando documentación o comunidad cuando sea necesario. La interacción constante con el código y su manipulación son claves para mejorar tus habilidades en ciencias de la computación.

Si bien todavía hay otros elementos que integrar, como condiciones if-else o booleanos, dominar el manejo de operadores InFix es un gran paso adelante. ¡Anímate a seguir profundizando en estos elementos y a experimentar con el código! Recuerda, si tienes preguntas o comentarios, la comunidad está aquí para ayudarte.

Aportes 1

Preguntas 0

Ordenar por:

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

Buah, ahora sí me dejo roto la clase xD Podría decirse que entendí en un 90% lo que estamos haciendo, es decir, de manera recursiva vamos poniendo las expresiones que están a la derecha de nuestra expresión general, por ejemplo:

5 + 5 + 5 + 5;

La vida del programa sería algo así:

1. 5 + obtenerDerecha
2. 5 + 5 + obtenerDerecha
3. 5 + 5 + 5 + obtenerDerecha
4. 5 + 5 +  5 + 5

Obviamente cada caracter sería un nodo del ATS que se está armando, y ese “obtenerDerecha” sería el equivalente a el self._parse_expresion() que tenemos en el código, que justamente se encarga de ir obteniendo los demás tokens.
.
Sin embargo, las cosas que aún no me quedan clarar es, cómo influyen las precedencias en todo esto, es decir, imagino que la precedencia es el orden de importancia de la operación ¿no?, pues no se cómo es que el programa detecta ese orden jaja, y tampoco veo claro cuál sería la expresión general o el AST que esto estaría generando al final D: