model_visitor.py 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  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. return self.constructors
  19. def __getattr__(self, attr):
  20. if attr.startswith("visit_"):
  21. return empty
  22. else:
  23. raise AttributeError()
  24. def visit_start(self, tree):
  25. for t in tree.get_tail():
  26. self.visit(t)
  27. def visit_include_files(self, tree):
  28. self.includes.append(tree.get_children("STRVALUE")[0].get_text())
  29. def visit_import(self, tree):
  30. url = tree.get_children("MV_URL")[0]
  31. target = tree.get_children("MODEL_ID")[0]
  32. self.constructors.extend(['"import_node"', jsonstr(url.get_text()), jsonstr(target.get_text())])
  33. def visit_export(self, tree):
  34. url = tree.get_children("MV_URL")[0]
  35. target = tree.get_children("MODEL_ID")[0]
  36. self.constructors.extend(['"export_node"', jsonstr(target.get_text()), jsonstr(url.get_text())])
  37. def visit_model(self, tree):
  38. children = tree.get_children("MODEL_ID")
  39. model_type = children[0].get_text()
  40. model_name = children[1].get_text()
  41. self.constructors.extend(['"instantiate_model"', jsonstr(model_type), jsonstr(model_name)])
  42. self.constructors.extend(['"define_inheritance"', jsonstr(model_name), jsonstr("Inheritance")])
  43. self.current_model = model_name
  44. for element in tree.get_children("model_element"):
  45. self.visit(element)
  46. def visit_model_element(self, tree):
  47. children = tree.get_children("MODEL_ID")
  48. element_type = children[0].get_text()
  49. if len(children) == 2 or len(children) == 4:
  50. element_name = children[1].get_text()
  51. else:
  52. element_name = "__%s" % self.free_id
  53. self.free_id += 1
  54. if len(children) > 2:
  55. # So we have a source and target; but aren't sure which is which, because the name is optional!
  56. source_name = children[-2].get_text()
  57. target_name = children[-1].get_text()
  58. self.constructors.extend(['"instantiate_link"', jsonstr(self.current_model), jsonstr(element_type), jsonstr(element_name), jsonstr(source_name), jsonstr(target_name)])
  59. else:
  60. self.constructors.extend(['"instantiate_node"', jsonstr(self.current_model), jsonstr(element_type), jsonstr(element_name)])
  61. self.current_element = element_name
  62. if tree.get_children("inheritance"):
  63. self.visit(tree.get_children("inheritance")[0])
  64. for attr in tree.get_children("model_attribute"):
  65. self.visit(attr)
  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"', jsonstr(self.current_model), jsonstr("Inheritance"), jsonstr("%s_inherits_from_%s" % (self.current_element, superclass)), jsonstr(self.current_element), jsonstr(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. if is_definition:
  76. attr_name = children[0].get_text()
  77. attr_type = children[1].get_text()
  78. self.constructors.extend(['"instantiate_link"', jsonstr(self.current_model), jsonstr("Association"), jsonstr(self.current_element + "_" + attr_name), jsonstr(self.current_element), jsonstr(attr_type)])
  79. full_attribute_name = self.current_element + "_" + attr_name
  80. self.constructors.extend(['"instantiate_attribute"', jsonstr(self.current_model), jsonstr(full_attribute_name), jsonstr("name"), jsonstr(attr_name)])
  81. if is_assign:
  82. # There are also some attributes to set!
  83. old_element = self.current_element
  84. self.current_element = full_attribute_name
  85. for f in tree.get_children("model_attr_instance"):
  86. self.visit(f)
  87. self.current_element = old_element
  88. elif is_assign:
  89. self.visit(tree.get_children("model_attr_instance")[0])
  90. elif is_constraint:
  91. constraint = tree.get_children("ANYTHING_EXCEPT_DOLLAR")[0].get_text()
  92. whitespaces = len(constraint) - len(constraint.lstrip())
  93. constraint = "\n".join(["\t" + line[whitespaces-1:].replace(" ", "\t") for line in constraint.split("\n") if len(line.strip()) != 0])
  94. constraint = "".join(["include %s\n" % i for i in self.includes]) + \
  95. "String function constraint(model : Element, name : String):\n" + \
  96. "\tElement self\n" + \
  97. '\tself = model["model"][name]\n' + \
  98. constraint + "\n"
  99. with open(".constraint.alc", 'w') as f:
  100. f.write(constraint)
  101. f.flush()
  102. directory = os.path.realpath(__file__).rsplit(os.sep, 1)[0]
  103. self.constructors.extend(['"add_constraint"', jsonstr(self.current_model), jsonstr(self.current_element)] + do_compile(".constraint.alc", directory + "/../grammars/actionlanguage.g", "CS"))
  104. def visit_model_attr_instance(self, tree):
  105. children = tree.get_children("MODEL_ID")
  106. attr_name = children[0].get_text()
  107. attr_value = tree.get_children("value")[0]
  108. 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()])