Guest User

Untitled

a guest
Jul 23rd, 2018
89
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.03 KB | None | 0 0
  1. class Scanner():
  2.  
  3. def __init__(self, source):
  4. self.source = source
  5. self.position = 0
  6. self.buffer = ''
  7. self.line = 1
  8.  
  9. def current(self):
  10. return self.source[self.position]
  11.  
  12. def next(self):
  13. self.position += 1
  14. return self.current()
  15.  
  16. def reset(self):
  17. self.buffer = ''
  18.  
  19. def save(self):
  20. self.buffer = self.buffer + self.current()
  21.  
  22. def is_operand(self, token):
  23. return ":;[].+-=".find(token) != -1
  24.  
  25. def scan(self):
  26. try:
  27. while True:
  28. # Eat EOL's but keep track of the line number
  29. if self.current() == "\n" or self.current == "\r":
  30. self.next()
  31. self.line += 1
  32. # Regular whitespace consumption
  33. elif self.current().isspace():
  34. while self.current().isspace():
  35. self.next()
  36. # Return an operand as a parse token
  37. elif self.is_operand(self.current()):
  38. token = self.current()
  39. self.next()
  40. return (token, self.line)
  41. # Return an integer value
  42. elif self.current().isdigit():
  43. self.reset()
  44. while self.current().isdigit():
  45. self.save()
  46. self.next()
  47. return (int(self.buffer), self.line)
  48. else:
  49. raise SyntaxError, "Unknown input `%s' on line %d" % (self.current(), self.line)
  50. except IndexError:
  51. return (False, self.line)
  52.  
  53. class Parser():
  54.  
  55. def __init__(self, scanner):
  56. self.scanner = scanner
  57. self.reset()
  58.  
  59. def reset(self):
  60. self.ast = []
  61. self.quote_stack = [self.ast]
  62.  
  63. def save(self, node):
  64. self.quote_stack[-1].append(node)
  65.  
  66. def parse(self):
  67. token, line = self.scanner.scan()
  68. while token != False:
  69. if token == '[':
  70. self.quote_stack[-1].append([])
  71. self.quote_stack.append(self.quote_stack[-1][-1])
  72. elif token == ']':
  73. if len(self.quote_stack) == 1:
  74. raise SyntaxError, "quote underflow on line %d" % (line,)
  75. self.quote_stack.pop()
  76. else:
  77. self.quote_stack[-1].append(token)
  78. token, line = self.scanner.scan()
  79. return self.ast
  80.  
  81. class Compiler():
  82.  
  83. def __init__(self, ast):
  84. self.ast = ast
  85. self.base = 0
  86. self.offset = 0
  87. self.code = []
  88.  
  89. def emit(self, bytes):
  90. bytes = ["{0:02X}".format(byte) for byte in bytes]
  91. for byte in bytes:
  92. self.code.append(byte)
  93.  
  94. def compile(self, tree):
  95. size = 0
  96. for node in tree:
  97. if type(node) is int:
  98. self.emit([0xa9, node, 0x48])
  99. self.offset += 3
  100. size += 3
  101. elif type(node) is str:
  102. if node == '.':
  103. self.emit([0x68, 0x20, 0xee, 0xff])
  104. self.offset += 4
  105. size += 4
  106. elif node == '+':
  107. self.emit([0x68, 0x85, 0x00, 0x68, 0x65, 0x00, 0x48])
  108. self.offset += 7
  109. size += 7
  110. else:
  111. raise SyntaxError, "unknown word"
  112. elif type(node) is list:
  113. # push high byte of offset
  114. self.emit([0xa9, (self.offset & 0xff00) >> 8, 0x48])
  115. # push low byte of offset
  116. self.emit([0xa9, self.offset & 0xff, 0x48])
  117. self.offset += 6
  118. size += 6
  119. self.compile(node)
  120. else:
  121. raise SyntaxError, "unknown node"
  122. self.emit([0])
  123. print "".join(self.code)
  124. return size
  125.  
  126. if __name__ == '__main__':
  127. scanner = Scanner("33 32 + . ")
  128. parser = Parser(scanner)
  129. ast = parser.parse()
  130. compiler = Compiler(ast)
  131. compiler.compile(ast)
Add Comment
Please, Sign In to add comment