from visitor import Visitor from compiler import main as do_compile import os def empty(s): return None class ModelVisitor(Visitor): def __init__(self, args): Visitor.__init__(self, args) self.constructors = [] self.free_id = 0 self.name_maps = {} self.current_model = None self.current_element = [] self.includes = [] def dump(self): return self.constructors def __getattr__(self, attr): if attr.startswith("visit_"): return empty else: raise AttributeError() def visit_start(self, tree): for t in tree.get_tail(): self.visit(t) def visit_include_files(self, tree): self.includes.append('include %s' % tree.get_children("STRVALUE")[0].get_text()) def visit_import(self, tree): url = tree.get_children("MV_URL")[0] target = tree.get_children("MODEL_ID")[0] self.constructors.extend(["import_node", url.get_text(), target.get_text()]) def visit_export(self, tree): url = tree.get_children("MV_URL")[0] target = tree.get_children("MODEL_ID")[0] self.constructors.extend(["export_node", target.get_text(), url.get_text()]) def visit_model(self, tree): children = tree.get_children("MODEL_ID") model_type = children[0].get_text() model_name = children[-1].get_text() self.constructors.extend(["instantiate_model", model_type, model_name]) self.current_model = model_name for element in tree.get_children("model_element"): self.visit(element) def visit_model_element(self, tree): children = tree.get_children("MODEL_ID") element_type = children[0].get_text() if len(children) == 2 or len(children) == 4: element_name = children[1].get_text() else: element_name = "__%s" % self.free_id self.free_id += 1 if len(children) > 2: # So we have a source and target; but aren't sure which is which, because the name is optional! source_name = children[-2].get_text() target_name = children[-1].get_text() self.constructors.extend(["instantiate_link", self.current_model, element_type, element_name, source_name, target_name]) else: self.constructors.extend(["instantiate_node", self.current_model, element_type, element_name]) self.current_element.append(element_name) if tree.get_children("inheritance"): self.visit(tree.get_children("inheritance")[0]) for attr in tree.get_children("model_attribute"): self.visit(attr) self.current_element.pop() return element_name def visit_inheritance(self, tree): for token in tree.get_children("MODEL_ID"): superclass = token.get_text() self.constructors.extend(["instantiate_link", self.current_model, "Inheritance", "%s_inherits_from_%s" % (self.current_element[-1], superclass), self.current_element[-1], superclass]) def visit_model_attribute(self, tree): children = tree.get_children("MODEL_ID") is_definition = bool(tree.get_children("COLON")) is_assign = bool(tree.get_children("model_attr_instance")) is_nested = bool(tree.get_children("model_element")) if is_definition: attr_name = children[0].get_text() attr_optional = len(tree.get_children("OPTIONAL")) > 0 attr_type = children[1].get_text() self.constructors.extend(["model_define_attribute", self.current_model, self.current_element[-1], attr_name, attr_optional, attr_type]) full_attribute_name = self.current_element[-1] + "_" + attr_name if is_assign: # There are also some attributes to set! self.current_element.append(full_attribute_name) for f in tree.get_children("model_attr_instance"): self.visit(f) self.current_element.pop() elif is_assign: self.visit(tree.get_children("model_attr_instance")[0]) elif is_nested: if tree.get_children("MODEL_ID"): contains_link = tree.get_children("MODEL_ID")[0].get_text() else: contains_link = "" entry = self.visit(tree.get_children("model_element")[0]) self.constructors.extend(["instantiate_link", self.current_model, contains_link, "__%s" % self.free_id, self.current_element[-1], entry]) self.free_id += 1 def visit_model_attr_instance(self, tree): def constructors_compile(code): code_fragments = code.split("\n") code_fragments = [i for i in code_fragments if i.strip() != ""] code_fragments = [i.replace(" ", "\t") for i in code_fragments] initial_tabs = min([len(i) - len(i.lstrip("\t")) for i in code_fragments]) code_fragments = self.includes + [i[initial_tabs:] for i in code_fragments] code = "\n".join(code_fragments) code += "\n" with open(".code.alc", 'w') as f: f.write(code) f.flush() directory = os.path.realpath(__file__).rsplit(os.sep, 1)[0] compiled = do_compile(".code.alc", directory + "/../grammars/actionlanguage.g", "CS") return compiled children = tree.get_children("MODEL_ID") attr_name = children[0].get_text() if tree.get_children("value"): # Value attribute attr_value = tree.get_children("value")[0].get_tail()[0] if attr_value.head == "STRVALUE": attr_value = attr_value.get_text()[1:-1] elif attr_value.head == "TRUE": attr_value = True elif attr_value.head == "FALSE": attr_value = False elif attr_value.head == "DEC_NUMBER": attr_value = int(attr_value.get_text()) elif attr_value.head == "FLOAT_NUMBER": attr_value = float(attr_value.get_text()) else: raise Exception(attr_value.head) self.constructors.extend(["instantiate_attribute", self.current_model, self.current_element[-1], attr_name, attr_value]) elif tree.get_children("DOLLAR"): # Coded attribute self.constructors.extend(["instantiate_attribute_code", self.current_model, self.current_element[-1], attr_name]) self.constructors.extend(constructors_compile(tree.get_children("ANYTHING_EXCEPT_DOLLAR")[0].get_text()))