model_visitor.py 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. from visitor import Visitor
  2. from compiler import main as do_compile
  3. import os
  4. def jsonstr(s):
  5. return '"%s"' % s
  6. def empty(s):
  7. return None
  8. class ModelVisitor(Visitor):
  9. def __init__(self, args):
  10. Visitor.__init__(self, args)
  11. self.constructors = []
  12. self.free_id = 0
  13. self.name_maps = {}
  14. self.current_model = None
  15. self.current_element = None
  16. self.includes = []
  17. def dump(self):
  18. print(self.constructors)
  19. return self.constructors
  20. def __getattr__(self, attr):
  21. if attr.startswith("visit_"):
  22. return empty
  23. else:
  24. raise AttributeError()
  25. def visit_start(self, tree):
  26. for t in tree.get_tail():
  27. self.visit(t)
  28. def visit_include_files(self, tree):
  29. self.includes.append(tree.get_children("STRVALUE")[0].get_text())
  30. def visit_import(self, tree):
  31. url = tree.get_children("MV_URL")[0]
  32. target = tree.get_children("MODEL_ID")[0]
  33. self.constructors.extend(['"import_node"', jsonstr(url.get_text()), jsonstr(target.get_text())])
  34. def visit_export(self, tree):
  35. url = tree.get_children("MV_URL")[0]
  36. target = tree.get_children("MODEL_ID")[0]
  37. self.constructors.extend(['"export_node"', jsonstr(target.get_text()), jsonstr(url.get_text())])
  38. def visit_model(self, tree):
  39. children = tree.get_children("MODEL_ID")
  40. model_type = children[0].get_text()
  41. model_name = children[1].get_text()
  42. self.constructors.extend(['"instantiate_model"', jsonstr(model_type), jsonstr(model_name)])
  43. self.constructors.extend(['"define_inheritance"', jsonstr(model_name), jsonstr("Inheritance")])
  44. self.current_model = model_name
  45. for element in tree.get_children("model_element"):
  46. self.visit(element)
  47. def visit_model_element(self, tree):
  48. children = tree.get_children("MODEL_ID")
  49. element_type = children[0].get_text()
  50. if len(children) == 2 or len(children) == 4:
  51. element_name = children[1].get_text()
  52. else:
  53. element_name = "__%s" % self.free_id
  54. self.free_id += 1
  55. if len(children) > 2:
  56. # So we have a source and target; but aren't sure which is which, because the name is optional!
  57. source_name = children[-2].get_text()
  58. target_name = children[-1].get_text()
  59. self.constructors.extend(['"instantiate_link"', jsonstr(self.current_model), jsonstr(element_type), jsonstr(element_name), jsonstr(source_name), jsonstr(target_name)])
  60. else:
  61. self.constructors.extend(['"instantiate_node"', jsonstr(self.current_model), jsonstr(element_type), jsonstr(element_name)])
  62. self.current_element = element_name
  63. for attr in tree.get_children("model_attribute"):
  64. self.visit(attr)
  65. def visit_model_attribute(self, tree):
  66. children = tree.get_children("MODEL_ID")
  67. is_definition = bool(tree.get_children("COLON"))
  68. is_constraint = bool(tree.get_children("DOLLAR"))
  69. is_assign = bool(tree.get_children("model_attr_instance"))
  70. if is_definition:
  71. attr_name = children[0].get_text()
  72. attr_type = children[1].get_text()
  73. self.constructors.extend(['"instantiate_link"', jsonstr(self.current_model), jsonstr("Association"), jsonstr(self.current_element + "_" + attr_name), jsonstr(self.current_element), jsonstr(attr_type)])
  74. full_attribute_name = self.current_element + "_" + attr_name
  75. self.constructors.extend(['"instantiate_attribute"', jsonstr(self.current_model), jsonstr(full_attribute_name), jsonstr("name"), jsonstr(attr_name)])
  76. if is_assign:
  77. # There are also some attributes to set!
  78. old_element = self.current_element
  79. self.current_element = full_attribute_name
  80. for f in tree.get_children("model_attr_instance"):
  81. self.visit(f)
  82. self.current_element = old_element
  83. elif is_assign:
  84. self.visit(tree.get_children("model_attr_instance")[0])
  85. elif is_constraint:
  86. constraint = tree.get_children("ANYTHING_EXCEPT_DOLLAR")[0].get_text()
  87. whitespaces = len(constraint) - len(constraint.lstrip())
  88. constraint = "\n".join(["\t" + line[whitespaces-1:].replace(" ", "\t") for line in constraint.split("\n") if len(line.strip()) != 0])
  89. constraint = "".join(["include %s\n" % i for i in self.includes]) + \
  90. "String function constraint(model : Element, element : String):\n" + \
  91. "\tElement self\n" + \
  92. '\tself = model["model"][element]\n' + \
  93. constraint + "\n"
  94. with open(".constraint.alc", 'w') as f:
  95. f.write(constraint)
  96. f.flush()
  97. directory = os.path.realpath(__file__).rsplit(os.sep, 1)[0]
  98. self.constructors.extend(['"add_constraint"', jsonstr(self.current_model), jsonstr(self.current_element)] + do_compile(".constraint.alc", directory + "/../grammars/actionlanguage.g", "CS"))
  99. def visit_model_attr_instance(self, tree):
  100. children = tree.get_children("MODEL_ID")
  101. attr_name = children[0].get_text()
  102. attr_value = tree.get_children("value")[0]
  103. self.constructors.extend(['"instantiate_attribute"', jsonstr(self.current_model), jsonstr(self.current_element), jsonstr(attr_name), jsonstr(attr_value.get_text()) if attr_value.head == "STRVALUE" else attr_value.get_text()])