Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- class Scanner():
- def __init__(self, source):
- self.source = source
- self.position = 0
- self.buffer = ''
- self.line = 1
- def current(self):
- return self.source[self.position]
- def next(self):
- self.position += 1
- return self.current()
- def reset(self):
- self.buffer = ''
- def save(self):
- self.buffer = self.buffer + self.current()
- def is_operand(self, token):
- return ":;[].+-=".find(token) != -1
- def scan(self):
- try:
- while True:
- # Eat EOL's but keep track of the line number
- if self.current() == "\n" or self.current == "\r":
- self.next()
- self.line += 1
- # Regular whitespace consumption
- elif self.current().isspace():
- while self.current().isspace():
- self.next()
- # Return an operand as a parse token
- elif self.is_operand(self.current()):
- token = self.current()
- self.next()
- return (token, self.line)
- # Return an integer value
- elif self.current().isdigit():
- self.reset()
- while self.current().isdigit():
- self.save()
- self.next()
- return (int(self.buffer), self.line)
- else:
- raise SyntaxError, "Unknown input `%s' on line %d" % (self.current(), self.line)
- except IndexError:
- return (False, self.line)
- class Parser():
- def __init__(self, scanner):
- self.scanner = scanner
- self.reset()
- def reset(self):
- self.ast = []
- self.quote_stack = [self.ast]
- def save(self, node):
- self.quote_stack[-1].append(node)
- def parse(self):
- token, line = self.scanner.scan()
- while token != False:
- if token == '[':
- self.quote_stack[-1].append([])
- self.quote_stack.append(self.quote_stack[-1][-1])
- elif token == ']':
- if len(self.quote_stack) == 1:
- raise SyntaxError, "quote underflow on line %d" % (line,)
- self.quote_stack.pop()
- else:
- self.quote_stack[-1].append(token)
- token, line = self.scanner.scan()
- return self.ast
- class Compiler():
- def __init__(self, ast):
- self.ast = ast
- self.base = 0
- self.offset = 0
- self.code = []
- def emit(self, bytes):
- bytes = ["{0:02X}".format(byte) for byte in bytes]
- for byte in bytes:
- self.code.append(byte)
- def compile(self, tree):
- size = 0
- for node in tree:
- if type(node) is int:
- self.emit([0xa9, node, 0x48])
- self.offset += 3
- size += 3
- elif type(node) is str:
- if node == '.':
- self.emit([0x68, 0x20, 0xee, 0xff])
- self.offset += 4
- size += 4
- elif node == '+':
- self.emit([0x68, 0x85, 0x00, 0x68, 0x65, 0x00, 0x48])
- self.offset += 7
- size += 7
- else:
- raise SyntaxError, "unknown word"
- elif type(node) is list:
- # push high byte of offset
- self.emit([0xa9, (self.offset & 0xff00) >> 8, 0x48])
- # push low byte of offset
- self.emit([0xa9, self.offset & 0xff, 0x48])
- self.offset += 6
- size += 6
- self.compile(node)
- else:
- raise SyntaxError, "unknown node"
- self.emit([0])
- print "".join(self.code)
- return size
- if __name__ == '__main__':
- scanner = Scanner("33 32 + . ")
- parser = Parser(scanner)
- ast = parser.parse()
- compiler = Compiler(ast)
- compiler.compile(ast)
Add Comment
Please, Sign In to add comment