Una vez escribí una historia sobre un hombre que era herido y llevado a un hospital. Cuando empezaban a operarlo, descubrían que era un androide, no un humano, pero él no lo sabía. Ellos debían revelarle la verdad. Casi al tiempo, el señor Garson Poole descubrió que su realidad consistía de una cinta agujereada que viajaba de carrete a carrete en su pecho. Fascinado, empezó a llenar algunos de los agujeros y a añadir otros más. De inmediato, su mundo cambió. Una bandada de patos voló a través de la habitación cuando abrió un nuevo agujero en la cinta. Finalmente, cortó la cinta de pleno, y el mundo desapareció. Sin embargo, también desaparecieron los otros personajes de la historia…
El párrafo anterior corresponde a un relato de Philip K. Dick titulado Cómo construir un universo que no se derrumbe en dos dias. Con esta entrada quiero empezar una serie de posts sobre lenguajes de programación. Para empezar, he escogido hacer un intérprete sencillo para el lenguaje Brainfuck.
¿Qué es un intérprete?
Un intérprete es un programa que traduce el código que le pasamos como entrada y muestra el resultado. Al contrario que un compilador, que traduce la entrada a código máquina para ser ejecutado. Para hacer nuestro intérprete, hemos elegido el lenguaje python.
¿Qué es Brainfuck?
Brainfuck es un lenguaje de programación, de los denominados esotéricos, que sólo tiene 8 símbolos o intrucciones y con una sintaxis muy sencilla. El espacio de memoria consiste en un vector inicializado a cero y un puntero que señala la primera posición del vector.
No resulta un lenguaje práctico, pero es muy interesante y además se puede aprender en cinco minutos. Veamos el léxico:
‘>’ : Incrementa la posición del puntero.
‘<‘: Decrementa la posición del puntero.
‘+’: Incrementa el valor de la celda señalada por el puntero.
‘-‘: Decrementa el valor de la celda señalada por el puntero.
‘.’: Muestra por pantalla el valor de la celda señalada por el puntero.
‘,’: Lee un valor y lo almacena en la celda señalada por el puntero.
‘[‘: Inicio del bucle
‘]’: Fin del bucle
Nuestro intérprete
Tenemos un vector llamado espacio, con 1024 elementos, inicializado a cero. La variable ptr apunta inicialmente a la primera posición del vector. Vamos recorriendo la cadena de entrada carácter a carácter gracias a la variable pos_token.
# FUNCION def interprete(entrada): pos_token = 0 espacio = [0]*1024 ptr = 0 pos = [] len_entrada = len(entrada) while (pos_token < len_entrada): aux = entrada[pos_token] if (aux == ‘>’): ptr = ptr+1 elif(aux == ‘<‘): ptr = ptr-1 elif (aux == ‘+’): espacio[ptr] = espacio[ptr]+1 elif (aux == ‘-‘): espacio[ptr] = espacio[ptr]-1 elif (aux == ‘.’): print «%s» % (chr(int(espacio[ptr]))) elif (aux == ‘,’): espacio[ptr] = raw_input() elif (aux == ‘[‘): pos.append(pos_token) elif (aux == ‘]’): if (espacio[ptr] != 0): pos_token = pos[-1] else: pos.pop() else: continue pos_token = pos_token + 1 return # MAIN print(«Introduzca q para salir») entrada = raw_input(«Entrada: «) while (entrada != «q»): interprete(entrada) entrada = raw_input(«Entrada: «)
Resultados
En lugar de imprimir el clásico «Hello world!» vamos a cambiar un poco mostrando «CULTURAWEB». En Brainfuck, debemos imprimir el código ASCII. Para la ‘C’ es el 76, para la ‘U’ es el 85, etc. Para ello haremos un bucle. La primera posición será el contador o número de veces que se ejecutará, 10. En las celda siguientes pondremos la cifra de las decenas, 6,8,7, etc. Luego iremos recorriendo las celdas, incrementando su valor hasta llegar al número ASCII del carácter e imprimiendo por pantalla.
++++++++++[>++++++>++++++++>+++++++>++++++++>++++++++>++++++++>++++++>++++++++>++++++>++++++<<<<<<<<<<-]>+++++++.>+++++.>++++++.>++++.>+++++.>++.>+++++.>+++++++.>+++++++++.>++++.
El código anterior produce el siguiente resultado:
C U L T U R A W E B
Conclusiones
El intérprete es muy simple y no comprueba errores léxicos ni sintácticos. En siguientes ediciones de Cómo construir un universo que no se derrumbe en dos días iremos avanzado en conceptos sobre los lenguajes de programación. F***