lol its in c
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

227 lines
7.5 KiB

  1. import sys
  2. import re
  3. ## Need to convert asxxxx syntax to rgbds syntax
  4. module = sys.argv[1]
  5. class Token:
  6. def __init__(self, kind, value, line_nr):
  7. self.kind = kind
  8. self.value = value
  9. self.line_nr = line_nr
  10. def isA(self, kind, value=None):
  11. return self.kind == kind and (value is None or value == self.value)
  12. def __repr__(self):
  13. return "[%s:%s:%d]" % (self.kind, self.value, self.line_nr)
  14. class Tokenizer:
  15. TOKEN_REGEX = re.compile('|'.join('(?P<%s>%s)' % pair for pair in [
  16. ('HEX', r'0x[0-9A-Fa-f]+'),
  17. ('ASSIGN', r'='),
  18. ('ALABEL', r'\d+\$'),
  19. ('NUMBER', r'\d+(\.\d*)?'),
  20. ('COMMENT', r';[^\n]*'),
  21. ('LABEL', r':+'),
  22. ('EXPR', r'#'),
  23. ('STRING', '"[^"]*"'),
  24. ('DIRECTIVE', r'\.[A-Za-z_][A-Za-z0-9_\.]*'),
  25. ('ID', r'[A-Za-z_][A-Za-z0-9_\.]*'),
  26. ('OP', r'[+\-*/,\(\)<>]'),
  27. ('NEWLINE', r'\n'),
  28. ('SKIP', r'[ \t]+'),
  29. ('MISMATCH', r'.'),
  30. ]))
  31. def __init__(self, code):
  32. self.__tokens = []
  33. line_num = 1
  34. for mo in self.TOKEN_REGEX.finditer(code):
  35. kind = mo.lastgroup
  36. value = mo.group()
  37. if kind == 'MISMATCH':
  38. print("ERR:", code.split("\n")[line_num-1])
  39. raise RuntimeError("Syntax error on line: %d: %s\n%s", line_num, value)
  40. elif kind == 'SKIP':
  41. pass
  42. else:
  43. if kind == 'HEX':
  44. value = "$" + value[2:]
  45. if kind == 'ALABEL':
  46. value = "._ANNO_" + value[:-1]
  47. kind = "ID"
  48. self.__tokens.append(Token(kind, value, line_num))
  49. if kind == 'NEWLINE':
  50. line_num += 1
  51. self.__tokens.append(Token('NEWLINE', '\n', line_num))
  52. def peek(self):
  53. return self.__tokens[0]
  54. def pop(self):
  55. return self.__tokens.pop(0)
  56. def expect(self, kind, value=None):
  57. pop = self.pop()
  58. if not pop.isA(kind, value):
  59. if value is not None:
  60. raise SyntaxError("%s != %s:%s" % (pop, kind, value))
  61. raise SyntaxError("%s != %s" % (pop, kind))
  62. def __bool__(self):
  63. return bool(self.__tokens)
  64. tok = Tokenizer(sys.stdin.read())
  65. def processExpression():
  66. while True:
  67. t = tok.peek()
  68. if t.isA('EXPR'):
  69. tok.pop()
  70. t = tok.peek()
  71. if t.isA('OP', '<'):
  72. sys.stdout.write('LOW')
  73. tok.pop()
  74. t = tok.peek()
  75. if t.isA('OP', '>'):
  76. sys.stdout.write('HIGH')
  77. tok.pop()
  78. t = tok.peek()
  79. if t.isA('OP', '('):
  80. tok.pop()
  81. sys.stdout.write('(')
  82. processExpression()
  83. t = tok.pop()
  84. assert t.isA('OP', ')')
  85. sys.stdout.write(')')
  86. if t.isA('ID') and t.value.startswith("b_"):
  87. t.value = "BANK(%s)" % (t.value[1:])
  88. if t.isA('NEWLINE') or t.isA('OP', ')') or t.isA('OP', ','):
  89. break
  90. sys.stdout.write(t.value)
  91. tok.pop()
  92. def processParameter():
  93. t = tok.pop()
  94. if t.isA('EXPR'):
  95. processExpression()
  96. elif t.isA('NEWLINE'):
  97. return
  98. elif t.isA('ID') or t.isA('NUMBER') or t.isA('HEX'):
  99. sys.stdout.write(t.value)
  100. elif t.isA('OP', '('):
  101. sys.stdout.write("[")
  102. processExpression()
  103. t = tok.pop()
  104. while not t.isA('OP', ')'):
  105. sys.stdout.write(t.value)
  106. t = tok.pop()
  107. assert t.isA('OP', ')'), t
  108. sys.stdout.write("]")
  109. else:
  110. raise Exception(t)
  111. while tok:
  112. start = tok.pop()
  113. if start.isA('NEWLINE'):
  114. pass
  115. elif start.isA('COMMENT'):
  116. print(start.value)
  117. elif start.isA('DIRECTIVE'):
  118. if start.value in {'.module', '.optsdcc', '.globl'}:
  119. while not tok.pop().isA('NEWLINE'):
  120. pass
  121. elif start.value == '.area':
  122. area_name = tok.pop().value
  123. if area_name == "_DATA":
  124. print('SECTION "%s_%s", WRAM0' % (module, area_name))
  125. elif area_name == "_DABS":
  126. print('SECTION "%s_%s", SRAM' % (module, area_name))
  127. elif area_name == "_HOME":
  128. print('SECTION FRAGMENT "%s_%s", ROM0' % (module, area_name))
  129. elif area_name == "_CODE":
  130. print('SECTION FRAGMENT "%s_%s", ROM0' % (module, area_name))
  131. elif area_name.startswith("_CODE_"):
  132. print('SECTION FRAGMENT "%s_%s", ROMX, BANK[%d]' % (module, area_name, int(area_name[6:])))
  133. elif area_name == "_CABS":
  134. print('SECTION FRAGMENT "%s_%s", ROM0' % (module, area_name))
  135. elif area_name == "_GSINIT":
  136. print('SECTION FRAGMENT "GSINIT", ROMX, BANK[1]')
  137. elif area_name == "_GSFINAL":
  138. print('SECTION FRAGMENT "GSFINAL", ROMX, BANK[1]')
  139. elif area_name == "_auto":
  140. print('SECTION FRAGMENT "code_%s", ROMX' % (module))
  141. else:
  142. raise Exception(area_name)
  143. while not tok.pop().isA('NEWLINE'):
  144. pass
  145. elif start.value == '.ds':
  146. sys.stdout.write("ds ")
  147. processExpression()
  148. sys.stdout.write("\n")
  149. elif start.value == '.ascii':
  150. sys.stdout.write("db ")
  151. sys.stdout.write(tok.pop().value)
  152. sys.stdout.write("\n")
  153. elif start.value == '.db':
  154. sys.stdout.write("db ")
  155. processParameter()
  156. while tok.peek().isA('OP', ','):
  157. sys.stdout.write(",")
  158. tok.pop()
  159. processParameter()
  160. sys.stdout.write("\n")
  161. elif start.value == '.dw':
  162. sys.stdout.write("dw ")
  163. processParameter()
  164. while tok.peek().isA('OP', ','):
  165. sys.stdout.write(",")
  166. tok.pop()
  167. processParameter()
  168. sys.stdout.write("\n")
  169. elif start.value == '.incbin':
  170. sys.stdout.write("incbin ")
  171. while not tok.peek().isA('NEWLINE'):
  172. sys.stdout.write(tok.pop().value)
  173. sys.stdout.write("\n")
  174. tok.pop()
  175. else:
  176. raise Exception(start, tok.peek())
  177. elif start.isA('ID'):
  178. if tok.peek().isA('ASSIGN'):
  179. tok.pop()
  180. sys.stdout.write("%s = " % (start.value))
  181. processExpression()
  182. sys.stdout.write("\n")
  183. elif tok.peek().isA('LABEL'):
  184. print("%s%s" % (start.value, tok.pop().value))
  185. elif start.isA('ID', 'ldhl'):
  186. tok.expect('ID', 'sp')
  187. tok.expect('OP', ',')
  188. sys.stdout.write("ld hl, sp + ")
  189. processParameter()
  190. sys.stdout.write("\n")
  191. elif start.isA('ID', 'lda'):
  192. tok.expect('ID', 'hl')
  193. tok.expect('OP', ',')
  194. t = tok.pop()
  195. assert t.isA('NUMBER') or t.isA('HEX')
  196. tok.expect('OP', '(')
  197. tok.expect('ID', 'sp')
  198. tok.expect('OP', ')')
  199. sys.stdout.write("ld hl, sp + %s\n" % (t.value))
  200. else:
  201. sys.stdout.write("%s " % (start.value))
  202. if not tok.peek().isA('NEWLINE'):
  203. processParameter()
  204. if tok.peek().isA('OP', ','):
  205. tok.pop()
  206. sys.stdout.write(", ")
  207. processParameter()
  208. sys.stdout.write("\n")
  209. tok.expect('NEWLINE')
  210. else:
  211. raise Exception(start)