-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbf.py
More file actions
executable file
·132 lines (108 loc) · 3.25 KB
/
bf.py
File metadata and controls
executable file
·132 lines (108 loc) · 3.25 KB
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import re
import sys
from collections import deque
'''
get from github jcharra/ook
'''
class Tape(object):
def __init__(self):
self.cells = deque([0])
self.index = 0
def right(self):
self.index += 1
if self.index == len(self.cells):
self.cells.append(0)
def left(self):
self.index -= 1
if self.index < 0:
self.index = 0
self.cells.appendleft(0)
def inc(self):
self.cells[self.index] += 1
def dec(self):
self.cells[self.index] -= 1
def get(self):
return self.cells[self.index]
def set(self, val):
self.cells[self.index] = val
def __repr__(self):
return " ".join([str(x) for x in self.cells])
class BFInterpreter(object):
def __init__(self):
self.tape = Tape()
self.commands = []
def run_commands(self, cmds):
self.commands = cmds
self.command_index = 0
try:
while True:
self.execute_next()
except IndexError:
pass
def execute_next(self):
cmd = self.commands[self.command_index]
if cmd == '[':
if not self.tape.get():
self.goto_matching_paren(1)
return
elif cmd == ']':
if self.tape.get():
self.goto_matching_paren(-1)
return
else:
self.interpret(cmd)
self.command_index += 1
def goto_matching_paren(self, direction):
onstack = 1
while onstack:
self.command_index += direction
if self.commands[self.command_index] == ']':
onstack -= direction
elif self.commands[self.command_index] == '[':
onstack += direction
self.command_index += 1
def interpret(self, item):
if item == '+':
self.tape.inc()
elif item == '-':
self.tape.dec()
elif item == '>':
self.tape.right()
elif item == '<':
self.tape.left()
elif item == '.':
sys.stdout.write(chr(self.tape.get()))
elif item == ',':
try:
val = int(raw_input())
self.tape.set(val)
except:
# Ignore invalid input
pass
ook2bf = {('ook.', 'ook.'): '+',
('ook!', 'ook!'): '-',
('ook!', 'ook.'): '.',
('ook.', 'ook!'): ',',
('ook.', 'ook?'): '>',
('ook?', 'ook.'): '<',
('ook!', 'ook?'): '[',
('ook?', 'ook!'): ']'}
OOK_REGEX = "(ook[\.\!\?])\s*(ook[\.\!\?])"
def convertOokToBF(bf_input):
output = []
for match in re.findall(OOK_REGEX, bf_input.lower()):
if match in ook2bf:
output.append(ook2bf[match])
return "".join(output)
def print_usage():
print "\nUsage: python bf.py [-b|-o] <INPUT_FILE>\n"
if __name__ == '__main__':
if len(sys.argv) < 3 or sys.argv[1] not in ("-o", "-b"):
print_usage()
sys.exit()
fname = sys.argv[2]
listing = file(fname, 'r').read()
if sys.argv[1] == "-o":
listing = convertOokToBF(listing)
interpreter = BFInterpreter()
interpreter.run_commands(listing)