summaryrefslogtreecommitdiff
path: root/preprocessor.py
diff options
context:
space:
mode:
authoryenatch <yenatch@gmail.com>2013-08-30 13:33:09 -0700
committeryenatch <yenatch@gmail.com>2013-08-30 13:33:09 -0700
commit0b36af8da526ef1389d2c08bb61d6ea5fdb41f2e (patch)
tree243498feeaaa2a3726e8de489d4da0b8202ae95e /preprocessor.py
parentb86d0da040448f286aa65ff5b2bacb05fff200a8 (diff)
parentd2333a90c9eed0be38d722bfcd0d8b5dee0e56a7 (diff)
Merge pull request #3 from kanzure/proposed-yenatch-master
Proposed merge of kanzure/master into yenatch/master
Diffstat (limited to 'preprocessor.py')
-rw-r--r--preprocessor.py66
1 files changed, 42 insertions, 24 deletions
diff --git a/preprocessor.py b/preprocessor.py
index e8e959c06..e529fe043 100644
--- a/preprocessor.py
+++ b/preprocessor.py
@@ -3,18 +3,14 @@
import sys
-from extras.crystal import (
+from extras.pokemontools.crystal import (
command_classes,
Warp,
XYTrigger,
Signpost,
PeopleEvent,
DataByteWordMacro,
- PointerLabelBeforeBank,
- PointerLabelAfterBank,
- MoneyByteParam,
ItemFragment,
- TextEndingCommand,
text_command_classes,
movement_command_classes,
music_classes,
@@ -43,6 +39,9 @@ show_original_lines = False
# helpful for debugging macros
do_macro_sanity_check = False
+class SkippableMacro(object):
+ macro_name = "db"
+
chars = {
"ガ": 0x05,
"ギ": 0x06,
@@ -410,11 +409,10 @@ def quote_translator(asm):
def extract_token(asm):
return asm.split(" ")[0].strip()
-def make_macro_table():
+def make_macro_table(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.
"""
@@ -426,7 +424,19 @@ def macro_test(asm):
else:
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.
"""
@@ -465,10 +475,10 @@ def macro_translator(macro, token, line):
if show_original_lines:
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
# (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)
return
@@ -498,8 +508,6 @@ def macro_translator(macro, token, line):
elif param_klass.byte_type == "dw":
if param_klass.size == 2:
allowed_length += 1 # just label
- elif param_klass == MoneyByteParam:
- allowed_length += 1
elif param_klass.size == 3:
allowed_length += 2 # bank and label
else:
@@ -527,7 +535,10 @@ def macro_translator(macro, token, line):
index = 0
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"]
param_klass = param_type["class"]
byte_type = param_klass.byte_type # db or dw
@@ -543,22 +554,22 @@ def macro_translator(macro, token, line):
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
output += ("db " + param + "\n")
# write the pointer second
output += ("dw " + params[index+1].strip() + "\n")
index += 2
correction += 1
- elif size == 3 and issubclass(param_klass, PointerLabelAfterBank):
+ elif size == 3 and is_based_on(param_klass, "PointerLabelAfterBank"):
# write the pointer first
output += ("dw " + param + "\n")
# write the bank second
output += ("db " + params[index+1].strip() + "\n")
index += 2
correction += 1
- elif size == 3 and issubclass(param_klass, MoneyByteParam):
- output += ("db " + MoneyByteParam.from_asm(param) + "\n")
+ elif size == 3 and "from_asm" in dir(param_klass):
+ output += ("db " + param_klass.from_asm(param) + "\n")
index += 1
else:
raise Exception, "dunno what to do with this macro " + \
@@ -573,7 +584,7 @@ def macro_translator(macro, token, line):
sys.stdout.write(output)
-def read_line(l):
+def read_line(l, skippable_macros, macro_table):
"""Preprocesses a given line of asm."""
# strip comments from asm
@@ -599,16 +610,23 @@ def read_line(l):
# check against other preprocessor features
else:
- macro, token = macro_test(asm)
+ macro, token = macro_test(asm, macro_table)
if macro:
- macro_translator(macro, token, asm)
+ macro_translator(macro, token, asm, skippable_macros)
else:
sys.stdout.write(asm)
if comment: sys.stdout.write(comment)
-def preprocess(lines=None):
+def preprocess(macros, skippable_macros=None, lines=None):
"""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:
# read each line from stdin
@@ -618,8 +636,8 @@ def preprocess(lines=None):
lines = lines.split("\n")
for l in lines:
- read_line(l)
+ read_line(l, skippable_macros, macro_table)
# only run against stdin when not included as a module
if __name__ == "__main__":
- preprocess()
+ preprocess(macros)