Skip to content

Instantly share code, notes, and snippets.

@wasabili
Created November 21, 2010 14:30
Show Gist options
  • Save wasabili/708773 to your computer and use it in GitHub Desktop.
Save wasabili/708773 to your computer and use it in GitHub Desktop.
Whitespace Interpreter
import sys
class Stream:
def __init__(self, data):
self.data = list(data)
self.seeker = 0
self.length = len(self.data)
self.labels = {}
self.update()
def update(self):
self.token = self.data[self.seeker]
def next(self):
self.seeker += 1
self.update()
#if self.token not in (SPACE, LF, TAB):
# self.next()
def mark(self, label):
self.labels[label] = self.seeker
def jump(self, label):
self.seeker = self.labels[label]
def hasnext(self):
return not self.seeker == self.length -1
SPACE = ' '
TAB = '\t'
LF = '\n'
class Whitespace:
def __init__(self, data):
self.stack = []
self.stream = Stream(data)
def eval(self):
while self.stream.hasnext():
self.imp()
def imp(self):
if self.stream.token == SPACE:
self.stream.next()
self.stack_manipulation()
elif self.stream.token == LF:
self.stream.next()
self.flow_control()
else:
self.stream.next()
if self.stream.token == SPACE:
self.stream.next()
self.arithmetic()
elif self.stream.token == TAB:
self.stream.next()
self.heap_access()
elif self.stream.token == LF:
self.stream.next()
self.io()
def stack_manipulation(self):
if self.stream.token == SPACE:
self.stream.next()
var = self.get_num()
stack.append(var)
elif self.stream.token == LF:
self.stream.next()
if self.stream.token == SPACE:
self.stream.next()
var = self.stack[-1]
self.stack.append(var)
elif self.stream.token == TAB:
self.stream.next()
a = self.stack.pop()
b = self.stack.pop()
self.stack.append(a)
self.stack.append(b)
elif self.stream.token == LF:
self.stream.next()
self.stack.pop()
elif self.stream.token == TAB:
self.stream.next()
if self.stream.token == SPACE:
self.stream.next()
var = self.get_num()
a = self.stack[-var]
self.stack.append(a)
elif self.stream.token == LF:
self.stream.next()
var = self.get_num()
self.stack = self.stack[:-(var+1)]+self.stack[-1]
def arithmetic(self):
if self.stream.token == SPACE:
self.stream.next()
if self.stream.token == SPACE:
self.stream.next()
a = self.stack.pop()
b = self.stack.pop()
self.stack.append(a+b)
elif self.stream.token == TAB:
self.stream.next()
a = self.stack.pop()
b = self.stack.pop()
self.stack.append(b-a)
elif self.stream.token == LF:
self.stream.next()
a = self.stack.pop()
b = self.stack.pop()
self.stack.append(a*b)
elif self.stream.token == TAB:
self.stream.next()
if self.stream.token == SPACE:
self.stream.next()
a = self.stack.pop()
b = self.stack.pop()
self.stack.append(b/a)
elif self.stream.token == TAB:
self.stream.next()
a = self.stack.pop()
b = self.stack.pop()
self.stack.append(b%a)
def heap_access(self):
print 'Unsupported'
def flow_control(self):
if self.stream.token == SPACE:
self.stream.next()
if self.stream.token == SPACE:
self.stream.next()
var = self.get_num()
self.stream.mark(var)
elif self.stream.token == TAB:
self.stream.next()
print 'Unsupported'
elif self.stream.token == LF:
self.stream.next()
var = self.get_num()
self.stream.jump(var)
elif self.stream.token == TAB:
self.stream.next()
if self.stream.token == SPACE:
self.stream.next()
var = self.get_num()
if self.stack[-1] == 0:
self.stream.jump(var)
elif self.stream.token == TAB:
self.stream.next()
var = self.get_num()
if self.stack[-1] < 0:
self.stream.jump(var)
elif self.stream.token == LF:
self.stream.next()
print 'Unsupported'
elif self.stream.token == LF:
self.stream.next()
if self.stream.token == LF:
self.stream.next()
sys.exit(0)
def io(self):
if self.stream.token == SPACE:
self.stream.next()
if self.stream.token == SPACE:
self.stream.next()
sys.stdout.write(chr(self.stack[-1]))
elif self.stream.token == TAB:
self.stream.next()
sys.stdout.write(self.stack[-1])
elif self.stream.token == TAB:
self.stream.next()
if self.stream.token == SPACE:
self.stream.next()
var = ord(sys.stdin.read(1))
self.stack.append(var)
elif self.stream.token == TAB:
self.stream.next()
var = int(sys.stdin.read(1))
self.stack.append(var)
def get_num(self):
if self.stream.token == SPACE:
sign = 1
elif self.stream.token == TAB:
sign = -1
self.stream.next()
var = 0
while not self.stream.token == LF:
if self.stream.token == SPACE:
var *= 2
elif self.stream.token == TAB:
var *= 2
var += 1
self.stream.next()
self.stream.next()
return var
if __name__ == '__main__':
data = raw_input()
Whitespace(data).eval()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment