Ahhhhh!!! ¡Ya tiene vida SigmaF! 😱
Introducción al desarrollo de intérpretes y lenguajes de programación
Construcción de Intérpretes en Python desde Cero
Programación en Platzi: Compiladores e Intérpretes en Español
Construcción del lexer o tokenizador
Análisis Léxico: Creación de Tokens para Léxers
Tipos de Datos y Tokens en Python
Programación: Construcción de Lexer con Test-Driven Development
Pruebas Regulares en Python: Implementación de un Lexer
Tokens y Palabras Clave en Python: Gestión Avanzada
Tokens y Reconocimiento de Funciones en Lexers
Implementación de Operadores en Lexer de Platzi
Operadores Lógicos en Lenguajes de Programación
REPL en Python: Crear, Ejecutar y Probar Lexer Básico
Construcción del parser o analizador sintáctico
Construcción de un AST para Lenguaje Platzi
Creación de Nodos Abstractos para AST en Python
Parser de Lenguaje: Creación de Nodos AST en Python
Parseo de Let Statements en Lenguaje Platzi
Funciones de Tokenización en Lenguaje de Programación
Errores comunes al programar en Python
Base de Datos Relacional: Diseño y Consultas Básicas
Parsing con Pratt: Manejo de Precedencia y Asociatividad
Pruebas de AST para parsers en Python
Parseo de Expresiones con Pratt Parsing en Python
Parseo de Identificadores en AST Python
Parseo de Identificadores: Expresiones en PlatziLang
Parseo de Enteros en Python: Implementación y Pruebas
Operadores Prefijo en Parsers: Diseño e Implementación
Operadores InFix: Implementación y Pruebas en Python
Parseo de Operadores InFix en Python
Expresiones Booleanas en Lenguaje Platzi: Implementación y Testeo
"Precedencia de Operadores en Python"
Parentesis en Expresiones Matemáticas en Python
Tipos de Datos en el Lenguaje de Programación Platzi
Programación de Parsers en Lenguajes de Programación
Parsiendo Funciones en Lenguaje Platzi: Creación y Pruebas de Nodos AST
Programación Funcional: Construcción y Parsing en Python
Parentesis: Uso y Función en Llamadas a Procedimientos
Precedencia de Llamadas en Parsers: Implementación en AST
Parseo de Expresiones en LET y RETURN Statements
Construcción del REPL en Python: Lexer y Parser en Sintaxis Abstracta
Evaluación o análisis semántico
Análisis Semántico en Lenguajes de Programación
Evaluación de Código: Intérpretes vs Compiladores
Representación de Objetos en Python: Enteros, Booleanos y Null
Evaluación de enteros en Python: Crear y probar evaluador recursivo
Diseño de Patrones Singleton en Python
Semántica de Prefijos en Lenguajes de Programación
Evaluación de Expresiones Infix en Python
Condicionales en Lenguajes de Programación
Evaluación del Statement Return en Python
Manejo de Errores Semánticos en Lenguajes de Programación
Declaración de Variables y Ambientes en Lenguajes de Programación
Entornos y Cláusulas en Python: Manejo y Error Handling Avanzado
Declaración de Procedimientos en Lenguaje Platzi
Implementación y uso de closures en Platzi Programming
Mejora del intérprete
Implementación de strings en un intérprete Python
Operaciones en Strings: Concatenación y Comparación
Construcción de Funciones Built-in en Python
Función Longitud en Lenguaje Platzi
Siguientes pasos
Creación de Listas y Diccionarios en Python Avanzado
Construcción de intérpretes con Python desde cero
No tienes acceso a esta clase
¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera
Los lenguajes de programación funcionan con estructuras llamadas ambientes. Un ambiente es, esencialmente, un diccionario que almacena nombres de variables y sus valores asociados. Esta estructura es fundamental para que los programas puedan acceder y modificar estos valores según sea necesario. Al definir nuevos valores o acceder a ellos, los ambientes juegan un rol crucial. En particular, cuando hablamos de funciones, estas generan su propio ambiente, conocido como closures. Este concepto está estrechamente relacionado con el scope, o el ámbito de visibilidad de variables dentro de un programa.
En el diseño de un lenguaje de programación, es crucial manejar adecuadamente las situaciones en las que ocurren errores. Existen dos tipos principales de errores que debemos considerar:
La implementación de errores y la declaración de variables se logra mediante una serie de pasos en el código. Vamos a explorar cómo estructurar esto en Python:
# Declaramos un nuevo tipo de error para identificadores desconocidos
def error_identifier_desconocido(identificador):
return f"Identificador no encontrado: {identificador}"
# Evaluación de nodos let statement
def evaluar_let_statement(nodo, ambiente):
if nodo.tipo == 'ASTLetStatement': # Verificamos el tipo de nodo
valor_evaluado = evaluar(nodo.valor, ambiente) # Evaluación recursiva del valor
nombre_variable = nodo.nombre
ambiente[nombre_variable] = valor_evaluado # Guardamos el valor en el ambiente
# Evaluación de nodos identifier
def evaluar_identifier(nodo, ambiente):
try:
return ambiente[nodo.nombre] # Intentamos obtener el valor del ambiente
except KeyError:
raise error_identifier_desconocido(nodo.nombre) # Manejamos el error si no existe
El Read-Eval-Print Loop (REPL) es una herramienta fantástica para ejecutar código interactivo. Sin embargo, un REPL funcional debe manejar adecuadamente múltiples líneas de código. Para ello, ajustamos el REPL para recordar y procesar líneas anteriores, permitiendo la ejecución de programas más complejos:
# Inicializamos una lista para escanear
scan = []
# Función para manejar múltiples líneas
def manejar_multilineas_entrada(source, scanner):
scanner.append(source) # Almacenamos el source actual
return "\n".join(scanner)
# Uso en REPL
while True:
entrada = input(">> ")
programa_completo = manejar_multilineas_entrada(entrada, scan)
resultado = execute(programa_completo)
print(resultado)
Este código nos permite declarar variables, realizar operaciones aritméticas y almacenar resultados. Ahora, el REPL puede operar de manera efectiva con múltiples líneas y manejar variables a través de sesionas, mejorando significativamente la experiencia de codificación.
Nuestra aventura en la creación de un lenguaje de programación aún no termina. Aunque hemos logrado declarar variables, hacer operaciones aritméticas y manejar condiciones, aún falta un elemento esencial: las funciones. Las funciones nos permitirán reutilizar código y estructuras lógicas más complejas. Esto lo abordaremos en la próxima clase, llevando nuestro lenguaje a un nuevo nivel de funcionalidad.
Si tienes preguntas, comentarios o simplemente deseas compartir cómo va tu progreso, te invitamos a expresarlo. Construir un lenguaje de programación no es tarea fácil, y cada paso es un gran logro. ¡Sigue aprendiendo y explorando este apasionante mundo!
Aportes 6
Preguntas 0
Ahhhhh!!! ¡Ya tiene vida SigmaF! 😱
Me emocioné mucho cuando vi el multilínea funcionando, pero después me di cuenta de que si metes un error y quieres continuar, aunque o que escribas ahora esté bien, el error anterior sigue ahí.
¡Siiiiiiiiiii! Ahhhhhh que emocionanteeeeee, y creo que lo más emocionante es saber cómo funciona por dentro, y lo aún más emocionante es saber que puedo modificarlo y meterle cosas nuevas!!!
.
Pero mira que hermoso se ve, mira que bonito se ven todos esos tests pasando 🥺❤
.
Me siento como el meme de megamente “lo logre” jajajaja. Estoy ansioso de saber aun mas cosas para enriquecer el lenguaje de programación! =)
En el momento que escribí variable a = 5; variable b = 10; variable c = a + b; c;
y le di enter y vi un 15
. Dije ¡Whoaa! Tuve la sensación de que todos los esfuerzos realizados hasta este punto habrían valido la pena.
Uuuuh, que emoción ver como todo va funcionando correctamente
¿Quieres ver más aportes, preguntas y respuestas de la comunidad?