parser.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. from lark import Lark, logger
  2. from concrete_syntax.common import _Code, TBase
  3. from uuid import UUID
  4. from services.scd import SCD
  5. from services.od import OD
  6. grammar = r"""
  7. %import common.WS
  8. %ignore WS
  9. %ignore COMMENT
  10. ?start: (class_ | association | global_constraint)*
  11. IDENTIFIER: /[A-Za-z_][A-Za-z_0-9]*/
  12. COMMENT: /#[^\n]*\n/
  13. literal: INT
  14. | STR
  15. | BOOL
  16. | CODE
  17. | INDENTED_CODE
  18. INT: /[0-9]+/
  19. STR: /"[^"]*"/
  20. | /'[^']*'/
  21. BOOL: "True" | "False"
  22. CODE: /`[^`]*`/
  23. INDENTED_CODE: /```[^`]*```/
  24. INT_OR_INF: INT | "*"
  25. multiplicity: "[" INT ".." INT_OR_INF "]"
  26. ABSTRACT: "abstract"
  27. superclasses: IDENTIFIER ("," IDENTIFIER)*
  28. attrs: attr*
  29. constraint: CODE | INDENTED_CODE
  30. class_: [ABSTRACT] "class" IDENTIFIER [multiplicity] ["(" superclasses ")"] ["{" attrs [constraint] "}"]
  31. association: "association" IDENTIFIER [multiplicity] IDENTIFIER "->" IDENTIFIER [multiplicity] ["{" attrs [constraint] "}"]
  32. OPTIONAL: "optional"
  33. attr: [OPTIONAL] IDENTIFIER IDENTIFIER [constraint] ";"
  34. global_constraint: "global" IDENTIFIER constraint
  35. """
  36. parser = Lark(grammar, parser='lalr')
  37. def _handle_missing_multiplicity(multiplicity):
  38. if multiplicity != None:
  39. return multiplicity
  40. else:
  41. return (None, None)
  42. def parse_cd(state, m_text):
  43. type_model_id = state.read_dict(state.read_root(), "SCD")
  44. scd_mmm = UUID(state.read_value(type_model_id))
  45. m = state.create_node()
  46. cd = SCD(m, state)
  47. od = OD(scd_mmm, m, state)
  48. def _add_constraint_to_obj(obj_name, constraint):
  49. c = od.create_actioncode_value(f"{obj_name}.constraint", constraint.code)
  50. od.create_slot("constraint", obj_name, c)
  51. primitive_types = {
  52. type_name : UUID(state.read_value(state.read_dict(state.read_root(), type_name)))
  53. for type_name in ["Integer", "String", "Boolean"]
  54. }
  55. class T(TBase):
  56. def __init__(self, visit_tokens):
  57. super().__init__(visit_tokens)
  58. self.obj_counter = 0
  59. def ABSTRACT(self, el):
  60. return True
  61. def INT_OR_INF(self, el):
  62. # infinity only used for upper cardinality,
  63. # where the default value (None) represents infinity
  64. # cannot use `float('inf')` because then it violates the constraint of type 'Integer'
  65. return None if el == "*" else int(el)
  66. def multiplicity(self, el):
  67. [lower, upper] = el
  68. return (lower, upper)
  69. def superclasses(self, el):
  70. return list(el)
  71. def attrs(self, el):
  72. return list(el)
  73. def constraint(self, el):
  74. return el[0]
  75. def attr(self, el):
  76. [optional, attr_type, attr_name, constraint] = el
  77. return (optional == "optional", attr_type, attr_name, constraint)
  78. def global_constraint(self, el):
  79. [name, constraint] = el
  80. od.create_object(name, "GlobalConstraint")
  81. _add_constraint_to_obj(name, constraint)
  82. def process_attrs(self, attrs, class_name):
  83. if attrs != None:
  84. for attr in attrs:
  85. (optional, attr_type, attr_name, constraint) = attr
  86. if state.read_dict(m, attr_type) == None:
  87. cd.create_model_ref(attr_type, primitive_types[attr_type])
  88. cd.create_attribute_link(class_name, attr_type, attr_name, optional)
  89. if constraint != None:
  90. _add_constraint_to_obj(f"{class_name}_{attr_name}", constraint)
  91. def class_(self, el):
  92. [abstract, class_name, multiplicity, super_classes, attrs, constraint] = el
  93. (lower, upper) = _handle_missing_multiplicity(multiplicity)
  94. cd.create_class(class_name, abstract, lower, upper)
  95. if super_classes != None:
  96. for super_class in super_classes:
  97. cd.create_inheritance(class_name, super_class)
  98. if constraint != None:
  99. _add_constraint_to_obj(class_name, constraint)
  100. self.process_attrs(attrs, class_name)
  101. def association(self, el):
  102. [assoc_name, src_multiplicity, src_name, tgt_name, tgt_multiplicity, attrs, constraint] = el
  103. (src_lower, src_upper) = _handle_missing_multiplicity(src_multiplicity)
  104. (tgt_lower, tgt_upper) = _handle_missing_multiplicity(tgt_multiplicity)
  105. cd.create_association(assoc_name, src_name, tgt_name, src_lower, src_upper, tgt_lower, tgt_upper)
  106. if constraint != None:
  107. _add_constraint_to_obj(assoc_name, constraint)
  108. self.process_attrs(attrs, assoc_name)
  109. tree = parser.parse(m_text)
  110. t = T(visit_tokens=True).transform(tree)
  111. return m