Merge pull request #170 from kanzure/fix-up-preprocessor

Remove some globals from preprocessor.
This commit is contained in:
Bryan Bishop 2013-08-28 17:54:02 -07:00
commit 52c3daca54
2 changed files with 40 additions and 17 deletions

View File

@ -13,7 +13,6 @@ from extras.pokemontools.crystal import (
PointerLabelBeforeBank, PointerLabelBeforeBank,
PointerLabelAfterBank, PointerLabelAfterBank,
ItemFragment, ItemFragment,
TextEndingCommand,
text_command_classes, text_command_classes,
movement_command_classes, movement_command_classes,
music_classes, music_classes,
@ -42,6 +41,9 @@ show_original_lines = False
# helpful for debugging macros # helpful for debugging macros
do_macro_sanity_check = False do_macro_sanity_check = False
class SkippableMacro(object):
macro_name = "db"
chars = { chars = {
"": 0x05, "": 0x05,
"": 0x06, "": 0x06,
@ -409,11 +411,10 @@ def quote_translator(asm):
def extract_token(asm): def extract_token(asm):
return asm.split(" ")[0].strip() return asm.split(" ")[0].strip()
def make_macro_table(): def make_macro_table(macros):
return dict(((macro.macro_name, macro) for macro in macros)) return dict(((macro.macro_name, macro) for macro in macros))
macro_table = make_macro_table()
def macro_test(asm): def macro_test(asm, macro_table):
""" """
Returns a matching macro, or None/False. Returns a matching macro, or None/False.
""" """
@ -425,7 +426,19 @@ def macro_test(asm):
else: else:
return (None, None) return (None, None)
def macro_translator(macro, token, line): def is_based_on(something, base):
"""
Checks whether or not 'something' is a class that is a subclass of a class
by name. This is a terrible hack but it removes a direct dependency on
existing macros.
Used by macro_translator.
"""
options = [str(klass.__name__) for klass in something.__bases__]
options += [something.__name__]
return (base in options)
def macro_translator(macro, token, line, skippable_macros):
""" """
Converts a line with a macro into a rgbasm-compatible line. Converts a line with a macro into a rgbasm-compatible line.
""" """
@ -464,10 +477,10 @@ def macro_translator(macro, token, line):
if show_original_lines: if show_original_lines:
sys.stdout.write("; original_line: " + original_line) sys.stdout.write("; original_line: " + original_line)
# "db" is a macro because of TextEndingCommand # "db" is a macro because of SkippableMacro
# rgbasm can handle "db" so no preprocessing is required # rgbasm can handle "db" so no preprocessing is required
# (don't check its param count) # (don't check its param count)
if macro.macro_name == "db" and macro in [TextEndingCommand, ItemFragment]: if macro.__name__ in skippable_macros or (macro.macro_name == "db" and macro in skippable_macros):
sys.stdout.write(original_line) sys.stdout.write(original_line)
return return
@ -524,7 +537,10 @@ def macro_translator(macro, token, line):
index = 0 index = 0
while index < len(params): while index < len(params):
param_type = macro.param_types[index - correction] try:
param_type = macro.param_types[index - correction]
except KeyError as exception:
raise Exception("line is: " + str(line) + " and macro is: " + str(macro))
description = param_type["name"] description = param_type["name"]
param_klass = param_type["class"] param_klass = param_type["class"]
byte_type = param_klass.byte_type # db or dw byte_type = param_klass.byte_type # db or dw
@ -540,14 +556,14 @@ def macro_translator(macro, token, line):
output += ("; " + description + "\n") output += ("; " + description + "\n")
if size == 3 and issubclass(param_klass, PointerLabelBeforeBank): if size == 3 and is_based_on(param_klass, "PointerLabelBeforeBank"):
# write the bank first # write the bank first
output += ("db " + param + "\n") output += ("db " + param + "\n")
# write the pointer second # write the pointer second
output += ("dw " + params[index+1].strip() + "\n") output += ("dw " + params[index+1].strip() + "\n")
index += 2 index += 2
correction += 1 correction += 1
elif size == 3 and issubclass(param_klass, PointerLabelAfterBank): elif size == 3 and is_based_on(param_klass, "PointerLabelAfterBank"):
# write the pointer first # write the pointer first
output += ("dw " + param + "\n") output += ("dw " + param + "\n")
# write the bank second # write the bank second
@ -570,7 +586,7 @@ def macro_translator(macro, token, line):
sys.stdout.write(output) sys.stdout.write(output)
def read_line(l): def read_line(l, skippable_macros, macro_table):
"""Preprocesses a given line of asm.""" """Preprocesses a given line of asm."""
# strip comments from asm # strip comments from asm
@ -596,16 +612,23 @@ def read_line(l):
# check against other preprocessor features # check against other preprocessor features
else: else:
macro, token = macro_test(asm) macro, token = macro_test(asm, macro_table)
if macro: if macro:
macro_translator(macro, token, asm) macro_translator(macro, token, asm, skippable_macros)
else: else:
sys.stdout.write(asm) sys.stdout.write(asm)
if comment: sys.stdout.write(comment) if comment: sys.stdout.write(comment)
def preprocess(lines=None): def preprocess(macros, skippable_macros=None, lines=None):
"""Main entry point for the preprocessor.""" """Main entry point for the preprocessor."""
if skippable_macros == None:
skippable_macros = [SkippableMacro]
macro_table = make_macro_table(list(set(macros + skippable_macros)))
# HACK for pokecrystal. Must be after make_macro_table call.
skippable_macros += ["TextEndingCommand"]
if not lines: if not lines:
# read each line from stdin # read each line from stdin
@ -615,8 +638,8 @@ def preprocess(lines=None):
lines = lines.split("\n") lines = lines.split("\n")
for l in lines: for l in lines:
read_line(l) read_line(l, skippable_macros, macro_table)
# only run against stdin when not included as a module # only run against stdin when not included as a module
if __name__ == "__main__": if __name__ == "__main__":
preprocess() preprocess(macros)

View File

@ -13,4 +13,4 @@ if __name__ == '__main__':
dest = os.path.splitext(source)[0] + '.tx' dest = os.path.splitext(source)[0] + '.tx'
sys.stdin = open(source, 'r') sys.stdin = open(source, 'r')
sys.stdout = open(dest, 'w') sys.stdout = open(dest, 'w')
preprocessor.preprocess() preprocessor.preprocess(preprocessor.macros)