123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 |
- 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(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])
- if tree.get_children("LPAR"):
- self.constructors.extend(["define_inheritance", model_name, tree.get_children("MODEL_ID")[1].get_text()])
- 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_constraint = bool(tree.get_children("DOLLAR"))
- 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_type = children[1].get_text()
- self.constructors.extend(["instantiate_link", self.current_model, "Association", self.current_element[-1] + "_" + attr_name, self.current_element[-1], attr_type])
- full_attribute_name = self.current_element[-1] + "_" + attr_name
- self.constructors.extend(["instantiate_attribute", self.current_model, full_attribute_name, "name", 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_constraint:
- constraint = tree.get_children("ANYTHING_EXCEPT_DOLLAR")[0].get_text()
- whitespaces = len(constraint) - len(constraint.lstrip())
- constraint = "\n".join(["\t" + line[whitespaces-1:].replace(" ", "\t") for line in constraint.split("\n") if len(line.strip()) != 0])
- constraint = "".join(["include %s\n" % i for i in self.includes]) + \
- "String function constraint(model : Element, name : String):\n" + \
- "\tElement self\n" + \
- '\tself = model["model"][name]\n' + \
- constraint + "\n"
- with open(".constraint.alc", 'w') as f:
- f.write(constraint)
- f.flush()
- directory = os.path.realpath(__file__).rsplit(os.sep, 1)[0]
- compiled = do_compile(".constraint.alc", directory + "/../grammars/actionlanguage.g", "CS")
- self.constructors.extend(["add_constraint", self.current_model, self.current_element[-1]] + compiled)
- 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 = [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()))
|