sysmlpy 0.36.2__tar.gz → 0.37.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 (148) hide show
  1. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/PKG-INFO +34 -2
  2. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/README.md +33 -1
  3. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/pyproject.toml +1 -1
  4. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/__init__.py +5 -1
  5. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/antlr_visitor.py +142 -29
  6. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/definition.py +2 -14
  7. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/grammar/classes.py +206 -13
  8. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/usage.py +34 -3
  9. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/LICENSE +0 -0
  10. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/__main__.py +0 -0
  11. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/antlr/README.md +0 -0
  12. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/antlr/SysMLv2Lexer.interp +0 -0
  13. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/antlr/SysMLv2Lexer.py +0 -0
  14. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/antlr/SysMLv2Lexer.tokens +0 -0
  15. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/antlr/SysMLv2Parser.interp +0 -0
  16. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/antlr/SysMLv2Parser.py +0 -0
  17. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/antlr/SysMLv2Parser.tokens +0 -0
  18. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/antlr/SysMLv2ParserListener.py +0 -0
  19. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/antlr/SysMLv2ParserVisitor.py +0 -0
  20. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/antlr/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.interp +0 -0
  21. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/antlr/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.py +0 -0
  22. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/antlr/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.tokens +0 -0
  23. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/antlr_parser.py +0 -0
  24. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/boxes_view.py +0 -0
  25. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/examples/attribute_values.py +0 -0
  26. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/examples/part_attributes.py +0 -0
  27. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/examples/tuples_sequences.py +0 -0
  28. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/formatting.py +0 -0
  29. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/grammar/antlr4/README.md +0 -0
  30. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.g4 +0 -0
  31. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.interp +0 -0
  32. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.py +0 -0
  33. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.tokens +0 -0
  34. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.g4 +0 -0
  35. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.interp +0 -0
  36. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.py +0 -0
  37. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.tokens +0 -0
  38. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/grammar/antlr4/SysMLv2ParserListener.py +0 -0
  39. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/grammar/antlr4/SysMLv2ParserVisitor.py +0 -0
  40. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/grammar/antlr4/desc.xml +0 -0
  41. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/grammar/antlr4/examples/camera.sysml +0 -0
  42. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/grammar/antlr4/examples/toaster-system.sysml +0 -0
  43. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/grammar/antlr4/examples/vehicle-model.sysml +0 -0
  44. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/grammar/antlr4/pom.xml +0 -0
  45. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/LICENSE +0 -0
  46. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/README.md +0 -0
  47. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/__init__.py +0 -0
  48. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/domain/Analysis/AnalysisTooling.sysml +0 -0
  49. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/domain/Analysis/SampledFunctions.sysml +0 -0
  50. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/domain/Analysis/StateSpaceRepresentation.sysml +0 -0
  51. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/domain/Analysis/TradeStudies.sysml +0 -0
  52. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/domain/Cause and Effect/CausationConnections.sysml +0 -0
  53. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/domain/Cause and Effect/CauseAndEffect.sysml +0 -0
  54. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/domain/Geometry/ShapeItems.sysml +0 -0
  55. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/domain/Geometry/SpatialItems.sysml +0 -0
  56. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/domain/Metadata/ImageMetadata.sysml +0 -0
  57. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/domain/Metadata/ModelingMetadata.sysml +0 -0
  58. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/domain/Metadata/ParametersOfInterestMetadata.sysml +0 -0
  59. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/domain/Metadata/RiskMetadata.sysml +0 -0
  60. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/domain/Quantities and Units/ISQ.sysml +0 -0
  61. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/domain/Quantities and Units/ISQAcoustics.sysml +0 -0
  62. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/domain/Quantities and Units/ISQAtomicNuclear.sysml +0 -0
  63. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/domain/Quantities and Units/ISQBase.sysml +0 -0
  64. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/domain/Quantities and Units/ISQCharacteristicNumbers.sysml +0 -0
  65. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/domain/Quantities and Units/ISQChemistryMolecular.sysml +0 -0
  66. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/domain/Quantities and Units/ISQCondensedMatter.sysml +0 -0
  67. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/domain/Quantities and Units/ISQElectromagnetism.sysml +0 -0
  68. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/domain/Quantities and Units/ISQInformation.sysml +0 -0
  69. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/domain/Quantities and Units/ISQLight.sysml +0 -0
  70. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/domain/Quantities and Units/ISQMechanics.sysml +0 -0
  71. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/domain/Quantities and Units/ISQSpaceTime.sysml +0 -0
  72. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/domain/Quantities and Units/ISQThermodynamics.sysml +0 -0
  73. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/domain/Quantities and Units/MeasurementRefCalculations.sysml +0 -0
  74. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/domain/Quantities and Units/MeasurementReferences.sysml +0 -0
  75. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/domain/Quantities and Units/Quantities.sysml +0 -0
  76. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/domain/Quantities and Units/QuantityCalculations.sysml +0 -0
  77. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/domain/Quantities and Units/SI.sysml +0 -0
  78. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/domain/Quantities and Units/SIPrefixes.sysml +0 -0
  79. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/domain/Quantities and Units/TensorCalculations.sysml +0 -0
  80. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/domain/Quantities and Units/Time.sysml +0 -0
  81. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/domain/Quantities and Units/USCustomaryUnits.sysml +0 -0
  82. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/domain/Quantities and Units/VectorCalculations.sysml +0 -0
  83. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/domain/Requirement Derivation/DerivationConnections.sysml +0 -0
  84. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/domain/Requirement Derivation/RequirementDerivation.sysml +0 -0
  85. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/kernel/Base.kerml +0 -0
  86. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/kernel/BaseFunctions.kerml +0 -0
  87. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/kernel/BooleanFunctions.kerml +0 -0
  88. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/kernel/Clocks.kerml +0 -0
  89. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/kernel/CollectionFunctions.kerml +0 -0
  90. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/kernel/Collections.kerml +0 -0
  91. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/kernel/ComplexFunctions.kerml +0 -0
  92. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/kernel/ControlFunctions.kerml +0 -0
  93. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/kernel/ControlPerformances.kerml +0 -0
  94. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/kernel/DataFunctions.kerml +0 -0
  95. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/kernel/FeatureReferencingPerformances.kerml +0 -0
  96. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/kernel/IntegerFunctions.kerml +0 -0
  97. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/kernel/KerML.kerml +0 -0
  98. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/kernel/Links.kerml +0 -0
  99. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/kernel/Metaobjects.kerml +0 -0
  100. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/kernel/NaturalFunctions.kerml +0 -0
  101. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/kernel/NumericalFunctions.kerml +0 -0
  102. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/kernel/Objects.kerml +0 -0
  103. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/kernel/Observation.kerml +0 -0
  104. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/kernel/OccurrenceFunctions.kerml +0 -0
  105. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/kernel/Occurrences.kerml +0 -0
  106. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/kernel/Performances.kerml +0 -0
  107. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/kernel/RationalFunctions.kerml +0 -0
  108. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/kernel/RealFunctions.kerml +0 -0
  109. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/kernel/ScalarFunctions.kerml +0 -0
  110. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/kernel/ScalarValues.kerml +0 -0
  111. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/kernel/SequenceFunctions.kerml +0 -0
  112. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/kernel/SpatialFrames.kerml +0 -0
  113. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/kernel/StatePerformances.kerml +0 -0
  114. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/kernel/StringFunctions.kerml +0 -0
  115. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/kernel/Transfers.kerml +0 -0
  116. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/kernel/TransitionPerformances.kerml +0 -0
  117. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/kernel/TrigFunctions.kerml +0 -0
  118. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/kernel/Triggers.kerml +0 -0
  119. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/kernel/VectorFunctions.kerml +0 -0
  120. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/kernel/VectorValues.kerml +0 -0
  121. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/systems/Actions.sysml +0 -0
  122. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/systems/Allocations.sysml +0 -0
  123. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/systems/AnalysisCases.sysml +0 -0
  124. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/systems/Attributes.sysml +0 -0
  125. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/systems/Calculations.sysml +0 -0
  126. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/systems/Cases.sysml +0 -0
  127. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/systems/Connections.sysml +0 -0
  128. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/systems/Constraints.sysml +0 -0
  129. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/systems/Flows.sysml +0 -0
  130. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/systems/Interfaces.sysml +0 -0
  131. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/systems/Items.sysml +0 -0
  132. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/systems/Metadata.sysml +0 -0
  133. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/systems/Parts.sysml +0 -0
  134. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/systems/Ports.sysml +0 -0
  135. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/systems/Requirements.sysml +0 -0
  136. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/systems/StandardViewDefinitions.sysml +0 -0
  137. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/systems/States.sysml +0 -0
  138. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/systems/SysML.sysml +0 -0
  139. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/systems/UseCases.sysml +0 -0
  140. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/systems/VerificationCases.sysml +0 -0
  141. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/library/systems/Views.sysml +0 -0
  142. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/navigate.py +0 -0
  143. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/plantuml.py +0 -0
  144. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/project.py +0 -0
  145. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/semantic.py +0 -0
  146. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/store.py +0 -0
  147. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/us_customary_units.txt +0 -0
  148. {sysmlpy-0.36.2 → sysmlpy-0.37.0}/src/sysmlpy/validator.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sysmlpy
3
- Version: 0.36.2
3
+ Version: 0.37.0
4
4
  Summary:
5
5
  License-File: LICENSE
6
6
  Author: Jon R. Fox (mycr0ft)
@@ -39,6 +39,8 @@ The project had diverged so much from sysml2py that a new name, sysmlpy, was sel
39
39
 
40
40
  ![Lines of Code Over Time](loc_history.svg)
41
41
 
42
+ **v0.37.0:** Round-trip / corpus-load fixes surfaced by benchmarking against gosysml (the Go port — `github.com/mycr0ft/gosysml`). Implicit-package wrap could swallow its own closing brace when the source ended with a line comment and no trailing newline (e.g. `Subsetting_OwningType.sysml`); `AnnotatingElement` now dispatches `MetadataFeature` and `TextualRepresentation` (they were crashing on `NoneType`); three missing grammar classes (`InitialNodeMember`, `ActionTargetSuccessionMember`, `GuardedSuccessionMember`) now match the visitor's emitted dicts and round-trip `first X; then Y;` / `if c then X else Y;` / `succession S first A1 if c then A2;` chains inside action bodies; `TriggerExpression` now extracts the `WHEN argumentExpressionMember` branch and degrades gracefully on empty arguments; control-node names (`merge m`, `decide`, etc.) flow through; nested `ref action a : A;` usages keep their `ref` prefix; `BinaryInterfacePart.dump()` degrades gracefully on 0/1-end interface parts (graceful-fallback contract). Corpus parity with gosysml: **122/123** files round-trip cleanly (the lone remaining failure, `Import_Visibility_Valid.sysml`, has an XPECT header that *expects* its syntax error). Grammar round-trip suite: **96/96 passing**.
43
+
42
44
  **v0.36.0:** Boxes-backed state-machine visualizer — `as_state_transition_view_boxes()`, `render_state_transition_view()`, `render_state_transition_view_svg()` produce native UML `«state»` shapes, initial pseudostate, final bullseye, and orthogonal routing via the optional [`boxes`](https://github.com/mycr0ft/boxes) package. Handles `done`, guards, shorthand `accept X then Y`, dotted feature chains (`S2.S3`), composite states, `parallel` regions, entry/do/exit attributes. 19 new boxes_view tests. Also fixes the INCOSE flashlight `interface … connect … { perform …; }` parse crash in `grammar/classes.py`.
43
45
 
44
46
  **v0.31.0:** Documentation overhaul — all docs rewritten to showcase the modern public API. New Model Parsing and Model Navigation sections. Semantic Analysis updated with `AnalysisResult`. Grammar round-trip: 77/77 (100%). 211 core tests passing.
@@ -327,7 +329,7 @@ tree = classtree(model)
327
329
  print(tree.dump())
328
330
  ```
329
331
 
330
- **All 77 grammar round-trip tests pass** (100%). Covered categories: packages, parts, items, ports, interfaces, binding connectors, flow connections, all action forms (definition, shorthand, succession, decomposition), expressions, calculations, constraints, state definitions, requirements, analysis cases, control flow (if/else, while, loop, fork, join, decision, send, accept, terminate), and trade studies.
332
+ **All 96 grammar round-trip tests pass** (100%). Covered categories: packages, parts, items, ports, interfaces, binding connectors, flow connections, all action forms (definition, shorthand, succession, decomposition), expressions, calculations, constraints, state definitions, requirements, analysis cases, control flow (if/else, while, loop, fork, join, decision, send, accept, terminate), trade studies, views, viewpoints, render states, portion usages, and annotations.
331
333
 
332
334
  ## Semantic Analysis
333
335
 
@@ -770,6 +772,36 @@ See [`docs/plantuml-examples/`](docs/plantuml-examples/) for all rendered exampl
770
772
 
771
773
  ## Changelog
772
774
 
775
+ - **v0.36.3** — Fix view (and other prefixed-usage) body children being
776
+ dropped from the public API tree. `Package.load_from_grammar` built
777
+ `View` objects manually without calling `load_from_grammar`, so
778
+ `view.attributes` (and all other typed accessors) returned `[]` even
779
+ when the view body contained attributes, parts, etc. Now calls
780
+ `View().load_from_grammar(...)` matching `Part` and other usages.
781
+ Also fixes `Usage.load_from_grammar` (declaration branch) and
782
+ `Usage._ensure_body` to handle prefixed usages whose body lives on
783
+ `grammar.body` rather than `grammar.usage.completion.body.body`.
784
+
785
+ - **v0.36.2** — Preserve short name, doc, and nested children in
786
+ `Requirement.dump()`/`load_from_grammar`. Three gaps in the public
787
+ `Requirement` class were dropping data the parser had captured:
788
+ `declaredShortName` was never propagated, `doc /* … */` nodes were
789
+ walked past, and `dump()` never iterated `self.children` so nested
790
+ `requirement` usages were omitted from output.
791
+
792
+ - **v0.36.1** — Populate nested requirement children in
793
+ `Requirement.load_from_grammar`. Previously the body walk stubbed out
794
+ `DefinitionBodyItem` with `pass`, so nested requirements were parsed
795
+ by the grammar but dropped from the public object tree.
796
+
797
+ - **v0.36.0** — Boxes-backed state-machine visualizer:
798
+ `as_state_transition_view_boxes()`, `render_state_transition_view()`,
799
+ `render_state_transition_view_svg()` produce native UML `«state»`
800
+ shapes, initial pseudostate, final bullseye, and orthogonal routing
801
+ via the optional [`boxes`](https://github.com/mycr0ft/boxes) package.
802
+ 19 new boxes_view tests. Also fixes the INCOSE flashlight
803
+ `interface … connect … { perform …; }` parse crash.
804
+
773
805
  - **v0.32.5** — Fix double-space in dump output when `:>>` (redefinition) or
774
806
  `: ` (typing) appears after `attribute`, `part`, or other usage keywords.
775
807
  Root cause: `Redefinitions.keyword` and `TypedBy.keyword` had leading spaces
@@ -14,6 +14,8 @@ The project had diverged so much from sysml2py that a new name, sysmlpy, was sel
14
14
 
15
15
  ![Lines of Code Over Time](loc_history.svg)
16
16
 
17
+ **v0.37.0:** Round-trip / corpus-load fixes surfaced by benchmarking against gosysml (the Go port — `github.com/mycr0ft/gosysml`). Implicit-package wrap could swallow its own closing brace when the source ended with a line comment and no trailing newline (e.g. `Subsetting_OwningType.sysml`); `AnnotatingElement` now dispatches `MetadataFeature` and `TextualRepresentation` (they were crashing on `NoneType`); three missing grammar classes (`InitialNodeMember`, `ActionTargetSuccessionMember`, `GuardedSuccessionMember`) now match the visitor's emitted dicts and round-trip `first X; then Y;` / `if c then X else Y;` / `succession S first A1 if c then A2;` chains inside action bodies; `TriggerExpression` now extracts the `WHEN argumentExpressionMember` branch and degrades gracefully on empty arguments; control-node names (`merge m`, `decide`, etc.) flow through; nested `ref action a : A;` usages keep their `ref` prefix; `BinaryInterfacePart.dump()` degrades gracefully on 0/1-end interface parts (graceful-fallback contract). Corpus parity with gosysml: **122/123** files round-trip cleanly (the lone remaining failure, `Import_Visibility_Valid.sysml`, has an XPECT header that *expects* its syntax error). Grammar round-trip suite: **96/96 passing**.
18
+
17
19
  **v0.36.0:** Boxes-backed state-machine visualizer — `as_state_transition_view_boxes()`, `render_state_transition_view()`, `render_state_transition_view_svg()` produce native UML `«state»` shapes, initial pseudostate, final bullseye, and orthogonal routing via the optional [`boxes`](https://github.com/mycr0ft/boxes) package. Handles `done`, guards, shorthand `accept X then Y`, dotted feature chains (`S2.S3`), composite states, `parallel` regions, entry/do/exit attributes. 19 new boxes_view tests. Also fixes the INCOSE flashlight `interface … connect … { perform …; }` parse crash in `grammar/classes.py`.
18
20
 
19
21
  **v0.31.0:** Documentation overhaul — all docs rewritten to showcase the modern public API. New Model Parsing and Model Navigation sections. Semantic Analysis updated with `AnalysisResult`. Grammar round-trip: 77/77 (100%). 211 core tests passing.
@@ -302,7 +304,7 @@ tree = classtree(model)
302
304
  print(tree.dump())
303
305
  ```
304
306
 
305
- **All 77 grammar round-trip tests pass** (100%). Covered categories: packages, parts, items, ports, interfaces, binding connectors, flow connections, all action forms (definition, shorthand, succession, decomposition), expressions, calculations, constraints, state definitions, requirements, analysis cases, control flow (if/else, while, loop, fork, join, decision, send, accept, terminate), and trade studies.
307
+ **All 96 grammar round-trip tests pass** (100%). Covered categories: packages, parts, items, ports, interfaces, binding connectors, flow connections, all action forms (definition, shorthand, succession, decomposition), expressions, calculations, constraints, state definitions, requirements, analysis cases, control flow (if/else, while, loop, fork, join, decision, send, accept, terminate), trade studies, views, viewpoints, render states, portion usages, and annotations.
306
308
 
307
309
  ## Semantic Analysis
308
310
 
@@ -745,6 +747,36 @@ See [`docs/plantuml-examples/`](docs/plantuml-examples/) for all rendered exampl
745
747
 
746
748
  ## Changelog
747
749
 
750
+ - **v0.36.3** — Fix view (and other prefixed-usage) body children being
751
+ dropped from the public API tree. `Package.load_from_grammar` built
752
+ `View` objects manually without calling `load_from_grammar`, so
753
+ `view.attributes` (and all other typed accessors) returned `[]` even
754
+ when the view body contained attributes, parts, etc. Now calls
755
+ `View().load_from_grammar(...)` matching `Part` and other usages.
756
+ Also fixes `Usage.load_from_grammar` (declaration branch) and
757
+ `Usage._ensure_body` to handle prefixed usages whose body lives on
758
+ `grammar.body` rather than `grammar.usage.completion.body.body`.
759
+
760
+ - **v0.36.2** — Preserve short name, doc, and nested children in
761
+ `Requirement.dump()`/`load_from_grammar`. Three gaps in the public
762
+ `Requirement` class were dropping data the parser had captured:
763
+ `declaredShortName` was never propagated, `doc /* … */` nodes were
764
+ walked past, and `dump()` never iterated `self.children` so nested
765
+ `requirement` usages were omitted from output.
766
+
767
+ - **v0.36.1** — Populate nested requirement children in
768
+ `Requirement.load_from_grammar`. Previously the body walk stubbed out
769
+ `DefinitionBodyItem` with `pass`, so nested requirements were parsed
770
+ by the grammar but dropped from the public object tree.
771
+
772
+ - **v0.36.0** — Boxes-backed state-machine visualizer:
773
+ `as_state_transition_view_boxes()`, `render_state_transition_view()`,
774
+ `render_state_transition_view_svg()` produce native UML `«state»`
775
+ shapes, initial pseudostate, final bullseye, and orthogonal routing
776
+ via the optional [`boxes`](https://github.com/mycr0ft/boxes) package.
777
+ 19 new boxes_view tests. Also fixes the INCOSE flashlight
778
+ `interface … connect … { perform …; }` parse crash.
779
+
748
780
  - **v0.32.5** — Fix double-space in dump output when `:>>` (redefinition) or
749
781
  `: ` (typing) appears after `attribute`, `part`, or other usage keywords.
750
782
  Root cause: `Redefinitions.keyword` and `TypedBy.keyword` had leading spaces
@@ -6,7 +6,7 @@ build-backend = "poetry.core.masonry.api"
6
6
 
7
7
  [project]
8
8
  name = "sysmlpy"
9
- version = "0.36.2"
9
+ version = "0.37.0"
10
10
  description = ""
11
11
  authors = [{ name = "Jon R. Fox (mycr0ft)", email = "jon.fox@drfox.com" }]
12
12
  readme = "README.md"
@@ -24,7 +24,7 @@ __all__ = [
24
24
  "render_state_transition_view_svg", "boxes_view",
25
25
  ]
26
26
  __author__ = "Jon Fox"
27
- __version__ = "0.36.2"
27
+ __version__ = "0.37.0"
28
28
 
29
29
  from sysmlpy.usage import (
30
30
  Item, Attribute, Part, Port, Action, Reference, UseCase, Requirement, Interface, Message,
@@ -78,6 +78,10 @@ def load_grammar(s, debug=False):
78
78
  s_stripped = s.strip()
79
79
  needs_unwrap = not s_stripped.startswith('package')
80
80
  if needs_unwrap:
81
+ # Ensure the implicit closing brace cannot be swallowed by a
82
+ # trailing line comment without a terminating newline.
83
+ if not s_stripped.endswith('\n'):
84
+ s_stripped += '\n'
81
85
  s = f'package __implicit__ {{ {s_stripped} }}'
82
86
 
83
87
  try:
@@ -1907,13 +1907,22 @@ def _visit_initial_node_member(inm_ctx):
1907
1907
  name = None
1908
1908
  if hasattr(inm_ctx, 'qualifiedName') and inm_ctx.qualifiedName():
1909
1909
  name = inm_ctx.qualifiedName().getText()
1910
-
1910
+
1911
+ # relationshipBody may carry its own ";" (e.g. `first A3;` followed by
1912
+ # further succession members in the same actionBodyItem).
1913
+ has_semi = False
1914
+ if hasattr(inm_ctx, 'relationshipBody') and inm_ctx.relationshipBody():
1915
+ rb = inm_ctx.relationshipBody()
1916
+ if rb.SEMI() is not None:
1917
+ has_semi = True
1918
+
1911
1919
  return {
1912
1920
  "name": "InitialNodeMember",
1913
1921
  "prefix": prefix,
1914
1922
  "ownedRelatedElement": {
1915
1923
  "name": "InitialNode",
1916
1924
  "declaredName": name,
1925
+ "hasSemi": has_semi,
1917
1926
  "ownedRelationship": []
1918
1927
  }
1919
1928
  }
@@ -1921,14 +1930,15 @@ def _visit_initial_node_member(inm_ctx):
1921
1930
 
1922
1931
  def _visit_action_target_succession_member(atsm_ctx):
1923
1932
  """Visit an actionTargetSuccessionMember context and return an ActionTargetSuccessionMember dict.
1924
-
1933
+
1925
1934
  actionTargetSuccessionMember: memberPrefix actionTargetSuccession
1926
1935
  actionTargetSuccession: (targetSuccession | guardedTargetSuccession | defaultTargetSuccession) usageBody
1927
1936
  targetSuccession: sourceEndMember THEN connectorEndMember
1937
+ defaultTargetSuccession: ELSE transitionSuccessionMember
1928
1938
  """
1929
1939
  if atsm_ctx is None:
1930
1940
  return None
1931
-
1941
+
1932
1942
  prefix = None
1933
1943
  if hasattr(atsm_ctx, 'memberPrefix') and atsm_ctx.memberPrefix():
1934
1944
  mp = atsm_ctx.memberPrefix()
@@ -1937,31 +1947,99 @@ def _visit_action_target_succession_member(atsm_ctx):
1937
1947
  "name": "MemberPrefix",
1938
1948
  "visibility": _visit_visibility_indicator_dict(mp.visibilityIndicator())
1939
1949
  }
1940
-
1950
+
1951
+ keyword = "then"
1941
1952
  name = None
1953
+ condition = None
1954
+ has_semi = False
1942
1955
  if hasattr(atsm_ctx, 'actionTargetSuccession') and atsm_ctx.actionTargetSuccession():
1943
1956
  ats = atsm_ctx.actionTargetSuccession()
1944
- # Try targetSuccession path
1945
- if hasattr(ats, 'targetSuccession') and ats.targetSuccession():
1957
+
1958
+ def _usage_body_has_semi(ats):
1959
+ ub = ats.usageBody() if hasattr(ats, 'usageBody') else None
1960
+ if ub is not None:
1961
+ db = ub.definitionBody() if hasattr(ub, 'definitionBody') else None
1962
+ if db is not None and hasattr(db, 'SEMI') and db.SEMI():
1963
+ return True
1964
+ return False
1965
+
1966
+ # `else done` form (defaultTargetSuccession)
1967
+ if hasattr(ats, 'defaultTargetSuccession') and ats.defaultTargetSuccession():
1968
+ keyword = "else"
1969
+ dts = ats.defaultTargetSuccession()
1970
+ has_semi = _usage_body_has_semi(ats)
1971
+ if hasattr(dts, 'transitionSuccessionMember') and dts.transitionSuccessionMember():
1972
+ tsm2 = dts.transitionSuccessionMember()
1973
+ if hasattr(tsm2, 'transitionSuccession') and tsm2.transitionSuccession():
1974
+ ts2 = tsm2.transitionSuccession()
1975
+ if hasattr(ts2, 'connectorEndMember') and ts2.connectorEndMember():
1976
+ cem2 = ts2.connectorEndMember()
1977
+ if cem2 is not None:
1978
+ name = _extract_connector_end_name(cem2)
1979
+ # `if <cond> then X` form (guardedTargetSuccession)
1980
+ elif hasattr(ats, 'guardedTargetSuccession') and ats.guardedTargetSuccession():
1981
+ gts = ats.guardedTargetSuccession()
1982
+ has_semi = _usage_body_has_semi(ats)
1983
+ if hasattr(gts, 'guardExpressionMember') and gts.guardExpressionMember():
1984
+ gem = gts.guardExpressionMember()
1985
+ if hasattr(gem, 'ownedExpression') and gem.ownedExpression():
1986
+ condition = gem.ownedExpression().getText()
1987
+ if hasattr(gts, 'transitionSuccessionMember') and gts.transitionSuccessionMember():
1988
+ tsm3 = gts.transitionSuccessionMember()
1989
+ if hasattr(tsm3, 'transitionSuccession') and tsm3.transitionSuccession():
1990
+ ts3 = tsm3.transitionSuccession()
1991
+ if hasattr(ts3, 'connectorEndMember') and ts3.connectorEndMember():
1992
+ cem3 = ts3.connectorEndMember()
1993
+ if cem3 is not None:
1994
+ name = _extract_connector_end_name(cem3)
1995
+ # Standard `then X` form (targetSuccession)
1996
+ elif hasattr(ats, 'targetSuccession') and ats.targetSuccession():
1946
1997
  ts = ats.targetSuccession()
1998
+ has_semi = _usage_body_has_semi(ats)
1947
1999
  if hasattr(ts, 'connectorEndMember') and ts.connectorEndMember():
1948
2000
  cem = ts.connectorEndMember()
1949
- if hasattr(cem, 'connectorEnd') and cem.connectorEnd():
1950
- ce = cem.connectorEnd()
1951
- if hasattr(ce, 'name') and ce.name():
1952
- name = ce.name().getText()
1953
-
2001
+ if cem is not None:
2002
+ name = _extract_connector_end_name(cem)
2003
+
1954
2004
  return {
1955
2005
  "name": "ActionTargetSuccessionMember",
1956
2006
  "prefix": prefix,
1957
2007
  "ownedRelatedElement": {
1958
2008
  "name": "ActionTargetSuccession",
2009
+ "keyword": keyword,
1959
2010
  "declaredName": name,
2011
+ "condition": condition,
2012
+ "hasSemi": has_semi,
1960
2013
  "ownedRelationship": []
1961
2014
  }
1962
2015
  }
1963
2016
 
1964
2017
 
2018
+ def _extract_connector_end_name(ce_member_ctx):
2019
+ """Extract the target feature text from a connectorEndMember.
2020
+
2021
+ Handles plain names (connectorEnd.name), qualified references via
2022
+ ownedReferenceSubsetting, and feature chains.
2023
+ """
2024
+ if ce_member_ctx is None:
2025
+ return None
2026
+ ce = None
2027
+ if hasattr(ce_member_ctx, 'connectorEnd'):
2028
+ ce = ce_member_ctx.connectorEnd()
2029
+ if ce is None:
2030
+ return None
2031
+
2032
+ if hasattr(ce, 'name') and ce.name():
2033
+ return ce.name().getText()
2034
+
2035
+ # `then m` / `then some.chain` carry an ownedReferenceSubsetting whose
2036
+ # qualifiedName holds the target (possibly dotted).
2037
+ if hasattr(ce, 'ownedReferenceSubsetting') and ce.ownedReferenceSubsetting():
2038
+ return ce.ownedReferenceSubsetting().getText()
2039
+
2040
+ return None
2041
+
2042
+
1965
2043
  def _visit_guarded_succession_member(gsm_ctx):
1966
2044
  """Visit a guardedSuccessionMember context and return a GuardedSuccessionMember dict.
1967
2045
 
@@ -1980,6 +2058,9 @@ def _visit_guarded_succession_member(gsm_ctx):
1980
2058
  "visibility": _visit_visibility_indicator_dict(mp.visibilityIndicator())
1981
2059
  }
1982
2060
 
2061
+ keyword = "succession"
2062
+ declared_name = None
2063
+ has_semi = False
1983
2064
  source_name = None
1984
2065
  condition = None
1985
2066
  target_name = None
@@ -1997,27 +2078,40 @@ def _visit_guarded_succession_member(gsm_ctx):
1997
2078
  if hasattr(gem, 'ownedExpression') and gem.ownedExpression():
1998
2079
  condition = gem.ownedExpression().getText()
1999
2080
 
2081
+ # Extract declared name from optional usageDeclaration (`succession S ...`)
2082
+ if hasattr(gs, 'usageDeclaration') and gs.usageDeclaration():
2083
+ ud = gs.usageDeclaration()
2084
+ if hasattr(ud, 'identification') and ud.identification():
2085
+ ident = ud.identification()
2086
+ if hasattr(ident, 'name') and ident.name():
2087
+ declared_name = ident.name()[-1].getText()
2088
+
2000
2089
  # Extract target name from transitionSuccessionMember
2001
2090
  if hasattr(gs, 'transitionSuccessionMember') and gs.transitionSuccessionMember():
2002
2091
  tsm = gs.transitionSuccessionMember()
2003
2092
  if hasattr(tsm, 'transitionSuccession') and tsm.transitionSuccession():
2004
2093
  ts = tsm.transitionSuccession()
2005
2094
  if hasattr(ts, 'connectorEndMember') and ts.connectorEndMember():
2006
- cem = ts.connectorEndMember()
2007
- if hasattr(cem, 'connectorEnd') and cem.connectorEnd():
2008
- ce = cem.connectorEnd()
2009
- if hasattr(ce, 'name') and ce.name():
2010
- target_name = ce.name().getText()
2011
-
2095
+ target_name = _extract_connector_end_name(ts.connectorEndMember())
2096
+
2097
+ # Whether the trailing usageBody carries its own ";"
2098
+ ub = gs.usageBody() if hasattr(gs, 'usageBody') else None
2099
+ if ub is not None:
2100
+ db = ub.definitionBody() if hasattr(ub, 'definitionBody') else None
2101
+ if db is not None and hasattr(db, 'SEMI') and db.SEMI():
2102
+ has_semi = True
2103
+
2012
2104
  return {
2013
2105
  "name": "GuardedSuccessionMember",
2014
2106
  "prefix": prefix,
2015
2107
  "ownedRelatedElement": {
2016
2108
  "name": "GuardedSuccession",
2017
- "keyword": "succession",
2109
+ "keyword": keyword,
2110
+ "declaredName": declared_name,
2018
2111
  "sourceName": source_name,
2019
2112
  "condition": condition,
2020
2113
  "targetName": target_name,
2114
+ "hasSemi": has_semi,
2021
2115
  "ownedRelationship": []
2022
2116
  }
2023
2117
  }
@@ -2627,9 +2721,10 @@ def _visit_control_node(ctx):
2627
2721
  "name": "ControlNode",
2628
2722
  "prefix": None,
2629
2723
  "keyword": None,
2724
+ "declaredName": None,
2630
2725
  "body": None
2631
2726
  }
2632
-
2727
+
2633
2728
  sub = None
2634
2729
  if hasattr(ctx, 'mergeNode') and ctx.mergeNode():
2635
2730
  sub = ctx.mergeNode()
@@ -2643,13 +2738,20 @@ def _visit_control_node(ctx):
2643
2738
  elif hasattr(ctx, 'forkNode') and ctx.forkNode():
2644
2739
  sub = ctx.forkNode()
2645
2740
  result["keyword"] = "fork"
2646
-
2741
+
2647
2742
  if sub is not None:
2648
2743
  if hasattr(sub, 'controlNodePrefix') and sub.controlNodePrefix():
2649
2744
  result["prefix"] = _get_occurrence_usage_prefix(sub.controlNodePrefix())
2745
+ if hasattr(sub, 'usageDeclaration') and sub.usageDeclaration():
2746
+ ud = sub.usageDeclaration()
2747
+ if hasattr(ud, 'identification') and ud.identification():
2748
+ ident = ud.identification()
2749
+ if hasattr(ident, 'name') and ident.name():
2750
+ name_list = ident.name()
2751
+ result["declaredName"] = name_list[-1].getText()
2650
2752
  if hasattr(sub, 'actionBody') and sub.actionBody():
2651
2753
  result["body"] = _visit_action_body(sub.actionBody())
2652
-
2754
+
2653
2755
  return result
2654
2756
 
2655
2757
 
@@ -2861,17 +2963,17 @@ def _visit_succession(succ_ctx):
2861
2963
 
2862
2964
  def _make_action_usage_element(ctx, member_prefix=None):
2863
2965
  """Create an action usage element dictionary from an actionUsage context.
2864
-
2966
+
2865
2967
  This is used for nested action usages inside action bodies.
2866
2968
  """
2867
2969
  if ctx is None:
2868
2970
  return None
2869
-
2971
+
2972
+ occ_prefix = _get_occurrence_usage_prefix(ctx)
2870
2973
  name = None
2871
2974
  shortname = None
2872
2975
  typed_by = None
2873
- occ_prefix = None
2874
-
2976
+
2875
2977
  # Get name from actionUsageDeclaration -> usageDeclaration -> identification
2876
2978
  if ctx.actionUsageDeclaration():
2877
2979
  aud = ctx.actionUsageDeclaration()
@@ -5361,13 +5463,15 @@ def _visit_trigger_feature_value(ctx):
5361
5463
  # Determine trigger keyword
5362
5464
  is_at = te.AT() is not None
5363
5465
  is_after = te.AFTER() is not None
5466
+ is_when = getattr(te, 'WHEN', lambda: None)() is not None
5364
5467
  trigger_kind = {
5365
5468
  "name": "TimeTriggerKind",
5366
5469
  "isAt": is_at,
5367
- "isAfter": is_after
5470
+ "isAfter": is_after,
5471
+ "isWhen": is_when
5368
5472
  }
5369
-
5370
- # Extract expression from argumentMember
5473
+
5474
+ # Extract expression: (AT|AFTER) argumentMember | WHEN argumentExpressionMember
5371
5475
  owned_expr_member = None
5372
5476
  if hasattr(te, 'argumentMember') and te.argumentMember():
5373
5477
  am = te.argumentMember()
@@ -5378,7 +5482,16 @@ def _visit_trigger_feature_value(ctx):
5378
5482
  "name": "OwnedExpressionMember",
5379
5483
  "ownedRelatedElement": owned_expr
5380
5484
  }
5381
-
5485
+ elif hasattr(te, 'argumentExpressionMember') and te.argumentExpressionMember():
5486
+ aem = te.argumentExpressionMember()
5487
+ if hasattr(aem, 'ownedExpression') and aem.ownedExpression():
5488
+ oe = aem.ownedExpression()
5489
+ owned_expr = _visit_owned_expression(oe)
5490
+ owned_expr_member = {
5491
+ "name": "OwnedExpressionMember",
5492
+ "ownedRelatedElement": owned_expr
5493
+ }
5494
+
5382
5495
  trigger_expr = {
5383
5496
  "name": "TriggerExpression",
5384
5497
  "kind": trigger_kind,
@@ -1168,23 +1168,11 @@ class Package(Searchable):
1168
1168
  f.parent = self
1169
1169
  self.children.append(f)
1170
1170
  elif inner_class == "ViewDefinition":
1171
- v = View(definition=True)
1172
- v.grammar = inner_element
1173
- if hasattr(inner_element, 'declaration') and inner_element.declaration:
1174
- decl = inner_element.declaration
1175
- if hasattr(decl, 'identification') and decl.identification:
1176
- v.name = decl.identification.declaredName
1171
+ v = View(definition=True).load_from_grammar(inner_element)
1177
1172
  v.parent = self
1178
1173
  self.children.append(v)
1179
1174
  elif inner_class == "ViewUsage":
1180
- v = View()
1181
- v.grammar = inner_element
1182
- if hasattr(inner_element, 'declaration') and inner_element.declaration:
1183
- decl = inner_element.declaration
1184
- if hasattr(decl, 'declaration') and decl.declaration:
1185
- feat_decl = decl.declaration
1186
- if hasattr(feat_decl, 'identification') and feat_decl.identification:
1187
- v.name = feat_decl.identification.declaredName
1175
+ v = View().load_from_grammar(inner_element)
1188
1176
  v.parent = self
1189
1177
  self.children.append(v)
1190
1178
  elif inner_class == "ViewpointDefinition":