model_visitor.py 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. from visitor import Visitor
  2. from compiler import main as do_compile
  3. import os
  4. def empty(s):
  5. return None
  6. class ModelVisitor(Visitor):
  7. def __init__(self, args):
  8. Visitor.__init__(self, args)
  9. self.constructors = []
  10. self.free_id = 0
  11. self.name_maps = {}
  12. self.current_model = None
  13. self.current_element = None
  14. self.includes = []
  15. def dump(self):
  16. return self.constructors
  17. def __getattr__(self, attr):
  18. if attr.startswith("visit_"):
  19. return empty
  20. else:
  21. raise AttributeError()
  22. def visit_start(self, tree):
  23. for t in tree.get_tail():
  24. self.visit(t)
  25. def visit_include_files(self, tree):
  26. self.includes.append(tree.get_children("STRVALUE")[0].get_text())
  27. def visit_import(self, tree):
  28. url = tree.get_children("MV_URL")[0]
  29. target = tree.get_children("MODEL_ID")[0]
  30. self.constructors.extend(["import_node", url.get_text(), target.get_text()])
  31. def visit_export(self, tree):
  32. url = tree.get_children("MV_URL")[0]
  33. target = tree.get_children("MODEL_ID")[0]
  34. self.constructors.extend(["export_node", target.get_text(), url.get_text()])
  35. def visit_model(self, tree):
  36. children = tree.get_children("MODEL_ID")
  37. model_type = children[0].get_text()
  38. model_name = children[1].get_text()
  39. self.constructors.extend(["instantiate_model", model_type, model_name])
  40. if "LPAR" in tree.get_tail():
  41. self.constructors.extend(["define_inheritance", model_name, tree.get_children("MODEL_ID")[1].get_text()])
  42. self.current_model = model_name
  43. for element in tree.get_children("model_element"):
  44. self.visit(element)
  45. def visit_model_element(self, tree):
  46. children = tree.get_children("MODEL_ID")
  47. element_type = children[0].get_text()
  48. if len(children) == 2 or len(children) == 4:
  49. element_name = children[1].get_text()
  50. else:
  51. element_name = "__%s" % self.free_id
  52. self.free_id += 1
  53. if len(children) > 2:
  54. # So we have a source and target; but aren't sure which is which, because the name is optional!
  55. source_name = children[-2].get_text()
  56. target_name = children[-1].get_text()
  57. self.constructors.extend(["instantiate_link", self.current_model, element_type, element_name, source_name, target_name])
  58. else:
  59. self.constructors.extend(["instantiate_node", self.current_model, element_type, element_name])
  60. self.current_element = element_name
  61. if tree.get_children("inheritance"):
  62. self.visit(tree.get_children("inheritance")[0])
  63. for attr in tree.get_children("model_attribute"):
  64. self.visit(attr)
  65. return element_name
  66. def visit_inheritance(self, tree):
  67. for token in tree.get_children("MODEL_ID"):
  68. superclass = token.get_text()
  69. self.constructors.extend(["instantiate_link", self.current_model, "Inheritance", "%s_inherits_from_%s" % (self.current_element, superclass), self.current_element, superclass])
  70. def visit_model_attribute(self, tree):
  71. children = tree.get_children("MODEL_ID")
  72. is_definition = bool(tree.get_children("COLON"))
  73. is_constraint = bool(tree.get_children("DOLLAR"))
  74. is_assign = bool(tree.get_children("model_attr_instance"))
  75. is_nested = bool(tree.get_children("model_element"))
  76. if is_definition:
  77. attr_name = children[0].get_text()
  78. attr_type = children[1].get_text()
  79. self.constructors.extend(["instantiate_link", self.current_model, "Association", self.current_element + "_" + attr_name, self.current_element, attr_type])
  80. full_attribute_name = self.current_element + "_" + attr_name
  81. self.constructors.extend(["instantiate_attribute", self.current_model, full_attribute_name, "name", attr_name])
  82. if is_assign:
  83. # There are also some attributes to set!
  84. old_element = self.current_element
  85. self.current_element = full_attribute_name
  86. for f in tree.get_children("model_attr_instance"):
  87. self.visit(f)
  88. self.current_element = old_element
  89. elif is_assign:
  90. self.visit(tree.get_children("model_attr_instance")[0])
  91. elif is_constraint:
  92. constraint = tree.get_children("ANYTHING_EXCEPT_DOLLAR")[0].get_text()
  93. whitespaces = len(constraint) - len(constraint.lstrip())
  94. constraint = "\n".join(["\t" + line[whitespaces-1:].replace(" ", "\t") for line in constraint.split("\n") if len(line.strip()) != 0])
  95. constraint = "".join(["include %s\n" % i for i in self.includes]) + \
  96. "String function constraint(model : Element, name : String):\n" + \
  97. "\tElement self\n" + \
  98. '\tself = model["model"][name]\n' + \
  99. constraint + "\n"
  100. with open(".constraint.alc", 'w') as f:
  101. f.write(constraint)
  102. f.flush()
  103. directory = os.path.realpath(__file__).rsplit(os.sep, 1)[0]
  104. compiled = do_compile(".constraint.alc", directory + "/../grammars/actionlanguage.g", "CS")
  105. self.constructors.extend(["add_constraint", self.current_model, self.current_element] + compiled)
  106. elif is_nested:
  107. if tree.get_children("MODEL_ID"):
  108. contains_link = tree.get_children("MODEL_ID")[0].get_text()
  109. else:
  110. contains_link = ""
  111. entry = self.visit(tree.get_children("model_element")[0])
  112. self.constructors.extend(["instantiate_link", self.current_model, contains_link, "__%s" % self.free_id, self.current_element, entry])
  113. self.free_id += 1
  114. def visit_model_attr_instance(self, tree):
  115. def constructors_compile(code):
  116. code_fragments = code.split("\n")
  117. code_fragments = [i for i in code_fragments if i.strip() != ""]
  118. code_fragments = [i.replace(" ", "\t") for i in code_fragments]
  119. initial_tabs = min([len(i) - len(i.lstrip("\t")) for i in code_fragments])
  120. code_fragments = [i[initial_tabs:] for i in code_fragments]
  121. code = "\n".join(code_fragments)
  122. code += "\n"
  123. with open(".code.alc", 'w') as f:
  124. f.write(code)
  125. f.flush()
  126. directory = os.path.realpath(__file__).rsplit(os.sep, 1)[0]
  127. compiled = do_compile(".code.alc", directory + "/../grammars/actionlanguage.g", "CS")
  128. children = tree.get_children("MODEL_ID")
  129. attr_name = children[0].get_text()
  130. if tree.get_children("value"):
  131. # Value attribute
  132. attr_value = tree.get_children("value")[0].get_tail()[0]
  133. if attr_value.head == "STRVALUE":
  134. attr_value = attr_value.get_text()[1:-1]
  135. elif attr_value.head == "TRUE":
  136. attr_value = True
  137. elif attr_value.head == "FALSE":
  138. attr_value = False
  139. elif attr_value.head == "DEC_NUMBER":
  140. attr_value = int(attr_value.get_text())
  141. elif attr_value.head == "FLOAT_NUMBER":
  142. attr_value = float(attr_value.get_text())
  143. else:
  144. raise Exception(attr_value.head)
  145. self.constructors.extend(["instantiate_attribute", self.current_model, self.current_element, attr_name, attr_value])
  146. elif tree.get_children("DOLLAR"):
  147. # Coded attribute
  148. self.constructors.extend(["instantiate_attribute_code", self.current_model, self.current_element, attr_name, constructors_compile(tree.get_children("ANYTHING_EXCEPT_DOLLAR")[0].get_text())])
  149. else:
  150. # Assign direct reference
  151. self.constructors.extend(["instantiate_attribute_ref", self.current_model, self.current_element, attr_name, tree.get_children("MODEL_ID")[1].get_text()])