sysmlpy 0.86.0__tar.gz → 0.88.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/PKG-INFO +1 -1
  2. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/pyproject.toml +6 -1
  3. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/__init__.py +1 -1
  4. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/antlr_visitor.py +319 -46
  5. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/definition.py +63 -0
  6. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/grammar/classes.py +147 -22
  7. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/usage.py +24 -1
  8. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/LICENSE +0 -0
  9. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/README.md +0 -0
  10. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/__main__.py +0 -0
  11. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/antlr/README.md +0 -0
  12. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/antlr/SysMLv2Lexer.interp +0 -0
  13. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/antlr/SysMLv2Lexer.py +0 -0
  14. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/antlr/SysMLv2Lexer.tokens +0 -0
  15. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/antlr/SysMLv2Parser.interp +0 -0
  16. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/antlr/SysMLv2Parser.py +0 -0
  17. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/antlr/SysMLv2Parser.tokens +0 -0
  18. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/antlr/SysMLv2ParserListener.py +0 -0
  19. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/antlr/SysMLv2ParserVisitor.py +0 -0
  20. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/antlr/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.interp +0 -0
  21. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/antlr/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.py +0 -0
  22. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/antlr/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.tokens +0 -0
  23. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/antlr_parser.py +0 -0
  24. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/boxes_view.py +0 -0
  25. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/dfa_cache.py +0 -0
  26. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/diff.py +0 -0
  27. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/evaluator.py +0 -0
  28. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/examples/attribute_values.py +0 -0
  29. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/examples/part_attributes.py +0 -0
  30. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/examples/tuples_sequences.py +0 -0
  31. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/formatting.py +0 -0
  32. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/grammar/antlr4/README.md +0 -0
  33. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.g4 +0 -0
  34. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.interp +0 -0
  35. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.py +0 -0
  36. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.tokens +0 -0
  37. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.g4 +0 -0
  38. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.interp +0 -0
  39. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.py +0 -0
  40. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.tokens +0 -0
  41. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/grammar/antlr4/SysMLv2ParserListener.py +0 -0
  42. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/grammar/antlr4/SysMLv2ParserVisitor.py +0 -0
  43. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/grammar/antlr4/desc.xml +0 -0
  44. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/grammar/antlr4/examples/camera.sysml +0 -0
  45. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/grammar/antlr4/examples/toaster-system.sysml +0 -0
  46. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/grammar/antlr4/examples/vehicle-model.sysml +0 -0
  47. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/grammar/antlr4/pom.xml +0 -0
  48. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/interchange.py +0 -0
  49. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/LICENSE +0 -0
  50. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/README.md +0 -0
  51. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/__init__.py +0 -0
  52. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/domain/Analysis/AnalysisTooling.sysml +0 -0
  53. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/domain/Analysis/SampledFunctions.sysml +0 -0
  54. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/domain/Analysis/StateSpaceRepresentation.sysml +0 -0
  55. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/domain/Analysis/TradeStudies.sysml +0 -0
  56. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/domain/Cause and Effect/CausationConnections.sysml +0 -0
  57. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/domain/Cause and Effect/CauseAndEffect.sysml +0 -0
  58. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/domain/Geometry/ShapeItems.sysml +0 -0
  59. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/domain/Geometry/SpatialItems.sysml +0 -0
  60. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/domain/Metadata/ImageMetadata.sysml +0 -0
  61. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/domain/Metadata/ModelingMetadata.sysml +0 -0
  62. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/domain/Metadata/ParametersOfInterestMetadata.sysml +0 -0
  63. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/domain/Metadata/RiskMetadata.sysml +0 -0
  64. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/domain/Quantities and Units/ISQ.sysml +0 -0
  65. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/domain/Quantities and Units/ISQAcoustics.sysml +0 -0
  66. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/domain/Quantities and Units/ISQAtomicNuclear.sysml +0 -0
  67. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/domain/Quantities and Units/ISQBase.sysml +0 -0
  68. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/domain/Quantities and Units/ISQCharacteristicNumbers.sysml +0 -0
  69. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/domain/Quantities and Units/ISQChemistryMolecular.sysml +0 -0
  70. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/domain/Quantities and Units/ISQCondensedMatter.sysml +0 -0
  71. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/domain/Quantities and Units/ISQElectromagnetism.sysml +0 -0
  72. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/domain/Quantities and Units/ISQInformation.sysml +0 -0
  73. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/domain/Quantities and Units/ISQLight.sysml +0 -0
  74. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/domain/Quantities and Units/ISQMechanics.sysml +0 -0
  75. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/domain/Quantities and Units/ISQSpaceTime.sysml +0 -0
  76. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/domain/Quantities and Units/ISQThermodynamics.sysml +0 -0
  77. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/domain/Quantities and Units/MeasurementRefCalculations.sysml +0 -0
  78. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/domain/Quantities and Units/MeasurementReferences.sysml +0 -0
  79. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/domain/Quantities and Units/Quantities.sysml +0 -0
  80. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/domain/Quantities and Units/QuantityCalculations.sysml +0 -0
  81. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/domain/Quantities and Units/SI.sysml +0 -0
  82. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/domain/Quantities and Units/SIPrefixes.sysml +0 -0
  83. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/domain/Quantities and Units/TensorCalculations.sysml +0 -0
  84. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/domain/Quantities and Units/Time.sysml +0 -0
  85. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/domain/Quantities and Units/USCustomaryUnits.sysml +0 -0
  86. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/domain/Quantities and Units/VectorCalculations.sysml +0 -0
  87. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/domain/Requirement Derivation/DerivationConnections.sysml +0 -0
  88. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/domain/Requirement Derivation/RequirementDerivation.sysml +0 -0
  89. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/kernel/Base.kerml +0 -0
  90. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/kernel/BaseFunctions.kerml +0 -0
  91. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/kernel/BooleanFunctions.kerml +0 -0
  92. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/kernel/Clocks.kerml +0 -0
  93. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/kernel/CollectionFunctions.kerml +0 -0
  94. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/kernel/Collections.kerml +0 -0
  95. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/kernel/ComplexFunctions.kerml +0 -0
  96. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/kernel/ControlFunctions.kerml +0 -0
  97. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/kernel/ControlPerformances.kerml +0 -0
  98. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/kernel/DataFunctions.kerml +0 -0
  99. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/kernel/FeatureReferencingPerformances.kerml +0 -0
  100. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/kernel/IntegerFunctions.kerml +0 -0
  101. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/kernel/KerML.kerml +0 -0
  102. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/kernel/Links.kerml +0 -0
  103. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/kernel/Metaobjects.kerml +0 -0
  104. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/kernel/NaturalFunctions.kerml +0 -0
  105. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/kernel/NumericalFunctions.kerml +0 -0
  106. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/kernel/Objects.kerml +0 -0
  107. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/kernel/Observation.kerml +0 -0
  108. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/kernel/OccurrenceFunctions.kerml +0 -0
  109. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/kernel/Occurrences.kerml +0 -0
  110. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/kernel/Performances.kerml +0 -0
  111. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/kernel/RationalFunctions.kerml +0 -0
  112. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/kernel/RealFunctions.kerml +0 -0
  113. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/kernel/ScalarFunctions.kerml +0 -0
  114. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/kernel/ScalarValues.kerml +0 -0
  115. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/kernel/SequenceFunctions.kerml +0 -0
  116. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/kernel/SpatialFrames.kerml +0 -0
  117. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/kernel/StatePerformances.kerml +0 -0
  118. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/kernel/StringFunctions.kerml +0 -0
  119. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/kernel/Transfers.kerml +0 -0
  120. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/kernel/TransitionPerformances.kerml +0 -0
  121. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/kernel/TrigFunctions.kerml +0 -0
  122. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/kernel/Triggers.kerml +0 -0
  123. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/kernel/VectorFunctions.kerml +0 -0
  124. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/kernel/VectorValues.kerml +0 -0
  125. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/systems/Actions.sysml +0 -0
  126. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/systems/Allocations.sysml +0 -0
  127. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/systems/AnalysisCases.sysml +0 -0
  128. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/systems/Attributes.sysml +0 -0
  129. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/systems/Calculations.sysml +0 -0
  130. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/systems/Cases.sysml +0 -0
  131. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/systems/Connections.sysml +0 -0
  132. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/systems/Constraints.sysml +0 -0
  133. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/systems/Flows.sysml +0 -0
  134. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/systems/Interfaces.sysml +0 -0
  135. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/systems/Items.sysml +0 -0
  136. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/systems/Metadata.sysml +0 -0
  137. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/systems/Parts.sysml +0 -0
  138. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/systems/Ports.sysml +0 -0
  139. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/systems/Requirements.sysml +0 -0
  140. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/systems/StandardViewDefinitions.sysml +0 -0
  141. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/systems/States.sysml +0 -0
  142. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/systems/SysML.sysml +0 -0
  143. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/systems/UseCases.sysml +0 -0
  144. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/systems/VerificationCases.sysml +0 -0
  145. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/library/systems/Views.sysml +0 -0
  146. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/lsp/__init__.py +0 -0
  147. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/lsp/__main__.py +0 -0
  148. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/lsp/protocol.py +0 -0
  149. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/lsp/server.py +0 -0
  150. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/lsp/stdio.py +0 -0
  151. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/navigate.py +0 -0
  152. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/plantuml.py +0 -0
  153. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/project.py +0 -0
  154. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/semantic.py +0 -0
  155. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/sim.py +0 -0
  156. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/spreadsheet.py +0 -0
  157. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/store.py +0 -0
  158. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/traceability.py +0 -0
  159. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/us_customary_units.txt +0 -0
  160. {sysmlpy-0.86.0 → sysmlpy-0.88.0}/src/sysmlpy/validator.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sysmlpy
3
- Version: 0.86.0
3
+ Version: 0.88.0
4
4
  Summary:
5
5
  License-File: LICENSE
6
6
  Author: Jon R. Fox (mycr0ft)
@@ -6,7 +6,7 @@ build-backend = "poetry.core.masonry.api"
6
6
 
7
7
  [project]
8
8
  name = "sysmlpy"
9
- version = "0.86.0"
9
+ version = "0.88.0"
10
10
  description = ""
11
11
  authors = [{ name = "Jon R. Fox (mycr0ft)", email = "jon.fox@drfox.com" }]
12
12
  readme = "README.md"
@@ -38,3 +38,8 @@ sysmlpy-lsp = "sysmlpy.lsp.stdio:main"
38
38
  [tool.poetry.group.dev.dependencies]
39
39
  pytest = ">=8.0,<9.0"
40
40
 
41
+ [tool.pytest.ini_options]
42
+ markers = [
43
+ "conformance: OMG 2026-03 XPect parse conformance suite (slow; deselect with -m 'not conformance')",
44
+ ]
45
+
@@ -34,7 +34,7 @@ __all__ = [
34
34
  "render_state_transition_view_svg", "boxes_view",
35
35
  ]
36
36
  __author__ = "Jon Fox"
37
- __version__ = "0.86.0"
37
+ __version__ = "0.88.0"
38
38
 
39
39
  from sysmlpy.usage import (
40
40
  Item, Attribute, Part, Port, Action, Reference, UseCase, Requirement, Interface, Message,
@@ -2383,7 +2383,7 @@ def _make_assert_constraint_usage_dict(acu_ctx, prefix=None):
2383
2383
  if hasattr(cud, 'valuePart') and cud.valuePart():
2384
2384
  vp = cud.valuePart()
2385
2385
  if hasattr(vp, 'ownedExpression') and vp.ownedExpression():
2386
- expr = _visit_expression(vp.ownedExpression())
2386
+ expr = _visit_owned_expression(vp.ownedExpression())
2387
2387
  if expr:
2388
2388
  valuepart = {"name": "ValuePart", "ownedRelationship": expr}
2389
2389
 
@@ -2492,14 +2492,15 @@ def _make_satisfy_requirement_usage_dict(sru_ctx, prefix=None):
2492
2492
  }
2493
2493
  }
2494
2494
 
2495
- # Extract valuePart
2495
+ # Extract valuePart (``satisfy s1 : R = 3;``)
2496
+ # valuePart : featureValue ; featureValue : (EQ | COLON_EQ |
2497
+ # DEFAULT …) ownedExpression — use the shared extractor, which
2498
+ # handles the featureValue wrapper and the EQ/COLON_EQ/DEFAULT
2499
+ # flags (v0.88.0 — previously read vp.ownedExpression() directly,
2500
+ # which is one level too high, so the value was dropped).
2496
2501
  valuepart = None
2497
2502
  if hasattr(sru_ctx, 'valuePart') and sru_ctx.valuePart():
2498
- vp = sru_ctx.valuePart()
2499
- if hasattr(vp, 'ownedExpression') and vp.ownedExpression():
2500
- expr = _visit_expression(vp.ownedExpression())
2501
- if expr:
2502
- valuepart = {"name": "ValuePart", "ownedRelationship": expr}
2503
+ valuepart = _visit_value_part(sru_ctx.valuePart())
2503
2504
 
2504
2505
  # Extract satisfactionSubjectMember (after 'by')
2505
2506
  ssm = None
@@ -5024,30 +5025,48 @@ def _visit_entry_transition_member(ctx):
5024
5025
 
5025
5026
 
5026
5027
  def _visit_guarded_target_succession(ctx):
5027
- """Visit a guardedTargetSuccession context."""
5028
+ """Visit a guardedTargetSuccession context.
5029
+
5030
+ guardedTargetSuccession : guardExpressionMember THEN transitionSuccessionMember
5031
+
5032
+ Emits the ``ownedRelationship`` member-list shape the
5033
+ ``GuardedTargetSuccession`` grammar class loads (guard + target were
5034
+ silently dropped before v0.87.0, and the old dict shape crashed the
5035
+ class loader with a KeyError).
5036
+ """
5028
5037
  if ctx is None:
5029
5038
  return None
5030
-
5031
- guard = None
5032
- if hasattr(ctx, 'guardExpression') and ctx.guardExpression():
5033
- guard_dict = _visit_expression(ctx.guardExpression())
5034
- guard = {
5035
- "name": "GuardExpression",
5036
- "expression": guard_dict
5037
- }
5038
-
5039
- succession = None
5040
- if hasattr(ctx, 'succession') and ctx.succession():
5041
- succ = ctx.succession()
5042
- if isinstance(succ, list):
5043
- succ = succ[0]
5044
- if succ:
5045
- succession = _visit_succession(succ)
5046
-
5039
+
5040
+ owned_relationship = []
5041
+
5042
+ gem = None
5043
+ if hasattr(ctx, 'guardExpressionMember') and ctx.guardExpressionMember():
5044
+ gem = ctx.guardExpressionMember()
5045
+ if isinstance(gem, list):
5046
+ gem = gem[0]
5047
+ guard_member = _visit_guard_expression_member(gem)
5048
+ if guard_member:
5049
+ owned_relationship.append(guard_member)
5050
+
5051
+ tsm = None
5052
+ if hasattr(ctx, 'transitionSuccessionMember') and ctx.transitionSuccessionMember():
5053
+ tsm = ctx.transitionSuccessionMember()
5054
+ if isinstance(tsm, list):
5055
+ tsm = tsm[0]
5056
+ ts = None
5057
+ if hasattr(tsm, 'transitionSuccession') and tsm.transitionSuccession():
5058
+ ts = tsm.transitionSuccession()
5059
+ if isinstance(ts, list):
5060
+ ts = ts[0]
5061
+ if ts:
5062
+ owned_relationship.append({
5063
+ "name": "TransitionSuccessionMember",
5064
+ "ownedRelatedElement": _visit_transition_succession(ts),
5065
+ })
5066
+
5047
5067
  return {
5048
5068
  "name": "GuardedTargetSuccession",
5049
- "guard": guard,
5050
- "ownedRelatedElement": succession
5069
+ "ownedRelationship": owned_relationship,
5051
5070
  }
5052
5071
 
5053
5072
 
@@ -5548,6 +5567,8 @@ def _visit_payload_feature(ctx):
5548
5567
  PayloadFeature class expects:
5549
5568
  identification, valuepart, multiplicity1, multiplicity2, ownedRelationship (OwnedFeatureTyping), pfsp
5550
5569
  For 'accept VehicleStartSignal': ownedRelationship contains the type name.
5570
+ For 'accept msg : M': identification + pfsp (v0.88.0 — previously
5571
+ hardcoded to None, so the member's name and typing were dropped).
5551
5572
  """
5552
5573
  if ctx is None:
5553
5574
  return None
@@ -5580,14 +5601,49 @@ def _visit_payload_feature(ctx):
5580
5601
  }
5581
5602
  }
5582
5603
 
5604
+ # identification (``accept msg : M`` — first grammar alternative:
5605
+ # ``identification payloadFeatureSpecializationPart valuePart?``)
5606
+ identification = None
5607
+ if hasattr(ctx, 'identification') and ctx.identification():
5608
+ ident = ctx.identification()
5609
+ if ident:
5610
+ name_list = ident.name() if hasattr(ident, 'name') else None
5611
+ if name_list and isinstance(name_list, list):
5612
+ if len(name_list) == 2:
5613
+ shortname = name_list[0].getText()
5614
+ name = name_list[1].getText()
5615
+ elif len(name_list) == 1:
5616
+ name_text = name_list[0].getText()
5617
+ name = name_text
5618
+ shortname = None
5619
+ else:
5620
+ name = None
5621
+ shortname = None
5622
+ identification = {
5623
+ "name": "Identification",
5624
+ "declaredShortName": shortname,
5625
+ "declaredName": name
5626
+ }
5627
+
5628
+ # pfsp (the ``: M[1]`` specializations after the name)
5629
+ pfsp = None
5630
+ if hasattr(ctx, 'payloadFeatureSpecializationPart') and ctx.payloadFeatureSpecializationPart():
5631
+ pfsp = _build_pfsp_from_ctx(ctx.payloadFeatureSpecializationPart())
5632
+
5633
+ # valuePart (``accept msg = 3`` — ``identification valuePart``
5634
+ # alternative)
5635
+ valuepart = None
5636
+ if hasattr(ctx, 'valuePart') and ctx.valuePart():
5637
+ valuepart = _visit_value_part(ctx.valuePart())
5638
+
5583
5639
  return {
5584
5640
  "name": "PayloadFeature",
5585
- "identification": None,
5586
- "valuepart": None,
5641
+ "identification": identification,
5642
+ "valuepart": valuepart,
5587
5643
  "multiplicity1": None,
5588
5644
  "multiplicity2": None,
5589
5645
  "ownedRelationship": owned_rel,
5590
- "pfsp": None
5646
+ "pfsp": pfsp
5591
5647
  }
5592
5648
 
5593
5649
 
@@ -6661,6 +6717,10 @@ def _make_connection_usage_dict(ctx, prefix=None):
6661
6717
  """Create a ConnectionUsage dictionary."""
6662
6718
  name, shortname = _get_usage_identification(ctx)
6663
6719
 
6720
+ # Typed-by etc. on the connection declaration (e.g.
6721
+ # ``connection cn1 : CD``) — previously hardcoded to None.
6722
+ specialization = _build_full_specialization_from_ctx(ctx)
6723
+
6664
6724
  # Parse the connector part (``connect X to Y``) so endpoints survive
6665
6725
  # into the grammar object tree (v0.67.0 — fixes the "part": None stub)
6666
6726
  # connectionUsage: occurrenceUsagePrefix ( CONNECTION usageDeclaration?
@@ -6731,7 +6791,7 @@ def _make_connection_usage_dict(ctx, prefix=None):
6731
6791
  "declaredShortName": shortname,
6732
6792
  "declaredName": name
6733
6793
  },
6734
- "specialization": None
6794
+ "specialization": specialization
6735
6795
  }
6736
6796
  },
6737
6797
  "part": conn_part_dict,
@@ -8050,6 +8110,9 @@ def _make_view_usage_dict(ctx, prefix=None):
8050
8110
  body_items = []
8051
8111
  if hasattr(ctx, 'viewBody') and ctx.viewBody():
8052
8112
  body_items = _visit_view_body_dict(ctx.viewBody())
8113
+ # Typed-by / redefinition / subsets on the view declaration
8114
+ # (e.g. ``view v : Engine``) — previously hardcoded to None.
8115
+ specialization = _build_full_specialization_from_ctx(ctx)
8053
8116
  return {
8054
8117
  "name": "PackageMember",
8055
8118
  "prefix": None,
@@ -8071,7 +8134,7 @@ def _make_view_usage_dict(ctx, prefix=None):
8071
8134
  "declaredShortName": shortname,
8072
8135
  "declaredName": name
8073
8136
  },
8074
- "specialization": None
8137
+ "specialization": specialization
8075
8138
  }
8076
8139
  },
8077
8140
  "body": {
@@ -8092,6 +8155,7 @@ def _make_viewpoint_usage_dict(ctx, prefix=None):
8092
8155
  """
8093
8156
  name = None
8094
8157
  shortname = None
8158
+ specialization = None
8095
8159
  if ctx is not None:
8096
8160
  cud = None
8097
8161
  if hasattr(ctx, 'constraintUsageDeclaration') and ctx.constraintUsageDeclaration():
@@ -8112,6 +8176,11 @@ def _make_viewpoint_usage_dict(ctx, prefix=None):
8112
8176
  elif len(name_list) == 1:
8113
8177
  name_text = name_list[0].getText()
8114
8178
  name, shortname = _extract_name_shortname(name_text)
8179
+
8180
+ # Typed-by etc. on the viewpoint declaration (e.g.
8181
+ # ``viewpoint v : R``) — previously dropped.
8182
+ if ud is not None:
8183
+ specialization = _build_full_specialization_from_ud(ud)
8115
8184
 
8116
8185
  return {
8117
8186
  "name": "PackageMember",
@@ -8134,7 +8203,7 @@ def _make_viewpoint_usage_dict(ctx, prefix=None):
8134
8203
  "declaredShortName": shortname,
8135
8204
  "declaredName": name
8136
8205
  },
8137
- "specialization": None
8206
+ "specialization": specialization
8138
8207
  }
8139
8208
  },
8140
8209
  "body": {
@@ -8158,6 +8227,7 @@ def _make_concern_usage_dict(ctx, prefix=None):
8158
8227
  """
8159
8228
  name = None
8160
8229
  shortname = None
8230
+ specialization = None
8161
8231
  if ctx is not None:
8162
8232
  cud = None
8163
8233
  if hasattr(ctx, 'constraintUsageDeclaration') and ctx.constraintUsageDeclaration():
@@ -8178,6 +8248,10 @@ def _make_concern_usage_dict(ctx, prefix=None):
8178
8248
  elif len(name_list) == 1:
8179
8249
  name_text = name_list[0].getText()
8180
8250
  name, shortname = _extract_name_shortname(name_text)
8251
+
8252
+ # Typed-by etc. on the concern declaration — previously dropped.
8253
+ if ud is not None:
8254
+ specialization = _build_full_specialization_from_ud(ud)
8181
8255
 
8182
8256
  return {
8183
8257
  "name": "PackageMember",
@@ -8200,7 +8274,7 @@ def _make_concern_usage_dict(ctx, prefix=None):
8200
8274
  "declaredShortName": shortname,
8201
8275
  "declaredName": name
8202
8276
  },
8203
- "specialization": None
8277
+ "specialization": specialization
8204
8278
  }
8205
8279
  },
8206
8280
  "body": {
@@ -8236,6 +8310,7 @@ def _make_allocation_usage_dict(ctx, prefix=None):
8236
8310
  name = None
8237
8311
  shortname = None
8238
8312
  connector_part = None
8313
+ specialization = None
8239
8314
  if ctx is not None:
8240
8315
  aud = None
8241
8316
  if hasattr(ctx, 'allocationUsageDeclaration') and ctx.allocationUsageDeclaration():
@@ -8263,6 +8338,11 @@ def _make_allocation_usage_dict(ctx, prefix=None):
8263
8338
  if aud and hasattr(aud, 'connectorPart') and aud.connectorPart():
8264
8339
  connector_part = _build_connector_part_dict(aud.connectorPart())
8265
8340
 
8341
+ # Typed-by etc. on the allocation declaration (e.g.
8342
+ # ``allocation a1 : AD``) — previously dropped.
8343
+ if ud is not None:
8344
+ specialization = _build_full_specialization_from_ud(ud)
8345
+
8266
8346
  return {
8267
8347
  "name": "PackageMember",
8268
8348
  "prefix": None,
@@ -8284,7 +8364,7 @@ def _make_allocation_usage_dict(ctx, prefix=None):
8284
8364
  "declaredShortName": shortname,
8285
8365
  "declaredName": name
8286
8366
  },
8287
- "specialization": None
8367
+ "specialization": specialization
8288
8368
  }
8289
8369
  },
8290
8370
  "part": connector_part,
@@ -8309,6 +8389,7 @@ def _make_rendering_usage_dict(ctx, prefix=None):
8309
8389
  """
8310
8390
  name = None
8311
8391
  shortname = None
8392
+ specialization = None
8312
8393
  if ctx is not None:
8313
8394
  # RenderingUsage uses just `usage` (not usageDeclaration)
8314
8395
  usage = None
@@ -8330,6 +8411,12 @@ def _make_rendering_usage_dict(ctx, prefix=None):
8330
8411
  elif len(name_list) == 1:
8331
8412
  name_text = name_list[0].getText()
8332
8413
  name, shortname = _extract_name_shortname(name_text)
8414
+
8415
+ # Typed-by etc. on the rendering declaration (e.g.
8416
+ # ``rendering r1 : RD``) — previously dropped. The rendering
8417
+ # usage ctx carries ``usage`` directly, so the ctx-based
8418
+ # builder works here.
8419
+ specialization = _build_full_specialization_from_ctx(ctx)
8333
8420
 
8334
8421
  return {
8335
8422
  "name": "PackageMember",
@@ -8352,7 +8439,7 @@ def _make_rendering_usage_dict(ctx, prefix=None):
8352
8439
  "declaredShortName": shortname,
8353
8440
  "declaredName": name
8354
8441
  },
8355
- "specialization": None
8442
+ "specialization": specialization
8356
8443
  }
8357
8444
  },
8358
8445
  "body": {
@@ -8376,6 +8463,7 @@ def _make_individual_usage_dict(ctx, prefix=None):
8376
8463
  """
8377
8464
  name = None
8378
8465
  shortname = None
8466
+ specialization = None
8379
8467
  if ctx is not None:
8380
8468
  # individualUsage has `usage` at the end
8381
8469
  usage = None
@@ -8397,6 +8485,9 @@ def _make_individual_usage_dict(ctx, prefix=None):
8397
8485
  elif len(name_list) == 1:
8398
8486
  name_text = name_list[0].getText()
8399
8487
  name, shortname = _extract_name_shortname(name_text)
8488
+
8489
+ # Typed-by etc. on the individual declaration — previously dropped.
8490
+ specialization = _build_full_specialization_from_ctx(ctx)
8400
8491
 
8401
8492
  # Use IndividualUsageSimple per our simplified model
8402
8493
  return {
@@ -8420,7 +8511,7 @@ def _make_individual_usage_dict(ctx, prefix=None):
8420
8511
  "declaredShortName": shortname,
8421
8512
  "declaredName": name
8422
8513
  },
8423
- "specialization": None
8514
+ "specialization": specialization
8424
8515
  }
8425
8516
  },
8426
8517
  "body": {
@@ -8992,7 +9083,7 @@ def _make_view_rendering_member_dict(ctx, prefix=None):
8992
9083
  "declaredShortName": shortname,
8993
9084
  "declaredName": name
8994
9085
  },
8995
- "specialization": None
9086
+ "specialization": _build_full_specialization_from_ctx(usage_ctx)
8996
9087
  }
8997
9088
  },
8998
9089
  "completion": None
@@ -9074,6 +9165,102 @@ def _make_render_state_member_dict(ctx, prefix=None):
9074
9165
  }
9075
9166
 
9076
9167
 
9168
+ def _make_element_filter_member_dict(ctx):
9169
+ """Visit an elementFilterMember context and return its dict.
9170
+
9171
+ elementFilterMember : memberPrefix FILTER ownedExpression SEMI
9172
+
9173
+ e.g. ``filter @e1;`` — the element filter of a view.
9174
+ """
9175
+ if ctx is None:
9176
+ return None
9177
+
9178
+ prefix = None
9179
+ if hasattr(ctx, 'memberPrefix') and ctx.memberPrefix():
9180
+ mp = ctx.memberPrefix()
9181
+ if hasattr(mp, 'visibilityIndicator') and mp.visibilityIndicator():
9182
+ prefix = {
9183
+ "name": "MemberPrefix",
9184
+ "visibility": _visit_visibility_indicator_dict(mp.visibilityIndicator()),
9185
+ }
9186
+
9187
+ expr = None
9188
+ if hasattr(ctx, 'ownedExpression') and ctx.ownedExpression():
9189
+ expr = _visit_owned_expression(ctx.ownedExpression())
9190
+
9191
+ return {
9192
+ "name": "ElementFilterMember",
9193
+ "prefix": prefix,
9194
+ "ownedRelatedElement": expr,
9195
+ }
9196
+
9197
+
9198
+ def _make_expose_dict(ctx):
9199
+ """Visit an expose context and return its dict.
9200
+
9201
+ expose : EXPOSE ( membershipExpose | namespaceExpose ) relationshipBody
9202
+ membershipExpose : membershipImport
9203
+ namespaceExpose : namespaceImport
9204
+
9205
+ e.g. ``expose e;`` (membership form) or ``expose P::*;`` (namespace
9206
+ form). The membership/namespace payload reuses the Import dict
9207
+ shapes (without the import prefix).
9208
+ """
9209
+ if ctx is None:
9210
+ return None
9211
+
9212
+ relationship = None
9213
+
9214
+ if hasattr(ctx, 'membershipExpose') and ctx.membershipExpose():
9215
+ me = ctx.membershipExpose()
9216
+ if not hasattr(me, 'membershipImport') or me.membershipImport() is None:
9217
+ print("[visitor] expose: unsupported membershipExpose form, skipped")
9218
+ return None
9219
+ mi = me.membershipImport()
9220
+ qn_text = mi.qualifiedName().getText()
9221
+ is_recursive = mi.STAR_STAR() is not None
9222
+ relationship = {
9223
+ "name": "MembershipExpose",
9224
+ "membership": {
9225
+ "name": "ImportedMembership",
9226
+ "importedMembership": {
9227
+ "name": "QualifiedName",
9228
+ "names": qn_text.split("::"),
9229
+ },
9230
+ "isRecursive": is_recursive,
9231
+ },
9232
+ }
9233
+
9234
+ elif hasattr(ctx, 'namespaceExpose') and ctx.namespaceExpose():
9235
+ ne = ctx.namespaceExpose()
9236
+ if not hasattr(ne, 'namespaceImport') or ne.namespaceImport() is None:
9237
+ print("[visitor] expose: unsupported namespaceExpose form, skipped")
9238
+ return None
9239
+ ns = ne.namespaceImport()
9240
+ if ns.filterPackage() is not None:
9241
+ print("[visitor] expose: filterPackage form not supported, skipped")
9242
+ return None
9243
+ qn_text = ns.qualifiedName().getText()
9244
+ is_recursive = ns.STAR_STAR() is not None
9245
+ relationship = {
9246
+ "name": "NamespaceExpose",
9247
+ "namespace": {
9248
+ "name": "ImportedNamespace",
9249
+ "namespace": {"name": "QualifiedName", "names": qn_text.split("::")},
9250
+ "isRecursive": is_recursive,
9251
+ },
9252
+ }
9253
+
9254
+ if relationship is None:
9255
+ return None
9256
+
9257
+ return {
9258
+ "name": "Expose",
9259
+ "body": {"name": "RelationshipBody", "ownedRelationship": []},
9260
+ "ownedRelationship": relationship,
9261
+ }
9262
+
9263
+
9077
9264
  def _visit_view_definition_body_dict(body_ctx):
9078
9265
  """Visit a viewDefinitionBody and return a list of body item dicts.
9079
9266
 
@@ -9107,7 +9294,9 @@ def _visit_view_definition_body_dict(body_ctx):
9107
9294
  if item_dict:
9108
9295
  items.append(item_dict)
9109
9296
  elif hasattr(item_ctx, 'elementFilterMember') and item_ctx.elementFilterMember():
9110
- pass # TODO: handle elementFilterMember
9297
+ item_dict = _make_element_filter_member_dict(item_ctx.elementFilterMember())
9298
+ if item_dict:
9299
+ items.append(item_dict)
9111
9300
 
9112
9301
  return items
9113
9302
 
@@ -9146,9 +9335,13 @@ def _visit_view_body_dict(body_ctx):
9146
9335
  if item_dict:
9147
9336
  items.append(item_dict)
9148
9337
  elif hasattr(item_ctx, 'elementFilterMember') and item_ctx.elementFilterMember():
9149
- pass # TODO: handle elementFilterMember
9338
+ item_dict = _make_element_filter_member_dict(item_ctx.elementFilterMember())
9339
+ if item_dict:
9340
+ items.append(item_dict)
9150
9341
  elif hasattr(item_ctx, 'expose') and item_ctx.expose():
9151
- pass # TODO: handle expose
9342
+ item_dict = _make_expose_dict(item_ctx.expose())
9343
+ if item_dict:
9344
+ items.append(item_dict)
9152
9345
 
9153
9346
  return items
9154
9347
 
@@ -9853,6 +10046,21 @@ def _visit_definition_body_item_dict(item_ctx, is_interface=False):
9853
10046
  inner_element = None
9854
10047
  wrapper = None
9855
10048
 
10049
+ # Check for importRule first (first grammar alternative).
10050
+ # Imports are legal in every body — usage bodies included
10051
+ # (``part p1 { private import Q::*; }``). Reuse the package-body
10052
+ # Import dict shape and wrap it directly as the body item's
10053
+ # relationship (DefinitionBodyItem dispatches on item["name"],
10054
+ # same convention as RootNamespace) — previously silently
10055
+ # dropped (v0.88.0).
10056
+ if hasattr(item_ctx, 'importRule') and item_ctx.importRule():
10057
+ import_dict = _visit_import_rule_dict(item_ctx.importRule())
10058
+ if import_dict is not None:
10059
+ return {
10060
+ "name": "InterfaceBodyItem" if is_interface else "DefinitionBodyItem",
10061
+ "ownedRelationship": [import_dict],
10062
+ }
10063
+
9856
10064
  # Check for occurrenceUsageElement (part, item, port, action, etc.)
9857
10065
  if hasattr(item_ctx, 'occurrenceUsageElement') and item_ctx.occurrenceUsageElement():
9858
10066
  occ_elem = item_ctx.occurrenceUsageElement()
@@ -13976,6 +14184,22 @@ def _build_full_specialization_from_ctx(ctx):
13976
14184
  if isinstance(ud, list):
13977
14185
  ud = ud[0] if ud else None
13978
14186
 
14187
+ if ud is None and hasattr(ctx, 'usageDeclaration') and ctx.usageDeclaration():
14188
+ # Some usage contexts (e.g. viewUsage) carry the usageDeclaration
14189
+ # directly instead of through a nested ``usage`` element.
14190
+ ud = ctx.usageDeclaration()
14191
+ if isinstance(ud, list):
14192
+ ud = ud[0] if ud else None
14193
+
14194
+ if ud is None:
14195
+ return None
14196
+
14197
+ return _build_full_specialization_from_ud(ud)
14198
+
14199
+
14200
+ def _build_full_specialization_from_ud(ud):
14201
+ """Build a full FeatureSpecializationPart dict from a usageDeclaration
14202
+ ANTLR context (the shared core of the ctx-based variant above)."""
13979
14203
  if ud is None:
13980
14204
  return None
13981
14205
 
@@ -13997,6 +14221,24 @@ def _build_full_specialization_from_ctx(ctx):
13997
14221
  if not specs and multiplicity is None:
13998
14222
  return None
13999
14223
 
14224
+ specialization_list = _feature_specialization_dicts(specs)
14225
+
14226
+ return {
14227
+ "name": "FeatureSpecializationPart",
14228
+ "specialization": specialization_list,
14229
+ "multiplicity": multiplicity,
14230
+ "specialization2": [],
14231
+ "multiplicity2": None,
14232
+ }
14233
+
14234
+
14235
+ def _feature_specialization_dicts(specs):
14236
+ """Build FeatureSpecialization dicts from featureSpecialization ctxs.
14237
+
14238
+ Shared core for the FeatureSpecializationPart (usages) and
14239
+ PayloadFeatureSpecializationPart (payload features, e.g. accept
14240
+ members) builders. Handles typings, redefinitions, subsettings and
14241
+ references."""
14000
14242
  specialization_list = []
14001
14243
 
14002
14244
  for spec in specs:
@@ -14121,12 +14363,43 @@ def _build_full_specialization_from_ctx(ctx):
14121
14363
  }
14122
14364
  })
14123
14365
 
14366
+ return specialization_list
14367
+
14368
+
14369
+ def _build_pfsp_from_ctx(psp_ctx):
14370
+ """Build a PayloadFeatureSpecializationPart dict from a
14371
+ payloadFeatureSpecializationPart context.
14372
+
14373
+ Grammar: ``featureSpecialization+ multiplicityPart?
14374
+ featureSpecialization* | multiplicityPart featureSpecialization+``.
14375
+ Used by payload features (e.g. ``accept msg : M[1]``) — v0.88.0,
14376
+ previously hardcoded to None so the member's typing was dropped.
14377
+ """
14378
+ if psp_ctx is None:
14379
+ return None
14380
+
14381
+ first_group = []
14382
+ second_group = []
14383
+ seen_multiplicity = False
14384
+ for child in psp_ctx.children or []:
14385
+ child_name = type(child).__name__
14386
+ if child_name == 'MultiplicityPartContext':
14387
+ seen_multiplicity = True
14388
+ elif child_name == 'FeatureSpecializationContext':
14389
+ (second_group if seen_multiplicity else first_group).append(child)
14390
+
14391
+ specs = first_group + second_group
14392
+ specialization_list = _feature_specialization_dicts(specs)
14393
+ mp = _get_multiplicity_part(psp_ctx)
14394
+
14395
+ if not specialization_list and mp is None:
14396
+ return None
14397
+
14124
14398
  return {
14125
- "name": "FeatureSpecializationPart",
14126
- "specialization": specialization_list,
14127
- "multiplicity": multiplicity,
14128
- "specialization2": [],
14129
- "multiplicity2": None,
14399
+ "name": "PayloadFeatureSpecializationPart",
14400
+ "ownedRelationship": _feature_specialization_dicts(first_group),
14401
+ "ownedRelationship2": _feature_specialization_dicts(second_group),
14402
+ "mp": mp,
14130
14403
  }
14131
14404
 
14132
14405