sysmlpy 0.1.0__py3-none-any.whl
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.
- sysmlpy/__init__.py +226 -0
- sysmlpy/__main__.py +75 -0
- sysmlpy/antlr/README.md +146 -0
- sysmlpy/antlr/SysMLv2Lexer.interp +695 -0
- sysmlpy/antlr/SysMLv2Lexer.py +1123 -0
- sysmlpy/antlr/SysMLv2Lexer.tokens +444 -0
- sysmlpy/antlr/SysMLv2Parser.interp +960 -0
- sysmlpy/antlr/SysMLv2Parser.py +40750 -0
- sysmlpy/antlr/SysMLv2Parser.tokens +444 -0
- sysmlpy/antlr/SysMLv2ParserListener.py +4485 -0
- sysmlpy/antlr/SysMLv2ParserVisitor.py +2498 -0
- sysmlpy/antlr/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.interp +695 -0
- sysmlpy/antlr/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.py +1123 -0
- sysmlpy/antlr/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.tokens +444 -0
- sysmlpy/antlr_parser.py +185 -0
- sysmlpy/antlr_visitor.py +10864 -0
- sysmlpy/definition.py +1115 -0
- sysmlpy/examples/attribute_values.py +161 -0
- sysmlpy/examples/part_attributes.py +139 -0
- sysmlpy/examples/tuples_sequences.py +231 -0
- sysmlpy/formatting.py +47 -0
- sysmlpy/grammar/antlr4/README.md +30 -0
- sysmlpy/grammar/antlr4/SysMLv2Lexer.g4 +931 -0
- sysmlpy/grammar/antlr4/SysMLv2Lexer.interp +695 -0
- sysmlpy/grammar/antlr4/SysMLv2Lexer.py +1123 -0
- sysmlpy/grammar/antlr4/SysMLv2Lexer.tokens +444 -0
- sysmlpy/grammar/antlr4/SysMLv2Parser.g4 +2432 -0
- sysmlpy/grammar/antlr4/SysMLv2Parser.interp +960 -0
- sysmlpy/grammar/antlr4/SysMLv2Parser.py +40750 -0
- sysmlpy/grammar/antlr4/SysMLv2Parser.tokens +444 -0
- sysmlpy/grammar/antlr4/SysMLv2ParserListener.py +4485 -0
- sysmlpy/grammar/antlr4/SysMLv2ParserVisitor.py +2498 -0
- sysmlpy/grammar/antlr4/desc.xml +7 -0
- sysmlpy/grammar/antlr4/examples/camera.sysml +14 -0
- sysmlpy/grammar/antlr4/examples/toaster-system.sysml +193 -0
- sysmlpy/grammar/antlr4/examples/vehicle-model.sysml +118 -0
- sysmlpy/grammar/antlr4/pom.xml +59 -0
- sysmlpy/grammar/classes.py +8610 -0
- sysmlpy/library/LICENSE +165 -0
- sysmlpy/library/README.md +52 -0
- sysmlpy/library/__init__.py +0 -0
- sysmlpy/library/domain/Analysis/AnalysisTooling.sysml +34 -0
- sysmlpy/library/domain/Analysis/SampledFunctions.sysml +119 -0
- sysmlpy/library/domain/Analysis/StateSpaceRepresentation.sysml +143 -0
- sysmlpy/library/domain/Analysis/TradeStudies.sysml +171 -0
- sysmlpy/library/domain/Cause and Effect/CausationConnections.sysml +83 -0
- sysmlpy/library/domain/Cause and Effect/CauseAndEffect.sysml +81 -0
- sysmlpy/library/domain/Geometry/ShapeItems.sysml +899 -0
- sysmlpy/library/domain/Geometry/SpatialItems.sysml +168 -0
- sysmlpy/library/domain/Metadata/ImageMetadata.sysml +78 -0
- sysmlpy/library/domain/Metadata/ModelingMetadata.sysml +143 -0
- sysmlpy/library/domain/Metadata/ParametersOfInterestMetadata.sysml +39 -0
- sysmlpy/library/domain/Metadata/RiskMetadata.sysml +100 -0
- sysmlpy/library/domain/Quantities and Units/ISQ.sysml +42 -0
- sysmlpy/library/domain/Quantities and Units/ISQAcoustics.sysml +439 -0
- sysmlpy/library/domain/Quantities and Units/ISQAtomicNuclear.sysml +2726 -0
- sysmlpy/library/domain/Quantities and Units/ISQBase.sysml +206 -0
- sysmlpy/library/domain/Quantities and Units/ISQCharacteristicNumbers.sysml +1991 -0
- sysmlpy/library/domain/Quantities and Units/ISQChemistryMolecular.sysml +1353 -0
- sysmlpy/library/domain/Quantities and Units/ISQCondensedMatter.sysml +1223 -0
- sysmlpy/library/domain/Quantities and Units/ISQElectromagnetism.sysml +2333 -0
- sysmlpy/library/domain/Quantities and Units/ISQInformation.sysml +958 -0
- sysmlpy/library/domain/Quantities and Units/ISQLight.sysml +1537 -0
- sysmlpy/library/domain/Quantities and Units/ISQMechanics.sysml +1564 -0
- sysmlpy/library/domain/Quantities and Units/ISQSpaceTime.sysml +1169 -0
- sysmlpy/library/domain/Quantities and Units/ISQThermodynamics.sysml +1256 -0
- sysmlpy/library/domain/Quantities and Units/MeasurementRefCalculations.sysml +30 -0
- sysmlpy/library/domain/Quantities and Units/MeasurementReferences.sysml +526 -0
- sysmlpy/library/domain/Quantities and Units/Quantities.sysml +107 -0
- sysmlpy/library/domain/Quantities and Units/QuantityCalculations.sysml +70 -0
- sysmlpy/library/domain/Quantities and Units/SI.sysml +378 -0
- sysmlpy/library/domain/Quantities and Units/SIPrefixes.sysml +48 -0
- sysmlpy/library/domain/Quantities and Units/TensorCalculations.sysml +50 -0
- sysmlpy/library/domain/Quantities and Units/Time.sysml +274 -0
- sysmlpy/library/domain/Quantities and Units/USCustomaryUnits.sysml +260 -0
- sysmlpy/library/domain/Quantities and Units/VectorCalculations.sysml +62 -0
- sysmlpy/library/domain/Requirement Derivation/DerivationConnections.sysml +63 -0
- sysmlpy/library/domain/Requirement Derivation/RequirementDerivation.sysml +39 -0
- sysmlpy/library/kernel/Base.kerml +95 -0
- sysmlpy/library/kernel/BaseFunctions.kerml +80 -0
- sysmlpy/library/kernel/BooleanFunctions.kerml +22 -0
- sysmlpy/library/kernel/Clocks.kerml +156 -0
- sysmlpy/library/kernel/CollectionFunctions.kerml +68 -0
- sysmlpy/library/kernel/Collections.kerml +147 -0
- sysmlpy/library/kernel/ComplexFunctions.kerml +47 -0
- sysmlpy/library/kernel/ControlFunctions.kerml +117 -0
- sysmlpy/library/kernel/ControlPerformances.kerml +135 -0
- sysmlpy/library/kernel/DataFunctions.kerml +43 -0
- sysmlpy/library/kernel/FeatureReferencingPerformances.kerml +190 -0
- sysmlpy/library/kernel/IntegerFunctions.kerml +43 -0
- sysmlpy/library/kernel/KerML.kerml +483 -0
- sysmlpy/library/kernel/Links.kerml +67 -0
- sysmlpy/library/kernel/Metaobjects.kerml +58 -0
- sysmlpy/library/kernel/NaturalFunctions.kerml +27 -0
- sysmlpy/library/kernel/NumericalFunctions.kerml +43 -0
- sysmlpy/library/kernel/Objects.kerml +212 -0
- sysmlpy/library/kernel/Observation.kerml +161 -0
- sysmlpy/library/kernel/OccurrenceFunctions.kerml +154 -0
- sysmlpy/library/kernel/Occurrences.kerml +992 -0
- sysmlpy/library/kernel/Performances.kerml +293 -0
- sysmlpy/library/kernel/RationalFunctions.kerml +49 -0
- sysmlpy/library/kernel/RealFunctions.kerml +56 -0
- sysmlpy/library/kernel/ScalarFunctions.kerml +33 -0
- sysmlpy/library/kernel/ScalarValues.kerml +23 -0
- sysmlpy/library/kernel/SequenceFunctions.kerml +111 -0
- sysmlpy/library/kernel/SpatialFrames.kerml +197 -0
- sysmlpy/library/kernel/StatePerformances.kerml +145 -0
- sysmlpy/library/kernel/StringFunctions.kerml +25 -0
- sysmlpy/library/kernel/Transfers.kerml +281 -0
- sysmlpy/library/kernel/TransitionPerformances.kerml +66 -0
- sysmlpy/library/kernel/TrigFunctions.kerml +35 -0
- sysmlpy/library/kernel/Triggers.kerml +188 -0
- sysmlpy/library/kernel/VectorFunctions.kerml +273 -0
- sysmlpy/library/kernel/VectorValues.kerml +64 -0
- sysmlpy/library/systems/Actions.sysml +552 -0
- sysmlpy/library/systems/Allocations.sysml +29 -0
- sysmlpy/library/systems/AnalysisCases.sysml +38 -0
- sysmlpy/library/systems/Attributes.sysml +25 -0
- sysmlpy/library/systems/Calculations.sysml +37 -0
- sysmlpy/library/systems/Cases.sysml +71 -0
- sysmlpy/library/systems/Connections.sysml +60 -0
- sysmlpy/library/systems/Constraints.sysml +44 -0
- sysmlpy/library/systems/Flows.sysml +126 -0
- sysmlpy/library/systems/Interfaces.sysml +89 -0
- sysmlpy/library/systems/Items.sysml +153 -0
- sysmlpy/library/systems/Metadata.sysml +32 -0
- sysmlpy/library/systems/Parts.sysml +81 -0
- sysmlpy/library/systems/Ports.sysml +54 -0
- sysmlpy/library/systems/Requirements.sysml +194 -0
- sysmlpy/library/systems/StandardViewDefinitions.sysml +123 -0
- sysmlpy/library/systems/States.sysml +103 -0
- sysmlpy/library/systems/SysML.sysml +539 -0
- sysmlpy/library/systems/UseCases.sysml +57 -0
- sysmlpy/library/systems/VerificationCases.sysml +103 -0
- sysmlpy/library/systems/Views.sysml +164 -0
- sysmlpy/navigate.py +272 -0
- sysmlpy/store.py +547 -0
- sysmlpy/usage.py +2978 -0
- sysmlpy-0.1.0.dist-info/METADATA +230 -0
- sysmlpy-0.1.0.dist-info/RECORD +143 -0
- sysmlpy-0.1.0.dist-info/WHEEL +4 -0
- sysmlpy-0.1.0.dist-info/entry_points.txt +3 -0
- sysmlpy-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
"""Examples: Attribute Values, Types, and Complex Objects
|
|
2
|
+
|
|
3
|
+
This document explains how sysmlpy handles different types of attribute values:
|
|
4
|
+
- Simple values (strings, numbers)
|
|
5
|
+
- Pint quantities with units
|
|
6
|
+
- Tuples and lists (partial support)
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from sysmlpy import loads, Part, Attribute
|
|
10
|
+
from sysmlpy.usage import ureg
|
|
11
|
+
|
|
12
|
+
# =============================================================================
|
|
13
|
+
# 1. Simple Values
|
|
14
|
+
# =============================================================================
|
|
15
|
+
|
|
16
|
+
# Strings
|
|
17
|
+
model = loads('''
|
|
18
|
+
package Example {
|
|
19
|
+
attribute name : String = "Tesla";
|
|
20
|
+
}
|
|
21
|
+
''')
|
|
22
|
+
attr = model.children[0].children[0]
|
|
23
|
+
print(f"String: {attr.name} = {attr.get_value()}")
|
|
24
|
+
|
|
25
|
+
# Integers
|
|
26
|
+
model = loads('''
|
|
27
|
+
package Example {
|
|
28
|
+
attribute count : Integer = 42;
|
|
29
|
+
}
|
|
30
|
+
''')
|
|
31
|
+
attr = model.children[0].children[0]
|
|
32
|
+
print(f"Integer: {attr.name} = {attr.get_value()}")
|
|
33
|
+
|
|
34
|
+
# Reals
|
|
35
|
+
model = loads('''
|
|
36
|
+
package Example {
|
|
37
|
+
attribute price : Real = 49999.99;
|
|
38
|
+
}
|
|
39
|
+
''')
|
|
40
|
+
attr = model.children[0].children[0]
|
|
41
|
+
print(f"Real: {attr.name} = {attr.get_value()}")
|
|
42
|
+
|
|
43
|
+
# =============================================================================
|
|
44
|
+
# 2. Pint Quantities with Units
|
|
45
|
+
# =============================================================================
|
|
46
|
+
|
|
47
|
+
model = loads('''
|
|
48
|
+
package Example {
|
|
49
|
+
part def Vehicle {
|
|
50
|
+
attribute mass : Real = 1000 [kilogram];
|
|
51
|
+
attribute speed : Real = 60 [mile/hour];
|
|
52
|
+
attribute height : Real = 1.5 [meter];
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
''')
|
|
56
|
+
|
|
57
|
+
vehicle = model.children[0].children[0]
|
|
58
|
+
|
|
59
|
+
for attr in vehicle.children:
|
|
60
|
+
val = attr.get_value()
|
|
61
|
+
print(f"{attr.name} = {val}")
|
|
62
|
+
if hasattr(val, 'magnitude'):
|
|
63
|
+
print(f" magnitude: {val.magnitude}")
|
|
64
|
+
print(f" units: {val.units}")
|
|
65
|
+
|
|
66
|
+
# =============================================================================
|
|
67
|
+
# 3. Setting Values Programmatically
|
|
68
|
+
# =============================================================================
|
|
69
|
+
|
|
70
|
+
attr = Attribute()
|
|
71
|
+
attr._set_name("weight")
|
|
72
|
+
|
|
73
|
+
# With pint Quantity
|
|
74
|
+
attr.set_value(1500 * ureg.kilogram)
|
|
75
|
+
print(f"\nAfter setting: {attr.get_value()}")
|
|
76
|
+
|
|
77
|
+
# =============================================================================
|
|
78
|
+
# 4. Tuples and Lists (LIMITED SUPPORT)
|
|
79
|
+
# =============================================================================
|
|
80
|
+
|
|
81
|
+
# NOTE: The ANTLR4 grammar has partial support for sequences.
|
|
82
|
+
# Curly braces {} with commas do not currently parse.
|
|
83
|
+
# Workaround: Use multiple single-value attributes and combine in code.
|
|
84
|
+
|
|
85
|
+
# Workaround approach:
|
|
86
|
+
model = loads('''
|
|
87
|
+
package Example {
|
|
88
|
+
part def Vehicle {
|
|
89
|
+
attribute color1 : String = "red";
|
|
90
|
+
attribute color2 : String = "green";
|
|
91
|
+
attribute color3 : String = "blue";
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
''')
|
|
95
|
+
|
|
96
|
+
vehicle = model.children[0].children[0]
|
|
97
|
+
colors = []
|
|
98
|
+
for child in vehicle.children:
|
|
99
|
+
if isinstance(child, Attribute):
|
|
100
|
+
try:
|
|
101
|
+
colors.append(child.get_value())
|
|
102
|
+
except:
|
|
103
|
+
pass
|
|
104
|
+
print(f"\nColors as list: {colors}")
|
|
105
|
+
|
|
106
|
+
# =============================================================================
|
|
107
|
+
# 5. Type Resolution
|
|
108
|
+
# =============================================================================
|
|
109
|
+
|
|
110
|
+
# The type is stored in the grammar structure.
|
|
111
|
+
# typedby may not be populated during load_from_grammar (known issue).
|
|
112
|
+
|
|
113
|
+
model = loads('''
|
|
114
|
+
package Example {
|
|
115
|
+
part def Vehicle {
|
|
116
|
+
attribute mass : Real;
|
|
117
|
+
attribute name : String;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
''')
|
|
121
|
+
|
|
122
|
+
vehicle = model.children[0].children[0]
|
|
123
|
+
|
|
124
|
+
for attr in vehicle.children:
|
|
125
|
+
# Access grammar to see type info
|
|
126
|
+
print(f"{attr.name}: grammar type = {type(attr.grammar).__name__}")
|
|
127
|
+
|
|
128
|
+
# =============================================================================
|
|
129
|
+
# 6. Attribute Multiplicity
|
|
130
|
+
# =============================================================================
|
|
131
|
+
|
|
132
|
+
# Attributes can have multiplicity like Real[3] for arrays
|
|
133
|
+
# The type information is stored in the grammar but not yet exposed via Python API
|
|
134
|
+
|
|
135
|
+
model = loads('''
|
|
136
|
+
package Example {
|
|
137
|
+
attribute coords : Real[3];
|
|
138
|
+
}
|
|
139
|
+
''')
|
|
140
|
+
attr = model.children[0].children[0]
|
|
141
|
+
print(f"\nAttribute: {attr.name}")
|
|
142
|
+
|
|
143
|
+
# =============================================================================
|
|
144
|
+
# 7. Nested Attribute Bodies
|
|
145
|
+
# =============================================================================
|
|
146
|
+
|
|
147
|
+
# Attributes can contain nested elements (rare but valid)
|
|
148
|
+
model = loads('''
|
|
149
|
+
package Example {
|
|
150
|
+
part def Vehicle {
|
|
151
|
+
attribute sensors {
|
|
152
|
+
attribute temperature : Real;
|
|
153
|
+
attribute pressure : Real;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
''')
|
|
158
|
+
|
|
159
|
+
vehicle = model.children[0].children[0]
|
|
160
|
+
sensors = vehicle.children[0]
|
|
161
|
+
print(f"\n{sensors.name} children: {[c.name for c in sensors.children]}")
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"""Examples: Checking Attributes of a Part
|
|
2
|
+
|
|
3
|
+
NOTE: Currently, children are only loaded for 'part def' (definitions).
|
|
4
|
+
Using 'part' (usage) may not load nested children - this is a known limitation.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from sysmlpy import loads, Part, Attribute
|
|
8
|
+
from sysmlpy.usage import ureg
|
|
9
|
+
|
|
10
|
+
# =============================================================================
|
|
11
|
+
# 1. Basic Attribute Access
|
|
12
|
+
# =============================================================================
|
|
13
|
+
|
|
14
|
+
model = loads('''
|
|
15
|
+
package Example {
|
|
16
|
+
part def Vehicle {
|
|
17
|
+
attribute maxSpeed : Real;
|
|
18
|
+
attribute mass : Real;
|
|
19
|
+
part Engine { }
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
''')
|
|
23
|
+
|
|
24
|
+
vehicle = model.children[0].children[0]
|
|
25
|
+
|
|
26
|
+
print("All children:", vehicle.children)
|
|
27
|
+
|
|
28
|
+
# Filter for attributes
|
|
29
|
+
attrs = [c for c in vehicle.children if isinstance(c, Attribute)]
|
|
30
|
+
print("Attributes:", [a.name for a in attrs])
|
|
31
|
+
|
|
32
|
+
# Filter for nested parts
|
|
33
|
+
nested_parts = [c for c in vehicle.children if isinstance(c, Part)]
|
|
34
|
+
print("Nested parts:", [p.name for p in nested_parts])
|
|
35
|
+
|
|
36
|
+
# =============================================================================
|
|
37
|
+
# 2. Attribute Properties
|
|
38
|
+
# =============================================================================
|
|
39
|
+
|
|
40
|
+
model = loads('''
|
|
41
|
+
package Example {
|
|
42
|
+
part def Vehicle {
|
|
43
|
+
attribute maxSpeed : Real;
|
|
44
|
+
attribute mass : Real = 1000 [kilogram];
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
''')
|
|
48
|
+
|
|
49
|
+
vehicle = model.children[0].children[0]
|
|
50
|
+
|
|
51
|
+
for attr in vehicle.children:
|
|
52
|
+
print(f"\nAttribute: {attr.name}")
|
|
53
|
+
print(f" is_definition: {type(attr.grammar).__name__ == 'AttributeDefinition'}")
|
|
54
|
+
print(f" grammar type: {type(attr.grammar).__name__}")
|
|
55
|
+
|
|
56
|
+
# =============================================================================
|
|
57
|
+
# 3. Working with Values (Single Values)
|
|
58
|
+
# =============================================================================
|
|
59
|
+
|
|
60
|
+
# NOTE: get_value() requires the attribute to have been set with a value
|
|
61
|
+
# and the valuepart to exist in the grammar. This is still being improved.
|
|
62
|
+
|
|
63
|
+
model = loads('''
|
|
64
|
+
package Example {
|
|
65
|
+
part def Vehicle {
|
|
66
|
+
attribute mass : Real = 1000 [kilogram];
|
|
67
|
+
attribute name : String = "Tesla";
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
''')
|
|
71
|
+
|
|
72
|
+
vehicle = model.children[0].children[0]
|
|
73
|
+
|
|
74
|
+
for attr in vehicle.children:
|
|
75
|
+
try:
|
|
76
|
+
val = attr.get_value()
|
|
77
|
+
print(f"{attr.name} = {val}")
|
|
78
|
+
except Exception as e:
|
|
79
|
+
print(f"{attr.name}: get_value() needs valuepart - {type(e).__name__}")
|
|
80
|
+
|
|
81
|
+
# =============================================================================
|
|
82
|
+
# 4. Setting Values Programmatically
|
|
83
|
+
# =============================================================================
|
|
84
|
+
|
|
85
|
+
attr = Attribute()
|
|
86
|
+
attr._set_name("weight")
|
|
87
|
+
|
|
88
|
+
# Set with pint Quantity (recommended)
|
|
89
|
+
attr.set_value(1500 * ureg.kilogram)
|
|
90
|
+
print(f"\nAfter setting: {attr.get_value()}")
|
|
91
|
+
|
|
92
|
+
# NOTE: Setting with strings has a known bug where get_value() fails to parse.
|
|
93
|
+
# This will be fixed in a future update.
|
|
94
|
+
# attr.set_value("1200 [kilogram]") # BUG: get_value() fails after string assignment
|
|
95
|
+
|
|
96
|
+
# =============================================================================
|
|
97
|
+
# 5. Checking Type
|
|
98
|
+
# =============================================================================
|
|
99
|
+
|
|
100
|
+
# NOTE: typedby is populated during load_from_grammar but may need verification
|
|
101
|
+
|
|
102
|
+
model = loads('''
|
|
103
|
+
package Example {
|
|
104
|
+
part def Vehicle {
|
|
105
|
+
attribute mass : Real;
|
|
106
|
+
attribute name : String;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
''')
|
|
110
|
+
|
|
111
|
+
vehicle = model.children[0].children[0]
|
|
112
|
+
|
|
113
|
+
for attr in vehicle.children:
|
|
114
|
+
if attr.typedby:
|
|
115
|
+
print(f"{attr.name} : {attr.typedby.name}")
|
|
116
|
+
else:
|
|
117
|
+
# Access type from grammar structure
|
|
118
|
+
print(f"{attr.name} : (type in grammar, typedby not populated)")
|
|
119
|
+
|
|
120
|
+
# =============================================================================
|
|
121
|
+
# 6. Nested Parts
|
|
122
|
+
# =============================================================================
|
|
123
|
+
|
|
124
|
+
model = loads('''
|
|
125
|
+
package Example {
|
|
126
|
+
part def Vehicle {
|
|
127
|
+
attribute mass : Real;
|
|
128
|
+
part Engine {
|
|
129
|
+
attribute displacement : Real;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
''')
|
|
134
|
+
|
|
135
|
+
vehicle = model.children[0].children[0]
|
|
136
|
+
engine = vehicle.children[1] # Engine
|
|
137
|
+
|
|
138
|
+
print(f"\n{vehicle.name} contains: {[c.name for c in vehicle.children]}")
|
|
139
|
+
print(f"{engine.name} contains: {[c.name for c in engine.children]}")
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
"""Examples: Tuples and Sequences in SysML v2
|
|
2
|
+
|
|
3
|
+
SysML v2 supports tuples/sequences for collections. This document explains
|
|
4
|
+
the syntax and current status in sysmlpy.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from sysmlpy import loads, Part, Attribute
|
|
8
|
+
from sysmlpy.usage import ureg
|
|
9
|
+
|
|
10
|
+
# =============================================================================
|
|
11
|
+
# 1. Tuple Syntax in SysML v2
|
|
12
|
+
# =============================================================================
|
|
13
|
+
|
|
14
|
+
# SysML v2 uses parentheses with commas for tuples:
|
|
15
|
+
# attribute point : Anything[2] = (10, 20);
|
|
16
|
+
# attribute rgb : Anything[3] = (255, 128, 0);
|
|
17
|
+
|
|
18
|
+
# =============================================================================
|
|
19
|
+
# 2. Using Collections Library Types
|
|
20
|
+
# =============================================================================
|
|
21
|
+
|
|
22
|
+
# The Collections library (kernel/Collections.kerml) provides:
|
|
23
|
+
# - Array: Fixed-size multi-dimensional collection
|
|
24
|
+
# - List: Variable-size ordered collection
|
|
25
|
+
# - Set: Variable-size unordered unique collection
|
|
26
|
+
# - Bag: Variable-size unordered non-unique collection
|
|
27
|
+
# - Map: Collection of key-value pairs
|
|
28
|
+
# - KeyValuePair: A tuple of (key, value)
|
|
29
|
+
|
|
30
|
+
print("=" * 60)
|
|
31
|
+
print("Tuples and Sequences in SysML v2 - sysmlpy")
|
|
32
|
+
print("=" * 60)
|
|
33
|
+
|
|
34
|
+
# =============================================================================
|
|
35
|
+
# 3. Current Status
|
|
36
|
+
# =============================================================================
|
|
37
|
+
|
|
38
|
+
print("\n3. Current Status")
|
|
39
|
+
print("-" * 40)
|
|
40
|
+
|
|
41
|
+
# Simple values: WORKING
|
|
42
|
+
print("\nSimple values (Integer, Real, String, Boolean):")
|
|
43
|
+
model = loads('''
|
|
44
|
+
package Example {
|
|
45
|
+
attribute count : Integer = 42;
|
|
46
|
+
attribute price : Real = 19.99;
|
|
47
|
+
attribute name : String = "Widget";
|
|
48
|
+
attribute mass : Real = 100 [kilogram];
|
|
49
|
+
}
|
|
50
|
+
''')
|
|
51
|
+
pkg = model.children[0]
|
|
52
|
+
for attr in pkg.children:
|
|
53
|
+
try:
|
|
54
|
+
val = attr.get_value()
|
|
55
|
+
print(f" {attr.name} = {val}")
|
|
56
|
+
except Exception as e:
|
|
57
|
+
print(f" {attr.name}: ERROR - {type(e).__name__}")
|
|
58
|
+
|
|
59
|
+
# Tuples: PARTIAL (parse succeeds but value extraction needs work)
|
|
60
|
+
print("\nTuples like (10, 20):")
|
|
61
|
+
try:
|
|
62
|
+
model = loads('''
|
|
63
|
+
package Example {
|
|
64
|
+
attribute point : Real[2] = (10, 20);
|
|
65
|
+
}
|
|
66
|
+
''')
|
|
67
|
+
print(" SUCCESS - tuple parsing works!")
|
|
68
|
+
except Exception as e:
|
|
69
|
+
print(f" FAILED - {type(e).__name__}")
|
|
70
|
+
print(" (Known limitation: tuple syntax not yet fully supported)")
|
|
71
|
+
|
|
72
|
+
# =============================================================================
|
|
73
|
+
# 4. Recommended Workaround: Use Parts Instead of Tuples
|
|
74
|
+
# =============================================================================
|
|
75
|
+
|
|
76
|
+
print("\n4. Recommended Workaround: Use Parts with Named Fields")
|
|
77
|
+
print("-" * 40)
|
|
78
|
+
|
|
79
|
+
# Instead of tuples, use parts with named attributes:
|
|
80
|
+
model = loads('''
|
|
81
|
+
package Example {
|
|
82
|
+
/** A 2D position using a Part */
|
|
83
|
+
part def Position2D {
|
|
84
|
+
attribute x : Real = 10;
|
|
85
|
+
attribute y : Real = 20;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** RGB Color using a Part */
|
|
89
|
+
part def RGBColor {
|
|
90
|
+
attribute red : Integer = 255;
|
|
91
|
+
attribute green : Integer = 128;
|
|
92
|
+
attribute blue : Integer = 0;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** A vehicle with position and color */
|
|
96
|
+
part def Vehicle {
|
|
97
|
+
attribute mass : Real = 1000 [kilogram];
|
|
98
|
+
part position : Position2D;
|
|
99
|
+
part bodyColor : RGBColor;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
''')
|
|
103
|
+
|
|
104
|
+
# Get parts directly
|
|
105
|
+
parts = [c for c in model.children[0].children if isinstance(c, Part)]
|
|
106
|
+
print("\nPackage contents:")
|
|
107
|
+
for part in parts:
|
|
108
|
+
print(f" Part: {part.name}")
|
|
109
|
+
|
|
110
|
+
# Find Vehicle
|
|
111
|
+
vehicle = next((p for p in parts if p.name == 'Vehicle'), None)
|
|
112
|
+
if vehicle:
|
|
113
|
+
print(f"\nVehicle '{vehicle.name}':")
|
|
114
|
+
for child in vehicle.children:
|
|
115
|
+
if isinstance(child, Attribute):
|
|
116
|
+
try:
|
|
117
|
+
print(f" {child.name} = {child.get_value()}")
|
|
118
|
+
except Exception as e:
|
|
119
|
+
print(f" {child.name}: (get_value pending)")
|
|
120
|
+
elif isinstance(child, Part):
|
|
121
|
+
print(f" {child.name}:")
|
|
122
|
+
for subchild in child.children:
|
|
123
|
+
if isinstance(subchild, Attribute):
|
|
124
|
+
try:
|
|
125
|
+
print(f" {subchild.name} = {subchild.get_value()}")
|
|
126
|
+
except:
|
|
127
|
+
pass
|
|
128
|
+
|
|
129
|
+
# =============================================================================
|
|
130
|
+
# 5. Alternative: Use Multiple Attributes
|
|
131
|
+
# =============================================================================
|
|
132
|
+
|
|
133
|
+
print("\n5. Alternative: Use Multiple Single-Value Attributes")
|
|
134
|
+
print("-" * 40)
|
|
135
|
+
|
|
136
|
+
model = loads('''
|
|
137
|
+
package Example {
|
|
138
|
+
part def TemperatureReading {
|
|
139
|
+
attribute reading1 : Real;
|
|
140
|
+
attribute reading2 : Real;
|
|
141
|
+
attribute reading3 : Real;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
part sensor1 : TemperatureReading {
|
|
145
|
+
reading1 = 22.5 [degC];
|
|
146
|
+
reading2 = 23.0 [degC];
|
|
147
|
+
reading3 = 21.5 [degC];
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
''')
|
|
151
|
+
|
|
152
|
+
pkg = model.children[0]
|
|
153
|
+
parts = [c for c in pkg.children if isinstance(c, Part)]
|
|
154
|
+
sensor = next((p for p in parts if p.name == 'sensor1'), None)
|
|
155
|
+
if sensor:
|
|
156
|
+
print(f"\nTemperature readings for '{sensor.name}':")
|
|
157
|
+
for attr in sensor.children:
|
|
158
|
+
if isinstance(attr, Attribute):
|
|
159
|
+
try:
|
|
160
|
+
print(f" {attr.name} = {attr.get_value()}")
|
|
161
|
+
except:
|
|
162
|
+
pass
|
|
163
|
+
|
|
164
|
+
# =============================================================================
|
|
165
|
+
# 6. Collections Library Reference
|
|
166
|
+
# =============================================================================
|
|
167
|
+
|
|
168
|
+
print("\n6. Collections Library Reference")
|
|
169
|
+
print("-" * 40)
|
|
170
|
+
|
|
171
|
+
print("""
|
|
172
|
+
The kernel/Collections.kerml library provides these types:
|
|
173
|
+
|
|
174
|
+
datatype Collection - Base collection type with 'elements' feature
|
|
175
|
+
datatype OrderedCollection - Ordered collections
|
|
176
|
+
datatype UniqueCollection - Collections with unique elements
|
|
177
|
+
|
|
178
|
+
datatype Array - Fixed-size multi-dimensional collection
|
|
179
|
+
- Use 'dimensions' to specify shape
|
|
180
|
+
- Use 'elements' for flattened access
|
|
181
|
+
|
|
182
|
+
datatype List - Variable-size ordered collection
|
|
183
|
+
datatype Set - Variable-size unordered unique collection
|
|
184
|
+
datatype Bag - Variable-size unordered non-unique collection
|
|
185
|
+
|
|
186
|
+
datatype Map - Collection of key-value pairs
|
|
187
|
+
datatype KeyValuePair - A tuple of (key, value)
|
|
188
|
+
|
|
189
|
+
datatype OrderedMap - Ordered map
|
|
190
|
+
|
|
191
|
+
Example usage in SysML:
|
|
192
|
+
import Collections::*;
|
|
193
|
+
|
|
194
|
+
attribute measurements : List = #("temp1", "temp2", "temp3");
|
|
195
|
+
attribute dataPoint : KeyValuePair = (key = "x", val = 10);
|
|
196
|
+
""")
|
|
197
|
+
|
|
198
|
+
# =============================================================================
|
|
199
|
+
# 7. Summary
|
|
200
|
+
# =============================================================================
|
|
201
|
+
|
|
202
|
+
print("\n" + "=" * 60)
|
|
203
|
+
print("Summary: Tuple/Sequence Support in sysmlpy")
|
|
204
|
+
print("=" * 60)
|
|
205
|
+
print("""
|
|
206
|
+
+---------------------------+------------+
|
|
207
|
+
| Feature | Status |
|
|
208
|
+
+---------------------------+------------+
|
|
209
|
+
| Simple values | WORKS |
|
|
210
|
+
| Integer, Real, String | |
|
|
211
|
+
| Pint quantities | WORKS |
|
|
212
|
+
| Real = 100 [kilogram] | |
|
|
213
|
+
| Tuples | PARTIAL |
|
|
214
|
+
| (10, 20, 30) | (parses) |
|
|
215
|
+
| Lists with #() | NOT YET |
|
|
216
|
+
| #("a", "b", "c") | |
|
|
217
|
+
+---------------------------+------------+
|
|
218
|
+
|
|
219
|
+
Workarounds:
|
|
220
|
+
1. Use structured types (parts) instead of tuples
|
|
221
|
+
2. Use multiple single-value attributes
|
|
222
|
+
3. Use Parts with named fields for complex data
|
|
223
|
+
|
|
224
|
+
Recommended pattern:
|
|
225
|
+
part def Position2D {
|
|
226
|
+
attribute x : Real;
|
|
227
|
+
attribute y : Real;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
part origin : Position2D { x = 10; y = 20; }
|
|
231
|
+
""")
|
sysmlpy/formatting.py
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
Created on Wed May 31 13:26:53 2023
|
|
5
|
+
|
|
6
|
+
@author: christophercox
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from sysmlpy.grammar.classes import RootNamespace
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def remove_classes(model):
|
|
13
|
+
"""An example docstring for a class definition."""
|
|
14
|
+
if type(model) == type(dict()):
|
|
15
|
+
output = {}
|
|
16
|
+
for element in model:
|
|
17
|
+
if not "_" in element[0] and not "parent" in element:
|
|
18
|
+
# Remove internal parsing elements
|
|
19
|
+
output[element] = remove_classes(model[element])
|
|
20
|
+
elif type(model) == type(list()):
|
|
21
|
+
# List of classes
|
|
22
|
+
output = []
|
|
23
|
+
for member in model:
|
|
24
|
+
output.append(remove_classes(member))
|
|
25
|
+
elif type(model) == type(None):
|
|
26
|
+
return None
|
|
27
|
+
elif type(model) == type(bool()) or type(model) == type(str()):
|
|
28
|
+
return model
|
|
29
|
+
else:
|
|
30
|
+
output = {"name": model.__class__.__name__}
|
|
31
|
+
model_out = remove_classes(model.__dict__)
|
|
32
|
+
output.update(model_out)
|
|
33
|
+
|
|
34
|
+
return output
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def reformat(model):
|
|
38
|
+
"""An example docstring for a class definition."""
|
|
39
|
+
# Convert to dictionary format
|
|
40
|
+
model_out = {"name": model.__class__.__name__}
|
|
41
|
+
model_out.update(remove_classes(model.__dict__))
|
|
42
|
+
|
|
43
|
+
return model_out
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def classtree(model):
|
|
47
|
+
return RootNamespace(model)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# SysML v2 — ANTLR4 Grammar
|
|
2
|
+
|
|
3
|
+
ANTLR4 grammar for the [SysML v2](https://www.omg.org/spec/SysML/2.0) textual
|
|
4
|
+
notation, automatically generated from the OMG specification grammar (KEBNF
|
|
5
|
+
format).
|
|
6
|
+
|
|
7
|
+
## Source
|
|
8
|
+
|
|
9
|
+
- **Specification**: [Systems-Modeling/SysML-v2-Release](https://github.com/Systems-Modeling/SysML-v2-Release)
|
|
10
|
+
- **Release tag**: `2026-03`
|
|
11
|
+
- **Generator**: [daltskin/sysml-v2-grammar](https://github.com/daltskin/sysml-v2-grammar)
|
|
12
|
+
|
|
13
|
+
## Grammar Structure
|
|
14
|
+
|
|
15
|
+
| File | Description |
|
|
16
|
+
|------|-------------|
|
|
17
|
+
| `SysMLv2Lexer.g4` | Lexer grammar — keywords, operators, literals, whitespace |
|
|
18
|
+
| `SysMLv2Parser.g4` | Parser grammar — full SysML v2 textual syntax |
|
|
19
|
+
|
|
20
|
+
## Entry Point
|
|
21
|
+
|
|
22
|
+
The start rule is `rootNamespace`.
|
|
23
|
+
|
|
24
|
+
## License
|
|
25
|
+
|
|
26
|
+
MIT — Copyright (c) 2026 J Dalton
|
|
27
|
+
|
|
28
|
+
The SysML v2 specification grammar is owned by the Object Management Group
|
|
29
|
+
(OMG). This project provides a derived ANTLR4 translation of the official
|
|
30
|
+
KEBNF grammar.
|