#! python 2.7 """ V: 0.7 Brainf**k Compiler bfInterpreter06.py Last edit was Tuesday, November 14th, 2017 Jacob DiDiodato An interpreter for the brainf**k language written by Urban Muller Supports the basic instructions for brainf**k as well as a few instructions I have implemented Program size has been reduced by ~12 times from version 0.0 This interpreter should not be used when time is tight as it does take a long time to execute most instructions If you find any bugs with this interpreter please PM me with the error message and steps to recreate the problem ----------------V0.7 PATCHNOTES---------------- Made the program slightly more efficient by precalculating upper and lower bounds on tape increments. -> Takes slightly more time to compile Ascii mandelbrot fractal took 286.495 seconds as opposed to 294.403 that it took with the last version ----------------------------------------------- Note: This program relies on you having and using Python 2.7. It is almost certain that this won't work on Python 3.X. If you are using Python 3.X and refuse/don't understand how to change Python versions then consider using 2to3 which is a Python program that will change the Python 2.X semantics to Python 3.X, also be aware that is is UB in terms of my program so I can't guarantee that will work either. Just change to Python 2.7 :P My apologies if I forgot to censor a f**k, I checked through this document a few times and it is written uncensored. --SYMBOLS IN BRAINF**K-- > - Move the tape pointer over 1 cell towards positive direction < - Move the tape pointer over 1 cell towards negative direction + - Increments the current unit of tape by 1 - - Decrements the current unit of tape by 1 . - Prints the value of the current tape , - Takes an input from stdio and reads the decimal value into the current cell [ - If the cell under the tape pointer is pointing to zero (or less?) then jump to (and pass) the matching square bracket ] - Jump back to the matching square bracket unless the cell that the tape pointer is pointing to is zero (or less?) ------------------------ -----EXTRA SYMBOLS----- / - Clears the current unit of tape (i.e sets it to zero) * - Sets the current unit of tape to 255 | - Sets the current unit of tape to 128 { - If the cell that the tape pointer is pointing to is zero (or less?) then jump to (and pass) the matching curly bracket } - Required to end the conditional block ------------------------ """ import os, sys def checkClosed(srcText): stack = [] i = 0 numInstructions = len(srcText) while i < numInstructions: try: if (srcText[i] == "[" or srcText[i] == "{"): stack.append(srcText[i]) elif (srcText[i] == "]" or srcText[i] == "}") and srcText[i] == chr(ord(stack.pop())): return -1 except IndexError: print "Error: Forgot to open loop or conditional." return -1 i += 1 return 0 def interpret(srcText): runningTab = "" repeat = 1 i = 0 open("pySrc.py", "w").close() pySrc = open("pySrc.py", "a") pySrc.write("#! python 2.7\nfrom __future__ import print_function\n\ntape = [0] * 30000\ncurrentCell = 15000\n\n") numInstructions = len(srcText) while i < numInstructions: if srcText[i] == ">": try: while srcText[i + 1] == ">": repeat += 1 i += 1 except IndexError: pass upperBound = 29999 - repeat pySrc.write(runningTab + "if (currentCell <= " + str(upperBound) + "):\n") pySrc.write(runningTab + "\tcurrentCell += " + str(repeat) + "\n") elif srcText[i] == "<": try: while srcText[i + 1] == "<": repeat += 1 i += 1 except IndexError: pass lowerBound = 0 + repeat pySrc.write(runningTab + "if (currentCell >= " + str(lowerBound) + "):\n") pySrc.write(runningTab + "\tcurrentCell -= " + str(repeat) + "\n") elif srcText[i] == "+": try: while srcText[i + 1] == "+": repeat += 1 i += 1 except IndexError: pass pySrc.write(runningTab + "tape[currentCell] += " + str(repeat) + "\n") elif srcText[i] == "-": try: while srcText[i + 1] == "-": repeat += 1 i += 1 except IndexError: pass pySrc.write(runningTab + "tape[currentCell] -= " + str(repeat) + "\n") elif srcText[i] == ".": pySrc.write(runningTab + "print(chr(tape[currentCell]), end = '')\n") elif srcText[i] == ",": pySrc.write(runningTab + "userInput = raw_input('')\n" + runningTab + "for i in range(len(userInput)):\n" + runningTab + "\ttape[currentCell] = ord(userInput[i])\n" + runningTab + "\tcurrentCell += 1\n") elif srcText[i] == "[": pySrc.write(runningTab + "while tape[currentCell] > 0:\n") runningTab += "\t" try: if srcText[i + 1] == "]": pySrc.write(runningTab + "pass\n") except IndexError: print "Error: Forgot to close loop." pySrc.close() os.remove("pySrc.py") raise SystemExit elif srcText[i] == "]": runningTab = runningTab[0:len(runningTab) - 1] elif srcText[i] == "{": pySrc.write(runningTab + "if tape[currentCell] > 0:\n") runningTab += "\t" try: if srcText[i + 1] == "}": pySrc.write(runningTab + "pass\n") except IndexError: print "Error: Forgot to close conditional." pySrc.close() os.remove("pySrc.py") raise SystemExit elif srcText[i] == "}": runningTab = runningTab[0:len(runningTab) - 1] elif srcText[i] == "/": pySrc.write(runningTab + "tape[currentCell] = 0\n") elif srcText[i] == "*": pySrc.write(runningTab + "tape[currentCell] = 255\n") elif srcText[i] == "|": pySrc.write(runningTab + "tape[currentCell] = 128\n") repeat = 1 i += 1 pySrc.close() os.system("python pySrc.py") os.remove("pySrc.py") def main(): #Get the filename from the cmd arguments try: filename = str(sys.argv[1]) except: print "Usage: python " + sys.argv[0] + " " else: #check if the file exists try: #Open the file src = open(filename, "r") except IOError: #Give an English definition of the error print "The file \"" + filename + "\" does not exist." else: retval = checkClosed(src.read()) if (retval == 0): src.seek(0) interpret(src.read()) if __name__ == "__main__": main()