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
sysmlpy/__init__.py
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
SysML v2 Python Library
|
|
5
|
+
|
|
6
|
+
A pure Python implementation for parsing SysML v2.0 models.
|
|
7
|
+
Uses the ANTLR4 parser for full SysML v2 grammar support.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
__all__ = [
|
|
11
|
+
"load", "loads", "load_grammar", "load_antlr", "load_grammar_antlr",
|
|
12
|
+
"Searchable",
|
|
13
|
+
"Store", "InMemoryStore", "NetworkXStore", "create_store", "new_id",
|
|
14
|
+
]
|
|
15
|
+
__author__ = "Jon Fox"
|
|
16
|
+
__version__ = "0.12.1"
|
|
17
|
+
|
|
18
|
+
from sysmlpy.usage import (
|
|
19
|
+
Item, Attribute, Part, Port, Action, Reference, UseCase, Requirement, Interface, Message,
|
|
20
|
+
State, Constraint, Connection, Flow, Calculation, Enumeration,
|
|
21
|
+
Allocation, Metadata, Rendering, Individual, FlowDef,
|
|
22
|
+
View, Viewpoint, Concern,
|
|
23
|
+
Case, AnalysisCase, VerificationCase,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
from sysmlpy.definition import Model, Package
|
|
27
|
+
from sysmlpy.navigate import Searchable
|
|
28
|
+
from sysmlpy.store import Store, InMemoryStore, NetworkXStore, create_store, new_id
|
|
29
|
+
|
|
30
|
+
from sysmlpy.usage import ureg
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def load_grammar(s, debug=False):
|
|
34
|
+
"""SysML load from string to dictionary
|
|
35
|
+
|
|
36
|
+
Deserialize a string containing a SysML v2.0 document to a Python dictionary.
|
|
37
|
+
|
|
38
|
+
Parameters
|
|
39
|
+
----------
|
|
40
|
+
s : str or _io.TextIOWrapper
|
|
41
|
+
String instance of SysML v2.0 document or file pointer
|
|
42
|
+
|
|
43
|
+
Returns
|
|
44
|
+
-------
|
|
45
|
+
dict
|
|
46
|
+
Dictionary version structured utilizing SysML v2.0 grammar
|
|
47
|
+
|
|
48
|
+
Raises
|
|
49
|
+
------
|
|
50
|
+
TypeError
|
|
51
|
+
Input was not str or file
|
|
52
|
+
"""
|
|
53
|
+
import sysmlpy.antlr_visitor as antlr_visitor
|
|
54
|
+
import sysmlpy.antlr_parser as antlr_parser
|
|
55
|
+
import io
|
|
56
|
+
|
|
57
|
+
# Handle file pointer or string
|
|
58
|
+
if isinstance(s, io.TextIOWrapper):
|
|
59
|
+
s = s.read()
|
|
60
|
+
elif not isinstance(s, str):
|
|
61
|
+
raise TypeError(
|
|
62
|
+
f"the SysML object must be str or file, not {s.__class__.__name__}"
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
# Wrap in package if not starting with 'package' for parsing
|
|
66
|
+
s_stripped = s.strip()
|
|
67
|
+
needs_unwrap = not s_stripped.startswith('package')
|
|
68
|
+
if needs_unwrap:
|
|
69
|
+
s = f'package __implicit__ {{ {s_stripped} }}'
|
|
70
|
+
|
|
71
|
+
try:
|
|
72
|
+
result = antlr_visitor.parse_to_dict(s)
|
|
73
|
+
|
|
74
|
+
# If we wrapped, we need to return a format compatible with what the tests expect
|
|
75
|
+
# The grammar classes expect "PackageBodyElement" as the top-level name
|
|
76
|
+
if needs_unwrap:
|
|
77
|
+
# Navigate to Package body ownedRelationship
|
|
78
|
+
pkg_member = result['ownedRelationship'][0]
|
|
79
|
+
pkg_elem = pkg_member['ownedRelatedElement']
|
|
80
|
+
pkg = pkg_elem['ownedRelatedElement']
|
|
81
|
+
body = pkg['body']
|
|
82
|
+
|
|
83
|
+
# Return in PackageBodyElement format (no Package wrapper)
|
|
84
|
+
return {
|
|
85
|
+
"name": "PackageBodyElement",
|
|
86
|
+
"ownedRelationship": body['ownedRelationship']
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return result
|
|
90
|
+
except antlr_parser.SysMLSyntaxError as e:
|
|
91
|
+
print("ANTLR4 returned the following error: {}".format(e))
|
|
92
|
+
raise
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def load(fp):
|
|
96
|
+
"""SysML load from file pointer
|
|
97
|
+
|
|
98
|
+
Deserialize ``fp`` (a ``.read()``-supporting file-like object containing
|
|
99
|
+
a SysML v2.0 document) to a Python dictionary object.
|
|
100
|
+
|
|
101
|
+
Parameters
|
|
102
|
+
----------
|
|
103
|
+
fp : _io.TextIOWrapper
|
|
104
|
+
File pointer to SysML v2.0 document
|
|
105
|
+
|
|
106
|
+
Returns
|
|
107
|
+
-------
|
|
108
|
+
dict
|
|
109
|
+
Dictionary version structured utilizing SysML v2.0 grammar
|
|
110
|
+
|
|
111
|
+
Raises
|
|
112
|
+
------
|
|
113
|
+
TypeError
|
|
114
|
+
Input was not _io.TextIOWrapper
|
|
115
|
+
"""
|
|
116
|
+
import io
|
|
117
|
+
|
|
118
|
+
if not isinstance(fp, io.TextIOWrapper):
|
|
119
|
+
raise TypeError(
|
|
120
|
+
f"the SysML object must be _io.TextIOWrapper, "
|
|
121
|
+
f"not {fp.__class__.__name__}"
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
return loads(fp.read())
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def loads(s: str, library=None):
|
|
128
|
+
"""Loads a model from string.
|
|
129
|
+
|
|
130
|
+
This shortcut function allows a user to build a model from a string by
|
|
131
|
+
first instantiating a base model class which builds out a default namespace
|
|
132
|
+
and then that model loads all elements underneath.
|
|
133
|
+
|
|
134
|
+
Uses the ANTLR4 parser.
|
|
135
|
+
|
|
136
|
+
Parameters
|
|
137
|
+
----------
|
|
138
|
+
s : str
|
|
139
|
+
The SysML v2 source code to parse.
|
|
140
|
+
library : str or Path, optional
|
|
141
|
+
Path to SysML v2 library files for resolving imports.
|
|
142
|
+
"""
|
|
143
|
+
return Model().load(s, library=library)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def load_grammar_antlr(fp, debug=False, library=None):
|
|
147
|
+
"""SysML load from file pointer using ANTLR4 parser.
|
|
148
|
+
|
|
149
|
+
Deserialize ``fp`` (a ``.read()``-supporting file-like object containing
|
|
150
|
+
a SysML v2.0 document) or ``s`` (a ``str`` instance containing a SysML
|
|
151
|
+
v2.0 document) to a Python dictionary object using the ANTLR4 parser.
|
|
152
|
+
|
|
153
|
+
Parameters
|
|
154
|
+
----------
|
|
155
|
+
fp : _io.TextIOWrapper or str
|
|
156
|
+
File pointer to SysML v2.0 document or string instance of SysML v2.0
|
|
157
|
+
document
|
|
158
|
+
debug : bool
|
|
159
|
+
Enable debug output.
|
|
160
|
+
library : str or Path, optional
|
|
161
|
+
Path to SysML v2 library files for resolving imports.
|
|
162
|
+
|
|
163
|
+
Returns
|
|
164
|
+
-------
|
|
165
|
+
dict
|
|
166
|
+
Dictionary version structured utilizing SysML v2.0 grammar
|
|
167
|
+
|
|
168
|
+
Raises
|
|
169
|
+
------
|
|
170
|
+
TypeError
|
|
171
|
+
Input was not _io.TextIOWrapper or str
|
|
172
|
+
|
|
173
|
+
"""
|
|
174
|
+
import io
|
|
175
|
+
import sysmlpy.antlr_visitor as antlr_visitor
|
|
176
|
+
import sysmlpy.antlr_parser as antlr_parser
|
|
177
|
+
|
|
178
|
+
if isinstance(fp, io.TextIOWrapper):
|
|
179
|
+
s = fp.read()
|
|
180
|
+
elif isinstance(fp, str):
|
|
181
|
+
s = fp
|
|
182
|
+
else:
|
|
183
|
+
raise TypeError(
|
|
184
|
+
f"the SysML object must be _io.TextIOWrapper or str "
|
|
185
|
+
f"not {fp.__class__.__name__}"
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
try:
|
|
189
|
+
return antlr_visitor.parse_to_dict(s, library=library)
|
|
190
|
+
except antlr_parser.SysMLSyntaxError as e:
|
|
191
|
+
print("ANTLR4 returned the following error: {}".format(e))
|
|
192
|
+
raise
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def load_antlr(fp):
|
|
196
|
+
"""SysML load from file pointer using ANTLR4 parser.
|
|
197
|
+
|
|
198
|
+
Deserialize ``fp`` (a ``.read()``-supporting file-like object containing
|
|
199
|
+
a SysML v2.0 document) to a Python dictionary object.
|
|
200
|
+
|
|
201
|
+
Parameters
|
|
202
|
+
----------
|
|
203
|
+
fp : _io.TextIOWrapper
|
|
204
|
+
File pointer to SysML v2.0 document
|
|
205
|
+
|
|
206
|
+
Returns
|
|
207
|
+
-------
|
|
208
|
+
dict
|
|
209
|
+
Dictionary version structured utilizing SysML v2.0 grammar
|
|
210
|
+
|
|
211
|
+
Raises
|
|
212
|
+
------
|
|
213
|
+
TypeError
|
|
214
|
+
Input was not _io.TextIOWrapper
|
|
215
|
+
"""
|
|
216
|
+
import io
|
|
217
|
+
|
|
218
|
+
if not isinstance(fp, io.TextIOWrapper):
|
|
219
|
+
raise TypeError(
|
|
220
|
+
f"the SysML object must be _io.TextIOWrapper, "
|
|
221
|
+
f"not {fp.__class__.__name__}"
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
return loads(fp.read())
|
|
225
|
+
|
|
226
|
+
|
sysmlpy/__main__.py
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""Command line interface for sysmlpy."""
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
import sys
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
from sysmlpy import loads
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def main():
|
|
13
|
+
parser = argparse.ArgumentParser(
|
|
14
|
+
prog="sysmlpy",
|
|
15
|
+
description="Parse SysML v2 files and display their Python representation"
|
|
16
|
+
)
|
|
17
|
+
parser.add_argument(
|
|
18
|
+
"file",
|
|
19
|
+
type=str,
|
|
20
|
+
help="Path to the SysML v2 file to parse"
|
|
21
|
+
)
|
|
22
|
+
parser.add_argument(
|
|
23
|
+
"--python",
|
|
24
|
+
action="store_true",
|
|
25
|
+
help="Display the Python repr() representation of the parsed model"
|
|
26
|
+
)
|
|
27
|
+
parser.add_argument(
|
|
28
|
+
"-l", "--library",
|
|
29
|
+
type=str,
|
|
30
|
+
help="Path to SysML v2 library files to use for parsing"
|
|
31
|
+
)
|
|
32
|
+
parser.add_argument(
|
|
33
|
+
"--dump",
|
|
34
|
+
action="store_true",
|
|
35
|
+
help="Display the SysML text output (dump format)"
|
|
36
|
+
)
|
|
37
|
+
parser.add_argument(
|
|
38
|
+
"--json",
|
|
39
|
+
action="store_true",
|
|
40
|
+
help="Display the dictionary/JSON representation"
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
args = parser.parse_args()
|
|
44
|
+
|
|
45
|
+
file_path = Path(args.file)
|
|
46
|
+
if not file_path.exists():
|
|
47
|
+
print(f"Error: File '{args.file}' not found.", file=sys.stderr)
|
|
48
|
+
sys.exit(1)
|
|
49
|
+
|
|
50
|
+
try:
|
|
51
|
+
with open(file_path, 'r') as f:
|
|
52
|
+
content = f.read()
|
|
53
|
+
except IOError as e:
|
|
54
|
+
print(f"Error reading file: {e}", file=sys.stderr)
|
|
55
|
+
sys.exit(1)
|
|
56
|
+
|
|
57
|
+
try:
|
|
58
|
+
model = loads(content, library=args.library)
|
|
59
|
+
except Exception as e:
|
|
60
|
+
print(f"Error parsing SysML file: {e}", file=sys.stderr)
|
|
61
|
+
sys.exit(1)
|
|
62
|
+
|
|
63
|
+
if args.json:
|
|
64
|
+
from sysmlpy import load_grammar
|
|
65
|
+
grammar_dict = load_grammar(content)
|
|
66
|
+
import json
|
|
67
|
+
print(json.dumps(grammar_dict, indent=2))
|
|
68
|
+
elif args.dump:
|
|
69
|
+
print(model.dump())
|
|
70
|
+
else:
|
|
71
|
+
# Default or --python flag: show repr()
|
|
72
|
+
print(repr(model))
|
|
73
|
+
|
|
74
|
+
if __name__ == "__main__":
|
|
75
|
+
main()
|
sysmlpy/antlr/README.md
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# ANTLR4 Parser for SysML v2
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
sysmlpy now includes an experimental **ANTLR4-based parser** as an alternative to the textX parser. This provides a pure Python implementation that can parse SysML v2.0 using grammars derived from the official OMG specification.
|
|
6
|
+
|
|
7
|
+
## Why ANTLR4?
|
|
8
|
+
|
|
9
|
+
The original textX parser requires manual conversion from the official XText grammar (used in the OMG SysML v2 Pilot Implementation). This is labor-intensive and can drift from the official specification.
|
|
10
|
+
|
|
11
|
+
The ANTLR4 approach:
|
|
12
|
+
- Uses grammars auto-generated from the official OMG KEBNF specification
|
|
13
|
+
- Grammar version tracks the OMG release (e.g., v2026.03.0 for 2026-03 release)
|
|
14
|
+
- Provides a pure Python alternative to Java/TypeScript-based SysMLv2 parsers
|
|
15
|
+
|
|
16
|
+
## Project Structure
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
src/sysmlpy/
|
|
20
|
+
├── antlr_parser.py # Core ANTLR4 parsing functions
|
|
21
|
+
├── antlr_visitor.py # Convert parse tree to Python classes
|
|
22
|
+
├── antlr/ # Generated ANTLR4 parser (auto-generated)
|
|
23
|
+
│ ├── SysMLv2Lexer.py
|
|
24
|
+
│ ├── SysMLv2Parser.py
|
|
25
|
+
│ ├── SysMLv2ParserVisitor.py
|
|
26
|
+
│ └── ...
|
|
27
|
+
└── grammar/antlr4/ # Grammar source files
|
|
28
|
+
├── SysMLv2Lexer.g4
|
|
29
|
+
├── SysMLv2Parser.g4
|
|
30
|
+
└── examples/ # Test files
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Usage
|
|
34
|
+
|
|
35
|
+
### Using the ANTLR4 Parser
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
from sysmlpy import load_antlr, loads, load_grammar
|
|
39
|
+
|
|
40
|
+
# Load from file
|
|
41
|
+
with open('model.sysml', 'r') as f:
|
|
42
|
+
model = load_antlr(f)
|
|
43
|
+
|
|
44
|
+
# Load from string
|
|
45
|
+
model = loads('''
|
|
46
|
+
package VehicleModel {
|
|
47
|
+
part def Vehicle {
|
|
48
|
+
attribute mass : Real;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
''')
|
|
52
|
+
|
|
53
|
+
# Get raw grammar dictionary
|
|
54
|
+
grammar_dict = load_grammar('package Test;')
|
|
55
|
+
|
|
56
|
+
# Print the model
|
|
57
|
+
print(model.dump())
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Round-trip Support
|
|
61
|
+
|
|
62
|
+
The ANTLR4 parser supports round-trip parsing:
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
from sysmlpy import loads
|
|
66
|
+
|
|
67
|
+
# Parse SysML
|
|
68
|
+
model = loads('package Test { part def Vehicle; }')
|
|
69
|
+
|
|
70
|
+
# Dump to string
|
|
71
|
+
output = model.dump()
|
|
72
|
+
|
|
73
|
+
# Parse again - should produce identical output
|
|
74
|
+
model2 = loads(output)
|
|
75
|
+
assert output == model2.dump()
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Choosing the Parser
|
|
79
|
+
|
|
80
|
+
All public API functions now use the ANTLR4 parser:
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
from sysmlpy import loads # ANTLR4-based (default)
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Grammar Sources
|
|
87
|
+
|
|
88
|
+
The ANTLR4 grammar is sourced from [daltskin/sysml-v2-grammar](https://github.com/daltskin/sysml-v2-grammar), which automatically generates ANTLR4 grammars from the OMG SysML v2 specification KEBNF files.
|
|
89
|
+
|
|
90
|
+
- **Current grammar version:** v2026.03.0
|
|
91
|
+
- **OMG release:** 2026-03
|
|
92
|
+
- **Source:** [Systems-Modeling/SysML-v2-Release](https://github.com/Systems-Modeling/SysML-v2-Release)
|
|
93
|
+
|
|
94
|
+
## What's Supported
|
|
95
|
+
|
|
96
|
+
The following SysML v2 constructs work with the ANTLR4 parser:
|
|
97
|
+
|
|
98
|
+
- Package definitions
|
|
99
|
+
- Part definitions and usages
|
|
100
|
+
- Attribute definitions and usages
|
|
101
|
+
- Item definitions and usages
|
|
102
|
+
- Port definitions and usages
|
|
103
|
+
- Requirement definitions
|
|
104
|
+
- Use case definitions
|
|
105
|
+
|
|
106
|
+
## Known Limitations
|
|
107
|
+
|
|
108
|
+
1. **Some complex elements** - Requirements, UseCases, and Ports with full bodies may have partial support
|
|
109
|
+
2. **Round-trip fidelity** - Some whitespace/formatting differences may occur
|
|
110
|
+
3. **Grammar drift** - The auto-generated grammar may have minor differences from the official OMG specification
|
|
111
|
+
|
|
112
|
+
## Updating the Grammar
|
|
113
|
+
|
|
114
|
+
To update to a newer OMG release:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
# Download the latest grammar release from daltskin/sysml-v2-grammar
|
|
118
|
+
# Or regenerate from the OMG KEBNF specification
|
|
119
|
+
|
|
120
|
+
# Regenerate the Python parser
|
|
121
|
+
java -jar antlr-4.13.2-complete.jar -Xexact-output-dir \
|
|
122
|
+
-o src/sysmlpy/antlr \
|
|
123
|
+
-visitor -listener -Dlanguage=Python3 \
|
|
124
|
+
src/sysmlpy/grammar/antlr4/SysMLv2Lexer.g4 \
|
|
125
|
+
src/sysmlpy/grammar/antlr4/SysMLv2Parser.g4
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Comparison: textX vs ANTLR4
|
|
129
|
+
|
|
130
|
+
| Feature | textX | ANTLR4 |
|
|
131
|
+
|---------|-------|--------|
|
|
132
|
+
| Grammar source | Manual XText conversion | Auto-generated from OMG KEBNF |
|
|
133
|
+
| Grammar updates | Labor-intensive | Automated |
|
|
134
|
+
| Parse performance | Good | Good |
|
|
135
|
+
| Error messages | Good | Excellent |
|
|
136
|
+
| Python-only | Yes | Yes |
|
|
137
|
+
| Round-trip support | Full | Partial |
|
|
138
|
+
| Specification tracking | Manual | Automatic |
|
|
139
|
+
|
|
140
|
+
## Future Work
|
|
141
|
+
|
|
142
|
+
1. Complete support for all SysML v2 constructs
|
|
143
|
+
2. Improve round-trip fidelity
|
|
144
|
+
3. Add conformance tests against OMG test suite
|
|
145
|
+
4. Consider making ANTLR4 the default parser
|
|
146
|
+
5. Remove textX dependency once ANTLR4 is stable
|