|
@@ -0,0 +1,184 @@
|
|
|
+class Comment(object):
|
|
|
+ def __init__(self, content):
|
|
|
+ self.content = content
|
|
|
+
|
|
|
+ def generate(self, state=None):
|
|
|
+ yield "; " + self.content
|
|
|
+
|
|
|
+def _should_quote(arg):
|
|
|
+ return (' ' in arg) or ('$' in arg)
|
|
|
+
|
|
|
+def assemble_line(parts):
|
|
|
+ quoted_parts = [("%s" % p) if _should_quote(p) else p
|
|
|
+ for p in parts if p is not None]
|
|
|
+ return ' '.join(quoted_parts)
|
|
|
+
|
|
|
+class Instruction(object):
|
|
|
+ def __init__(self, name, *parameters):
|
|
|
+ self.name = name
|
|
|
+ self.parameters = parameters
|
|
|
+
|
|
|
+ def generate(self, state=None):
|
|
|
+ yield assemble_line([self.name] + list(self.parameters))
|
|
|
+
|
|
|
+def make_instruction_class(name):
|
|
|
+ def __init__(self, *parameters):
|
|
|
+ Instruction.__init__(self, name, *parameters)
|
|
|
+
|
|
|
+ return type(name, (Instruction,), {'__init__': __init__})
|
|
|
+
|
|
|
+File = make_instruction_class('File')
|
|
|
+
|
|
|
+class Scope(object):
|
|
|
+ def __init__(self, contents=None):
|
|
|
+ self.contents = contents or []
|
|
|
+
|
|
|
+ def generate_children(self, state=None):
|
|
|
+ for child in self.contents:
|
|
|
+ for line in child.generate(state):
|
|
|
+ yield ' ' + line
|
|
|
+
|
|
|
+class Section(Scope):
|
|
|
+ def __init__(self, name=None, index_var=None, selected=True, contents=None):
|
|
|
+ super(Section, self).__init__(contents)
|
|
|
+ self.name = name
|
|
|
+ self.index_var = index_var
|
|
|
+ self.selected = selected
|
|
|
+
|
|
|
+ def generate(self, state=None):
|
|
|
+ parts = ['Section',
|
|
|
+ None if self.selected else '/o',
|
|
|
+ self.name, self.index_var]
|
|
|
+
|
|
|
+ yield assemble_line(parts)
|
|
|
+ for line in self.generate_children(state):
|
|
|
+ yield line
|
|
|
+ yield 'SectionEnd'
|
|
|
+ yield '' # Blank line after a section
|
|
|
+
|
|
|
+class SectionGroup(Scope):
|
|
|
+ def __init__(self, name, index_var=None, expanded=False, contents=None):
|
|
|
+ super(SectionGroup, self).__init__(contents)
|
|
|
+ self.name = name
|
|
|
+ self.expanded = expanded
|
|
|
+ self.index_var = index_var
|
|
|
+
|
|
|
+ def generate(self, state=None):
|
|
|
+ parts = ['SectionGroup',
|
|
|
+ '/e' if self.expanded else None,
|
|
|
+ self.name, self.index_var]
|
|
|
+ yield assemble_line(parts)
|
|
|
+ for line in self.generate_children(state):
|
|
|
+ yield line
|
|
|
+ yield 'SectionGroupEnd'
|
|
|
+
|
|
|
+class Function(Scope):
|
|
|
+ def __init__(self, name, contents=None):
|
|
|
+ super(Function, self).__init__(contents)
|
|
|
+ self.name = name
|
|
|
+
|
|
|
+ def generate(self, state=None):
|
|
|
+ yield assemble_line(['Function', self.name])
|
|
|
+ for line in self.generate_children(state):
|
|
|
+ yield
|
|
|
+
|
|
|
+class Label(object):
|
|
|
+ def __init__(self, name):
|
|
|
+ self.name = name
|
|
|
+
|
|
|
+ def generate(self, scope):
|
|
|
+ yield self.name + ":"
|
|
|
+
|
|
|
+class Conditional(object):
|
|
|
+ # e.g. IfSilent, IntCmp
|
|
|
+ def __init__(self, name, *parameters, ifbody=None, elsebody=None):
|
|
|
+ self.name = name
|
|
|
+ self.parameters = parameters
|
|
|
+ self.ifbody = ifbody or []
|
|
|
+ self.elsebody = elsebody or []
|
|
|
+
|
|
|
+ def generate(self, state):
|
|
|
+ if_counter = state.get('if_counter', 1)
|
|
|
+ state['if_counter'] = if_counter + 1
|
|
|
+ yield assemble_line([self.name] + self.parameters + ["0",
|
|
|
+ ("else%d" if self.elsebody else "endif%d") % if_counter])
|
|
|
+ for child in self.ifbody:
|
|
|
+ for line in child.generate(state):
|
|
|
+ yield " " + line
|
|
|
+
|
|
|
+ if self.elsebody:
|
|
|
+ yield (" Goto endif%d" % if_counter)
|
|
|
+ yield ("else%d:" % if_counter)
|
|
|
+ for child in self.elsebody:
|
|
|
+ for line in child.generate(state):
|
|
|
+ yield " " + line
|
|
|
+
|
|
|
+ yield ("endif%d:" % if_counter)
|
|
|
+
|
|
|
+
|
|
|
+class CompilerCommand(object):
|
|
|
+ def __init__(self, name, *parameters):
|
|
|
+ self.name = name
|
|
|
+ self.parameters = parameters
|
|
|
+
|
|
|
+ def generate(self, state=None):
|
|
|
+ yield "!" + assemble_line([self.name] + list(self.parameters))
|
|
|
+
|
|
|
+class CompilerConditional(object):
|
|
|
+ # ifdef etc
|
|
|
+ def __init__(self, name, parameters, ifbody=None, elsebody=None):
|
|
|
+ self.name = name
|
|
|
+ self.parameters = parameters
|
|
|
+ self.ifbody = ifbody or []
|
|
|
+ self.elsebody = elsebody or []
|
|
|
+
|
|
|
+ def generate(self, state=None):
|
|
|
+ yield "!" + assemble_line([self.name] + self.parameters)
|
|
|
+ for child in self.ifbody:
|
|
|
+ for line in child.generate(state):
|
|
|
+ yield ' ' + line
|
|
|
+ if self.elsebody:
|
|
|
+ yield "!else"
|
|
|
+ for child in self.elsebody:
|
|
|
+ for line in child.generate(state):
|
|
|
+ yield ' ' + line
|
|
|
+
|
|
|
+ yield "!endif"
|
|
|
+
|
|
|
+def make_compiler_command_class(name):
|
|
|
+ def __init__(self, *parameters):
|
|
|
+ CompilerCommand.__init__(self, name, *parameters)
|
|
|
+
|
|
|
+ return type(name, (CompilerCommand,), {'__init__': __init__})
|
|
|
+
|
|
|
+define = make_compiler_command_class('define')
|
|
|
+insertmacro = make_compiler_command_class('insertmacro')
|
|
|
+
|
|
|
+class Macro(Scope):
|
|
|
+ def __init__(self, name, parameters):
|
|
|
+ super(Macro, self).__init__()
|
|
|
+ self.name = name
|
|
|
+ self.parameters = parameters
|
|
|
+
|
|
|
+ def generate(self, state=None):
|
|
|
+ yield "!" + assemble_line([self.name] + self.parameters)
|
|
|
+ for line in self.generate_children(state):
|
|
|
+ yield " " + line
|
|
|
+ yield "!macroend"
|
|
|
+
|
|
|
+class Document(object):
|
|
|
+ def __init__(self, children=None):
|
|
|
+ self.children = children or []
|
|
|
+
|
|
|
+ def generate(self, state):
|
|
|
+ for child in self.children:
|
|
|
+ for line in child.generate(state):
|
|
|
+ yield line
|
|
|
+
|
|
|
+ def write(self, fileobj_or_path):
|
|
|
+ if isinstance(fileobj_or_path, str):
|
|
|
+ with open(fileobj_or_path, 'w') as f:
|
|
|
+ return self.write(f)
|
|
|
+
|
|
|
+ for line in self.generate(state={}):
|
|
|
+ fileobj_or_path.write(line + '\n')
|