-
Notifications
You must be signed in to change notification settings - Fork 0
/
BrainFuck.py
84 lines (78 loc) · 2.37 KB
/
BrainFuck.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
import sys
# In case you done goof
class CompileExcpetion(Exception):
pass
class RuntimeException(Exception):
pass
def BrainFuck(code):
# strip all of the non executable characters
code = ''.join(c for c in code if c in '<>,.+-[]')
# make sure while loops are correct
braceCount = 0
loop_stack = [] # queue for while loop jump 'pointers'
loop_lookup = {} # dictionary to store the while loop jumps
for x in range(len(code)):
if code[x] == '[':
braceCount += 1
loop_stack.append(x)
elif code[x] == ']':
braceCount -= 1
# all looping pointers are stored in this dictionary.
# since python dictionaries are O(1), this is the easiest opition
start = loop_stack.pop()
loop_lookup[x] = start - 1
loop_lookup[start] = x
if braceCount < 0:
raise CompileExcpetion("ERROR: Miss matched braces.")
if braceCount != 0:
raise CompileExcpetion("ERROR: Expected another ] somewhere.")
# Alright, lets start the actual program
memory = [0]*30000 # as defined by Urban Meuller, the dude who made BrainFuck
mem_ptr = 0 # points to current block of memory
code_ptr = 0 # points to current executable byte
while(code_ptr != len(code)):
# increment block
if code[code_ptr] == '+':
memory[mem_ptr] += 1
if memory[mem_ptr] >= 256:
raise RuntimeException("Integer Overflow")
# decrement block
elif code[code_ptr] == '-':
memory[mem_ptr] -= 1
if memory[mem_ptr] < 0:
raise RuntimeException("Integer Underflow")
# move pointer one block to the right
elif code[code_ptr] == '>':
mem_ptr += 1
if mem_ptr > 30000:
raise RuntimeException("Over memory bounds")
# move pointer one block to the left
elif code[code_ptr] == '<':
mem_ptr -= 1
if mem_ptr < 0:
raise RuntimeException("Under memory bounds")
# write character
elif code[code_ptr] == '.':
sys.stdout.write(chr(memory[mem_ptr]))
# read character
elif code[code_ptr] == ',':
memory[mem_ptr] = ord(sys.stdin.read(1))
# loop start
elif code[code_ptr] == '[':
if memory[mem_ptr] == 0:
code_ptr = loop_lookup[code_ptr]
# loop ending
elif code[code_ptr] == ']':
code_ptr = loop_lookup[code_ptr]
code_ptr += 1
if __name__ == '__main__':
if len(sys.argv) != 2:
print "Usage: python BrainFuck.py <brain_fuck_source>"
exit()
try:
f = open(sys.argv[1])
except IOError:
print "Error reading file: " + sys.argv[1]
exit()
code = f.read()
BrainFuck(code)