Skip to content

Instantly share code, notes, and snippets.

@justinfay
Created January 23, 2017 11:05
Show Gist options
  • Select an option

  • Save justinfay/1144c56eacbfb982777225f23a2f80ff to your computer and use it in GitHub Desktop.

Select an option

Save justinfay/1144c56eacbfb982777225f23a2f80ff to your computer and use it in GitHub Desktop.
"""
Taken from: https://learnxinyminutes.com/docs/brainfuck/
There are eight commands:
+ : Increments the value at the current cell by one.
- : Decrements the value at the current cell by one.
> : Moves the data pointer to the next cell (cell on the right).
< : Moves the data pointer to the previous cell (cell on the left).
. : Prints the ASCII value at the current cell (i.e. 65 = 'A').
, : Reads a single input character into the current cell.
[ : If the value at the current cell is zero, skips to the corresponding ] .
Otherwise, move to the next instruction.
] : If the value at the current cell is zero, move to the next instruction.
Otherwise, move backwards in the instructions to the corresponding [ .
[ and ] form a while loop. Obviously, they must be balanced.
"""
import sys
INCREMENT = '+'
DECREMENT = '-'
MOVER = '>'
MOVEL = '<'
PRINT = '.'
READ = ','
WHILE_START = '['
WHILE_END = ']'
OPERATIONS = (
INCREMENT,
DECREMENT,
MOVER,
MOVEL,
PRINT,
READ,
WHILE_START,
WHILE_END)
TAPE = [0]*30000
def lex(stream):
return [char for char in stream if char in OPERATIONS]
def parse(tokens):
index = 0
# A stack of executed instructions.
stack = []
while True:
try:
next_ = tokens.pop(0)
except IndexError:
break
else:
stack.append(next_)
if next_ == INCREMENT:
TAPE[index] += 1
elif next_ == DECREMENT:
TAPE[index] -= 1
elif next_ == MOVER:
index += 1
elif next_ == MOVEL:
if index == 0:
raise RuntimeError()
index -= 1
elif next_ == PRINT:
print(chr(TAPE[index]), end='')
elif next_ == READ:
TAPE[index] = ord(sys.stdin.read(1))
elif next_ == WHILE_START:
if TAPE[index] == 0:
# Skip to matching ']'.
while True:
n = tokens.pop(0)
if n == WHILE_END:
tokens.insert(0, n)
break
stack.append(n)
elif next_ == WHILE_END:
if TAPE[index] != 0:
# Go back to opening '['.
while True:
n = stack.pop()
tokens.insert(0, n)
if n == WHILE_START:
break
def read_file(path):
with open(path) as fh:
return fh.read()
if __name__ == "__main__":
path = sys.argv[1]
parse(lex(read_file(path)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment