parser.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  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. constraint_name = f"{obj_name}.constraint"
  50. od.create_actioncode_value(constraint_name, constraint.code)
  51. od.create_slot("constraint", obj_name, constraint_name)
  52. primitive_types = {
  53. type_name : UUID(state.read_value(state.read_dict(state.read_root(), type_name)))
  54. for type_name in ["Integer", "String", "Boolean"]
  55. }
  56. class T(TBase):
  57. def __init__(self, visit_tokens):
  58. super().__init__(visit_tokens)
  59. self.obj_counter = 0
  60. def ABSTRACT(self, el):
  61. return True
  62. def INT_OR_INF(self, el):
  63. # infinity only used for upper cardinality,
  64. # where the default value (None) represents infinity
  65. # cannot use `float('inf')` because then it violates the constraint of type 'Integer'
  66. return None if el == "*" else int(el)
  67. def multiplicity(self, el):
  68. [lower, upper] = el
  69. return (lower, upper)
  70. def superclasses(self, el):
  71. return list(el)
  72. def attrs(self, el):
  73. return list(el)
  74. def constraint(self, el):
  75. return el[0]
  76. def attr(self, el):
  77. [optional, attr_type, attr_name, constraint] = el
  78. return (optional == "optional", attr_type, attr_name, constraint)
  79. def global_constraint(self, el):
  80. [name, constraint] = el
  81. od.create_object(name, "GlobalConstraint")
  82. _add_constraint_to_obj(name, constraint)
  83. def process_attrs(self, attrs, class_name):
  84. if attrs != None:
  85. for attr in attrs:
  86. (optional, attr_type, attr_name, constraint) = attr
  87. if state.read_dict(m, attr_type) == None:
  88. cd.create_model_ref(attr_type, primitive_types[attr_type])
  89. cd.create_attribute_link(class_name, attr_type, attr_name, optional)
  90. if constraint != None:
  91. _add_constraint_to_obj(f"{class_name}_{attr_name}", constraint)
  92. def class_(self, el):
  93. [abstract, class_name, multiplicity, super_classes, attrs, constraint] = el
  94. (lower, upper) = _handle_missing_multiplicity(multiplicity)
  95. cd.create_class(class_name, abstract, lower, upper)
  96. if super_classes != None:
  97. for super_class in super_classes:
  98. cd.create_inheritance(class_name, super_class)
  99. if constraint != None:
  100. _add_constraint_to_obj(class_name, constraint)
  101. self.process_attrs(attrs, class_name)
  102. def association(self, el):
  103. [assoc_name, src_multiplicity, src_name, tgt_name, tgt_multiplicity, attrs, constraint] = el
  104. (src_lower, src_upper) = _handle_missing_multiplicity(src_multiplicity)
  105. (tgt_lower, tgt_upper) = _handle_missing_multiplicity(tgt_multiplicity)
  106. cd.create_association(assoc_name, src_name, tgt_name, src_lower, src_upper, tgt_lower, tgt_upper)
  107. if constraint != None:
  108. _add_constraint_to_obj(assoc_name, constraint)
  109. self.process_attrs(attrs, assoc_name)
  110. tree = parser.parse(m_text)
  111. t = T(visit_tokens=True).transform(tree)
  112. return m