├── .github
└── workflows
│ ├── black.yml
│ ├── release.yml
│ └── workflows.yml
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── doc-cov.svg
├── docs
├── Makefile
├── make.bat
├── requirements.txt
└── source
│ ├── conf.py
│ └── index.rst
├── pyproject.toml
├── requirements.txt
├── src
└── sysml2py
│ ├── __init__.py
│ ├── definition.py
│ ├── formatting.py
│ ├── grammar
│ ├── KerML.tx
│ ├── KerMLExpressions.tx
│ ├── SysML.tx
│ ├── SysML_compiled.tx
│ └── classes.py
│ ├── textx
│ ├── KerML.xtext
│ ├── KerMLExpressions.xtext
│ ├── SysML.xtext
│ └── xtext_to_textx.py
│ └── usage.py
└── tests
├── .DS_Store
├── __init__.py
├── class_test.py
├── conftest.py
├── functions.py
├── grammar_test.py
└── main_test.py
/.github/workflows/black.yml:
--------------------------------------------------------------------------------
1 | name: Format code
2 |
3 | on:
4 | push:
5 | branches:
6 | - '*'
7 | - '!main'
8 |
9 | permissions: write-all
10 |
11 | jobs:
12 | lint:
13 | runs-on: ubuntu-latest
14 | steps:
15 | - uses: actions/checkout@v3
16 | - name: ":robot: Format code with black"
17 | run: |
18 | pip install black
19 | black .
20 | - name: Test ${{ github.event.push.head }} docstring coverage
21 | run: |
22 | pip install docstr-coverage
23 | docstr-coverage src/sysml2py --badge=doc-cov --fail-under=0 -e ".*/(textx|tests)"
24 | - name: Commit changes
25 | uses: EndBug/add-and-commit@v4
26 | with:
27 | author_name: ${{ github.actor }}
28 | author_email: ${{ github.actor }}@users.noreply.github.com
29 | message: ":robot: Format code with black"
30 | add: "."
31 | branch: ${{ github.ref }}
32 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release Workflow
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 |
8 | permissions: write-all
9 |
10 | jobs:
11 | documentation:
12 | name: Build Sphinx Documentation
13 | runs-on: ubuntu-latest
14 | environment:
15 | name: github-pages
16 | url: ${{ steps.deployment.outputs.page_url }}
17 | steps:
18 | - uses: actions/setup-python@v4
19 | with:
20 | python-version: '3.9'
21 | - id: deployment
22 | uses: sphinx-notes/pages@v3
23 | with:
24 | documentation_path: ./docs/source
25 |
26 | codecoverage:
27 | name: Determine code and documentation coverage
28 | runs-on: ubuntu-latest
29 | steps:
30 | - uses: actions/checkout@v3
31 | - name: Set up Python
32 | uses: actions/setup-python@v4
33 | with:
34 | python-version: '3.9'
35 | - name: Install dependencies
36 | run: |
37 | python -m pip install --upgrade pip
38 | pip install --upgrade setuptools
39 | pip install -r requirements.txt
40 | - name: Test ${{ github.event.push.head }} coverage
41 | env:
42 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
43 | run: |
44 | python -m pip install coveralls pytest pyyaml textx
45 | python -m coverage run --source=src -m pytest tests/ && coverage report
46 | coveralls
47 |
48 | versioning:
49 | name: Semantic Versioning
50 | runs-on: ubuntu-latest
51 | environment:
52 | name: pypi
53 | url: https://pypi.org/p/sysml2py
54 | needs: [documentation, codecoverage]
55 | steps:
56 | - uses: actions/checkout@v3
57 | with:
58 | fetch-depth: 0
59 | - name: Python Semantic Release 📦 to PyPI
60 | id: release
61 | uses: python-semantic-release/python-semantic-release@v8.0.3
62 | with:
63 | github_token: ${{ secrets.GITHUB_TOKEN }}
64 | repository_username: __token__
65 | repository_password: ${{ secrets.PYPI_API_TOKEN }}
66 | - name: Publish package to PyPI
67 | uses: pypa/gh-action-pypi-publish@release/v1
68 | if: ${{ steps.release.outputs.released }} == 'true'
69 | with:
70 | password: ${{ secrets.PYPI_API_TOKEN }}
71 | - name: Publish package to GitHub Release
72 | uses: python-semantic-release/upload-to-gh-release@main
73 | if: ${{ steps.release.outputs.released }} == 'true'
74 | with:
75 | github_token: ${{ secrets.GITHUB_TOKEN }}
76 | tag: ${{ steps.release.outputs.tag }}
77 |
--------------------------------------------------------------------------------
/.github/workflows/workflows.yml:
--------------------------------------------------------------------------------
1 | name: Test Commit
2 |
3 | on:
4 | push:
5 | branches:
6 | - '*'
7 | - '!main'
8 |
9 | jobs:
10 | build:
11 |
12 | runs-on: ubuntu-latest
13 | strategy:
14 | matrix:
15 | python-version: ["3.11"]
16 |
17 | steps:
18 | - uses: actions/checkout@v3
19 | - name: Set up Python
20 | uses: actions/setup-python@v4
21 | with:
22 | python-version: '3.x'
23 | - name: Install dependencies
24 | run: |
25 | python -m pip install --upgrade pip
26 | pip install --upgrade setuptools
27 | pip install -r requirements.txt
28 | - name: Test ${{ github.event.push.head }} coverage
29 | env:
30 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
31 | run: |
32 | python -m pip install coveralls pytest
33 | python -m coverage run --source=src -m pytest tests && coverage report
34 | coveralls
35 | - name: Test with pytest
36 | run: |
37 | pip install pytest-timeout pytest-html
38 | pytest --timeout=300 tests --doctest-modules --html=report-${{ matrix.python-version }}.html --self-contained-html --junitxml=junit/test-results-${{ matrix.python-version }}.xml
39 | - name: Upload pytest test results
40 | uses: actions/upload-artifact@v3
41 | with:
42 | name: pytest-junit-results-${{ matrix.python-version }}
43 | path: junit/test-results-${{ matrix.python-version }}.xml
44 | # Use always() to always run this step to publish test results when there are test failures
45 | if: ${{ always() }}
46 | - name: Upload pytest test results
47 | uses: actions/upload-artifact@v3
48 | with:
49 | name: pytest-html-results-${{ matrix.python-version }}
50 | path: report-${{ matrix.python-version }}.html
51 | # Use always() to always run this step to publish test results when there are test failures
52 | if: ${{ always() }}
53 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | share/python-wheels/
24 | *.egg-info/
25 | .installed.cfg
26 | *.egg
27 | MANIFEST
28 |
29 | # PyInstaller
30 | # Usually these files are written by a python script from a template
31 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
32 | *.manifest
33 | *.spec
34 |
35 | # Installer logs
36 | pip-log.txt
37 | pip-delete-this-directory.txt
38 |
39 | # Unit test / coverage reports
40 | htmlcov/
41 | .tox/
42 | .nox/
43 | .coverage
44 | .coverage.*
45 | .cache
46 | nosetests.xml
47 | coverage.xml
48 | *.cover
49 | *.py,cover
50 | .hypothesis/
51 | .pytest_cache/
52 | cover/
53 |
54 | # Translations
55 | *.mo
56 | *.pot
57 |
58 | # Django stuff:
59 | *.log
60 | local_settings.py
61 | db.sqlite3
62 | db.sqlite3-journal
63 |
64 | # Flask stuff:
65 | instance/
66 | .webassets-cache
67 |
68 | # Scrapy stuff:
69 | .scrapy
70 |
71 | # Sphinx documentation
72 | docs/_build/
73 |
74 | # PyBuilder
75 | .pybuilder/
76 | target/
77 |
78 | # Jupyter Notebook
79 | .ipynb_checkpoints
80 |
81 | # IPython
82 | profile_default/
83 | ipython_config.py
84 |
85 | # pyenv
86 | # For a library or package, you might want to ignore these files since the code is
87 | # intended to run in multiple environments; otherwise, check them in:
88 | # .python-version
89 |
90 | # pipenv
91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
94 | # install all needed dependencies.
95 | #Pipfile.lock
96 |
97 | # poetry
98 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
99 | # This is especially recommended for binary packages to ensure reproducibility, and is more
100 | # commonly ignored for libraries.
101 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
102 | #poetry.lock
103 |
104 | # pdm
105 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
106 | #pdm.lock
107 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
108 | # in version control.
109 | # https://pdm.fming.dev/#use-with-ide
110 | .pdm.toml
111 |
112 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
113 | __pypackages__/
114 |
115 | # Celery stuff
116 | celerybeat-schedule
117 | celerybeat.pid
118 |
119 | # SageMath parsed files
120 | *.sage.py
121 |
122 | # Environments
123 | .env
124 | .venv
125 | env/
126 | venv/
127 | ENV/
128 | env.bak/
129 | venv.bak/
130 |
131 | # Spyder project settings
132 | .spyderproject
133 | .spyproject
134 |
135 | # Rope project settings
136 | .ropeproject
137 |
138 | # mkdocs documentation
139 | /site
140 |
141 | # mypy
142 | .mypy_cache/
143 | .dmypy.json
144 | dmypy.json
145 |
146 | # Pyre type checker
147 | .pyre/
148 |
149 | # pytype static type analyzer
150 | .pytype/
151 |
152 | # Cython debug symbols
153 | cython_debug/
154 |
155 | # PyCharm
156 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
157 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
158 | # and can be added to the global gitignore or merged into this file. For a more nuclear
159 | # option (not recommended) you can uncomment the following to ignore the entire idea folder.
160 | #.idea/
161 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # CHANGELOG
2 |
3 |
4 |
5 | ## v0.5.3 (2024-05-30)
6 |
7 | ### :memo:
8 |
9 | * :memo: Added full docstrings to init ([`0e06f1d`](https://github.com/Westfall-io/sysml2py/commit/0e06f1d73b476706eae4dddf02ff3e3b3c052ada))
10 |
11 | ### Other
12 |
13 | * :green_heart: Deployment fix and updates for pypi ([`ee89465`](https://github.com/Westfall-io/sysml2py/commit/ee894656417cdf5be5f2126f0374d15377bd12c6))
14 |
15 | * :green_heart: Updating release workflow as well ([`8c72ce9`](https://github.com/Westfall-io/sysml2py/commit/8c72ce97d613b4d59d0773bb8498cdeb8bbc992d))
16 |
17 | * :green_heart: Removing distribute ([`2dd552e`](https://github.com/Westfall-io/sysml2py/commit/2dd552e55097193d3cf6d181015c51a6b1fd795f))
18 |
19 | * :green_heart: Updating test script to ensure available resources for pytest ([`6a9c297`](https://github.com/Westfall-io/sysml2py/commit/6a9c29790e53f06e382d74f3b5e36bbfc1ed9de9))
20 |
21 | * :arrow_up: Fixing issue with dependencies for astropy ([`ac3b2ee`](https://github.com/Westfall-io/sysml2py/commit/ac3b2ee6965e899854d4e0f4f1946a61bd4f9e67))
22 |
23 | * :arrow_up: Fixing issue with dependencies and cython3 failing ([`bb4feb6`](https://github.com/Westfall-io/sysml2py/commit/bb4feb6b4227c40a6f4b0f3d6cb6d87e43ec3565))
24 |
25 |
26 | ## v0.5.2 (2023-08-12)
27 |
28 | ### :ambulance:
29 |
30 | * :ambulance: Permissions fix ([`8c5ea13`](https://github.com/Westfall-io/sysml2py/commit/8c5ea13b9d28aa2f846fc9f1e7f985eeae7e615d))
31 |
32 | * :ambulance: Added configuration to workflow ([`e8b932b`](https://github.com/Westfall-io/sysml2py/commit/e8b932b9ab4e3e16ff43cf4549c571e70a5cd218))
33 |
34 |
35 | ## v0.5.1 (2023-08-12)
36 |
37 | ### :ambulance:
38 |
39 | * :ambulance: Correct workflow yaml ([`8c410ee`](https://github.com/Westfall-io/sysml2py/commit/8c410ee7e486b7624e31d19faf94c6692b110f88))
40 |
41 | * :ambulance: Fix to upload to pypi ([`3309eb5`](https://github.com/Westfall-io/sysml2py/commit/3309eb5641f3671e6690bd61ac04b986c5d0a0c8))
42 |
43 |
44 | ## v0.5.0 (2023-08-12)
45 |
46 | ### :ambulance:
47 |
48 | * :ambulance: Fix for attribute change when adding units ([`1daacac`](https://github.com/Westfall-io/sysml2py/commit/1daacac3e81062bd35a5cac832f3cafccc9317a9))
49 |
50 | * :ambulance: Fixed critical grammar changes with SysML and KerML overwrites. ([`34978bb`](https://github.com/Westfall-io/sysml2py/commit/34978bbd33a0793cb618605aa87950fda64d5f68))
51 |
52 | ### :bug:
53 |
54 | * :bug: Removing optional from in flow statement that won't return programmatically. ([`716961b`](https://github.com/Westfall-io/sysml2py/commit/716961b003e51c286af8c63e2cad5d5806acef20))
55 |
56 | * :bug: Fixed issue with Primary expression get definition response. ([`5512466`](https://github.com/Westfall-io/sysml2py/commit/55124661dd6f8c08efb2136db65bb22111012ae4))
57 |
58 | * :bug: Updated secondary primary expression in attribute. ([`97f2086`](https://github.com/Westfall-io/sysml2py/commit/97f20867c29b577ce0f3d6d3eb5dd1cabe0dafaf))
59 |
60 | * :bug: Fixed changes to primary expression in attribute ([`ace773c`](https://github.com/Westfall-io/sysml2py/commit/ace773c595db76e208fe4d909f91ceae4171fef6))
61 |
62 | * :bug: Duplicate feature chaining in primary expression. ([`8217463`](https://github.com/Westfall-io/sysml2py/commit/821746349450467c3ab9b46bc86922d2476f8640))
63 |
64 | ### :sparkles:
65 |
66 | * :sparkles: Adding analysis grammar and tests. ([`9400f9b`](https://github.com/Westfall-io/sysml2py/commit/9400f9bef19757733b4d8a90d66f7e9678a42f6c))
67 |
68 | * :sparkles: Adding requirement grammar classes and tests. ([`0d73498`](https://github.com/Westfall-io/sysml2py/commit/0d7349852aa361fe45ff5ffbc457226675f87b73))
69 |
70 | * :sparkles: Adding constraint grammar and tests. ([`6212fd0`](https://github.com/Westfall-io/sysml2py/commit/6212fd0fa4cd2261cd0b17e3871b5367080a0005))
71 |
72 | * :sparkles: State grammar with appropriate tests. ([`b896efe`](https://github.com/Westfall-io/sysml2py/commit/b896efe2e0331383aa520621275ec8ae911f1871))
73 |
74 | * :sparkles: State grammar classes initial implementation with first test. ([`61d3df1`](https://github.com/Westfall-io/sysml2py/commit/61d3df1571b25e554bad631d005d11ce9ac5c0a4))
75 |
76 | * :sparkles: Added all calculation grammar classes and tests that pass. ([`393fa4c`](https://github.com/Westfall-io/sysml2py/commit/393fa4cce83471500401c3c7737a89c94e17f8cc))
77 |
78 | * :sparkles: Adding grammar for expressions. ([`f69c1ef`](https://github.com/Westfall-io/sysml2py/commit/f69c1ef446730912ef9feb34638cde7596cc6ecc))
79 |
80 | * :sparkles: Partial addition of constraint grammar classes ([`5fc5c23`](https://github.com/Westfall-io/sysml2py/commit/5fc5c23aea9b8c27a151dfa21f89f06d5a8a237d))
81 |
82 | * :sparkles: Action definition with 2 of 4 tests complete. ([`9530eed`](https://github.com/Westfall-io/sysml2py/commit/9530eed3aeda5bb059cdcff2555cc5c041d6e3bc))
83 |
84 | * :sparkles: Adding first action definition grammar classes. ([`3454a50`](https://github.com/Westfall-io/sysml2py/commit/3454a5048789917e7a4e02092ab3c602ba180157))
85 |
86 | * :sparkles: Adding flow grammar and test. ([`4fe01c9`](https://github.com/Westfall-io/sysml2py/commit/4fe01c9f2394bada05cc703f95177c90a32f37ee))
87 |
88 | * :sparkles: Flow Connector added to grammar and initial test built. ([`872b76d`](https://github.com/Westfall-io/sysml2py/commit/872b76ded8c366f1b429968041f4214817395e1d))
89 |
90 | ### :white_check_mark:
91 |
92 | * :white_check_mark: Completed tests for state grammar. ([`2c2213c`](https://github.com/Westfall-io/sysml2py/commit/2c2213cbc96b4fe16e66f680f3a10672f09f05d3))
93 |
94 | * :white_check_mark: Added two additional tests for expressions, tests all pass. ([`afae042`](https://github.com/Westfall-io/sysml2py/commit/afae0426a30b4cebffec8a974c7b7823dbb80f3c))
95 |
96 | * :white_check_mark: Grammar changes now pass all tests. ([`7771f05`](https://github.com/Westfall-io/sysml2py/commit/7771f053121a6edce9277b1de0536e2323d6276b))
97 |
98 | * :white_check_mark: Added final training example tests for action definition. ([`a399f5b`](https://github.com/Westfall-io/sysml2py/commit/a399f5b295dd17de4979c3f2937f3016524ef8d6))
99 |
100 | * :white_check_mark: Second example test for flow connector. ([`7d00034`](https://github.com/Westfall-io/sysml2py/commit/7d00034efbfd60e993a69a697210896cab16cfb5))
101 |
102 | ### :zap:
103 |
104 | * :zap: Removing commits to push off main, should not run into pull error for semantic parsing ([`77272f3`](https://github.com/Westfall-io/sysml2py/commit/77272f3202378dbf637ad38c8e1cf69c68484198))
105 |
106 | * :zap: Removing excess lines from code coverage. ([`442bc0c`](https://github.com/Westfall-io/sysml2py/commit/442bc0c32048c9575de9f9025963bcca5f0bdfbc))
107 |
108 | * :zap: Now loads from a single compiled grammar file that overwrites any previous grammar from imports. ([`2f90c7b`](https://github.com/Westfall-io/sysml2py/commit/2f90c7b57a6a9e738601d42b75863bfd03f457bc))
109 |
110 | ### Other
111 |
112 | * :art: Updating semantic parsing with lessons learned from windstorm ([`2f66dbf`](https://github.com/Westfall-io/sysml2py/commit/2f66dbf4b023d05397d2fa5267d0ae4d29846f87))
113 |
114 |
115 | ## v0.4.4 (2023-07-26)
116 |
117 | ### :bug:
118 |
119 | * :bug: Fixes for load_grammar functions. ([`0e45818`](https://github.com/Westfall-io/sysml2py/commit/0e4581889f55928576e939026a8ab5c3debdccc0))
120 |
121 | ### Other
122 |
123 | * :test_tube: Fix for test that can't find grammar. ([`18f7aca`](https://github.com/Westfall-io/sysml2py/commit/18f7acab8be6b0d3d70ea7ee1f17fb8d3a11377d))
124 |
125 | * :test_tube: Adding to coverage with failure tests. ([`7c2e96e`](https://github.com/Westfall-io/sysml2py/commit/7c2e96eae65cb536027f01501b1dcc876d3a163e))
126 |
127 |
128 | ## v0.4.3 (2023-07-25)
129 |
130 | ### :bug:
131 |
132 | * :bug: Fixed issue with port subnodes. ([`67720b1`](https://github.com/Westfall-io/sysml2py/commit/67720b19307df138dff10d5138f74aba1fa87734))
133 |
134 | * :bug: Fixed issue with usage classes with body objects. ([`afc5522`](https://github.com/Westfall-io/sysml2py/commit/afc5522c64088595030f68d578af2f303613226e))
135 |
136 |
137 | ## v0.4.2 (2023-07-24)
138 |
139 | ### :bug:
140 |
141 | * :bug: Enforce some syntax with Models always starting with packages. ([`0cccdf1`](https://github.com/Westfall-io/sysml2py/commit/0cccdf1d5f97c864d82edffc9ec54bd93cf1cb54))
142 |
143 | ### Other
144 |
145 | * :green_heart: Adding github actions back into commit. ([`e1ab9f4`](https://github.com/Westfall-io/sysml2py/commit/e1ab9f4b7fa53591ce11de3f5813a67b7070dc8c))
146 |
147 |
148 | ## v0.4.1 (2023-07-24)
149 |
150 | ### :bug:
151 |
152 | * :bug: Fix poetry build for pypi builds. ([`3c90e28`](https://github.com/Westfall-io/sysml2py/commit/3c90e28707710002018569509f87e9266ccef446))
153 |
154 |
155 | ## v0.4.0 (2023-07-21)
156 |
157 | ### :bug:
158 |
159 | * :bug: Fix for definition naming. ([`ff62dc1`](https://github.com/Westfall-io/sysml2py/commit/ff62dc10131d8c53fd4361f7100403dc1c4424f6))
160 |
161 | * :bug: Reverting change to author. ([`ae5d19e`](https://github.com/Westfall-io/sysml2py/commit/ae5d19e5581b3493e985bd01bb356b1dcd3d1618))
162 |
163 | * :bug: Added test and definition file that was causing the error. ([`b7787d4`](https://github.com/Westfall-io/sysml2py/commit/b7787d4ccba53e421e3f877a46eca331698e2950))
164 |
165 | * :bug: Fixed an issue where something defined within a package could not be typed by another definition ([`ee257eb`](https://github.com/Westfall-io/sysml2py/commit/ee257eba9cdaec2a8ac52f65cf702881879aa445))
166 |
167 | ### :heavy_plus_sign:
168 |
169 | * :heavy_plus_sign: Using poetry package management, added dependencies. ([`5c625dd`](https://github.com/Westfall-io/sysml2py/commit/5c625dd6e51a6090a699aab229c335d8946d7bd5))
170 |
171 | * :heavy_plus_sign: Adding pytest-html to test workflow. ([`4f2cedc`](https://github.com/Westfall-io/sysml2py/commit/4f2cedc50162ac2013b5dc60481a7bc646debad3))
172 |
173 | ### :memo:
174 |
175 | * :memo: Updates to project info to assist sphinx build. ([`939d2ff`](https://github.com/Westfall-io/sysml2py/commit/939d2ff4867ccc792b78c8a1229ef937653093ec))
176 |
177 | * :memo: Fixing spacing. ([`25e78d0`](https://github.com/Westfall-io/sysml2py/commit/25e78d01066b96146be587988e1735367747f52c))
178 |
179 | * :memo: Adding more badges. ([`76899b1`](https://github.com/Westfall-io/sysml2py/commit/76899b192545087066493c7a65c388266c09d01c))
180 |
181 | * :memo: Added trello to Readme ([`26e304c`](https://github.com/Westfall-io/sysml2py/commit/26e304c10ea7599259d75f43992996887161183a))
182 |
183 | ### :sparkles:
184 |
185 | * :sparkles: Added a new base model class to replace collapse function. Model will create packages and other custom classes for use. Additionally, packages can be created from grammar. ([`3dc5fca`](https://github.com/Westfall-io/sysml2py/commit/3dc5fcad2e892b0e14c1c9f74cbea868df6844a5))
186 |
187 | * :sparkles: Added port with ability to create subfeatures with directionality. ([`94c0a19`](https://github.com/Westfall-io/sysml2py/commit/94c0a19b08203a3db953858bf968de5c2f2084bc))
188 |
189 | * :sparkles: New package class. ([`3766690`](https://github.com/Westfall-io/sysml2py/commit/3766690bd848de0475eb047af1870da358dd51ab))
190 |
191 | ### :white_check_mark:
192 |
193 | * :white_check_mark: Adding child as optional to get def functions. ([`da90c49`](https://github.com/Westfall-io/sysml2py/commit/da90c49e3b6d80258ea6bdc2391031ead534833f))
194 |
195 | * :white_check_mark: Correcting tests ([`fba8dce`](https://github.com/Westfall-io/sysml2py/commit/fba8dcef847f4d5c39ad97c72b9cb711236df335))
196 |
197 | * :white_check_mark: Package tests added. ([`803192b`](https://github.com/Westfall-io/sysml2py/commit/803192b75749facc0d19cae596038663b3708714))
198 |
199 | ### Other
200 |
201 | * :construction_worker: Adding src to path for pytest in pyproject.toml ([`510d672`](https://github.com/Westfall-io/sysml2py/commit/510d672b98c747c7ad573aa1d7fbf28d2252b4a1))
202 |
203 | * :construction_worker: Corrected test directory again. ([`92d5dc2`](https://github.com/Westfall-io/sysml2py/commit/92d5dc2c1bf1f416d6e248ddbf4bb45727a3e5fe))
204 |
205 | * :construction_worker: Corrected test directory. ([`2bfc6df`](https://github.com/Westfall-io/sysml2py/commit/2bfc6dfc1f6767a4caddd0e69fbc459fc5a0ed4a))
206 |
207 | * :green_heart: Adding coveralls to all branches. ([`425024d`](https://github.com/Westfall-io/sysml2py/commit/425024d1b7ebf80010c2f8a7e7d866b32ba4e5d8))
208 |
209 | * :construction_worker: Adding html to artifacts. ([`4b74045`](https://github.com/Westfall-io/sysml2py/commit/4b74045fc81d32fe33629dc215d1126145f572c3))
210 |
211 | * :green_heart: Adding conftest.py ([`dbd32b9`](https://github.com/Westfall-io/sysml2py/commit/dbd32b967febd7396de40ff7e73a9b75182e7507))
212 |
213 | * :green_heart: Adding path to init to correct test workflow. ([`d29bfb6`](https://github.com/Westfall-io/sysml2py/commit/d29bfb6692d950bf384182dda96ebb017c8231af))
214 |
215 |
216 | ## v0.3.1 (2023-07-11)
217 |
218 | ### :memo:
219 |
220 | * :memo: Documentation changes. ([`edfd629`](https://github.com/Westfall-io/sysml2py/commit/edfd629ec5ef6611d2b9643706cee6b1bf40ea47))
221 |
222 |
223 | ## v0.3.0 (2023-07-11)
224 |
225 | ### :memo:
226 |
227 | * :memo: Updates to readme, also added a loadfromgrammar function to Usage. ([`e999436`](https://github.com/Westfall-io/sysml2py/commit/e999436193ccee31dfadaf5a193705cf61e99496))
228 |
229 | ### :sparkles:
230 |
231 | * :sparkles: Added some rollup classes the abstract underlying grammar. They have functions to manipulate the grammar. ([`b1e01a4`](https://github.com/Westfall-io/sysml2py/commit/b1e01a465200e79f96a30da4f2ce5b861850ddd5))
232 |
233 | ### Other
234 |
235 | * :arrow_up: Merge from main and add astropy to main dependencies to handle units. ([`98f260b`](https://github.com/Westfall-io/sysml2py/commit/98f260b888f54f9f6911b043387cd0fbc4d81c88))
236 |
237 |
238 | ## v0.2.10 (2023-06-21)
239 |
240 |
241 | ## v0.2.9 (2023-06-21)
242 |
243 |
244 | ## v0.2.8 (2023-06-21)
245 |
246 |
247 | ## v0.2.7 (2023-06-21)
248 |
249 |
250 | ## v0.2.6 (2023-06-21)
251 |
252 |
253 | ## v0.2.5 (2023-06-21)
254 |
255 |
256 | ## v0.2.4 (2023-06-21)
257 |
258 |
259 | ## v0.2.3 (2023-06-21)
260 |
261 |
262 | ## v0.2.2 (2023-06-21)
263 |
264 |
265 | ## v0.2.1 (2023-06-21)
266 |
267 |
268 | ## v0.2.0 (2023-06-21)
269 |
270 | ### :ambulance:
271 |
272 | * :ambulance: Fixing merge errors from black ([`e101e70`](https://github.com/Westfall-io/sysml2py/commit/e101e70ea50ccd52cc5226c6860bcbe1b9411d3a))
273 |
274 | * :ambulance: Fix for build script ([`4c6f238`](https://github.com/Westfall-io/sysml2py/commit/4c6f238afcf37c8620f082dfee19a8a4282a47e3))
275 |
276 | ### :bug:
277 |
278 | * :bug: Adding textx to requirements. ([`d3c1c76`](https://github.com/Westfall-io/sysml2py/commit/d3c1c767b39a68d67c0eea7802982de770c1bc48))
279 |
280 | * :bug: Workflow fixes ([`9b883ea`](https://github.com/Westfall-io/sysml2py/commit/9b883eaef9932e80299dc94ede0646a2ceb1a405))
281 |
282 | ### :construction:
283 |
284 | * :construction: Forgot to git pull ([`4cf3100`](https://github.com/Westfall-io/sysml2py/commit/4cf3100b719f9ee17beb556b116cf46fd9db1886))
285 |
286 | * :construction: Adding more documentation and cleanup ([`8a8675e`](https://github.com/Westfall-io/sysml2py/commit/8a8675e3828beef65903491a578477e14ba5ffa5))
287 |
288 | * :construction: More adds. ([`42258b6`](https://github.com/Westfall-io/sysml2py/commit/42258b66704bb42a2f2b2632722bab30887cb8a9))
289 |
290 | * :construction: Fix yaml ([`0fc1c2f`](https://github.com/Westfall-io/sysml2py/commit/0fc1c2f860cfc3a5e61138c53cfc5b4b8a24ab84))
291 |
292 | * :construction: Fixes and updates to CI/CD ([`c0640f1`](https://github.com/Westfall-io/sysml2py/commit/c0640f1ded084d7d178d0a1a0ad87e434c388d37))
293 |
294 | ### :memo:
295 |
296 | * :memo: Updates to version ([`208cdd6`](https://github.com/Westfall-io/sysml2py/commit/208cdd62db514b466b0b64aa70134e54cea46ce0))
297 |
298 | * :memo: remove excess brackets ([`e258d1c`](https://github.com/Westfall-io/sysml2py/commit/e258d1cdccbf3614b6be37f6322ddee006756809))
299 |
300 | * :memo: Docstring coverage add to README ([`3720f3a`](https://github.com/Westfall-io/sysml2py/commit/3720f3a07002b1129b90d552f7a291c8662c6c09))
301 |
302 | * :memo: Time to add documentationgit add docsgit add docs ([`f933521`](https://github.com/Westfall-io/sysml2py/commit/f9335216ae484aa2145fd2178b206bcff510958b))
303 |
304 | ### :sparkles:
305 |
306 | * :sparkles: More tests. ([`41d1f5e`](https://github.com/Westfall-io/sysml2py/commit/41d1f5eb343c4afe02224fd6b9d68bed3f5cebaa))
307 |
308 | * :sparkles: More tests and classes. ([`cd59e2e`](https://github.com/Westfall-io/sysml2py/commit/cd59e2e7b2ff2c2eeb599480293f09efabcd79d9))
309 |
310 | * :sparkles: More badge for readme. ([`4be8d54`](https://github.com/Westfall-io/sysml2py/commit/4be8d54efb78fa6030c8c80702f13e9ce295c5da))
311 |
312 | ### :white_check_mark:
313 |
314 | * :white_check_mark: Adding import test, namespaces are bugged. ([`6d35922`](https://github.com/Westfall-io/sysml2py/commit/6d35922290ee468a3604102ce78da9f7f2846b36))
315 |
316 | * :white_check_mark: Added test, updated workflow ([`b21d14b`](https://github.com/Westfall-io/sysml2py/commit/b21d14bdff81269f58f648ae44cc87466385b328))
317 |
318 | ### :zap:
319 |
320 | * :zap: Adding code coverage badge to readme. ([`c72fe86`](https://github.com/Westfall-io/sysml2py/commit/c72fe8699891d30a588abdafc27d3f030900a31a))
321 |
322 | ### Other
323 |
324 | * :green_heart: Ignore repo upload. ([`c5efb11`](https://github.com/Westfall-io/sysml2py/commit/c5efb1139b987c89374ab3acf2586589e65d963e))
325 |
326 | * :rocket: Moving to 0.1.2. ([`e6b7c2d`](https://github.com/Westfall-io/sysml2py/commit/e6b7c2d92da8d0a26f4baf438c363fca75f4141c))
327 |
328 | * :construction_worker: Fix to build script to include grammar files. ([`9a85d55`](https://github.com/Westfall-io/sysml2py/commit/9a85d5547ba7c5343e1966d87d501583b2bc4c88))
329 |
330 | * :rocket: Moving to 0.1.0 baseline, most of the base functionality is here. ([`aa7333d`](https://github.com/Westfall-io/sysml2py/commit/aa7333dffb77f364da4ee4f4c9375838e49d5568))
331 |
332 | * :green_heart: Fixing?? ([`21824c9`](https://github.com/Westfall-io/sysml2py/commit/21824c9c0f34b6f436b84f257bf373ceaf8cf98d))
333 |
334 | * :green_heart: Fixing? ([`0f9b849`](https://github.com/Westfall-io/sysml2py/commit/0f9b849174ca818f6de6076e4a8362ea32def4b6))
335 |
336 | * :green_heart: Fixing code coverage with better import flat file usage. ([`1a11479`](https://github.com/Westfall-io/sysml2py/commit/1a114792dcce922388f014acb26e8691e3a4fe02))
337 |
338 | * :green_heart: Fixes for tests. ([`e11d3e9`](https://github.com/Westfall-io/sysml2py/commit/e11d3e948c266bd6dc814cc68460f6d0bdc0e86a))
339 |
340 | * :green_heart: Fixes to doc? ([`1f27b22`](https://github.com/Westfall-io/sysml2py/commit/1f27b220215f9c91836b7f5945cc8e62ad3fcaf3))
341 |
342 | * :green_heart: I broke it. ([`38243bc`](https://github.com/Westfall-io/sysml2py/commit/38243bce4125a204eb74f4692572731fc07c31eb))
343 |
344 | * :green_heart: Let's see if this breaks github actions. ([`3cf03e8`](https://github.com/Westfall-io/sysml2py/commit/3cf03e82e64da027ffd9aa9f727ff0183cc2ee82))
345 |
346 | * :green_heart: Fix for correct path to code coverage check. ([`2fccb2c`](https://github.com/Westfall-io/sysml2py/commit/2fccb2c5333a8a5001854b1f759eef91c9d60c6e))
347 |
348 | * :green_heart: Fixes???? ([`0955e8b`](https://github.com/Westfall-io/sysml2py/commit/0955e8b6ee5ca7182ecd25a7a0fc80cea58b7dee))
349 |
350 | * :green_heart: Fixes??? ([`2616e90`](https://github.com/Westfall-io/sysml2py/commit/2616e900bc0cec252b7d04bce61f47740782f229))
351 |
352 | * :green_heart: Fixes?? ([`b414758`](https://github.com/Westfall-io/sysml2py/commit/b4147584a2d74aa9cd910932e36f58f6c865df66))
353 |
354 | * :green_heart: Fixes? ([`37fa8a5`](https://github.com/Westfall-io/sysml2py/commit/37fa8a5bca43c05d4432cbfc894d30d4f0c8b6fc))
355 |
356 | * :green_heart: Adding code coverage detection. ([`b977536`](https://github.com/Westfall-io/sysml2py/commit/b977536f2a1289ef8a69a00ec4761e277d7a2c1b))
357 |
358 | * :green_heart: Seeing if I can drop the separate document workflow. ([`7692fc7`](https://github.com/Westfall-io/sysml2py/commit/7692fc71ed63a03b3266f3408fbac56f12d5496b))
359 |
360 | * :green_heart: Need more in req.txt ([`2a65bfc`](https://github.com/Westfall-io/sysml2py/commit/2a65bfcbf1599ae8999735a02b99366950fbca3f))
361 |
362 | * :green_heart: Testing if we need to change directory. ([`96fc0c5`](https://github.com/Westfall-io/sysml2py/commit/96fc0c552930c697616caf7d9ef6fca68a1e4d77))
363 |
364 | * :green_heart: Test to check for new build changes to documentation. ([`382c9de`](https://github.com/Westfall-io/sysml2py/commit/382c9debe679ef82abe288da8d1a26647c16bfd4))
365 |
366 | * :green_heart: Fixes?? ([`c6c0b0f`](https://github.com/Westfall-io/sysml2py/commit/c6c0b0fdbf6db0924296fe5eb0a261be80d29667))
367 |
368 | * :green_heart: Fixes? ([`1d57172`](https://github.com/Westfall-io/sysml2py/commit/1d57172c96128dca989c7799c6b84ab22dd55b57))
369 |
370 | * :green_heart: Adding documentation to github action ([`124645c`](https://github.com/Westfall-io/sysml2py/commit/124645c3b0629f15090da7a71b1315fce26ebd1d))
371 |
372 | * :fire: Removing mac files. ([`18174bd`](https://github.com/Westfall-io/sysml2py/commit/18174bdc0d678666fa56e8a1233e7bd64a095a36))
373 |
374 | * :green_heart: Set write all ([`6ed68a0`](https://github.com/Westfall-io/sysml2py/commit/6ed68a0149cd237eb8be070c3f63d8cc52ac278e))
375 |
376 | * :green_heart: Let's see if this works, adding permissions in the script/ ([`e21687a`](https://github.com/Westfall-io/sysml2py/commit/e21687ad1f165f6da83b5ccca119f25bf2f885dc))
377 |
378 | * :green_heart: Trying this for autoformat. ([`4fa5563`](https://github.com/Westfall-io/sysml2py/commit/4fa5563b5a4e7e49f5807e979480d1346ae08379))
379 |
380 | * :green_heart: Adding autoformatting instead of checking ([`b7b38dc`](https://github.com/Westfall-io/sysml2py/commit/b7b38dc71d7c0bdc4770d64fb7d2b3b79e8ad955))
381 |
382 | * :green_heart: Adding Black linting ([`ee365ae`](https://github.com/Westfall-io/sysml2py/commit/ee365aec7c3471a5843522a08c9afb951cef623c))
383 |
384 | * :fire: Getting rid of mac files. ([`b41512a`](https://github.com/Westfall-io/sysml2py/commit/b41512a0aaea95c5a2791967ed01df9e67dba129))
385 |
386 | * :clown: Rework into textx which has similar syntax to current standard. ([`b0f5991`](https://github.com/Westfall-io/sysml2py/commit/b0f599120a4c2c2258011e610ad340072d02213e))
387 |
388 | * :poop Removing more excess files. ([`4bbe0f3`](https://github.com/Westfall-io/sysml2py/commit/4bbe0f3a3e5795bb570cb378df8b4fb05f0f190c))
389 |
390 | * :clown: Adding workflows ([`e4cfccd`](https://github.com/Westfall-io/sysml2py/commit/e4cfccd1660a608333f64f0549e52cd9cb3491fb))
391 |
392 | * :clown_face: First commit of some data ([`42c1782`](https://github.com/Westfall-io/sysml2py/commit/42c1782455b44ea207e586993c7d362769f5b156))
393 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Westfall-io
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # sysml2py
2 | [](https://badge.fury.io/py/sysml2py)[](https://pypi.python.org/pypi/sysml2py/)[](https://coveralls.io/github/Westfall-io/sysml2py)[](https://lbesson.mit-license.org/)
3 |
4 | [](https://trello.com/b/xHfFUzlk/sysml2py)
5 |
6 | ## Description
7 | sysml2py is an open source pure Python library for constructing python-based
8 | classes consistent with the [SysML v2.0 standard](https://github.com/Systems-Modeling/SysML-v2-Release).
9 |
10 | ## Requirements
11 | sysml2py requires the following Python packages:
12 | - [textX](https://github.com/textX/textX)
13 | - [pyyaml](https://github.com/yaml/pyyaml)
14 | - [astropy](https://github.com/astropy/astropy)
15 |
16 | ## Installation
17 |
18 | Multiple installation methods are supported by sysml2py, including:
19 |
20 | | **Logo** | **Platform** | **Command** |
21 | |:-----------------------------------------------------------------:|:------------:|:---------------------------------------------------------------------------------:|
22 | |  | PyPI | ``python -m pip install sysml2py`` |
23 | |  | GitHub | ``python -m pip install https://github.com/Westfall-io/sysml2py/archive/refs/heads/main.zip`` |
24 |
25 | ## Documentation
26 |
27 | Documentation can be found [here.](https://westfall-io.github.io/sysml2py/)
28 |
29 | ### Basic Usage
30 |
31 | The code below will create a part called Stage 1, with a shortname of <'3.1'>
32 | referencing a specific requirement or document. It has a mass attribute of 100
33 | kg. It has a thrust attribute of 1000 N. These attributes are created and placed
34 | as a child of the part. Next, we recall the part value for thrust and add 199 N.
35 | Finally, we can dump the output from this class.
36 | ```
37 | from sysml2py import Attribute, Part
38 |
39 | import astropy.units as u
40 | a = Attribute()._set_name('mass')
41 | a.set_value(100*u.kg)
42 | b = Attribute()._set_name('thrust')
43 | b.set_value(1000*u.N)
44 | c = Part()._set_name("Stage_1")._set_name("'3.1'", short=True)
45 | c._set_child(a)
46 | c._set_child(b)
47 | v = "Stage_1.thrust"
48 | c._get_child(v).set_value(c._get_child(v).get_value()+199*u.N)
49 | print(c.dump())
50 | ```
51 |
52 | It will output the following, which isn't yet fully correct as we need to import
53 | the SI units to be valid SysML.
54 | ```
55 | part <'3.1'> Stage_1 {
56 | attribute mass= 100.0 [kg];
57 | attribute thrust= 1199.0 [N];
58 | }
59 | ```
60 |
61 | The package is able to handle Items, Parts, and Attributes.
62 |
63 | ```
64 | a = Part()._set_name('camera')
65 | b = Item()._set_name('lens')
66 | d = Attribute()._set_name('mass')
67 | c = Part()._set_name("sensor")
68 | c._set_child(a)
69 | c._set_child(b)
70 | a._set_child(d)
71 | print(c.dump())
72 | ```
73 |
74 | will return:
75 | ```
76 | part sensor {
77 | part camera {
78 | attribute mass;
79 | }
80 | item lens;
81 | }
82 | ```
83 |
84 | ## Release Planning
85 | Development can be tracked via [Trello.](https://trello.com/b/xHfFUzlk/sysml2py)
86 |
87 | ## License
88 | sysml2py is released under the MIT license, hence allowing commercial use of the library.
89 |
--------------------------------------------------------------------------------
/doc-cov.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/Makefile:
--------------------------------------------------------------------------------
1 | # Minimal makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line, and also
5 | # from the environment for the first two.
6 | SPHINXOPTS ?=
7 | SPHINXBUILD ?= sphinx-build
8 | SOURCEDIR = source
9 | BUILDDIR = build
10 |
11 | # Put it first so that "make" without argument is like "make help".
12 | help:
13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
14 |
15 | .PHONY: help Makefile
16 |
17 | # Catch-all target: route all unknown targets to Sphinx using the new
18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
19 | %: Makefile
20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
21 |
--------------------------------------------------------------------------------
/docs/make.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | pushd %~dp0
4 |
5 | REM Command file for Sphinx documentation
6 |
7 | if "%SPHINXBUILD%" == "" (
8 | set SPHINXBUILD=sphinx-build
9 | )
10 | set SOURCEDIR=source
11 | set BUILDDIR=build
12 |
13 | if "%1" == "" goto help
14 |
15 | %SPHINXBUILD% >NUL 2>NUL
16 | if errorlevel 9009 (
17 | echo.
18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
19 | echo.installed, then set the SPHINXBUILD environment variable to point
20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you
21 | echo.may add the Sphinx directory to PATH.
22 | echo.
23 | echo.If you don't have Sphinx installed, grab it from
24 | echo.https://www.sphinx-doc.org/
25 | exit /b 1
26 | )
27 |
28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
29 | goto end
30 |
31 | :help
32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
33 |
34 | :end
35 | popd
36 |
--------------------------------------------------------------------------------
/docs/requirements.txt:
--------------------------------------------------------------------------------
1 | sphinx-rtd-theme==1.2.1
2 | PyYAML==6.0
3 | textX==3.1.1
4 |
--------------------------------------------------------------------------------
/docs/source/conf.py:
--------------------------------------------------------------------------------
1 | # Configuration file for the Sphinx documentation builder.
2 | #
3 | # This file only contains a selection of the most common options. For a full
4 | # list see the documentation:
5 | # https://www.sphinx-doc.org/en/master/usage/configuration.html
6 |
7 | # -- Path setup --------------------------------------------------------------
8 |
9 | # If extensions (or modules to document with autodoc) are in another directory,
10 | # add these directories to sys.path here. If the directory is relative to the
11 | # documentation root, use os.path.abspath to make it absolute, like shown here.
12 | #
13 | import os
14 | import sys
15 |
16 | sys.path.insert(0, os.path.abspath("../../src"))
17 | sys.path.insert(0, os.path.abspath("../src"))
18 |
19 | # -- Project information -----------------------------------------------------
20 |
21 | project = "sysml2py"
22 | copyright = "2023, Christopher Cox"
23 | author = "Christopher Cox"
24 |
25 | # The full version, including alpha/beta/rc tags
26 | release = "0.1.2"
27 |
28 |
29 | # -- General configuration ---------------------------------------------------
30 |
31 | # Add any Sphinx extension module names here, as strings. They can be
32 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
33 | # ones.
34 | extensions = ["sphinx.ext.autodoc", "sphinx.ext.coverage", "sphinx.ext.napoleon"]
35 |
36 | # Add any paths that contain templates here, relative to this directory.
37 | templates_path = ["_templates"]
38 |
39 | # List of patterns, relative to source directory, that match files and
40 | # directories to ignore when looking for source files.
41 | # This pattern also affects html_static_path and html_extra_path.
42 | exclude_patterns = []
43 |
44 |
45 | # -- Options for HTML output -------------------------------------------------
46 |
47 | # The theme to use for HTML and HTML Help pages. See the documentation for
48 | # a list of builtin themes.
49 | #
50 | html_theme = "sphinx_rtd_theme"
51 |
52 | # Add any paths that contain custom static files (such as style sheets) here,
53 | # relative to this directory. They are copied after the builtin static files,
54 | # so a file named "default.css" will overwrite the builtin "default.css".
55 | html_static_path = ["_static"]
56 |
--------------------------------------------------------------------------------
/docs/source/index.rst:
--------------------------------------------------------------------------------
1 | Welcome to sysml2py's documentation!
2 | ====================================
3 |
4 | .. automodule:: sysml2py
5 | :members:
6 |
7 | .. toctree::
8 | :maxdepth: 2
9 | :caption: Contents:
10 |
11 |
12 |
13 | Indices and tables
14 | ==================
15 |
16 | * :ref:`genindex`
17 | * :ref:`modindex`
18 | * :ref:`search`
19 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [build-system]
2 | #requires = ["setuptools>=61.0"]
3 | #build-backend = "setuptools.build_meta"
4 | requires = ["poetry-core"]
5 | build-backend = "poetry.core.masonry.api"
6 |
7 | [project]
8 | name = "sysml2py"
9 | version = "0.5.3"
10 | description = "SysML v2.0 Parser"
11 | authors = [
12 | { name="Christopher Cox", email="chris.cox@westfall.io" },
13 | ]
14 | readme = "README.md"
15 | license = {file = "LICENSE"}
16 | requires-python = ">=3.7"
17 | classifiers = [
18 | "Development Status :: 3 - Alpha",
19 | "Programming Language :: Python :: 3",
20 | "License :: OSI Approved :: MIT License",
21 | "Operating System :: OS Independent",
22 | ]
23 |
24 | [tool.setuptools]
25 | include-package-data = true
26 |
27 | [tool.setuptools.packages.find]
28 | where = ["src/sysml2py", "src"]
29 |
30 | [tool.setuptools.package-data]
31 | grammar = ["*.tx"]
32 |
33 | [tool.pytest.ini_options]
34 | pythonpath = [
35 | "src"
36 | ]
37 |
38 | [tool.semantic_release]
39 | version_variable = [
40 | "src/sysml2py/__init__.py:version",
41 | ]
42 | version_toml=[
43 | "pyproject.toml:tool.poetry.version",
44 | "pyproject.toml:project.version",
45 | ]
46 | commit_parser = "emoji"
47 | build_command = "pip install poetry && poetry build"
48 | commit_message = ":bookmark:{version}\n\nAutomatically generated by python-semantic-release"
49 |
50 | [tool.semantic_release.changelog]
51 | exclude_commit_patterns = [":robot:",":twisted_rightwards_arrows:",
52 | ":poop:", "^[^:].*"]
53 |
54 | [tool.semantic_release.commit_parser_options]
55 | major_tags = [":boom:"]
56 | minor_tags = [
57 | ":sparkles:",
58 | ":children_crossing:",
59 | ":lipstick:",
60 | ":iphone:",
61 | ":egg:",
62 | ":chart_with_upwards_trend:",
63 | ]
64 | patch_tags = [
65 | ":ambulance:",
66 | ":lock:",
67 | ":bug:",
68 | ":zap:",
69 | ":goal_net:",
70 | ":alien:",
71 | ":wheelchair:",
72 | ":speech_balloon:",
73 | ":mag:",
74 | ":apple:",
75 | ":penguin:",
76 | ":checkered_flag:",
77 | ":robot:",
78 | ":green_apple:",
79 | ":memo:",
80 | ":heavy_plus_sign:",
81 | ":construction:",
82 | ":white_check_mark:",
83 | ]
84 |
85 | [tool.semantic_release.branches.main]
86 | match = "(main|master)"
87 | prerelease = false
88 | build_command = "pip install poetry && poetry build"
89 |
90 | [tool.semantic_release.branches."dev0.5.x"]
91 | match = "dev0.5.x"
92 | prerelease = true
93 | prerelease_token = "rc"
94 | build_command = "pip install poetry && poetry build"
95 |
96 | [project.urls]
97 | "Homepage" = "https://github.com/Westfall-io/sysml2py"
98 | "Bug Tracker" = "https://github.com/Westfall-io/sysml2py/issues"
99 |
100 | [tool.poetry]
101 | name = "sysml2py"
102 | version = "0.5.3"
103 | description = ""
104 | authors = ["Christopher Cox "]
105 | readme = "README.md"
106 | packages = [{ include = "sysml2py", from = "src" }]
107 |
108 | [tool.poetry.dependencies]
109 | python = "^3.9"
110 | textx = "^3.1.1"
111 | astropy = "^5.3.1"
112 | pyyaml = "^6.0.1"
113 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | PyYAML==6.0.1
2 | textX==3.1.1
3 | astropy==5.3.4
4 | mypy==1.4.1
5 |
--------------------------------------------------------------------------------
/src/sysml2py/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | """
4 | Created on Mon May 29 23:26:16 2023
5 |
6 | @author: christophercox
7 | """
8 |
9 | __all__ = ["load", "loads", "load_grammar"]
10 | __author__ = "Christopher Cox"
11 | __version__ = "0.1.0"
12 |
13 | # These are interchangable
14 | from sysml2py.usage import Item, Attribute, Part, Port
15 |
16 | # These are definition only
17 | from sysml2py.definition import Model, Package
18 |
19 |
20 | def enforce_grammar(): # pragma: no cover
21 | """Enforce grammar compiles the language for xtext
22 |
23 | This opens each of the files: KerMLExpressions, KerML, and SysML and
24 | makes a superfile with all of the definitions and strips the comments. This
25 | includes changes made to shift from java textx to the python xtext library.
26 |
27 | """
28 | import re
29 |
30 | comments_strip_rule = r"(?:(?:(? ModelType:
36 | from sysml2py import load_grammar
37 |
38 | # Try to load the grammar from the string
39 | definition = load_grammar(s)["ownedRelationship"]
40 |
41 | # Add each sub-element to children.
42 | member_grammar = []
43 | for member in definition:
44 | if member["ownedRelatedElement"]["name"] == "DefinitionElement":
45 | de = member["ownedRelatedElement"]
46 | if de["ownedRelatedElement"]["name"] == "Package":
47 | p = Package().load_from_grammar(
48 | PackageGrammar(de["ownedRelatedElement"])
49 | )
50 | self.children.append(p)
51 | member_grammar.append(p._get_definition(child="PackageBody"))
52 | else:
53 | raise ValueError("Base Model must be encapsulated by a package.")
54 | else:
55 | raise ValueError("Base Model must be encapsulated by a package.")
56 |
57 | self.grammar = RootNamespace(
58 | {"name": "PackageBodyElement", "ownedRelationship": member_grammar}
59 | )
60 |
61 | return self
62 |
63 | def _ensure_body(self):
64 | # Add children
65 | body = []
66 | for abc in self.children:
67 | v = abc._get_definition(child="PackageBody")
68 | if isinstance(v, list):
69 | for subchild in v:
70 | body.append(PackageMember(subchild).get_definition())
71 | else:
72 | body.append(PackageMember(v).get_definition())
73 |
74 | if len(body) > 0:
75 | self.grammar = RootNamespace(
76 | {"name": "PackageBodyElement", "ownedRelationship": body}
77 | )
78 |
79 | return self
80 |
81 | def _get_definition(self):
82 | return self.grammar.get_definition()
83 |
84 | def dump(self):
85 | if len(self.children) == 0:
86 | raise ValueError("Base Model has no elements to output.")
87 |
88 | self._ensure_body()
89 | return classtree(self._get_definition()).dump()
90 |
91 | def _set_child(self, child):
92 | self.children.append(child)
93 | return self
94 |
95 | def _get_child(self, featurechain):
96 | # 'x.y.z'
97 | if isinstance(featurechain, str):
98 | fc = featurechain.split(".")
99 | else:
100 | raise TypeError
101 |
102 | if fc[0] == self.name:
103 | # This first one must match self name, otherwise pass it all
104 | featurechain = ".".join(fc[1:])
105 |
106 | for child in self.children:
107 | fcs = featurechain.split(".")
108 | if child.name == fcs[0]:
109 | if len(fcs) == 1:
110 | return child
111 | else:
112 | return child._get_child(featurechain)
113 |
114 |
115 | class Package:
116 | def __init__(self):
117 | self.name = str(uuidlib.uuid4())
118 | self.children = []
119 | self.typedby = None
120 | self.grammar = PackageGrammar()
121 |
122 | def _set_name(self, name, short=False):
123 | if short:
124 | if self.grammar.declaration.identification is None:
125 | self.grammar.declaration.identification = Identification()
126 | self.grammar.declaration.identification.declaredShortName = "<" + name + ">"
127 | else:
128 | self.name = name
129 | if self.grammar.declaration.identification is None:
130 | self.grammar.declaration.identification = Identification()
131 | self.grammar.declaration.identification.declaredName = name
132 |
133 | return self
134 |
135 | def _get_name(self):
136 | return self.grammar.declaration.identification.declaredName
137 |
138 | def _set_child(self, child):
139 | self.children.append(child)
140 | return self
141 |
142 | def _get_child(self, featurechain):
143 | # 'x.y.z'
144 | if isinstance(featurechain, str):
145 | fc = featurechain.split(".")
146 | else:
147 | raise TypeError
148 |
149 | if fc[0] == self.name:
150 | # This first one must match self name, otherwise pass it all
151 | featurechain = ".".join(fc[1:])
152 |
153 | for child in self.children:
154 | fcs = featurechain.split(".")
155 | if child.name == fcs[0]:
156 | if len(fcs) == 1:
157 | return child
158 | else:
159 | return child._get_child(featurechain)
160 |
161 | def _ensure_body(self):
162 | # Add children
163 | body = []
164 | for abc in self.children:
165 | v = abc._get_definition(child="PackageBody")
166 | if isinstance(v, list):
167 | for subchild in v:
168 | body.append(PackageMember(subchild).get_definition())
169 | else:
170 | body.append(PackageMember(v).get_definition())
171 | if len(body) > 0:
172 | self.grammar.body = PackageBody(
173 | {"name": "PackageBody", "ownedRelationship": body}
174 | )
175 |
176 | def _get_definition(self, child=None):
177 | self._ensure_body()
178 |
179 | package = {
180 | "name": "DefinitionElement",
181 | "ownedRelatedElement": self.grammar.get_definition(),
182 | }
183 | package = {
184 | "name": "PackageMember",
185 | "ownedRelatedElement": package,
186 | "prefix": None,
187 | }
188 | if not child:
189 | package = {
190 | "name": "PackageBodyElement",
191 | "ownedRelationship": [package],
192 | "prefix": None,
193 | }
194 |
195 | # Add the typed by definition to the package output
196 | if self.typedby is not None:
197 | # Packages cannot be typed, they should import from other packages
198 | raise NotImplementedError
199 |
200 | return package
201 |
202 | def dump(self, child=None):
203 | return classtree(self._get_definition(child=False)).dump()
204 |
205 | def load_from_grammar(self, grammar):
206 | self.name = grammar.declaration.identification.declaredName
207 | self.grammar = grammar
208 | for child in grammar.body.children:
209 | if child.children[0].__class__.__name__ == "UsageElement":
210 | # PackageMember -> UsageElement
211 | if (
212 | child.children[0].children.children.children.__class__.__name__
213 | == "ItemUsage"
214 | ):
215 | self.children.append(
216 | Item().load_from_grammar(
217 | child.children[0].children.children.children
218 | )
219 | )
220 | elif (
221 | child.children[0].children.children.children.__class__.__name__
222 | == "PartUsage"
223 | ):
224 | self.children.append(
225 | Part().load_from_grammar(
226 | child.children[0].children.children.children
227 | )
228 | )
229 | else:
230 | print(child.children[0].children[0].__class__.__name__)
231 | raise NotImplementedError
232 | else:
233 | # Not a UsageElement
234 | if child.children[0].children[0].__class__.__name__ == "Package":
235 | self.children.append(
236 | Package().load_from_grammar(child.children[0].children[0])
237 | )
238 | elif (
239 | child.children[0].children[0].__class__.__name__ == "ItemDefinition"
240 | ):
241 | self.children.append(
242 | Item().load_from_grammar(child.children[0].children[0])
243 | )
244 | else:
245 | print(child.children[0].children[0].__class__.__name__)
246 | raise NotImplementedError
247 |
248 | # self.children.append()
249 | return self
250 |
251 | def _get_grammar(self):
252 | # Force updates to grammar if something has changed.
253 | self._ensure_body()
254 | return self.grammar
255 |
--------------------------------------------------------------------------------
/src/sysml2py/formatting.py:
--------------------------------------------------------------------------------
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 sysml2py.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)
48 |
--------------------------------------------------------------------------------
/src/sysml2py/grammar/KerML.tx:
--------------------------------------------------------------------------------
1 | import KerMLExpressions
2 | /*****************************************************************************
3 | * SysML 2 Pilot Implementation
4 | * Copyright (c) 2018-2023 Model Driven Solutions, Inc.
5 | * Copyright (c) 2018 IncQuery Labs Ltd.
6 | * Copyright (c) 2019 Maplesoft (Waterloo Maple, Inc.)
7 | * Copyright (c) 2019 Mgnite Inc.
8 | *
9 | * This program is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU Lesser General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * This program is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU Lesser General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public License
20 | * along with this program. If not, see .
21 | *
22 | * @license LGPL-3.0-or-later
23 | *
24 | * Contributors:
25 | * Ed Seidewitz, MDS
26 | * Zoltan Kiss, IncQuery
27 | * Balazs Grill, IncQuery
28 | * Hisashi Miyashita, Maplesoft/Mgnite
29 | *
30 | *****************************************************************************/
31 |
32 | /* ROOT NAMESPACE */
33 |
34 | RootNamespace :
35 | NamespaceBodyElement*
36 | ;
37 |
38 | /* ELEMENTS */
39 |
40 | /* Elements */
41 |
42 | Identification :
43 | '<' declaredShortName = Name '>' ( declaredName = Name )?
44 | | declaredName = Name
45 | ;
46 |
47 | /* Relationships */
48 |
49 | RelationshipBody :
50 | ';' | '{' RelationshipOwnedElement* '}'
51 | ;
52 |
53 | RelationshipOwnedElement :
54 | ownedRelatedElement += OwnedRelatedElement
55 | | ownedRelationship += OwnedAnnotation
56 | ;
57 |
58 | OwnedRelatedElement :
59 | NonFeatureElement | FeatureElement
60 | ;
61 |
62 | /* DEPENDENCIES */
63 |
64 | Dependency :
65 | ( ownedRelationship += PrefixMetadataAnnotation )*
66 | 'dependency' ( Identification? 'from' )?
67 | client += QualifiedName ( ',' client += QualifiedName )* 'to'
68 | supplier += QualifiedName ( ',' supplier += QualifiedName )*
69 | RelationshipBody
70 | ;
71 |
72 | /* ANNOTATIONS */
73 |
74 | Annotation :
75 | annotatedElement = QualifiedName
76 | ;
77 |
78 | OwnedAnnotation :
79 | ownedRelatedElement += AnnotatingElement
80 | ;
81 |
82 | AnnotatingElement :
83 | CommentKerML
84 | | Documentation
85 | | TextualRepresentation
86 | | MetadataFeature
87 | ;
88 |
89 | /* Comments */
90 |
91 | CommentKerML :
92 | // Comment is reserved in TextX
93 | ( 'comment' Identification?
94 | ('about' ownedRelationship += Annotation
95 | ( ',' ownedRelationship += Annotation )* )?
96 | )?
97 | body = REGULAR_COMMENT
98 | ;
99 |
100 | Documentation :
101 | 'doc' Identification? body=REGULAR_COMMENT
102 | ;
103 |
104 | /* Textual Representation */
105 |
106 | TextualRepresentation :
107 | ( 'rep' Identification? )?
108 | 'language' language = STRING_VALUE
109 | body = REGULAR_COMMENT
110 | ;
111 |
112 | /* NAMESPACES */
113 |
114 | Namespace :
115 | ( ownedRelationship += PrefixMetadataMember )*
116 | NamespaceDeclaration NamespaceBody
117 | ;
118 |
119 | NamespaceDeclaration :
120 | 'namespace' Identification?
121 | ;
122 |
123 | NamespaceBody :
124 | ';'
125 | | '{' ( // Note: PackageBodyElement is expanded here to avoid
126 | // infinite loops in the incremental parser.
127 | ownedRelationship += NamespaceMember
128 | | ownedRelationship += AliasMember
129 | | ownedRelationship += Import )*
130 | '}'
131 | ;
132 |
133 | /* Namespace Bodies */
134 |
135 | NamespaceBodyElement :
136 | ownedRelationship += NamespaceMember
137 | | ownedRelationship += AliasMember
138 | | ownedRelationship += Import
139 | ;
140 |
141 | MemberPrefix :
142 | ( visibility = VisibilityIndicator )?
143 | ;
144 |
145 | NamespaceMember :
146 | NonFeatureMember | NamespaceFeatureMember
147 | ;
148 |
149 | NonFeatureMember :
150 | MemberPrefix ownedRelatedElement += MemberElement
151 | ;
152 |
153 | NamespaceFeatureMember :
154 | MemberPrefix ownedRelatedElement += FeatureElement
155 | ;
156 |
157 | AliasMember :
158 | MemberPrefix
159 | 'alias' ( '<' memberShortName = Name '>' )? ( memberName = Name )?
160 | 'for' memberElement = QualifiedName
161 | RelationshipBody
162 | ;
163 |
164 | ImportPrefix :
165 | ( visibility = VisibilityIndicator )?
166 | 'import' ( isImportAll ?= 'all' )?
167 | ;
168 |
169 | Import :
170 | ( MembershipImport | NamespaceImport )
171 | RelationshipBody
172 | ;
173 |
174 | MembershipImport :
175 | ImportPrefix ImportedMembership
176 | ;
177 |
178 | ImportedMembership :
179 | importedMembership = QualifiedName
180 | ( '::' isRecursive ?= '**' )?
181 | ;
182 |
183 | NamespaceImport :
184 | ImportPrefix
185 | ( ImportedNamespace
186 | | ownedRelatedElement += FilterPackage
187 | )
188 | ;
189 |
190 | ImportedNamespace :
191 | importedNamespace = QualifiedName '::' '*'
192 | ( '::' isRecursive ?= '**' )?
193 | ;
194 |
195 | FilterPackage :
196 | ownedRelationship += FilterPackageImport
197 | ( ownedRelationship += FilterPackageMember )+
198 | ;
199 |
200 | FilterPackageImport :
201 | FilterPackageMembershipImport | FilterPackageNamespaceImport
202 | ;
203 |
204 | FilterPackageMembershipImport :
205 | ImportedMembership
206 | ;
207 |
208 | FilterPackageNamespaceImport :
209 | ImportedNamespace
210 | ;
211 |
212 | FilterPackageMember :
213 | visibility = FilterPackageMemberVisibility ownedRelatedElement += OwnedExpression ']'
214 | ;
215 |
216 | FilterPackageMemberVisibility :
217 | private = '['
218 | ;
219 |
220 | VisibilityIndicator :
221 | public = 'public' | private = 'private' | protected = 'protected'
222 | ;
223 |
224 | /* Namespace Elements */
225 |
226 | MemberElement :
227 | AnnotatingElement | NonFeatureElement
228 | ;
229 |
230 | NonFeatureElement :
231 | Dependency
232 | | Namespace
233 | | Package
234 | | LibraryPackage
235 | | Multiplicity
236 | | Type
237 | | Classifier
238 | | Class
239 | | Structure
240 | | Metaclass
241 | | DataType
242 | | Association
243 | | AssociationStructure
244 | | Interaction
245 | | Behavior
246 | | Function
247 | | Predicate
248 | | Specialization
249 | | Conjugation
250 | | FeatureTyping
251 | | Subclassification
252 | | Disjoining
253 | | FeatureInverting
254 | | Subsetting
255 | | Redefinition
256 | | TypeFeaturing
257 | ;
258 |
259 | FeatureElement :
260 | Feature
261 | | Step
262 | | Expression
263 | | BooleanExpression
264 | | Invariant
265 | | Connector
266 | | BindingConnector
267 | | Succession
268 | | ItemFlow
269 | | SuccessionItemFlow
270 | ;
271 |
272 | /* PACKAGES */
273 |
274 | Package :
275 | ( ownedRelationship += PrefixMetadataMember )*
276 | PackageDeclaration PackageBody
277 | ;
278 |
279 | LibraryPackage :
280 | ( isStandard ?= 'standard' )? 'library'
281 | ( ownedRelationship += PrefixMetadataMember )*
282 | PackageDeclaration PackageBody
283 | ;
284 |
285 | PackageDeclaration :
286 | 'package' Identification?
287 | ;
288 |
289 | PackageBody :
290 | ';'
291 | | '{' ( // Note: PackageBodyElement is expanded here to avoid
292 | // infinite loops in the incremental parser.
293 | ownedRelationship += NamespaceMember
294 | | ownedRelationship += ElementFilterMember
295 | | ownedRelationship += AliasMember
296 | | ownedRelationship += Import )*
297 | '}'
298 | ;
299 |
300 | ElementFilterMember :
301 | MemberPrefix
302 | 'filter' ownedRelatedElement += OwnedExpression ';'
303 | ;
304 |
305 | /* TYPES */
306 |
307 | /* Types */
308 |
309 | TypePrefix :
310 | ( isAbstract ?= 'abstract' )?
311 | ( ownedRelationship += PrefixMetadataMember )*
312 | ;
313 |
314 | Type :
315 | TypePrefix 'type'
316 | TypeDeclaration TypeBody
317 | ;
318 |
319 | TypeDeclaration :
320 | ( isSufficient ?= 'all' )? Identification?
321 | ( ownedRelationship += OwnedMultiplicity )?
322 | ( SpecializationPart | ConjugationPart )+
323 | TypeRelationshipPart*
324 | ;
325 |
326 | SpecializationPart :
327 | ( ':>' | 'specializes' ) ownedRelationship += OwnedSpecialization
328 | ( ',' ownedRelationship += OwnedSpecialization )*
329 | ;
330 |
331 | ConjugationPart :
332 | ( '~' | 'conjugates' ) ownedRelationship += OwnedConjugation
333 | ;
334 |
335 | TypeRelationshipPart :
336 | DisjoiningPart | UnioningPart | IntersectingPart | DifferencingPart
337 | ;
338 |
339 | DisjoiningPart :
340 | 'disjoint' 'from' ownedRelationship += OwnedDisjoining
341 | ( ',' ownedRelationship += OwnedDisjoining )*
342 | ;
343 |
344 | UnioningPart :
345 | 'unions' ownedRelationship += Unioning
346 | ( ',' ownedRelationship += Unioning )*
347 | ;
348 |
349 | IntersectingPart :
350 | 'intersects' ownedRelationship += Intersecting
351 | ( ',' ownedRelationship += Intersecting )*
352 | ;
353 |
354 | DifferencingPart :
355 | 'differences' ownedRelationship += Differencing
356 | ( ',' ownedRelationship += Differencing )*
357 | ;
358 |
359 | TypeBody :
360 | ';'
361 | | '{' ( ownedRelationship += NonFeatureMember
362 | | ownedRelationship += FeatureMember
363 | | ownedRelationship += AliasMember
364 | | ownedRelationship += Import
365 | )*
366 | '}'
367 | ;
368 |
369 | /* Feature Membership */
370 |
371 | FeatureMember :
372 | TypeFeatureMember | OwnedFeatureMember
373 | ;
374 |
375 | TypeFeatureMember :
376 | MemberPrefix 'member' ownedRelatedElement += FeatureElement
377 | ;
378 |
379 | OwnedFeatureMember :
380 | MemberPrefix ownedRelatedElement += FeatureElement
381 | ;
382 |
383 | /* Specialization */
384 |
385 | Specialization :
386 | ( 'specialization' Identification? )?
387 | 'subtype'
388 | ( specific = QualifiedName
389 | | ownedRelatedElement += OwnedFeatureChain )
390 | ( ':>' | 'specializes')
391 | ( general = QualifiedName
392 | | ownedRelatedElement += OwnedFeatureChain )
393 | RelationshipBody
394 | ;
395 |
396 | OwnedSpecialization :
397 | general = QualifiedName
398 | | ownedRelatedElement += OwnedFeatureChain
399 | ;
400 |
401 | /* Conjugation */
402 |
403 | Conjugation :
404 | ( 'conjugation' Identification? )?
405 | 'conjugate'
406 | ( conjugatedType = QualifiedName
407 | | ownedRelatedElement += OwnedFeatureChain )
408 | ( '~' | 'conjugates')
409 | ( originalType = QualifiedName
410 | | ownedRelatedElement += OwnedFeatureChain )
411 | RelationshipBody
412 | ;
413 |
414 | OwnedConjugation :
415 | originalType = QualifiedName
416 | | ownedRelatedElement += OwnedFeatureChain
417 | ;
418 |
419 | /* Disjoining */
420 |
421 | Disjoining :
422 | ( 'disjoining' Identification? )?
423 | 'disjoint'
424 | ( typeDisjoined = QualifiedName
425 | | ownedRelatedElement += OwnedFeatureChain )
426 | 'from'
427 | ( disjoiningType = QualifiedName
428 | | ownedRelatedElement += OwnedFeatureChain )
429 | RelationshipBody
430 | ;
431 |
432 | OwnedDisjoining :
433 | disjoiningType = QualifiedName
434 | | ownedRelatedElement += OwnedFeatureChain
435 | ;
436 |
437 | /* Unioning, Intersecting and Differencing */
438 |
439 | Unioning :
440 | unioningType = QualifiedName
441 | | ownedRelatedElement += OwnedFeatureChain
442 | ;
443 |
444 | Intersecting :
445 | intersectingType = QualifiedName
446 | | ownedRelatedElement += OwnedFeatureChain
447 | ;
448 |
449 | Differencing :
450 | differencingType = QualifiedName
451 | | ownedRelatedElement += OwnedFeatureChain
452 | ;
453 |
454 | /* CLASSIFIERS */
455 |
456 | /* Classifiers */
457 |
458 | Classifier :
459 | TypePrefix 'classifier'
460 | ClassifierDeclaration TypeBody
461 | ;
462 |
463 | ClassifierDeclaration :
464 | (isSufficient ?= 'all' )? Identification?
465 | ( ownedRelationship += OwnedMultiplicity )?
466 | ( SuperclassingPart | ClassifierConjugationPart )?
467 | TypeRelationshipPart*
468 | ;
469 |
470 | SuperclassingPart :
471 | ( ':>' | 'specializes' ) ownedRelationship += Ownedsubclassification
472 | ( ',' ownedRelationship += Ownedsubclassification )*
473 | ;
474 |
475 | ClassifierConjugationPart :
476 | ( '~' | 'conjugates' ) ownedRelationship += ClassifierConjugation
477 | ;
478 |
479 | /* Subclassification */
480 |
481 | Subclassification :
482 | ( 'specialization' Identification? )?
483 | 'subclassifier' subclassifier = QualifiedName
484 | ( ':>' | 'specializes') superclassifier = QualifiedName
485 | RelationshipBody
486 | ;
487 |
488 | Ownedsubclassification :
489 | superclassifier = QualifiedName
490 | ;
491 |
492 | /* Classifier Conjugation */
493 |
494 | ClassifierConjugation :
495 | originalType = QualifiedName
496 | ;
497 |
498 | /* FEATURES */
499 |
500 | /* Features */
501 |
502 | FeatureDirection :
503 | in = 'in' | out = 'out' | inout = 'inout'
504 | ;
505 |
506 | FeaturePrefix :
507 | ( direction = FeatureDirection )?
508 | ( isAbstract ?= 'abstract' )?
509 | ( isComposite ?= 'composite' | isPortion ?= 'portion' )?
510 | ( isReadOnly ?= 'readonly' )?
511 | ( isDerived ?= 'derived' )?
512 | ( isEnd ?= 'end' )?
513 | ( ownedRelationship += PrefixMetadataMember )*
514 | ;
515 |
516 | Feature :
517 | FeaturePrefix
518 | ( 'feature'? FeatureDeclaration
519 | | ownedRelationship += PrefixMetadataMember
520 | | 'feature'
521 | )
522 | ValuePart? TypeBody
523 | ;
524 |
525 | FeatureDeclaration :
526 | ( isSufficient ?= 'all' )?
527 | ( Identification ( FeatureSpecializationPart | FeatureConjugationPart )?
528 | | FeatureSpecializationPart
529 | | FeatureConjugationPart
530 | )
531 | FeatureRelationshipPart*
532 | ;
533 |
534 | FeatureRelationshipPart :
535 | TypeRelationshipPart | ChainingPart | InvertingPart | TypeFeaturingPart
536 | ;
537 |
538 | ChainingPart :
539 | 'chains' ( ownedRelationship += OwnedFeatureChaining | FeatureChain )
540 | ;
541 |
542 | InvertingPart :
543 | 'inverse' 'of' ownedRelationship += OwnedFeatureInverting
544 | ;
545 |
546 | TypeFeaturingPart :
547 | 'featured' 'by' ownedRelationship += OwnedTypeFeaturing
548 | ( ',' ownedRelationship += OwnedTypeFeaturing )*
549 | ;
550 |
551 | FeatureSpecializationPart :
552 | ( FeatureSpecialization )+ MultiplicityPart? FeatureSpecialization*
553 | | MultiplicityPart FeatureSpecialization*
554 | ;
555 |
556 | MultiplicityPart :
557 | ownedRelationship += OwnedMultiplicity
558 | | ( ownedRelationship += OwnedMultiplicity )?
559 |
560 | ( isOrdered ?= 'ordered' isNonunique ?= 'nonunique'
561 | | isNonunique2 ?= 'nonunique' isOrdered2 ?= 'ordered'
562 | )
563 |
564 | ;
565 |
566 | FeatureSpecialization :
567 | typings=Typings | Subsettings | References | Redefinitions
568 | ;
569 |
570 | Typings :
571 | typedby=TypedBy ( ',' ownedRelationship += OwnedFeatureTyping )*
572 | ;
573 |
574 | TypedBy :
575 | ( ':' | 'typed' 'by' ) ownedRelationship += OwnedFeatureTyping
576 | ;
577 |
578 | Subsettings :
579 | Subsets ( ',' ownedRelationship += OwnedSubsetting )*
580 | ;
581 |
582 | Subsets :
583 | ( ':>' | 'subsets' ) ownedRelationship += OwnedSubsetting
584 | ;
585 |
586 | References :
587 | ReferencesKeyword ownedRelationship += OwnedReferenceSubsetting
588 | ;
589 |
590 | ReferencesKeyword :
591 | '::>' | 'references'
592 | ;
593 |
594 | Redefinitions :
595 | Redefines ( ',' ownedRelationship += OwnedRedefinition )*
596 | ;
597 |
598 | Redefines :
599 | ( ':>>' | 'redefines' ) ownedRelationship += OwnedRedefinition
600 | ;
601 |
602 | /* Feature Inverting */
603 |
604 | FeatureInverting :
605 | ( 'inverting' Identification? )?
606 | 'inverse'
607 | ( featureInverted = QualifiedName
608 | | ownedRelatedElement += OwnedFeatureChain )
609 | 'of'
610 | ( invertingFeature = QualifiedName
611 | | ownedRelatedElement += OwnedFeatureChain )
612 | RelationshipBody
613 | ;
614 |
615 | OwnedFeatureInverting :
616 | invertingFeature = QualifiedName
617 | | ownedRelatedElement += OwnedFeatureChain
618 | ;
619 |
620 | /* Type Featuring */
621 |
622 | TypeFeaturing :
623 | 'featuring' ( Identification? 'of')?
624 | featureOfType = QualifiedName
625 | 'by' featuringType = QualifiedName
626 | RelationshipBody
627 | ;
628 |
629 | OwnedTypeFeaturing :
630 | featuringType = QualifiedName
631 | ;
632 |
633 | /* Feature Typing */
634 |
635 | FeatureTyping :
636 | ( 'specialization' Identification? )?
637 | 'typing' typedFeature = QualifiedName
638 | (':' | 'typed' 'by') type=FeatureType
639 | RelationshipBody
640 | ;
641 |
642 |
643 | OwnedFeatureTyping :
644 | type=FeatureType
645 | ;
646 |
647 | FeatureType :
648 | type = QualifiedName | ownedRelatedElement += OwnedFeatureChain
649 | ;
650 |
651 | /* Subsetting */
652 |
653 | Subsetting :
654 | ( 'specialization' Identification? )?
655 | 'subset'
656 | ( subsettingFeature = QualifiedName
657 | | ownedRelatedElement += OwnedFeatureChain )
658 | ( ':>' | 'subsets' )
659 | ( subsettedFeature = QualifiedName
660 | | ownedRelatedElement += OwnedFeatureChain )
661 | RelationshipBody
662 | ;
663 |
664 | OwnedSubsetting :
665 | subsettedFeature = QualifiedName
666 | | ownedRelatedElement += OwnedFeatureChain
667 | ;
668 |
669 | OwnedReferenceSubsetting :
670 | referencedFeature = QualifiedName
671 | | ownedRelatedElement += OwnedFeatureChain
672 | ;
673 |
674 | /* Redefinition */
675 |
676 | Redefinition :
677 | ( 'specialization' Identification? )?
678 | 'redefinition'
679 | ( redefiningFeature = QualifiedName
680 | | ownedRelatedElement += OwnedFeatureChain )
681 | ( ':>>' | 'redefines' )
682 | ( redefinedFeature = QualifiedName
683 | | ownedRelatedElement += OwnedFeatureChain )
684 | RelationshipBody
685 | ;
686 |
687 | OwnedRedefinition :
688 | redefinedFeature = QualifiedName
689 | | ownedRelatedElement += OwnedFeatureChain
690 | ;
691 |
692 | /* Feature Conjugation */
693 |
694 | FeatureConjugationPart :
695 | ( '~' | 'conjugates' ) ownedRelationship += FeatureConjugation
696 | ;
697 |
698 | FeatureConjugation :
699 | originalType = QualifiedName
700 | ;
701 |
702 | /* FEATURE VALUES */
703 |
704 | ValuePart :
705 | ownedRelationship += FeatureValue
706 | | ownedRelationship += FeatureValueExpression
707 | ownedRelationship += EmptyFeatureWriteMember
708 | ;
709 |
710 | FeatureValue :
711 | ( '=' | isDefault ?= 'default' ( '=' | isInitial ?= ':=' )? )
712 | ownedRelatedElement = OwnedExpression
713 | ;
714 |
715 | FeatureValueExpression :
716 | isInitial ?= ':='
717 | ownedRelatedElement += OwnedExpression
718 | ;
719 |
720 | EmptyFeatureWriteMember :
721 | ownedRelatedElement += EmptyFeatureWrite
722 | ;
723 |
724 | EmptyFeatureWrite :
725 | ownedRelationship += EmptyTargetMember
726 | ownedRelationship += EmptyParameterMember
727 | ;
728 |
729 | EmptyTargetMember :
730 | ownedRelatedElement += EmptyTargetParameter
731 | ;
732 |
733 | EmptyTargetParameter :
734 | ownedRelationship += TargetFeatureMember
735 | ;
736 |
737 | TargetFeatureMember :
738 | ownedRelatedElement += TargetFeature
739 | ;
740 |
741 | TargetFeature :
742 | ownedRelationship += EmptyFeatureMember
743 | ;
744 |
745 | EmptyFeatureMember :
746 | ownedRelatedElement += EmptyFeature
747 | ;
748 |
749 | EmptyParameterMember :
750 | ownedRelatedElement += EmptyFeature
751 | ;
752 |
753 | /* MULTIPLICITIES */
754 |
755 | Multiplicity :
756 | MultiplicitySubset | MultiplicityRange
757 | ;
758 |
759 | MultiplicitySubset :
760 | 'multiplicity' Identification? Subsets TypeBody
761 | ;
762 |
763 | MultiplicityRange :
764 | 'multiplicity' Identification? MultiplicityBounds TypeBody
765 | ;
766 |
767 | OwnedMultiplicity :
768 | ownedRelatedElement += OwnedMultiplicityRange
769 | ;
770 |
771 | OwnedMultiplicityRange :
772 | MultiplicityBounds
773 | ;
774 |
775 | MultiplicityBounds :
776 | // TODO: Allow general expressions for bounds. (Causes LL parsing issues.)
777 | '[' ownedRelationship += MultiplicityExpressionMember
778 | ( '..' ownedRelationship += MultiplicityExpressionMember )? ']'
779 | ;
780 |
781 |
782 | MultiplicityRelatedElement :
783 | (LiteralExpression | FeatureReferenceExpression)
784 | ;
785 |
786 | MultiplicityExpressionMember :
787 | ownedRelatedElement += MultiplicityRelatedElement
788 | ;
789 |
790 | /* CLASSIFICATION */
791 |
792 | /* Data Types */
793 |
794 | DataType :
795 | TypePrefix 'datatype'
796 | ClassifierDeclaration TypeBody
797 | ;
798 |
799 | /* Classes */
800 |
801 | Class :
802 | TypePrefix 'class'
803 | ClassifierDeclaration TypeBody
804 | ;
805 |
806 | /* STRUCTURES */
807 |
808 | Structure :
809 | TypePrefix 'struct'
810 | ClassifierDeclaration TypeBody
811 | ;
812 |
813 |
814 | /* ASSOCIATIONS */
815 |
816 | Association :
817 | TypePrefix 'assoc'
818 | ClassifierDeclaration TypeBody
819 | ;
820 |
821 | AssociationStructure :
822 | TypePrefix 'assoc' 'struct'
823 | ClassifierDeclaration TypeBody
824 | ;
825 |
826 | /* CONNECTORS */
827 |
828 | /* Connectors */
829 |
830 | Connector :
831 | FeaturePrefix 'connector'
832 | ConnectorDeclaration TypeBody
833 | ;
834 |
835 | ConnectorDeclaration :
836 | BinaryConnectorDeclaration | NaryConnectorDeclaration
837 | ;
838 |
839 | BinaryConnectorDeclaration :
840 | ( FeatureDeclaration? 'from' | isSufficient ?= 'all' 'from'? )?
841 | ownedRelationship += ConnectorEndMember 'to'
842 | ownedRelationship += ConnectorEndMember
843 | ;
844 |
845 | NaryConnectorDeclaration :
846 | FeatureDeclaration?
847 | ( '(' ownedRelationship += ConnectorEndMember ','
848 | ownedRelationship += ConnectorEndMember
849 | ( ',' ownedRelationship += ConnectorEndMember )*
850 | ')' )?
851 | ;
852 |
853 | ConnectorEndMember :
854 | ownedRelatedElement += ConnectorEnd
855 | ;
856 |
857 | ConnectorEnd :
858 | ( declaredName = Name ReferencesKeyword )?
859 | ownedRelationship += OwnedReferenceSubsetting
860 | ( ownedRelationship += OwnedMultiplicity )?
861 | ;
862 |
863 | /* Binding Connectors */
864 |
865 | BindingConnector :
866 | FeaturePrefix 'binding'
867 | BindingConnectorDeclaration TypeBody
868 | ;
869 |
870 | BindingConnectorDeclaration :
871 | FeatureDeclaration
872 | ( 'of' ownedRelationship += ConnectorEndMember
873 | '=' ownedRelationship += ConnectorEndMember )?
874 | | ( isSufficient ?= 'all' )?
875 | ( 'of'? ownedRelationship += ConnectorEndMember
876 | '=' ownedRelationship += ConnectorEndMember )?
877 | ;
878 |
879 | /* Successions */
880 |
881 | Succession :
882 | FeaturePrefix 'succession'
883 | SuccessionDeclaration TypeBody
884 | ;
885 |
886 | SuccessionDeclaration :
887 | FeatureDeclaration
888 | ( 'first' ownedRelationship += ConnectorEndMember
889 | 'then' ownedRelationship += ConnectorEndMember )?
890 | | ( isSufficient ?= 'all' )?
891 | ( 'first'? ownedRelationship += ConnectorEndMember
892 | 'then' ownedRelationship += ConnectorEndMember )?
893 | ;
894 |
895 | /* BEHAVIORS */
896 |
897 | /* Behaviors */
898 |
899 | Behavior :
900 | TypePrefix 'behavior'
901 | ClassifierDeclaration TypeBody
902 | ;
903 |
904 | /* Steps */
905 |
906 | Step :
907 | FeaturePrefix 'step'
908 | StepDeclaration TypeBody
909 | ;
910 |
911 | StepDeclaration :
912 | FeatureDeclaration? ValuePart?
913 | ;
914 |
915 | /* FUNCTIONS */
916 |
917 | /* Functions */
918 |
919 | Function :
920 | TypePrefix 'function'
921 | ClassifierDeclaration FunctionBody
922 | ;
923 |
924 | FunctionBody :
925 | ';' | '{' FunctionBodyPart '}'
926 | ;
927 |
928 | FunctionBodyPart :
929 | ( ownedRelationship += NonFeatureMember
930 | | ownedRelationship += FeatureMember
931 | | ownedRelationship += AliasMember
932 | | ownedRelationship += Import
933 | | ownedRelationship += ReturnFeatureMember
934 | )*
935 | ( ownedRelationship += ResultExpressionMember )?
936 | ;
937 |
938 | ReturnFeatureMember :
939 | MemberPrefix 'return' ownedRelatedElement += FeatureElement
940 | ;
941 |
942 |
943 | ResultExpressionMember :
944 | MemberPrefix ownedRelatedElement += OwnedExpression
945 | ;
946 |
947 | /* Expressions */
948 |
949 | Expression :
950 | FeaturePrefix 'expr'
951 | ExpressionDeclaration FunctionBody
952 | ;
953 |
954 | ExpressionDeclaration :
955 | FeatureDeclaration? ValuePart?
956 | ;
957 |
958 | /* Predicates */
959 |
960 | Predicate :
961 | TypePrefix 'predicate'
962 | ClassifierDeclaration FunctionBody
963 | ;
964 |
965 | /* Boolean Expressions */
966 |
967 | BooleanExpression :
968 | FeaturePrefix 'bool'
969 | ExpressionDeclaration FunctionBody
970 | ;
971 |
972 | /* Invariants */
973 |
974 | Invariant :
975 | FeaturePrefix 'inv' ( 'true' | isNegated ?= 'false' )?
976 | ExpressionDeclaration FunctionBody
977 | ;
978 |
979 | /* INTERACTIONS */
980 |
981 | /* Interactions */
982 |
983 | Interaction :
984 | TypePrefix 'interaction'
985 | ClassifierDeclaration TypeBody
986 | ;
987 |
988 | /* Item Flows */
989 |
990 | ItemFlow :
991 | FeaturePrefix 'flow'
992 | ItemFlowDeclaration TypeBody
993 | ;
994 |
995 | SuccessionItemFlow :
996 | FeaturePrefix 'succession' 'flow' ItemFlowDeclaration TypeBody
997 | ;
998 |
999 | ItemFlowDeclaration :
1000 | FeatureDeclaration? ValuePart?
1001 | ( 'of' ownedRelationship += ItemFeatureMember )?
1002 | ( 'from' ownedRelationship += ItemFlowEndMember
1003 | 'to' ownedRelationship += ItemFlowEndMember )?
1004 | | ( isSufficient ?= 'all' )?
1005 | ownedRelationship += ItemFlowEndMember 'to'
1006 | ownedRelationship += ItemFlowEndMember
1007 | ;
1008 |
1009 | ItemFeatureMember :
1010 | ownedRelatedElement += ItemFeature
1011 | ;
1012 |
1013 | ItemFeature :
1014 | Identification? ItemFeatureSpecializationPart ValuePart?
1015 | | Identification? ValuePart
1016 | | ownedRelationship += OwnedFeatureTyping ( ownedRelationship += OwnedMultiplicity )?
1017 | | ownedRelationship += OwnedMultiplicity ownedRelationship += OwnedFeatureTyping
1018 | ;
1019 |
1020 | ItemFeatureSpecializationPart :
1021 | ( FeatureSpecialization )+ MultiplicityPart? FeatureSpecialization*
1022 | | MultiplicityPart FeatureSpecialization+
1023 | ;
1024 |
1025 | ItemFlowEndMember :
1026 | ownedRelatedElement += ItemFlowEnd
1027 | ;
1028 |
1029 | ItemFlowEnd :
1030 | ( ownedRelationship += ItemFlowEndSubsetting )?
1031 | ownedRelationship += ItemFlowFeatureMember
1032 | ;
1033 |
1034 | ItemFlowEndSubsetting :
1035 | referencedFeature = QualifiedName '.'
1036 | | ownedRelatedElement += FeatureChainPrefix
1037 | ;
1038 |
1039 | FeatureChainPrefix :
1040 | ( ownedRelationship += OwnedFeatureChaining '.' )+
1041 | ownedRelationship += OwnedFeatureChaining '.'
1042 | ;
1043 |
1044 | ItemFlowFeatureMember :
1045 | ownedRelatedElement += ItemFlowFeature
1046 | ;
1047 |
1048 | ItemFlowFeature :
1049 | ownedRelationship += ItemFlowRedefinition
1050 | ;
1051 |
1052 | ItemFlowRedefinition :
1053 | redefinedFeature = QualifiedName
1054 | ;
1055 |
1056 | /* METADATA */
1057 |
1058 | Metaclass :
1059 | TypePrefix 'metaclass'
1060 | ClassifierDeclaration TypeBody
1061 | ;
1062 |
1063 | PrefixMetadataAnnotation :
1064 | '#' ownedRelatedElement += PrefixMetadataFeature
1065 | ;
1066 |
1067 | PrefixMetadataMember :
1068 | '#' ownedRelatedElement += PrefixMetadataFeature
1069 | ;
1070 |
1071 | PrefixMetadataFeature :
1072 | ownedRelationship += MetadataTyping
1073 | ;
1074 |
1075 | MetadataFeature :
1076 | ( '@' | 'metadata' ) MetadataFeatureDeclaration
1077 | ( 'about' ownedRelationship += Annotation
1078 | ( ',' ownedRelationship += Annotation )*
1079 | )?
1080 | MetadataBody
1081 | ;
1082 |
1083 | MetadataFeatureDeclaration :
1084 | ( Identification ( ':' | 'typed' 'by' ) )? ownedRelationship += MetadataTyping
1085 | ;
1086 |
1087 | MetadataTyping :
1088 | type = QualifiedName
1089 | ;
1090 |
1091 | MetadataBody :
1092 | ';'
1093 | | '{' ( ownedRelationship += NonFeatureMember
1094 | | ownedRelationship += MetadataBodyFeatureMember
1095 | | ownedRelationship += AliasMember
1096 | | ownedRelationship += Import
1097 | )*
1098 | '}'
1099 | ;
1100 |
1101 | MetadataBodyFeatureMember :
1102 | ownedRelatedElement += MetadataBodyFeature
1103 | ;
1104 |
1105 | MetadataBodyFeature :
1106 | 'feature'? ( ':>>' | 'redefines' )? ownedRelationship += OwnedRedefinition
1107 | FeatureSpecializationPart? ValuePart?
1108 | MetadataBody
1109 | ;
1110 |
1111 | /* EXPRESSIONS */
1112 |
1113 |
1114 | ExpressionBody :
1115 | '{' FunctionBodyPart '}'
1116 | ;
1117 |
--------------------------------------------------------------------------------
/src/sysml2py/grammar/KerMLExpressions.tx:
--------------------------------------------------------------------------------
1 | /*****************************************************************************
2 | * SysML 2 Pilot Implementation
3 | * Copyright (c) 2018-2023 Model Driven Solutions, Inc.
4 | * Copyright (c) 2018 IncQuery Labs Ltd.
5 | * Copyright (c) 2019 Maplesoft (Waterloo Maple, Inc.)
6 | * Copyright (c) 2019 Mgnite Inc.
7 | *
8 | * This program is free software: you can redistribute it and/or modify
9 | * it under the terms of the GNU Lesser General Public License as published by
10 | * the Free Software Foundation, either version 3 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * This program is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU Lesser General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU Lesser General Public License
19 | * along with this program. If not, see .
20 | *
21 | * @license LGPL-3.0-or-later
22 | *
23 | * Contributors:
24 | * Ed Seidewitz, MDS
25 | * Zoltan Kiss, IncQuery
26 | * Balazs Grill, IncQuery
27 | * Hisashi Miyashita, Maplesoft/Mgnite
28 | *
29 | *****************************************************************************/
30 |
31 | /* EXPRESSIONS */
32 |
33 | /* Operator Expressions */
34 |
35 | OwnedExpressionMember :
36 | ownedRelatedElement = OwnedExpression
37 | ;
38 |
39 | OwnedExpression :
40 | expression=ConditionalExpression
41 | ;
42 |
43 | // Conditional Test Expressions
44 |
45 | OwnedExpressionReference :
46 | ownedRelationship += OwnedExpressionMember
47 | ;
48 |
49 | ConditionalExpression :
50 | operand = NullCoalescingExpression
51 | | operator = ConditionalOperator operand += NullCoalescingExpression
52 | '?' operand += OwnedExpressionReference 'else' operand += OwnedExpressionReference
53 | ;
54 |
55 | ConditionalOperator :
56 | 'if'
57 | ;
58 |
59 | // Null Coalescing Expressions
60 |
61 | NullCoalescingExpression :
62 | implies = ImpliesExpression (
63 | operator = NullCoalescingOperator operand += ImpliesExpressionReference )*
64 | ;
65 |
66 | NullCoalescingOperator :
67 | '??'
68 | ;
69 |
70 | // Logical Expressions
71 |
72 | ImpliesExpressionReference :
73 | ownedRelationship += ImpliesExpressionMember
74 | ;
75 |
76 | ImpliesExpressionMember :
77 | ownedRelatedElement += ImpliesExpression
78 | ;
79 |
80 | ImpliesExpression :
81 | or = OrExpression (
82 | operator = ImpliesOperator operand += OrExpressionReference )*
83 | ;
84 |
85 | ImpliesOperator :
86 | 'implies'
87 | ;
88 |
89 | OrExpressionReference :
90 | ownedRelationship += OrExpressionMember
91 | ;
92 |
93 | OrExpressionMember :
94 | ownedRelatedElement += OrExpression
95 | ;
96 |
97 | OrExpression :
98 | xor=XorExpression (
99 | ( operator = OrOperator operand += XorExpression
100 | | operator = ConditionalOrOperator operand += XorExpressionReference ) )*
101 | ;
102 |
103 | OrOperator :
104 | '|'
105 | ;
106 |
107 | ConditionalOrOperator :
108 | 'or'
109 | ;
110 |
111 | XorExpressionReference :
112 | ownedRelationship += XorExpressionMember
113 | ;
114 |
115 | XorExpressionMember :
116 | ownedRelatedElement += XorExpression
117 | ;
118 |
119 | XorExpression :
120 | and=AndExpression (
121 | operator = XorOperator operand += AndExpression )*
122 | ;
123 |
124 | XorOperator :
125 | 'xor'
126 | ;
127 |
128 | AndOperand :
129 | (operator = AndOperator operand = EqualityExpression)
130 | |
131 | (operator = ConditionalAndOperator operand = EqualityExpressionReference)
132 | ;
133 |
134 | AndExpression :
135 | equality=EqualityExpression
136 | (operation+=AndOperand)*
137 | ;
138 |
139 | AndOperator :
140 | '&'
141 | ;
142 |
143 | ConditionalAndOperator :
144 | 'and'
145 | ;
146 |
147 | // Equality Expressions
148 |
149 | EqualityExpressionReference :
150 | ownedRelationship = EqualityExpressionMember
151 | ;
152 |
153 | EqualityExpressionMember :
154 | ownedRelatedElement = EqualityExpression
155 | ;
156 |
157 | EqualityOperand:
158 | operator=EqualityOperator operand=ClassificationExpression
159 | ;
160 |
161 | EqualityExpression :
162 | classification=ClassificationExpression
163 | (operation+=EqualityOperand)*
164 | ;
165 |
166 | EqualityOperator :
167 | '==' | '!=' | '===' | '!=='
168 | ;
169 |
170 | // Classification Expressions
171 |
172 | ClassificationExpression :
173 | relational=RelationalExpression
174 | (
175 | operator = ClassificationTestOperator ownedRelationship += TypeReferenceMember
176 | |
177 | operator = CastOperator ownedRelationship += TypeResultMember
178 | )?
179 | | operand += SelfReferenceExpression
180 | operator = ClassificationTestOperator ownedRelationship += TypeReferenceMember
181 | | operand += MetadataReference
182 | operator = MetaClassificationTestOperator ownedRelationship += TypeReferenceMember
183 | | operand += SelfReferenceExpression
184 | operator = CastOperator ownedRelationship += TypeResultMember
185 | | operand += MetadataReference
186 | operator = MetaCastOperator ownedRelationship += TypeResultMember
187 | ;
188 |
189 | ClassificationTestOperator :
190 | 'hastype' | 'istype' | '@'
191 | ;
192 |
193 | MetaClassificationTestOperator :
194 | '@@'
195 | ;
196 |
197 | CastOperator :
198 | 'as'
199 | ;
200 |
201 | MetaCastOperator :
202 | 'meta'
203 | ;
204 |
205 | MetadataReference :
206 | referencedElement = QualifiedName
207 | ;
208 |
209 | TypeReferenceMember :
210 | ownedRelatedElement += TypeReference
211 | ;
212 |
213 | TypeResultMember :
214 | ownedRelatedElement += TypeReference
215 | ;
216 |
217 | TypeReference :
218 | ownedRelationship += ReferenceTyping
219 | ;
220 |
221 | ReferenceTyping :
222 | type = QualifiedName
223 | ;
224 |
225 | SelfReferenceExpression :
226 | ownedRelationship += SelfReferenceMember
227 | ;
228 |
229 | SelfReferenceMember :
230 | ownedRelatedElement += EmptyFeature
231 | ;
232 |
233 | EmptyFeature ://This doesn't work.
234 | 'emptyfeature'
235 | ;
236 |
237 | // Relational Expressions
238 | RelationalOperand:
239 | operator=RelationalOperator operand=RangeExpression
240 | ;
241 |
242 | RelationalExpression :
243 | range=RangeExpression operation+=RelationalOperand*
244 | ;
245 |
246 | RelationalOperator :
247 | '<=' | '>=' | '<' | '>'
248 | ;
249 |
250 | // Range Expressions
251 |
252 | RangeExpression :
253 | additive=AdditiveExpression ('..' operand = AdditiveExpression )?
254 | ;
255 |
256 | // Arithmetic Expressions
257 |
258 | AdditiveOperand:
259 | operator=AdditiveOperator operand=MultiplicativeExpression
260 | ;
261 |
262 | AdditiveExpression :
263 | multiplicitive=MultiplicativeExpression
264 | (operation+=AdditiveOperand)*
265 | ;
266 |
267 | AdditiveOperator :
268 | '+' | '-'
269 | ;
270 |
271 | MultiplicativeOperand:
272 | operator=MultiplicativeOperator operand=ExponentiationExpression
273 | ;
274 |
275 | MultiplicativeExpression :
276 | exponential=ExponentiationExpression operation+=MultiplicativeOperand*
277 | ;
278 |
279 | MultiplicativeOperator :
280 | '*' | '/' | '%'
281 | ;
282 |
283 | ExponentiationExpression :
284 | unary=UnaryExpression (
285 | operator = ExponentiationOperator operand += UnaryExpression )*
286 | ;
287 |
288 | ExponentiationOperator :
289 | '**' | '^'
290 | ;
291 |
292 | // Unary Expressions
293 |
294 | UnaryExpression :
295 | operator = UnaryOperator operand += ExtentExpression
296 | | extent=ExtentExpression
297 | ;
298 |
299 | UnaryOperator :
300 | '+' | '-' | '~' | 'not'
301 | ;
302 |
303 | // Extent Expressions
304 |
305 | ExtentExpression :
306 | operator = 'all' ownedRelationship += TypeResultMember
307 | | primary=PrimaryExpression
308 | ;
309 |
310 | /* Primary Expressions */
311 |
312 | PrimaryExpression :
313 | base=BaseExpression
314 | ( '.' ownedRelationship1 += FeatureChainMember )?
315 | (
316 | ( operator += '#' '(' operand += SequenceExpression ')'
317 | | operator += '[' operand += SequenceExpression ']'
318 | | operator += '->' ownedRelationship = ReferenceTyping
319 | ( operand += BodyExpression | operand += FunctionReferenceExpression | operand+= ArgumentList )
320 | | operator += '.' operand += BodyExpression
321 | | operator += '.?' operand += BodyExpression
322 | )
323 | ( '.' ownedRelationship2 += FeatureChainMember )?
324 | )*
325 | ;
326 |
327 | FunctionReferenceExpression :
328 | ownedRelationship += FunctionReferenceMember
329 | ;
330 |
331 | FunctionReferenceMember :
332 | ownedRelatedElement += FunctionReference
333 | ;
334 |
335 | FunctionReference :
336 | ownedRelationship += ReferenceTyping
337 | ;
338 |
339 | FeatureChainMember :
340 | ownedRelatedElement = OwnedFeatureChain
341 | | memberElement = QualifiedName
342 | ;
343 |
344 | /* Base Expressions */
345 |
346 | BaseExpression :
347 | ownedRelationship=NullExpression
348 | | ownedRelationship=LiteralExpression
349 | | ownedRelationship=InvocationExpression
350 | | ownedRelationship=FeatureReferenceExpression
351 | | ownedRelationship=MetadataAccessExpression
352 | | ownedRelationship=BodyExpression
353 | | '(' ownedRelationship=SequenceExpression ')'
354 | ;
355 |
356 | // Expression Bodies
357 |
358 | BodyExpression :
359 | ownedRelationship = ExpressionBodyMember
360 | ;
361 |
362 | ExpressionBodyMember :
363 | ownedRelatedElement = ExpressionBody
364 | ;
365 |
366 | // This default production is overridden in the KerML and SysML grammars.
367 | ExpressionBody :
368 | '{' ( ownedRelationship += BodyParameterMember ';' )*
369 | ownedRelationship += ResultExpressionMember '}'
370 | ;
371 |
372 | ResultExpressionMember :
373 | ownedRelatedElement += OwnedExpression
374 | ;
375 |
376 | BodyParameterMember :
377 | 'in' ownedRelatedElement += BodyParameter
378 | ;
379 |
380 | BodyParameter :
381 | declaredName = Name
382 | ;
383 |
384 | // Sequence Expressions
385 |
386 | SequenceOperand:
387 | (',' operand = OwnedExpression)
388 | |
389 | ','
390 | ;
391 |
392 | SequenceExpression :
393 | ownedRelationship=OwnedExpression operation+=SequenceOperand*
394 | ;
395 |
396 | // Feature Reference Expressions
397 |
398 | FeatureReferenceExpression :
399 | ownedRelationship += FeatureReferenceMember
400 | ;
401 |
402 | FeatureReferenceMember :
403 | memberElement = QualifiedName
404 | ;
405 |
406 | // Metadata Access Expressions
407 |
408 | MetadataAccessExpression :
409 | referencedElement = QualifiedName '.' 'metadata'
410 | ;
411 |
412 | // Invocation Expressions
413 |
414 | InvocationExpression :
415 | ownedRelationship=OwnedFeatureTyping arg_list=ArgumentList
416 | ;
417 |
418 | OwnedFeatureTyping :
419 | type = QualifiedName
420 | | ownedRelatedElement += OwnedFeatureChain
421 | ;
422 |
423 | OwnedFeatureChain :
424 | feature=FeatureChain
425 | ;
426 |
427 | // For use in KerML and SysML grammars
428 | FeatureChain :
429 | ownedRelationship += OwnedFeatureChaining['.']
430 | ;
431 |
432 | OwnedFeatureChaining :
433 | chainingFeature = QualifiedName
434 | ;
435 |
436 | ArgumentList :
437 | '(' ( pos_list=PositionalArgumentList | named_list=NamedArgumentList )? ')'
438 | ;
439 |
440 | PositionalArgumentList :
441 | ownedRelationship += ArgumentMember[',']
442 | ;
443 |
444 | ArgumentMember :
445 | ownedRelatedElement = Argument
446 | ;
447 |
448 | Argument :
449 | ownedRelationship = ArgumentValue
450 | ;
451 |
452 | NamedArgumentList :
453 | ownedRelationship += NamedArgumentMember[',']
454 | ;
455 |
456 | NamedArgumentMember :
457 | ownedRelatedElement = NamedArgument
458 | ;
459 |
460 | NamedArgument :
461 | redefinition = ParameterRedefinition '=' value = ArgumentValue
462 | ;
463 |
464 | ParameterRedefinition :
465 | redefinedFeature = QualifiedName
466 | ;
467 |
468 | ArgumentValue :
469 | ownedRelatedElement = OwnedExpression
470 | ;
471 |
472 | // Null Expressions
473 |
474 | NullExpression :
475 | ( 'null' | '(' ')' )
476 | ;
477 |
478 | /* Literal Expressions */
479 |
480 | LiteralExpression :
481 | LiteralBoolean
482 | | LiteralString
483 | | LiteralReal
484 | | LiteralInteger
485 | | LiteralInfinity
486 | ;
487 |
488 | LiteralBoolean :
489 | value = BooleanValue
490 | ;
491 |
492 | BooleanValue :
493 | 'true' | 'false'
494 | ;
495 |
496 | LiteralString :
497 | value = STRING_VALUE
498 | ;
499 |
500 | LiteralInteger :
501 | value = DECIMAL_VALUE
502 | ;
503 |
504 | LiteralReal :
505 | value = RealValue
506 | ;
507 |
508 | RealValue :
509 | DECIMAL_VALUE? '.' ( DECIMAL_VALUE | EXP_VALUE ) | EXP_VALUE
510 | ;
511 |
512 | LiteralInfinity :
513 | value='*'
514 | ;
515 |
516 | /* NAMES */
517 |
518 | ReservedKeyword:
519 | 'about' | /to[\s]/ | 'connect' | 'connection' | 'from' | /of[\s]/ | 'then' |
520 | 'entry' | /accept[\s]/ | /do[\s]/ | /exit[\s]/ | /action[\s]/ | /at[\s]/ |
521 | /assign[\s]/
522 | ;
523 |
524 | Name:
525 | !ReservedKeyword ID | UNRESTRICTED_NAME
526 | ;
527 |
528 | Qualification :
529 | ( '::' Name )+
530 | ;
531 |
532 | QualifiedName:
533 | //name1=Name ( '::' names+=Name )*
534 | names+=Name['::']
535 | ;
536 |
537 | /* TERMINALS */
538 |
539 | DECIMAL_VALUE :
540 | /[0-9]+/;
541 |
542 | EXP_VALUE:
543 | DECIMAL_VALUE ('e' | 'E') ('+' | '-')? DECIMAL_VALUE;
544 |
545 | ID :
546 | /[a-zA-Z_][a-zA-Z_0-9]*/;
547 |
548 | UNRESTRICTED_NAME :
549 | /* Old format?
550 | /''' ('\' ('b' | 't' | 'n' | 'f' | 'r' | '"' | "'" | '\') | !('\' | '''))* '''/;
551 | */
552 | /[\'].*[\']/;
553 |
554 | STRING_VALUE :
555 | /*/'"' ('\' ('b' | 't' | 'n' | 'f' | 'r' | '"' | "'" | '\') | !('\' | '"'))* '"'/;*/
556 | /[\"].*[\"]/;
557 |
558 | REGULAR_COMMENT:
559 | /\/\*(.|\n)*?\*\//
560 | ;
561 |
562 | Comment:
563 | // Reserved for textx, but in the model
564 | /\/\/.*$/
565 | ;
566 |
567 | ML_NOTE:
568 | /'\/*'->'*\/'/;
569 |
570 | SL_NOTE:
571 | /'\/\/' (!('
572 | ' | '
') !('
573 | ' | '
')*)? ('
'? '
574 | ')?/;
575 |
576 | WS:
577 | /(' ' | ' ' | '
' | '
578 | ')+/;
579 |
--------------------------------------------------------------------------------
/src/sysml2py/textx/KerML.xtext:
--------------------------------------------------------------------------------
1 | /*****************************************************************************
2 | * SysML 2 Pilot Implementation
3 | * Copyright (c) 2018-2023 Model Driven Solutions, Inc.
4 | * Copyright (c) 2018 IncQuery Labs Ltd.
5 | * Copyright (c) 2019 Maplesoft (Waterloo Maple, Inc.)
6 | * Copyright (c) 2019 Mgnite Inc.
7 | *
8 | * This program is free software: you can redistribute it and/or modify
9 | * it under the terms of the GNU Lesser General Public License as published by
10 | * the Free Software Foundation, either version 3 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * This program is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU Lesser General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU Lesser General Public License
19 | * along with this program. If not, see .
20 | *
21 | * @license LGPL-3.0-or-later
22 | *
23 | * Contributors:
24 | * Ed Seidewitz, MDS
25 | * Zoltan Kiss, IncQuery
26 | * Balazs Grill, IncQuery
27 | * Hisashi Miyashita, Maplesoft/Mgnite
28 | *
29 | *****************************************************************************/
30 |
31 | grammar org.omg.kerml.xtext.KerML with org.omg.kerml.expressions.xtext.KerMLExpressions
32 |
33 | import "http://www.eclipse.org/emf/2002/Ecore" as Ecore
34 | import "https://www.omg.org/spec/SysML/20230201" as SysML
35 |
36 | /* ROOT NAMESPACE */
37 |
38 | RootNamespace returns SysML::Namespace :
39 | {SysML::Namespace}NamespaceBodyElement*
40 | ;
41 |
42 | /* ELEMENTS */
43 |
44 | /* Elements */
45 |
46 | fragment Identification returns SysML::Element :
47 | '<' declaredShortName = Name '>' ( declaredName = Name )?
48 | | declaredName = Name
49 | ;
50 |
51 | /* Relationships */
52 |
53 | fragment RelationshipBody returns SysML::Relationship :
54 | ';' | '{' RelationshipOwnedElement* '}'
55 | ;
56 |
57 | fragment RelationshipOwnedElement returns SysML::Relationship:
58 | ownedRelatedElement += OwnedRelatedElement
59 | | ownedRelationship += OwnedAnnotation
60 | ;
61 |
62 | OwnedRelatedElement returns SysML::Element :
63 | NonFeatureElement | FeatureElement
64 | ;
65 |
66 | /* DEPENDENCIES */
67 |
68 | Dependency returns SysML::Dependency :
69 | ( ownedRelationship += PrefixMetadataAnnotation )*
70 | 'dependency' ( Identification? 'from' )?
71 | client += [SysML::Element|QualifiedName] ( ',' client += [SysML::Element|QualifiedName] )* 'to'
72 | supplier += [SysML::Element|QualifiedName] ( ',' supplier += [SysML::Element|QualifiedName] )*
73 | RelationshipBody
74 | ;
75 |
76 | /* ANNOTATIONS */
77 |
78 | Annotation returns SysML::Annotation :
79 | annotatedElement = [SysML::Element|QualifiedName]
80 | ;
81 |
82 | OwnedAnnotation returns SysML::Annotation :
83 | ownedRelatedElement += AnnotatingElement
84 | ;
85 |
86 | AnnotatingElement returns SysML::AnnotatingElement :
87 | Comment
88 | | Documentation
89 | | TextualRepresentation
90 | | MetadataFeature
91 | ;
92 |
93 | /* Comments */
94 |
95 | Comment returns SysML::Comment :
96 | ( 'comment' Identification?
97 | ('about' ownedRelationship += Annotation
98 | ( ',' ownedRelationship += Annotation )* )?
99 | )?
100 | body = REGULAR_COMMENT
101 | ;
102 |
103 | Documentation returns SysML::Documentation :
104 | 'doc' Identification? body = REGULAR_COMMENT
105 | ;
106 |
107 | /* Textual Representation */
108 |
109 | TextualRepresentation returns SysML::TextualRepresentation :
110 | ( 'rep' Identification? )?
111 | 'language' language = STRING_VALUE
112 | body = REGULAR_COMMENT
113 | ;
114 |
115 | /* NAMESPACES */
116 |
117 | Namespace returns SysML::Namespace :
118 | ( ownedRelationship += PrefixMetadataMember )*
119 | NamespaceDeclaration NamespaceBody
120 | ;
121 |
122 | fragment NamespaceDeclaration returns SysML::Namespace :
123 | 'namespace' Identification?
124 | ;
125 |
126 | fragment NamespaceBody returns SysML::Namespace :
127 | ';'
128 | | '{' ( // Note: PackageBodyElement is expanded here to avoid
129 | // infinite loops in the incremental parser.
130 | ownedRelationship += NamespaceMember
131 | | ownedRelationship += AliasMember
132 | | ownedRelationship += Import )*
133 | '}'
134 | ;
135 |
136 | /* Namespace Bodies */
137 |
138 | fragment NamespaceBodyElement returns SysML::Namespace :
139 | ownedRelationship += NamespaceMember
140 | | ownedRelationship += AliasMember
141 | | ownedRelationship += Import
142 | ;
143 |
144 | fragment MemberPrefix returns SysML::Membership :
145 | ( visibility = VisibilityIndicator )?
146 | ;
147 |
148 | NamespaceMember returns SysML::OwningMembership :
149 | NonFeatureMember | NamespaceFeatureMember
150 | ;
151 |
152 | NonFeatureMember returns SysML::OwningMembership :
153 | MemberPrefix ownedRelatedElement += MemberElement
154 | ;
155 |
156 | NamespaceFeatureMember returns SysML::OwningMembership :
157 | MemberPrefix ownedRelatedElement += FeatureElement
158 | ;
159 |
160 | AliasMember returns SysML::Membership :
161 | MemberPrefix
162 | 'alias' ( '<' memberShortName = Name '>' )? ( memberName = Name )?
163 | 'for' memberElement = [SysML::Element|QualifiedName]
164 | RelationshipBody
165 | ;
166 |
167 | fragment ImportPrefix returns SysML::Import :
168 | ( visibility = VisibilityIndicator )?
169 | 'import' ( isImportAll ?= 'all' )?
170 | ;
171 |
172 | Import returns SysML::Import :
173 | ( MembershipImport | NamespaceImport )
174 | RelationshipBody
175 | ;
176 |
177 | MembershipImport returns SysML::MembershipImport :
178 | ImportPrefix ImportedMembership
179 | ;
180 |
181 | fragment ImportedMembership returns SysML::MembershipImport :
182 | importedMembership = [SysML::Membership|QualifiedName]
183 | ( '::' isRecursive ?= '**' )?
184 | ;
185 |
186 | NamespaceImport returns SysML::NamespaceImport :
187 | ImportPrefix
188 | ( ImportedNamespace
189 | | ownedRelatedElement += FilterPackage
190 | )
191 | ;
192 |
193 | fragment ImportedNamespace returns SysML::NamespaceImport :
194 | importedNamespace = [SysML::Namespace|QualifiedName] '::' '*'
195 | ( '::' isRecursive ?= '**' )?
196 | ;
197 |
198 | FilterPackage returns SysML::Package :
199 | ownedRelationship += FilterPackageImport
200 | ( ownedRelationship += FilterPackageMember )+
201 | ;
202 |
203 | FilterPackageImport returns SysML::Import :
204 | FilterPackageMembershipImport | FilterPackageNamespaceImport
205 | ;
206 |
207 | FilterPackageMembershipImport returns SysML::MembershipImport :
208 | ImportedMembership
209 | ;
210 |
211 | FilterPackageNamespaceImport returns SysML::NamespaceImport :
212 | ImportedNamespace
213 | ;
214 |
215 | FilterPackageMember returns SysML::ElementFilterMembership :
216 | visibility = FilterPackageMemberVisibility ownedRelatedElement += OwnedExpression ']'
217 | ;
218 |
219 | enum FilterPackageMemberVisibility returns SysML::VisibilityKind :
220 | private = '['
221 | ;
222 |
223 | enum VisibilityIndicator returns SysML::VisibilityKind :
224 | public = 'public' | private = 'private' | protected = 'protected'
225 | ;
226 |
227 | /* Namespace Elements */
228 |
229 | MemberElement returns SysML::Element :
230 | AnnotatingElement | NonFeatureElement
231 | ;
232 |
233 | NonFeatureElement returns SysML::Element :
234 | Dependency
235 | | Namespace
236 | | Package
237 | | LibraryPackage
238 | | Multiplicity
239 | | Type
240 | | Classifier
241 | | Class
242 | | Structure
243 | | Metaclass
244 | | DataType
245 | | Association
246 | | AssociationStructure
247 | | Interaction
248 | | Behavior
249 | | Function
250 | | Predicate
251 | | Specialization
252 | | Conjugation
253 | | FeatureTyping
254 | | Subclassification
255 | | Disjoining
256 | | FeatureInverting
257 | | Subsetting
258 | | Redefinition
259 | | TypeFeaturing
260 | ;
261 |
262 | FeatureElement returns SysML::Feature :
263 | Feature
264 | | Step
265 | | Expression
266 | | BooleanExpression
267 | | Invariant
268 | | Connector
269 | | BindingConnector
270 | | Succession
271 | | ItemFlow
272 | | SuccessionItemFlow
273 | ;
274 |
275 | /* PACKAGES */
276 |
277 | Package returns SysML::Package :
278 | ( ownedRelationship += PrefixMetadataMember )*
279 | PackageDeclaration PackageBody
280 | ;
281 |
282 | LibraryPackage returns SysML::LibraryPackage :
283 | ( isStandard ?= 'standard' )? 'library'
284 | ( ownedRelationship += PrefixMetadataMember )*
285 | PackageDeclaration PackageBody
286 | ;
287 |
288 | fragment PackageDeclaration returns SysML::Package :
289 | 'package' Identification?
290 | ;
291 |
292 | fragment PackageBody returns SysML::Namespace :
293 | ';'
294 | | '{' ( // Note: PackageBodyElement is expanded here to avoid
295 | // infinite loops in the incremental parser.
296 | ownedRelationship += NamespaceMember
297 | | ownedRelationship += ElementFilterMember
298 | | ownedRelationship += AliasMember
299 | | ownedRelationship += Import )*
300 | '}'
301 | ;
302 |
303 | ElementFilterMember returns SysML::ElementFilterMembership :
304 | MemberPrefix
305 | 'filter' ownedRelatedElement += OwnedExpression ';'
306 | ;
307 |
308 | /* TYPES */
309 |
310 | /* Types */
311 |
312 | fragment TypePrefix returns SysML::Type :
313 | ( isAbstract ?= 'abstract' )?
314 | ( ownedRelationship += PrefixMetadataMember )*
315 | ;
316 |
317 | Type returns SysML::Type :
318 | TypePrefix 'type'
319 | TypeDeclaration TypeBody
320 | ;
321 |
322 | fragment TypeDeclaration returns SysML::Type :
323 | ( isSufficient ?= 'all' )? Identification?
324 | ( ownedRelationship += OwnedMultiplicity )?
325 | ( SpecializationPart | ConjugationPart )+
326 | TypeRelationshipPart*
327 | ;
328 |
329 | fragment SpecializationPart returns SysML::Type :
330 | ( ':>' | 'specializes' ) ownedRelationship += OwnedSpecialization
331 | ( ',' ownedRelationship += OwnedSpecialization )*
332 | ;
333 |
334 | fragment ConjugationPart returns SysML::Type :
335 | ( '~' | 'conjugates' ) ownedRelationship += OwnedConjugation
336 | ;
337 |
338 | fragment TypeRelationshipPart returns SysML::Type :
339 | DisjoiningPart | UnioningPart | IntersectingPart | DifferencingPart
340 | ;
341 |
342 | fragment DisjoiningPart returns SysML::Type :
343 | 'disjoint' 'from' ownedRelationship += OwnedDisjoining
344 | ( ',' ownedRelationship += OwnedDisjoining )*
345 | ;
346 |
347 | fragment UnioningPart returns SysML::Type :
348 | 'unions' ownedRelationship += Unioning
349 | ( ',' ownedRelationship += Unioning )*
350 | ;
351 |
352 | fragment IntersectingPart returns SysML::Type :
353 | 'intersects' ownedRelationship += Intersecting
354 | ( ',' ownedRelationship += Intersecting )*
355 | ;
356 |
357 | fragment DifferencingPart returns SysML::Type :
358 | 'differences' ownedRelationship += Differencing
359 | ( ',' ownedRelationship += Differencing )*
360 | ;
361 |
362 | fragment TypeBody returns SysML::Type :
363 | ';'
364 | | '{' ( ownedRelationship += NonFeatureMember
365 | | ownedRelationship += FeatureMember
366 | | ownedRelationship += AliasMember
367 | | ownedRelationship += Import
368 | )*
369 | '}'
370 | ;
371 |
372 | /* Feature Membership */
373 |
374 | FeatureMember returns SysML::OwningMembership :
375 | TypeFeatureMember | OwnedFeatureMember
376 | ;
377 |
378 | TypeFeatureMember returns SysML::OwningMembership :
379 | MemberPrefix 'member' ownedRelatedElement += FeatureElement
380 | ;
381 |
382 | OwnedFeatureMember returns SysML::FeatureMembership :
383 | MemberPrefix ownedRelatedElement += FeatureElement
384 | ;
385 |
386 | /* Specialization */
387 |
388 | Specialization returns SysML::Specialization :
389 | ( 'specialization' Identification? )?
390 | 'subtype'
391 | ( specific = [SysML::Type | QualifiedName]
392 | | ownedRelatedElement += OwnedFeatureChain )
393 | ( ':>' | 'specializes')
394 | ( general = [SysML::Type | QualifiedName]
395 | | ownedRelatedElement += OwnedFeatureChain )
396 | RelationshipBody
397 | ;
398 |
399 | OwnedSpecialization returns SysML::Specialization :
400 | general = [SysML::Type | QualifiedName]
401 | | ownedRelatedElement += OwnedFeatureChain
402 | ;
403 |
404 | /* Conjugation */
405 |
406 | Conjugation returns SysML::Conjugation :
407 | ( 'conjugation' Identification? )?
408 | 'conjugate'
409 | ( conjugatedType = [SysML::Type | QualifiedName]
410 | | ownedRelatedElement += OwnedFeatureChain )
411 | ( '~' | 'conjugates')
412 | ( originalType = [SysML::Type | QualifiedName]
413 | | ownedRelatedElement += OwnedFeatureChain )
414 | RelationshipBody
415 | ;
416 |
417 | OwnedConjugation returns SysML::Conjugation :
418 | originalType = [SysML::Type | QualifiedName]
419 | | ownedRelatedElement += OwnedFeatureChain
420 | ;
421 |
422 | /* Disjoining */
423 |
424 | Disjoining returns SysML::Disjoining :
425 | ( 'disjoining' Identification? )?
426 | 'disjoint'
427 | ( typeDisjoined = [SysML::Type | QualifiedName]
428 | | ownedRelatedElement += OwnedFeatureChain )
429 | 'from'
430 | ( disjoiningType = [SysML::Type | QualifiedName]
431 | | ownedRelatedElement += OwnedFeatureChain )
432 | RelationshipBody
433 | ;
434 |
435 | OwnedDisjoining returns SysML::Disjoining :
436 | disjoiningType = [SysML::Type | QualifiedName]
437 | | ownedRelatedElement += OwnedFeatureChain
438 | ;
439 |
440 | /* Unioning, Intersecting and Differencing */
441 |
442 | Unioning returns SysML::Unioning :
443 | unioningType = [SysML::Type | QualifiedName]
444 | | ownedRelatedElement += OwnedFeatureChain
445 | ;
446 |
447 | Intersecting returns SysML::Intersecting :
448 | intersectingType = [SysML::Type | QualifiedName]
449 | | ownedRelatedElement += OwnedFeatureChain
450 | ;
451 |
452 | Differencing returns SysML::Differencing :
453 | differencingType = [SysML::Type | QualifiedName]
454 | | ownedRelatedElement += OwnedFeatureChain
455 | ;
456 |
457 | /* CLASSIFIERS */
458 |
459 | /* Classifiers */
460 |
461 | Classifier returns SysML::Classifier :
462 | TypePrefix 'classifier'
463 | ClassifierDeclaration TypeBody
464 | ;
465 |
466 | fragment ClassifierDeclaration returns SysML::Classifier :
467 | (isSufficient ?= 'all' )? Identification?
468 | ( ownedRelationship += OwnedMultiplicity )?
469 | ( SuperclassingPart | ClassifierConjugationPart )?
470 | TypeRelationshipPart*
471 | ;
472 |
473 | fragment SuperclassingPart returns SysML::Classifier :
474 | ( ':>' | 'specializes' ) ownedRelationship += Ownedsubclassification
475 | ( ',' ownedRelationship += Ownedsubclassification )*
476 | ;
477 |
478 | fragment ClassifierConjugationPart returns SysML::Classifier :
479 | ( '~' | 'conjugates' ) ownedRelationship += ClassifierConjugation
480 | ;
481 |
482 | /* Subclassification */
483 |
484 | Subclassification returns SysML::Subclassification :
485 | ( 'specialization' Identification? )?
486 | 'subclassifier' subclassifier = [SysML::Classifier | QualifiedName]
487 | ( ':>' | 'specializes') superclassifier = [SysML::Classifier | QualifiedName]
488 | RelationshipBody
489 | ;
490 |
491 | Ownedsubclassification returns SysML::Subclassification :
492 | superclassifier = [SysML::Classifier | QualifiedName]
493 | ;
494 |
495 | /* Classifier Conjugation */
496 |
497 | ClassifierConjugation returns SysML::Conjugation :
498 | originalType = [SysML::Classifier | QualifiedName]
499 | ;
500 |
501 | /* FEATURES */
502 |
503 | /* Features */
504 |
505 | enum FeatureDirection returns SysML::FeatureDirectionKind:
506 | in = 'in' | out = 'out' | inout = 'inout'
507 | ;
508 |
509 | fragment FeaturePrefix returns SysML::Feature :
510 | ( direction = FeatureDirection )?
511 | ( isAbstract ?= 'abstract' )?
512 | ( isComposite ?= 'composite' | isPortion ?= 'portion' )?
513 | ( isReadOnly ?= 'readonly' )?
514 | ( isDerived ?= 'derived' )?
515 | ( isEnd ?= 'end' )?
516 | ( ownedRelationship += PrefixMetadataMember )*
517 | ;
518 |
519 | Feature returns SysML::Feature :
520 | FeaturePrefix
521 | ( 'feature'? FeatureDeclaration
522 | | ownedRelationship += PrefixMetadataMember
523 | | 'feature'
524 | )
525 | ValuePart? TypeBody
526 | ;
527 |
528 | fragment FeatureDeclaration returns SysML::Feature :
529 | ( isSufficient ?= 'all' )?
530 | ( Identification ( FeatureSpecializationPart | FeatureConjugationPart )?
531 | | FeatureSpecializationPart
532 | | FeatureConjugationPart
533 | )
534 | FeatureRelationshipPart*
535 | ;
536 |
537 | fragment FeatureRelationshipPart returns SysML::Feature :
538 | TypeRelationshipPart | ChainingPart | InvertingPart | TypeFeaturingPart
539 | ;
540 |
541 | fragment ChainingPart returns SysML::Feature :
542 | 'chains' ( ownedRelationship += OwnedFeatureChaining | FeatureChain )
543 | ;
544 |
545 | fragment InvertingPart returns SysML::Feature :
546 | 'inverse' 'of' ownedRelationship += OwnedFeatureInverting
547 | ;
548 |
549 | fragment TypeFeaturingPart returns SysML::Feature :
550 | 'featured' 'by' ownedRelationship += OwnedTypeFeaturing
551 | ( ',' ownedRelationship += OwnedTypeFeaturing )*
552 | ;
553 |
554 | fragment FeatureSpecializationPart returns SysML::Feature :
555 | ( -> FeatureSpecialization )+ MultiplicityPart? FeatureSpecialization*
556 | | MultiplicityPart FeatureSpecialization*
557 | ;
558 |
559 | fragment MultiplicityPart returns SysML::Feature :
560 | ownedRelationship += OwnedMultiplicity
561 | | ( ownedRelationship += OwnedMultiplicity )?
562 | ( isOrdered ?= 'ordered' isNonunique ?= 'nonunique'?
563 | | isNonunique ?= 'nonunique' isOrdered ?= 'ordered'?
564 | )
565 | ;
566 |
567 | fragment FeatureSpecialization returns SysML::Feature :
568 | Typings | Subsettings | References | Redefinitions
569 | ;
570 |
571 | fragment Typings returns SysML::Feature :
572 | TypedBy ( ',' ownedRelationship += OwnedFeatureTyping )*
573 | ;
574 |
575 | fragment TypedBy returns SysML::Feature :
576 | ( ':' | 'typed' 'by' ) ownedRelationship += OwnedFeatureTyping
577 | ;
578 |
579 | fragment Subsettings returns SysML::Feature :
580 | Subsets ( ',' ownedRelationship += OwnedSubsetting )*
581 | ;
582 |
583 | fragment Subsets returns SysML::Feature :
584 | ( ':>' | 'subsets' ) ownedRelationship += OwnedSubsetting
585 | ;
586 |
587 | fragment References returns SysML::Feature :
588 | ReferencesKeyword ownedRelationship += OwnedReferenceSubsetting
589 | ;
590 |
591 | ReferencesKeyword :
592 | '::>' | 'references'
593 | ;
594 |
595 | fragment Redefinitions returns SysML::Feature :
596 | Redefines ( ',' ownedRelationship += OwnedRedefinition )*
597 | ;
598 |
599 | fragment Redefines returns SysML::Feature :
600 | ( ':>>' | 'redefines' ) ownedRelationship += OwnedRedefinition
601 | ;
602 |
603 | /* Feature Inverting */
604 |
605 | FeatureInverting returns SysML::FeatureInverting :
606 | ( 'inverting' Identification? )?
607 | 'inverse'
608 | ( featureInverted = [SysML::Feature| QualifiedName]
609 | | ownedRelatedElement += OwnedFeatureChain )
610 | 'of'
611 | ( invertingFeature = [SysML::Feature | QualifiedName]
612 | | ownedRelatedElement += OwnedFeatureChain )
613 | RelationshipBody
614 | ;
615 |
616 | OwnedFeatureInverting returns SysML::FeatureInverting :
617 | invertingFeature = [SysML::Feature | QualifiedName]
618 | | ownedRelatedElement += OwnedFeatureChain
619 | ;
620 |
621 | /* Type Featuring */
622 |
623 | TypeFeaturing returns SysML::TypeFeaturing :
624 | 'featuring' ( Identification? 'of')?
625 | featureOfType = [SysML::Feature | QualifiedName]
626 | 'by' featuringType = [SysML::Feature | QualifiedName]
627 | RelationshipBody
628 | ;
629 |
630 | OwnedTypeFeaturing returns SysML::TypeFeaturing :
631 | featuringType = [SysML::Type | QualifiedName]
632 | ;
633 |
634 | /* Feature Typing */
635 |
636 | FeatureTyping returns SysML::FeatureTyping :
637 | ( 'specialization' Identification? )?
638 | 'typing' typedFeature = [SysML::Feature | QualifiedName]
639 | (':' | 'typed' 'by') FeatureType
640 | RelationshipBody
641 | ;
642 |
643 | @Override
644 | OwnedFeatureTyping returns SysML::FeatureTyping :
645 | FeatureType
646 | ;
647 |
648 | fragment FeatureType returns SysML::FeatureTyping :
649 | type = [SysML::Type | QualifiedName]
650 | | ownedRelatedElement += OwnedFeatureChain
651 | ;
652 |
653 | /* Subsetting */
654 |
655 | Subsetting returns SysML::Subsetting :
656 | ( 'specialization' Identification? )?
657 | 'subset'
658 | ( subsettingFeature = [SysML::Feature | QualifiedName]
659 | | ownedRelatedElement += OwnedFeatureChain )
660 | ( ':>' | 'subsets' )
661 | ( subsettedFeature = [SysML::Feature | QualifiedName]
662 | | ownedRelatedElement += OwnedFeatureChain )
663 | RelationshipBody
664 | ;
665 |
666 | OwnedSubsetting returns SysML::Subsetting:
667 | subsettedFeature = [SysML::Feature | QualifiedName]
668 | | ownedRelatedElement += OwnedFeatureChain
669 | ;
670 |
671 | OwnedReferenceSubsetting returns SysML::ReferenceSubsetting:
672 | referencedFeature = [SysML::Feature | QualifiedName]
673 | | ownedRelatedElement += OwnedFeatureChain
674 | ;
675 |
676 | /* Redefinition */
677 |
678 | Redefinition returns SysML::Redefinition :
679 | ( 'specialization' Identification? )?
680 | 'redefinition'
681 | ( redefiningFeature = [SysML::Feature | QualifiedName]
682 | | ownedRelatedElement += OwnedFeatureChain )
683 | ( ':>>' | 'redefines' )
684 | ( redefinedFeature = [SysML::Feature | QualifiedName]
685 | | ownedRelatedElement += OwnedFeatureChain )
686 | RelationshipBody
687 | ;
688 |
689 | OwnedRedefinition returns SysML::Redefinition:
690 | redefinedFeature = [SysML::Feature | QualifiedName]
691 | | ownedRelatedElement += OwnedFeatureChain
692 | ;
693 |
694 | /* Feature Conjugation */
695 |
696 | fragment FeatureConjugationPart returns SysML::Feature :
697 | ( '~' | 'conjugates' ) ownedRelationship += FeatureConjugation
698 | ;
699 |
700 | FeatureConjugation returns SysML::Conjugation :
701 | originalType = [SysML::Feature | QualifiedName ]
702 | ;
703 |
704 | /* FEATURE VALUES */
705 |
706 | fragment ValuePart returns SysML::Feature :
707 | ownedRelationship += FeatureValue
708 | | ownedRelationship += FeatureValueExpression
709 | ownedRelationship += EmptyFeatureWriteMember
710 | ;
711 |
712 | FeatureValue returns SysML::FeatureValue :
713 | ( '=' | isDefault ?= 'default' ( '=' | isInitial ?= ':=' )? )
714 | ownedRelatedElement += OwnedExpression
715 | ;
716 |
717 | FeatureValueExpression returns SysML::FeatureValue :
718 | isInitial ?= ':='
719 | ownedRelatedElement += OwnedExpression
720 | ;
721 |
722 | EmptyFeatureWriteMember returns SysML::OwningMembership :
723 | ownedRelatedElement += EmptyFeatureWrite
724 | ;
725 |
726 | EmptyFeatureWrite returns SysML::Step :
727 | ownedRelationship += EmptyTargetMember
728 | ownedRelationship += EmptyParameterMember
729 | ;
730 |
731 | EmptyTargetMember returns SysML::ParameterMembership :
732 | ownedRelatedElement += EmptyTargetParameter
733 | ;
734 |
735 | EmptyTargetParameter returns SysML::ReferenceUsage :
736 | ownedRelationship += TargetFeatureMember
737 | ;
738 |
739 | TargetFeatureMember returns SysML::FeatureMembership :
740 | ownedRelatedElement += TargetFeature
741 | ;
742 |
743 | TargetFeature returns SysML::Feature :
744 | ownedRelationship += EmptyFeatureMember
745 | ;
746 |
747 | EmptyFeatureMember returns SysML::FeatureMembership :
748 | ownedRelatedElement += EmptyFeature
749 | ;
750 |
751 | EmptyParameterMember returns SysML::ParameterMembership :
752 | ownedRelatedElement += EmptyFeature
753 | ;
754 |
755 | /* MULTIPLICITIES */
756 |
757 | Multiplicity returns SysML::Multiplicity :
758 | MultiplicitySubset | MultiplicityRange
759 | ;
760 |
761 | MultiplicitySubset returns SysML::Multiplicity :
762 | 'multiplicity' Identification? Subsets TypeBody
763 | ;
764 |
765 | MultiplicityRange returns SysML::MultiplicityRange :
766 | 'multiplicity' Identification? MultiplicityBounds TypeBody
767 | ;
768 |
769 | OwnedMultiplicity returns SysML::OwningMembership :
770 | ownedRelatedElement += OwnedMultiplicityRange
771 | ;
772 |
773 | OwnedMultiplicityRange returns SysML::MultiplicityRange :
774 | MultiplicityBounds
775 | ;
776 |
777 | fragment MultiplicityBounds returns SysML::MultiplicityRange :
778 | // TODO: Allow general expressions for bounds. (Causes LL parsing issues.)
779 | '[' ownedRelationship += MultiplicityExpressionMember
780 | ( '..' ownedRelationship += MultiplicityExpressionMember )? ']'
781 | ;
782 |
783 | MultiplicityExpressionMember returns SysML::OwningMembership :
784 | ownedRelatedElement += ( LiteralExpression | FeatureReferenceExpression )
785 | ;
786 |
787 | /* CLASSIFICATION */
788 |
789 | /* Data Types */
790 |
791 | DataType returns SysML::DataType :
792 | TypePrefix 'datatype'
793 | ClassifierDeclaration TypeBody
794 | ;
795 |
796 | /* Classes */
797 |
798 | Class returns SysML::Class :
799 | TypePrefix 'class'
800 | ClassifierDeclaration TypeBody
801 | ;
802 |
803 | /* STRUCTURES */
804 |
805 | Structure returns SysML::Structure :
806 | TypePrefix 'struct'
807 | ClassifierDeclaration TypeBody
808 | ;
809 |
810 |
811 | /* ASSOCIATIONS */
812 |
813 | Association returns SysML::Association :
814 | TypePrefix 'assoc'
815 | ClassifierDeclaration TypeBody
816 | ;
817 |
818 | AssociationStructure returns SysML::AssociationStructure :
819 | TypePrefix 'assoc' 'struct'
820 | ClassifierDeclaration TypeBody
821 | ;
822 |
823 | /* CONNECTORS */
824 |
825 | /* Connectors */
826 |
827 | Connector returns SysML::Connector :
828 | FeaturePrefix 'connector'
829 | ConnectorDeclaration TypeBody
830 | ;
831 |
832 | fragment ConnectorDeclaration returns SysML::Connector :
833 | BinaryConnectorDeclaration | NaryConnectorDeclaration
834 | ;
835 |
836 | fragment BinaryConnectorDeclaration returns SysML::Connector :
837 | ( FeatureDeclaration? 'from' | isSufficient ?= 'all' 'from'? )?
838 | ownedRelationship += ConnectorEndMember 'to'
839 | ownedRelationship += ConnectorEndMember
840 | ;
841 |
842 | fragment NaryConnectorDeclaration returns SysML::Connector :
843 | FeatureDeclaration?
844 | ( '(' ownedRelationship += ConnectorEndMember ','
845 | ownedRelationship += ConnectorEndMember
846 | ( ',' ownedRelationship += ConnectorEndMember )*
847 | ')' )?
848 | ;
849 |
850 | ConnectorEndMember returns SysML::EndFeatureMembership :
851 | ownedRelatedElement += ConnectorEnd
852 | ;
853 |
854 | ConnectorEnd returns SysML::Feature :
855 | ( declaredName = Name ReferencesKeyword )?
856 | ownedRelationship += OwnedReferenceSubsetting
857 | ( ownedRelationship += OwnedMultiplicity )?
858 | ;
859 |
860 | /* Binding Connectors */
861 |
862 | BindingConnector returns SysML::BindingConnector :
863 | FeaturePrefix 'binding'
864 | BindingConnectorDeclaration TypeBody
865 | ;
866 |
867 | fragment BindingConnectorDeclaration returns SysML::BindingConnector :
868 | FeatureDeclaration
869 | ( 'of' ownedRelationship += ConnectorEndMember
870 | '=' ownedRelationship += ConnectorEndMember )?
871 | | ( isSufficient ?= 'all' )?
872 | ( 'of'? ownedRelationship += ConnectorEndMember
873 | '=' ownedRelationship += ConnectorEndMember )?
874 | ;
875 |
876 | /* Successions */
877 |
878 | Succession returns SysML::Succession :
879 | FeaturePrefix 'succession'
880 | SuccessionDeclaration TypeBody
881 | ;
882 |
883 | fragment SuccessionDeclaration returns SysML::Succession :
884 | FeatureDeclaration
885 | ( 'first' ownedRelationship += ConnectorEndMember
886 | 'then' ownedRelationship += ConnectorEndMember )?
887 | | ( isSufficient ?= 'all' )?
888 | ( 'first'? ownedRelationship += ConnectorEndMember
889 | 'then' ownedRelationship += ConnectorEndMember )?
890 | ;
891 |
892 | /* BEHAVIORS */
893 |
894 | /* Behaviors */
895 |
896 | Behavior returns SysML::Behavior :
897 | TypePrefix 'behavior'
898 | ClassifierDeclaration TypeBody
899 | ;
900 |
901 | /* Steps */
902 |
903 | Step returns SysML::Step :
904 | FeaturePrefix 'step'
905 | StepDeclaration TypeBody
906 | ;
907 |
908 | fragment StepDeclaration returns SysML::Step :
909 | FeatureDeclaration? ValuePart?
910 | ;
911 |
912 | /* FUNCTIONS */
913 |
914 | /* Functions */
915 |
916 | Function returns SysML::Function :
917 | TypePrefix 'function'
918 | ClassifierDeclaration FunctionBody
919 | ;
920 |
921 | fragment FunctionBody returns SysML::Type :
922 | ';' | '{' FunctionBodyPart '}'
923 | ;
924 |
925 | fragment FunctionBodyPart returns SysML::Type :
926 | ( ownedRelationship += NonFeatureMember
927 | | ownedRelationship += FeatureMember
928 | | ownedRelationship += AliasMember
929 | | ownedRelationship += Import
930 | | ownedRelationship += ReturnFeatureMember
931 | )*
932 | ( ownedRelationship += ResultExpressionMember )?
933 | ;
934 |
935 | ReturnFeatureMember returns SysML::ReturnParameterMembership :
936 | MemberPrefix 'return'
937 | ownedRelatedElement += FeatureElement
938 | ;
939 |
940 | @Override
941 | ResultExpressionMember returns SysML::ResultExpressionMembership :
942 | MemberPrefix ownedRelatedElement += OwnedExpression
943 | ;
944 |
945 | /* Expressions */
946 |
947 | Expression returns SysML::Expression :
948 | FeaturePrefix 'expr'
949 | ExpressionDeclaration FunctionBody
950 | ;
951 |
952 | fragment ExpressionDeclaration returns SysML::Expression :
953 | FeatureDeclaration? ValuePart?
954 | ;
955 |
956 | /* Predicates */
957 |
958 | Predicate returns SysML::Predicate :
959 | TypePrefix 'predicate'
960 | ClassifierDeclaration FunctionBody
961 | ;
962 |
963 | /* Boolean Expressions */
964 |
965 | BooleanExpression returns SysML::BooleanExpression :
966 | FeaturePrefix 'bool'
967 | ExpressionDeclaration FunctionBody
968 | ;
969 |
970 | /* Invariants */
971 |
972 | Invariant returns SysML::Invariant :
973 | FeaturePrefix 'inv' ( 'true' | isNegated ?= 'false' )?
974 | ExpressionDeclaration FunctionBody
975 | ;
976 |
977 | /* INTERACTIONS */
978 |
979 | /* Interactions */
980 |
981 | Interaction returns SysML::Interaction :
982 | TypePrefix 'interaction'
983 | ClassifierDeclaration TypeBody
984 | ;
985 |
986 | /* Item Flows */
987 |
988 | ItemFlow returns SysML::ItemFlow :
989 | FeaturePrefix 'flow'
990 | ItemFlowDeclaration TypeBody
991 | ;
992 |
993 | SuccessionItemFlow returns SysML::SuccessionItemFlow :
994 | FeaturePrefix 'succession' 'flow' ItemFlowDeclaration TypeBody
995 | ;
996 |
997 | fragment ItemFlowDeclaration returns SysML::ItemFlow :
998 | FeatureDeclaration? ValuePart?
999 | ( 'of' ownedRelationship += ItemFeatureMember )?
1000 | ( 'from' ownedRelationship += ItemFlowEndMember
1001 | 'to' ownedRelationship += ItemFlowEndMember )?
1002 | | ( isSufficient ?= 'all' )?
1003 | ownedRelationship += ItemFlowEndMember 'to'
1004 | ownedRelationship += ItemFlowEndMember
1005 | ;
1006 |
1007 | ItemFeatureMember returns SysML::FeatureMembership :
1008 | ownedRelatedElement += ItemFeature
1009 | ;
1010 |
1011 | ItemFeature returns SysML::ItemFeature :
1012 | Identification? ItemFeatureSpecializationPart ValuePart?
1013 | | Identification? ValuePart
1014 | | ownedRelationship += OwnedFeatureTyping ( ownedRelationship += OwnedMultiplicity )?
1015 | | ownedRelationship += OwnedMultiplicity ownedRelationship += OwnedFeatureTyping
1016 | ;
1017 |
1018 | fragment ItemFeatureSpecializationPart returns SysML::Feature :
1019 | ( -> FeatureSpecialization )+ MultiplicityPart? FeatureSpecialization*
1020 | | MultiplicityPart FeatureSpecialization+
1021 | ;
1022 |
1023 | ItemFlowEndMember returns SysML::EndFeatureMembership :
1024 | ownedRelatedElement += ItemFlowEnd
1025 | ;
1026 |
1027 | ItemFlowEnd returns SysML::ItemFlowEnd :
1028 | ( ownedRelationship += ItemFlowEndSubsetting )?
1029 | ownedRelationship += ItemFlowFeatureMember
1030 | ;
1031 |
1032 | ItemFlowEndSubsetting returns SysML::ReferenceSubsetting :
1033 | referencedFeature = [SysML::Feature | QualifiedName] '.'
1034 | | ownedRelatedElement += FeatureChainPrefix
1035 | ;
1036 |
1037 | FeatureChainPrefix returns SysML::Feature :
1038 | ( ownedRelationship += OwnedFeatureChaining '.' )+
1039 | ownedRelationship += OwnedFeatureChaining '.'
1040 | ;
1041 |
1042 | ItemFlowFeatureMember returns SysML::FeatureMembership :
1043 | ownedRelatedElement += ItemFlowFeature
1044 | ;
1045 |
1046 | ItemFlowFeature returns SysML::Feature :
1047 | ownedRelationship += ItemFlowRedefinition
1048 | ;
1049 |
1050 | ItemFlowRedefinition returns SysML::Redefinition :
1051 | redefinedFeature = [SysML::Feature|QualifiedName]
1052 | ;
1053 |
1054 | /* METADATA */
1055 |
1056 | Metaclass returns SysML::Metaclass :
1057 | TypePrefix 'metaclass'
1058 | ClassifierDeclaration TypeBody
1059 | ;
1060 |
1061 | PrefixMetadataAnnotation returns SysML::Annotation :
1062 | '#' ownedRelatedElement += PrefixMetadataFeature
1063 | ;
1064 |
1065 | PrefixMetadataMember returns SysML::OwningMembership :
1066 | '#' ownedRelatedElement += PrefixMetadataFeature
1067 | ;
1068 |
1069 | PrefixMetadataFeature returns SysML::MetadataFeature :
1070 | ownedRelationship += MetadataTyping
1071 | ;
1072 |
1073 | MetadataFeature returns SysML::MetadataFeature :
1074 | ( '@' | 'metadata' ) MetadataFeatureDeclaration
1075 | ( 'about' ownedRelationship += Annotation
1076 | ( ',' ownedRelationship += Annotation )*
1077 | )?
1078 | MetadataBody
1079 | ;
1080 |
1081 | fragment MetadataFeatureDeclaration returns SysML::MetadataFeature :
1082 | ( Identification ( ':' | 'typed' 'by' ) )? ownedRelationship += MetadataTyping
1083 | ;
1084 |
1085 | MetadataTyping returns SysML::FeatureTyping :
1086 | type = [SysML::Metaclass | QualifiedName]
1087 | ;
1088 |
1089 | fragment MetadataBody returns SysML::Feature :
1090 | ';'
1091 | | '{' ( ownedRelationship += NonFeatureMember
1092 | | ownedRelationship += MetadataBodyFeatureMember
1093 | | ownedRelationship += AliasMember
1094 | | ownedRelationship += Import
1095 | )*
1096 | '}'
1097 | ;
1098 |
1099 | MetadataBodyFeatureMember returns SysML::FeatureMembership :
1100 | ownedRelatedElement += MetadataBodyFeature
1101 | ;
1102 |
1103 | MetadataBodyFeature returns SysML::Feature :
1104 | 'feature'? ( ':>>' | 'redefines' )? ownedRelationship += OwnedRedefinition
1105 | FeatureSpecializationPart? ValuePart?
1106 | MetadataBody
1107 | ;
1108 |
1109 | /* EXPRESSIONS */
1110 |
1111 | @Override
1112 | ExpressionBody returns SysML::Expression :
1113 | '{' FunctionBodyPart '}'
1114 | ;
1115 |
--------------------------------------------------------------------------------
/src/sysml2py/textx/KerMLExpressions.xtext:
--------------------------------------------------------------------------------
1 | /*****************************************************************************
2 | * SysML 2 Pilot Implementation
3 | * Copyright (c) 2018-2023 Model Driven Solutions, Inc.
4 | * Copyright (c) 2018 IncQuery Labs Ltd.
5 | * Copyright (c) 2019 Maplesoft (Waterloo Maple, Inc.)
6 | * Copyright (c) 2019 Mgnite Inc.
7 | *
8 | * This program is free software: you can redistribute it and/or modify
9 | * it under the terms of the GNU Lesser General Public License as published by
10 | * the Free Software Foundation, either version 3 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * This program is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU Lesser General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU Lesser General Public License
19 | * along with this program. If not, see .
20 | *
21 | * @license LGPL-3.0-or-later
22 | *
23 | * Contributors:
24 | * Ed Seidewitz, MDS
25 | * Zoltan Kiss, IncQuery
26 | * Balazs Grill, IncQuery
27 | * Hisashi Miyashita, Maplesoft/Mgnite
28 | *
29 | *****************************************************************************/
30 |
31 | grammar org.omg.kerml.expressions.xtext.KerMLExpressions hidden(WS, ML_NOTE, SL_NOTE)
32 |
33 | import "http://www.eclipse.org/emf/2002/Ecore" as Ecore
34 | import "https://www.omg.org/spec/SysML/20230201" as SysML
35 |
36 | /* EXPRESSIONS */
37 |
38 | /* Operator Expressions */
39 |
40 | OwnedExpressionMember returns SysML::FeatureMembership :
41 | ownedRelatedElement += OwnedExpression
42 | ;
43 |
44 | OwnedExpression returns SysML::Expression :
45 | ConditionalExpression
46 | ;
47 |
48 | // Conditional Test Expressions
49 |
50 | OwnedExpressionReference returns SysML::FeatureReferenceExpression :
51 | ownedRelationship += OwnedExpressionMember
52 | ;
53 |
54 | ConditionalExpression returns SysML::Expression :
55 | NullCoalescingExpression
56 | | {SysML::OperatorExpression} operator = ConditionalOperator operand += NullCoalescingExpression
57 | '?' operand += OwnedExpressionReference 'else' operand += OwnedExpressionReference
58 | ;
59 |
60 | ConditionalOperator :
61 | 'if'
62 | ;
63 |
64 | // Null Coalescing Expressions
65 |
66 | NullCoalescingExpression returns SysML::Expression :
67 | ImpliesExpression ( {SysML::OperatorExpression.operand += current}
68 | operator = NullCoalescingOperator operand += ImpliesExpressionReference )*
69 | ;
70 |
71 | NullCoalescingOperator :
72 | '??'
73 | ;
74 |
75 | // Logical Expressions
76 |
77 | ImpliesExpressionReference returns SysML::FeatureReferenceExpression :
78 | ownedRelationship += ImpliesExpressionMember
79 | ;
80 |
81 | ImpliesExpressionMember returns SysML::FeatureMembership :
82 | ownedRelatedElement += ImpliesExpression
83 | ;
84 |
85 | ImpliesExpression returns SysML::Expression :
86 | OrExpression ( {SysML::OperatorExpression.operand += current}
87 | operator = ImpliesOperator operand += OrExpressionReference )*
88 | ;
89 |
90 | ImpliesOperator :
91 | 'implies'
92 | ;
93 |
94 | OrExpressionReference returns SysML::FeatureReferenceExpression :
95 | ownedRelationship += OrExpressionMember
96 | ;
97 |
98 | OrExpressionMember returns SysML::FeatureMembership :
99 | ownedRelatedElement += OrExpression
100 | ;
101 |
102 | OrExpression returns SysML::Expression :
103 | XorExpression ( {SysML::OperatorExpression.operand += current}
104 | ( operator = OrOperator operand += XorExpression
105 | | operator = ConditionalOrOperator operand += XorExpressionReference ) )*
106 | ;
107 |
108 | OrOperator :
109 | '|'
110 | ;
111 |
112 | ConditionalOrOperator :
113 | 'or'
114 | ;
115 |
116 | XorExpressionReference returns SysML::FeatureReferenceExpression :
117 | ownedRelationship += XorExpressionMember
118 | ;
119 |
120 | XorExpressionMember returns SysML::FeatureMembership :
121 | ownedRelatedElement += XorExpression
122 | ;
123 |
124 | XorExpression returns SysML::Expression :
125 | AndExpression ( {SysML::OperatorExpression.operand += current}
126 | operator = XorOperator operand += AndExpression )*
127 | ;
128 |
129 | XorOperator :
130 | 'xor'
131 | ;
132 |
133 | AndExpression returns SysML::Expression :
134 | EqualityExpression ( {SysML::OperatorExpression.operand += current}
135 | ( operator = AndOperator operand += EqualityExpression
136 | | operator = ConditionalAndOperator operand += EqualityExpressionReference ) )*
137 | ;
138 |
139 | AndOperator :
140 | '&'
141 | ;
142 |
143 | ConditionalAndOperator :
144 | 'and'
145 | ;
146 |
147 | // Equality Expressions
148 |
149 | EqualityExpressionReference returns SysML::FeatureReferenceExpression :
150 | ownedRelationship += EqualityExpressionMember
151 | ;
152 |
153 | EqualityExpressionMember returns SysML::FeatureMembership :
154 | ownedRelatedElement += EqualityExpression
155 | ;
156 |
157 | EqualityExpression returns SysML::Expression :
158 | ClassificationExpression ( {SysML::OperatorExpression.operand += current}
159 | operator = EqualityOperator operand += ClassificationExpression )*
160 |
161 | ;
162 |
163 | EqualityOperator :
164 | '==' | '!=' | '===' | '!=='
165 | ;
166 |
167 | // Classification Expressions
168 |
169 | ClassificationExpression returns SysML::Expression :
170 | RelationalExpression
171 | ( {SysML::OperatorExpression.operand += current}
172 | operator = ClassificationTestOperator ownedRelationship += TypeReferenceMember
173 | | {SysML::OperatorExpression.operand += current}
174 | operator = CastOperator ownedRelationship += TypeResultMember
175 | )?
176 | | {SysML::OperatorExpression} operand += SelfReferenceExpression
177 | operator = ClassificationTestOperator ownedRelationship += TypeReferenceMember
178 | | {SysML::OperatorExpression} operand += MetadataReference
179 | operator = MetaClassificationTestOperator ownedRelationship += TypeReferenceMember
180 | | {SysML::OperatorExpression} operand += SelfReferenceExpression
181 | operator = CastOperator ownedRelationship += TypeResultMember
182 | | {SysML::OperatorExpression} operand += MetadataReference
183 | operator = MetaCastOperator ownedRelationship += TypeResultMember
184 | ;
185 |
186 | ClassificationTestOperator :
187 | 'hastype' | 'istype' | '@'
188 | ;
189 |
190 | MetaClassificationTestOperator :
191 | '@@'
192 | ;
193 |
194 | CastOperator :
195 | 'as'
196 | ;
197 |
198 | MetaCastOperator :
199 | 'meta'
200 | ;
201 |
202 | MetadataReference returns SysML::MetadataAccessExpression :
203 | referencedElement = [SysML::Element | QualifiedName]
204 | ;
205 |
206 | TypeReferenceMember returns SysML::FeatureMembership :
207 | ownedRelatedElement += TypeReference
208 | ;
209 |
210 | TypeResultMember returns SysML::ReturnParameterMembership :
211 | ownedRelatedElement += TypeReference
212 | ;
213 |
214 | TypeReference returns SysML::Feature :
215 | ownedRelationship += ReferenceTyping
216 | ;
217 |
218 | ReferenceTyping returns SysML::FeatureTyping :
219 | type = [SysML::Type | QualifiedName]
220 | ;
221 |
222 | SelfReferenceExpression returns SysML::FeatureReferenceExpression :
223 | ownedRelationship += SelfReferenceMember
224 | ;
225 |
226 | SelfReferenceMember returns SysML::ReturnParameterMembership :
227 | ownedRelatedElement += EmptyFeature
228 | ;
229 |
230 | EmptyFeature returns SysML::Feature :
231 | {SysML::Feature}
232 | ;
233 |
234 | // Relational Expressions
235 |
236 | RelationalExpression returns SysML::Expression :
237 | RangeExpression ( {SysML::OperatorExpression.operand += current}
238 | operator = RelationalOperator operand += RangeExpression )*
239 | ;
240 |
241 | RelationalOperator :
242 | '<' | '>' | '<=' | '>='
243 | ;
244 |
245 | // Range Expressions
246 |
247 | RangeExpression returns SysML::Expression :
248 | AdditiveExpression ( {SysML::OperatorExpression.operand += current}
249 | operator = '..' operand += AdditiveExpression )?
250 | ;
251 |
252 | // Arithmetic Expressions
253 |
254 | AdditiveExpression returns SysML::Expression :
255 | MultiplicativeExpression ( {SysML::OperatorExpression.operand += current}
256 | operator = AdditiveOperator operand += MultiplicativeExpression )*
257 | ;
258 |
259 | AdditiveOperator :
260 | '+' | '-'
261 | ;
262 |
263 | MultiplicativeExpression returns SysML::Expression :
264 | ExponentiationExpression ( {SysML::OperatorExpression.operand += current}
265 | operator = MultiplicativeOperator operand += ExponentiationExpression )*
266 | ;
267 |
268 | MultiplicativeOperator :
269 | '*' | '/' | '%'
270 | ;
271 |
272 | ExponentiationExpression returns SysML::Expression :
273 | UnaryExpression ( {SysML::OperatorExpression.operand += current}
274 | operator = ExponentiationOperator operand += UnaryExpression )*
275 | ;
276 |
277 | ExponentiationOperator :
278 | '**' | '^'
279 | ;
280 |
281 | // Unary Expressions
282 |
283 | UnaryExpression returns SysML::Expression:
284 | {SysML::OperatorExpression} operator = UnaryOperator operand += ExtentExpression
285 | | ExtentExpression
286 | ;
287 |
288 | UnaryOperator :
289 | '+' | '-' | '~' | 'not'
290 | ;
291 |
292 | // Extent Expressions
293 |
294 | ExtentExpression returns SysML::Expression :
295 | {SysML::OperatorExpression} operator = 'all' ownedRelationship += TypeResultMember
296 | | PrimaryExpression
297 | ;
298 |
299 | /* Primary Expressions */
300 |
301 | PrimaryExpression returns SysML::Expression :
302 | BaseExpression
303 | ( {SysML::FeatureChainExpression.operand += current} '.'
304 | ownedRelationship += FeatureChainMember
305 | )?
306 | ( ( {SysML::OperatorExpression.operand += current}
307 | operator = '#' '(' operand += SequenceExpression ')'
308 | | {SysML::OperatorExpression.operand += current}
309 | operator = '[' operand += SequenceExpression ']'
310 | | {SysML::OperatorExpression.operand += current} '->'
311 | ownedRelationship += ReferenceTyping
312 | ( operand += BodyExpression
313 | | operand += FunctionReferenceExpression
314 | | ArgumentList
315 | )
316 | | {SysML::CollectExpression.operand += current} '.'
317 | operand += BodyExpression
318 | | {SysML::SelectExpression.operand += current} '.?'
319 | operand += BodyExpression
320 | )
321 | ( {SysML::FeatureChainExpression.operand += current} '.'
322 | ownedRelationship += FeatureChainMember
323 | )?
324 | )*
325 | ;
326 |
327 | FunctionReferenceExpression returns SysML::FeatureReferenceExpression :
328 | ownedRelationship += FunctionReferenceMember
329 | ;
330 |
331 | FunctionReferenceMember returns SysML::FeatureMembership :
332 | ownedRelatedElement += FunctionReference
333 | ;
334 |
335 | FunctionReference returns SysML::Expression :
336 | ownedRelationship += ReferenceTyping
337 | ;
338 |
339 | FeatureChainMember returns SysML::Membership :
340 | memberElement = [SysML::Feature | QualifiedName]
341 | | {SysML::OwningMembership} ownedRelatedElement += OwnedFeatureChain
342 | ;
343 |
344 | /* Base Expressions */
345 |
346 | BaseExpression returns SysML::Expression :
347 | NullExpression
348 | | LiteralExpression
349 | | FeatureReferenceExpression
350 | | MetadataAccessExpression
351 | | InvocationExpression
352 | | BodyExpression
353 | | '(' SequenceExpression ')'
354 | ;
355 |
356 | // Expression Bodies
357 |
358 | BodyExpression returns SysML::FeatureReferenceExpression :
359 | ownedRelationship += ExpressionBodyMember
360 | ;
361 |
362 | ExpressionBodyMember returns SysML::FeatureMembership :
363 | ownedRelatedElement += ExpressionBody
364 | ;
365 |
366 | // This default production is overridden in the KerML and SysML grammars.
367 | ExpressionBody returns SysML::Expression :
368 | '{' ( ownedRelationship += BodyParameterMember ';' )*
369 | ownedRelationship += ResultExpressionMember '}'
370 | ;
371 |
372 | ResultExpressionMember returns SysML::ResultExpressionMembership :
373 | ownedRelatedElement += OwnedExpression
374 | ;
375 |
376 | BodyParameterMember returns SysML::ParameterMembership :
377 | 'in' ownedRelatedElement += BodyParameter
378 | ;
379 |
380 | BodyParameter returns SysML::Feature :
381 | declaredName = Name
382 | ;
383 |
384 | // Sequence Expressions
385 |
386 | SequenceExpression returns SysML::Expression :
387 | OwnedExpression
388 | ( ','
389 | | {SysML::OperatorExpression.operand += current} operator = ','
390 | operand += SequenceExpression
391 | )?
392 | ;
393 |
394 | // Feature Reference Expressions
395 |
396 | FeatureReferenceExpression returns SysML::FeatureReferenceExpression :
397 | ownedRelationship += FeatureReferenceMember
398 | ;
399 |
400 | FeatureReferenceMember returns SysML::Membership :
401 | memberElement = [SysML::Feature | QualifiedName]
402 | ;
403 |
404 | // Metadata Access Expressions
405 |
406 | MetadataAccessExpression returns SysML::MetadataAccessExpression :
407 | referencedElement = [SysML::Element | QualifiedName] '.' 'metadata'
408 | ;
409 |
410 | // Invocation Expressions
411 |
412 | InvocationExpression returns SysML::InvocationExpression :
413 | ownedRelationship += OwnedFeatureTyping ArgumentList
414 | ;
415 |
416 | OwnedFeatureTyping returns SysML::FeatureTyping :
417 | type = [SysML::Type | QualifiedName]
418 | | ownedRelatedElement += OwnedFeatureChain
419 | ;
420 |
421 | OwnedFeatureChain returns SysML::Feature :
422 | FeatureChain
423 | ;
424 |
425 | // For use in KerML and SysML grammars
426 | fragment FeatureChain returns SysML::Feature :
427 | ownedRelationship += OwnedFeatureChaining
428 | ( '.' ownedRelationship += OwnedFeatureChaining )+
429 | ;
430 |
431 | OwnedFeatureChaining returns SysML::FeatureChaining :
432 | chainingFeature = [SysML::Feature | QualifiedName]
433 | ;
434 |
435 | fragment ArgumentList returns SysML::Expression :
436 | '(' ( PositionalArgumentList | NamedArgumentList )? ')'
437 | ;
438 |
439 | fragment PositionalArgumentList returns SysML::Expression :
440 | ownedRelationship += ArgumentMember
441 | ( ',' ownedRelationship += ArgumentMember )*
442 | ;
443 |
444 | ArgumentMember returns SysML::ParameterMembership :
445 | ownedRelatedElement += Argument
446 | ;
447 |
448 | Argument returns SysML::Feature :
449 | ownedRelationship += ArgumentValue
450 | ;
451 |
452 | fragment NamedArgumentList returns SysML::Expression :
453 | ownedRelationship += NamedArgumentMember
454 | ( ',' ownedRelationship += NamedArgumentMember )*
455 | ;
456 |
457 | NamedArgumentMember returns SysML::ParameterMembership :
458 | ownedRelatedElement += NamedArgument
459 | ;
460 |
461 | NamedArgument returns SysML::Feature :
462 | ownedRelationship += ParameterRedefinition '=' ownedRelationship += ArgumentValue
463 | ;
464 |
465 | ParameterRedefinition returns SysML::Redefinition:
466 | redefinedFeature = [SysML::Feature | QualifiedName]
467 | ;
468 |
469 | ArgumentValue returns SysML::FeatureValue :
470 | ownedRelatedElement += OwnedExpression
471 | ;
472 |
473 | // Null Expressions
474 |
475 | NullExpression returns SysML::NullExpression :
476 | {SysML::NullExpression} ( 'null' | '(' ')' )
477 | ;
478 |
479 | /* Literal Expressions */
480 |
481 | LiteralExpression returns SysML::LiteralExpression :
482 | LiteralBoolean
483 | | LiteralString
484 | | LiteralInteger
485 | | LiteralReal
486 | | LiteralInfinity
487 | ;
488 |
489 | LiteralBoolean returns SysML::LiteralBoolean :
490 | value = BooleanValue
491 | ;
492 |
493 | BooleanValue returns Ecore::EBoolean :
494 | 'true' | 'false'
495 | ;
496 |
497 | LiteralString returns SysML::LiteralString :
498 | value = STRING_VALUE
499 | ;
500 |
501 | LiteralInteger returns SysML::LiteralInteger:
502 | value = DECIMAL_VALUE
503 | ;
504 |
505 | LiteralReal returns SysML::LiteralRational:
506 | value = RealValue
507 | ;
508 |
509 | RealValue returns Ecore::EDouble:
510 | DECIMAL_VALUE? '.' ( DECIMAL_VALUE | EXP_VALUE ) | EXP_VALUE
511 | ;
512 |
513 | LiteralInfinity returns SysML::LiteralInfinity :
514 | {SysML::LiteralInfinity} '*'
515 | ;
516 |
517 | /* NAMES */
518 |
519 | Name:
520 | ID | UNRESTRICTED_NAME
521 | ;
522 |
523 | Qualification :
524 | ( Name '::' )+
525 | ;
526 |
527 | QualifiedName:
528 | Qualification? Name
529 | ;
530 |
531 | /* TERMINALS */
532 |
533 | terminal DECIMAL_VALUE returns Ecore::EInt:
534 | '0'..'9' ('0'..'9')*;
535 |
536 | terminal EXP_VALUE:
537 | DECIMAL_VALUE ('e' | 'E') ('+' | '-')? DECIMAL_VALUE;
538 |
539 | terminal ID:
540 | ('a'..'z' | 'A'..'Z' | '_') ('a'..'z' | 'A'..'Z' | '_' | '0'..'9')*;
541 |
542 | terminal UNRESTRICTED_NAME returns Ecore::EString:
543 | '\'' ('\\' ('b' | 't' | 'n' | 'f' | 'r' | '"' | "'" | '\\') | !('\\' | '\''))* '\'';
544 |
545 | terminal STRING_VALUE returns Ecore::EString:
546 | '"' ('\\' ('b' | 't' | 'n' | 'f' | 'r' | '"' | "'" | '\\') | !('\\' | '"'))* '"';
547 |
548 | terminal REGULAR_COMMENT:
549 | '/*' ->'*/';
550 |
551 | terminal ML_NOTE:
552 | '//*'->'*/';
553 |
554 | terminal SL_NOTE:
555 | '//' (!('\n' | '\r') !('\n' | '\r')*)? ('\r'? '\n')?;
556 |
557 | terminal WS:
558 | (' ' | '\t' | '\r' | '\n')+;
--------------------------------------------------------------------------------
/src/sysml2py/textx/xtext_to_textx.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | """
4 | Created on Wed May 24 16:41:15 2023
5 |
6 | @author: christophercox
7 | """
8 | import re
9 |
10 |
11 | def xtext_to_textx(rules):
12 | # Remove grammar
13 | rules = re.sub("grammar .*", "", rules)
14 |
15 | # Remove imports
16 | rules = re.sub("import .*", "", rules)
17 |
18 | # Remove returns
19 | rules = re.sub("returns .*", ":", rules)
20 |
21 | # Remove terminal
22 | rules = re.sub("terminal ", "", rules)
23 |
24 | # Remove fragments
25 | rules = re.sub("fragment", "", rules)
26 | rules = re.sub("enum", "", rules)
27 | rules = re.sub(" ->", "", rules)
28 | rules = re.sub("[\s]?=>", "", rules)
29 | rules = re.sub("@Override", "", rules)
30 |
31 | # Remove SysML object references
32 | rules = re.sub("{SysML::[a-zA-Z]*}", "", rules)
33 | rules = re.sub("{SysML::[a-zA-Z\.\+\=\s]*}", "", rules)
34 |
35 | # Remove more SysML object references
36 | # rules = re.sub('SysML::Membership\|QualifiedName', 'QualifiedName', rules)
37 | # rules = re.sub('SysML::Namespace\|QualifiedName', 'QualifiedName', rules)
38 | # rules = re.sub('SysML::Element\|QualifiedName', 'QualifiedName', rules)
39 | # rules = re.sub('SysML::Feature[\s]?\|[\s]?QualifiedName', 'QualifiedName', rules)
40 | rules = re.sub(
41 | "\[[\s]?SysML::[a-zA-Z]*[\s]?\|[\s]?QualifiedName[\s]?\]",
42 | "[QualifiedName]",
43 | rules,
44 | )
45 | rules = re.sub(
46 | "SysML::ConjugatedPortDefinition | ConjugatedQualifiedName",
47 | "ConjugatedQualifiedName",
48 | rules,
49 | )
50 |
51 | # Fix doubles
52 | rules = re.sub("\[QualifiedName | QualifiedName\]", "[QualifiedName]", rules)
53 | rules = re.sub("\[QualifiedName\|QualifiedName\]", "[QualifiedName]", rules)
54 |
55 | # Special cases
56 | good_str = r"""
57 | MultiplicityRelatedElement :
58 | (LiteralExpression | FeatureReferenceExpression)
59 | ;
60 |
61 | MultiplicityExpressionMember :
62 | ownedRelatedElement += MultiplicityRelatedElement
63 | ;"""
64 |
65 | rules = re.sub("MultiplicityExpressionMember :[\s\S]*?;", good_str, rules)
66 |
67 | good_str = r"""
68 | ActionBodyItemTarget :
69 | ( BehaviorUsageMember | ActionNodeMember )
70 | ;
71 |
72 | ActionBodyItem :
73 | ownedRelationship += Import
74 | | ownedRelationship += AliasMember
75 | | ownedRelationship += DefinitionMember
76 | | ownedRelationship += VariantUsageMember
77 | | ownedRelationship += NonOccurrenceUsageMember
78 | | ( ownedRelationship += EmptySuccessionMember )?
79 | ownedRelationship += StructureUsageMember
80 | | ownedRelationship += InitialNodeMember
81 | ( ownedRelationship += TargetSuccessionMember )*
82 | | ( ownedRelationship += EmptySuccessionMember )?
83 | ownedRelationship += ActionBodyItemTarget
84 | ( ownedRelationship += TargetSuccessionMember )*
85 | | ownedRelationship += GuardedSuccessionMember
86 | ;
87 | """
88 | rules = re.sub("ActionBodyItem :[\s\S]*?;", good_str, rules)
89 |
90 | good_str = r"""
91 | IfNodeElseMember :
92 | ( ActionBodyParameterMember | IfNodeParameterMember )
93 | ;
94 |
95 | IfNode :
96 | ActionNodePrefix
97 | 'if' ownedRelationship += ExpressionParameterMember
98 | ownedRelationship += ActionBodyParameterMember
99 | ( 'else' ownedRelationship += IfNodeElseMember )?
100 | ;
101 | """
102 | rules = re.sub("IfNode :[\s\S]*?;", good_str, rules)
103 |
104 | good_str = r"""
105 | ( isOrdered ?= 'ordered' isNonunique ?= 'nonunique'
106 | | isNonunique2 ?= 'nonunique' isOrdered2 ?= 'ordered'
107 | )
108 | """
109 | rules = re.sub("\( isOrdered[a-zA-Z0-9\?\=\s'\|]*\)", good_str, rules)
110 |
111 | # These are totally broken
112 | empty_rule = "LifeClass"
113 | rules = re.sub(
114 | empty_rule + " :[\s\S]*?;",
115 | empty_rule + " ://This doesn't work.\n\t'" + empty_rule.lower() + "'\n;",
116 | rules,
117 | )
118 | empty_rule = "EmptyTargetEnd"
119 | rules = re.sub(
120 | empty_rule + " :[\s\S]*?;",
121 | empty_rule + " ://This doesn't work.\n\t'" + empty_rule.lower() + "'\n;",
122 | rules,
123 | )
124 | empty_rule = "PortConjugation"
125 | rules = re.sub(
126 | empty_rule + " :[\s\S]*?;",
127 | empty_rule + " ://This doesn't work.\n\t'" + empty_rule.lower() + "'\n;",
128 | rules,
129 | )
130 | empty_rule = "EmptySourceEnd"
131 | rules = re.sub(
132 | empty_rule + " :[\s\S]*?;",
133 | empty_rule + " ://This doesn't work.\n\t'" + empty_rule.lower() + "'\n;",
134 | rules,
135 | )
136 | empty_rule = "EmptyUsage"
137 | rules = re.sub(
138 | empty_rule + " :[\s\S]*?;",
139 | empty_rule + " ://This doesn't work.\n\t'" + empty_rule.lower() + "'\n;",
140 | rules,
141 | )
142 | empty_rule = "EmptyActionUsage"
143 | rules = re.sub(
144 | empty_rule + " :[\s\S]*?;",
145 | empty_rule + " ://This doesn't work.\n\t'" + empty_rule.lower() + "'\n;",
146 | rules,
147 | )
148 | empty_rule = "EmptyFeature"
149 | rules = re.sub(
150 | empty_rule + " :[\s\S]*?;",
151 | empty_rule + " ://This doesn't work.\n\t'" + empty_rule.lower() + "'\n;",
152 | rules,
153 | )
154 |
155 | # Base rules
156 | rules = re.sub(
157 | "DECIMAL_VALUE[\s]:[\s0-9\(\)'\*\.]*;", "DECIMAL_VALUE :\n /[0-9]*/;", rules
158 | )
159 | rules = re.sub(
160 | "ID[\s]?:[\sa-zA-Z0-9_'|().*]*;", "ID :\n /[a-zA-Z_][a-zA-Z_0-9]*/;", rules
161 | )
162 | # rules = re.sub("UNRESTRICTED_NAME[ ]?:[\sbtnfr\"!\\_'|().*]*;",
163 | # "UNRESTRICTED_NAME: \n /'\'' ('\\' ('b' | 't' | 'n' | 'f' | 'r' | '"' | "'" | '\\') | !('\\' | '\''))* '\''/;", rules)
164 |
165 | final_rules = """;
166 |
167 | ID :
168 | /[a-zA-Z_][a-zA-Z_0-9]*/;
169 |
170 | UNRESTRICTED_NAME :
171 | /'\'' ('\\' ('b' | 't' | 'n' | 'f' | 'r' | '"' | "'" | '\\') | !('\\' | '\''))* '\''/;
172 |
173 | STRING_VALUE :
174 | /'"' ('\\' ('b' | 't' | 'n' | 'f' | 'r' | '"' | "'" | '\\') | !('\\' | '"'))* '"'/;
175 |
176 | REGULAR_COMMENT:
177 | '/*''*/';
178 |
179 | ML_NOTE:
180 | /'\/*'->'*\/'/;
181 |
182 | SL_NOTE:
183 | /'\/\/' (!('\n' | '\r') !('\n' | '\r')*)? ('\r'? '\n')?/;
184 |
185 | WS:
186 | /(' ' | '\t' | '\r' | '\n')+/;
187 | """
188 | rules = re.sub(";[\s]*ID[\s\S]*;", final_rules, rules)
189 | return rules
190 |
191 |
192 | if __name__ == "__main__":
193 | with open("SysML.xtext", "r") as f:
194 | rules = f.read()
195 | f.close()
196 |
197 | rules = xtext_to_textx(rules)
198 |
199 | with open("SysML.tx", "w") as f:
200 | f.write("import KerML\nimport KerMLExpressions\n" + rules)
201 | f.close()
202 |
203 | with open("KerML.xtext", "r") as f:
204 | rules = f.read()
205 | f.close()
206 |
207 | rules = xtext_to_textx(rules)
208 |
209 | with open("KerML.tx", "w") as f:
210 | f.write("import KerMLExpressions\n" + rules)
211 | f.close()
212 |
213 | with open("KerMLExpressions.xtext", "r") as f:
214 | rules = f.read()
215 | f.close()
216 |
217 | rules = xtext_to_textx(rules)
218 |
219 | with open("KerMLExpressions.tx", "w") as f:
220 | f.write(rules)
221 | f.close()
222 |
--------------------------------------------------------------------------------
/src/sysml2py/usage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | """
4 | Created on Fri Jun 30 23:23:31 2023
5 |
6 | @author: christophercox
7 | """
8 |
9 |
10 | # import os
11 |
12 | # os.chdir(os.path.join(os.path.dirname(os.path.abspath(__file__)), ".."))
13 |
14 | import uuid as uuidlib
15 |
16 | import astropy.units as u
17 |
18 | from sysml2py.formatting import classtree
19 |
20 | from sysml2py.grammar.classes import (
21 | Identification,
22 | DefinitionBody,
23 | DefinitionBodyItem,
24 | FeatureSpecializationPart,
25 | )
26 |
27 | from sysml2py.grammar.classes import (
28 | AttributeUsage,
29 | AttributeDefinition,
30 | ValuePart,
31 | PartUsage,
32 | PartDefinition,
33 | ItemUsage,
34 | ItemDefinition,
35 | PortUsage,
36 | PortDefinition,
37 | DefaultReferenceUsage,
38 | RefPrefix,
39 | )
40 |
41 |
42 | class Usage:
43 | def __init__(self):
44 | self.name = str(uuidlib.uuid4())
45 | self.children = []
46 | self.typedby = None
47 | return self
48 |
49 | def _ensure_body(self, subgrammar="usage"):
50 | # Add children
51 | body = []
52 | for abc in self.children:
53 | body.append(
54 | DefinitionBodyItem(
55 | abc._get_definition(child="DefinitionBody")
56 | ).get_definition()
57 | )
58 |
59 | if len(body) > 0:
60 | getattr(self.grammar, subgrammar).completion.body.body = DefinitionBody(
61 | {"name": "DefinitionBody", "ownedRelatedElement": body}
62 | )
63 | return self
64 |
65 | def usage_dump(self, child):
66 | # This is a usage.
67 |
68 | self._ensure_body("usage")
69 |
70 | # Add packaging
71 | package = {
72 | "name": "StructureUsageElement",
73 | "ownedRelatedElement": self.grammar.get_definition(),
74 | }
75 | package = {"name": "OccurrenceUsageElement", "ownedRelatedElement": package}
76 |
77 | if child == "DefinitionBody":
78 | package = {
79 | "name": "OccurrenceUsageMember",
80 | "prefix": None,
81 | "ownedRelatedElement": [package],
82 | }
83 |
84 | package = {"name": "DefinitionBodyItem", "ownedRelationship": [package]}
85 | elif "PackageBody":
86 | package = {"name": "UsageElement", "ownedRelatedElement": package}
87 | package = {
88 | "name": "PackageMember",
89 | "ownedRelatedElement": package,
90 | "prefix": None,
91 | }
92 |
93 | return package
94 |
95 | def definition_dump(self, child):
96 | # This is a definition.
97 |
98 | self._ensure_body("definition")
99 |
100 | package = {
101 | "name": "DefinitionElement",
102 | "ownedRelatedElement": self.grammar.get_definition(),
103 | }
104 |
105 | if child == "DefinitionBody":
106 | package = {
107 | "name": "DefinitionMember",
108 | "prefix": None,
109 | "ownedRelatedElement": [package],
110 | }
111 |
112 | package = {"name": "DefinitionBodyItem", "ownedRelationship": [package]}
113 |
114 | elif child == "PackageBody" or child == None:
115 | # Add these packets to make this dump without parents
116 |
117 | package = {
118 | "name": "PackageMember",
119 | "ownedRelatedElement": package,
120 | "prefix": None,
121 | }
122 |
123 | return package
124 |
125 | def _get_definition(self, child=None):
126 | if "usage" in self.grammar.__dict__:
127 | package = self.usage_dump(child)
128 | else:
129 | package = self.definition_dump(child)
130 |
131 | if child is None:
132 | package = {
133 | "name": "PackageBodyElement",
134 | "ownedRelationship": [package],
135 | "prefix": None,
136 | }
137 |
138 | # Add the typed by definition to the package output
139 | if self.typedby is not None:
140 | if child is None:
141 | package["ownedRelationship"].insert(
142 | 0, self.typedby._get_definition(child="PackageBody")
143 | )
144 | elif child == "PackageBody":
145 | package = [self.typedby._get_definition(child="PackageBody"), package]
146 | else:
147 | package["ownedRelationship"].insert(
148 | 0, self.typedby._get_definition(child=child)["ownedRelationship"][0]
149 | )
150 |
151 | return package
152 |
153 | def dump(self, child=None):
154 | return classtree(self._get_definition(child)).dump()
155 |
156 | def _set_name(self, name, short=False):
157 | if hasattr(self.grammar, "usage"):
158 | path = self.grammar.usage.declaration.declaration
159 | elif hasattr(self.grammar, "definition"):
160 | path = self.grammar.definition.declaration
161 | else:
162 | if hasattr(self.grammar.declaration, "declaration"):
163 | path = self.grammar.declaration.declaration
164 | else:
165 | path = self.grammar.declaration
166 |
167 | if path.identification is None:
168 | path.identification = Identification()
169 |
170 | if short:
171 | path.identification.declaredShortName = "<" + name + ">"
172 | else:
173 | self.name = name
174 | path.identification.declaredName = name
175 |
176 | return self
177 |
178 | def _get_name(self):
179 | return self.grammar.usage.declaration.declaration.identification.declaredName
180 |
181 | def _set_child(self, child):
182 | self.children.append(child)
183 | return self
184 |
185 | def _get_child(self, featurechain):
186 | # 'x.y.z'
187 | if isinstance(featurechain, str):
188 | fc = featurechain.split(".")
189 | else:
190 | raise TypeError
191 |
192 | if fc[0] == self.name:
193 | # This first one must match self name, otherwise pass it all
194 | featurechain = ".".join(fc[1:])
195 |
196 | for child in self.children:
197 | fcs = featurechain.split(".")
198 | if child.name == fcs[0]:
199 | if len(fcs) == 1:
200 | return child
201 | else:
202 | return child._get_child(featurechain)
203 |
204 | def _set_typed_by(self, typed):
205 | # Only set if the pointed object is a definition
206 | if "definition" in typed.grammar.__dict__:
207 | self.typedby = typed
208 | if "definition" in self.grammar.__dict__:
209 | raise ValueError("A definition element cannot be defined.")
210 | else:
211 | if self.grammar.usage.declaration.declaration.specialization is None:
212 | package = {
213 | "name": "QualifiedName",
214 | "names": [typed.name],
215 | }
216 | package = {
217 | "name": "FeatureType",
218 | "type": package,
219 | "ownedRelatedElement": [],
220 | }
221 | package = {"name": "OwnedFeatureTyping", "type": package}
222 | package = {"name": "FeatureTyping", "ownedRelationship": package}
223 | package = {"name": "TypedBy", "ownedRelationship": [package]}
224 | package = {
225 | "name": "Typings",
226 | "typedby": package,
227 | "ownedRelationship": [],
228 | }
229 | package = {
230 | "name": "FeatureSpecialization",
231 | "ownedRelationship": package,
232 | }
233 | package = {
234 | "name": "FeatureSpecializationPart",
235 | "specialization": [package],
236 | "multiplicity": None,
237 | "specialization2": [],
238 | "multiplicity2": None,
239 | }
240 | self.grammar.usage.declaration.declaration.specialization = (
241 | FeatureSpecializationPart(package)
242 | )
243 | else:
244 | raise ValueError("Typed by element was not a definition.")
245 | return self
246 |
247 | def _get_grammar(self):
248 | self._ensure_body()
249 | return self.grammar
250 |
251 | def load_from_grammar(self, grammar):
252 | #!TODO Typed By
253 | self.__init__()
254 | self.grammar = grammar
255 | children = []
256 | if "usage" in self.grammar.__dict__:
257 | # This is a usage
258 | u_name = grammar.usage.declaration.declaration.identification.declaredName
259 | a_children = grammar.usage.completion.body.body.children
260 |
261 | for child in a_children:
262 | children.append(child.children[0].children[0])
263 | else:
264 | # This is a definition
265 | u_name = grammar.definition.declaration.identification.declaredName
266 | a_children = grammar.definition.body.children
267 | if len(a_children) > 0:
268 | children = a_children[0]
269 |
270 | if u_name is not None:
271 | self.name = u_name
272 |
273 | for child in children:
274 | sc = child.children
275 | if isinstance(sc, list):
276 | if len(sc) == 1:
277 | sc = sc[0]
278 |
279 | if sc.__class__.__name__ == "AttributeUsage":
280 | self.children.append(Attribute().load_from_grammar(sc))
281 | elif sc.__class__.__name__ == "ItemDefinition":
282 | self.children.append(Item().load_from_grammar(sc))
283 | elif sc.__class__.__name__ == "StructureUsageElement":
284 | if sc.children.__class__.__name__ == "PartUsage":
285 | self.children.append(Part().load_from_grammar(sc.children))
286 | elif sc.children.__class__.__name__ == "ItemUsage":
287 | self.children.append(Item().load_from_grammar(sc.children))
288 | else:
289 | print(child.children.children.__class__.__name__)
290 | raise NotImplementedError
291 | else:
292 | print(sc.__class__.__name__)
293 | raise NotImplementedError
294 |
295 | return self
296 |
297 | def add_directed_feature(self, direction, name=str(uuidlib.uuid4())):
298 | self._set_child(DefaultReference()._set_name(name).set_direction(direction))
299 | return self
300 |
301 | # def modify_directed_feature(self, direction, name):
302 | # child = self._get_child(name)
303 | # if child is not None:
304 | # pass
305 | # else:
306 | # raise AttributeError("Invalid Feature Name or Chain")
307 |
308 |
309 | class Attribute(Usage):
310 | def __init__(self, definition=False, name=None):
311 | Usage.__init__(self)
312 |
313 | if definition:
314 | self.grammar = AttributeDefinition()
315 | else:
316 | self.grammar = AttributeUsage()
317 |
318 | def usage_dump(self, child):
319 | # Override - base output
320 |
321 | # Add children
322 | body = []
323 | for abc in self.children:
324 | body.append(DefinitionBodyItem(abc.dump(child=True)).get_definition())
325 | if len(body) > 0:
326 | self.grammar.usage.completion.body.body = DefinitionBody(
327 | {"name": "DefinitionBody", "ownedRelatedElement": body}
328 | )
329 |
330 | # Add packaging
331 | package = {
332 | "name": "NonOccurrenceUsageElement",
333 | "ownedRelatedElement": self.grammar.get_definition(),
334 | }
335 |
336 | if child:
337 | package = {
338 | "name": "NonOccurrenceUsageMember",
339 | "prefix": None,
340 | "ownedRelatedElement": [package],
341 | }
342 | package = {"name": "DefinitionBodyItem", "ownedRelationship": [package]}
343 | else:
344 | # Add these packets to make this dump without parents
345 | package = {"name": "UsageElement", "ownedRelatedElement": package}
346 | package = {
347 | "name": "PackageMember",
348 | "ownedRelatedElement": package,
349 | "prefix": None,
350 | }
351 | return package
352 |
353 | def set_value(self, value):
354 | if not isinstance(value, u.quantity.Quantity):
355 | value = value * u.one
356 | if isinstance(value, u.quantity.Quantity):
357 | if str(value.unit) != "":
358 | package_units = {
359 | "name": "QualifiedName",
360 | "names": [str(value.unit)],
361 | }
362 | package_units = {
363 | "name": "FeatureReferenceMember",
364 | "memberElement": package_units,
365 | }
366 | package_units = {
367 | "name": "FeatureReferenceExpression",
368 | "ownedRelationship": [package_units],
369 | }
370 | package_units = {
371 | "name": "BaseExpression",
372 | "ownedRelationship": package_units,
373 | }
374 | package_units = {
375 | "name": "PrimaryExpression",
376 | "operand": [],
377 | "base": package_units,
378 | "operator": [],
379 | "ownedRelationship1": [],
380 | "ownedRelationship2": [],
381 | }
382 | package_units = {
383 | "name": "ExtentExpression",
384 | "operator": "",
385 | "ownedRelationship": [],
386 | "primary": package_units,
387 | }
388 | package_units = {
389 | "name": "UnaryExpression",
390 | "operand": [],
391 | "operator": None,
392 | "extent": package_units,
393 | }
394 | package_units = {
395 | "name": "ExponentiationExpression",
396 | "operand": [],
397 | "operator": [],
398 | "unary": package_units,
399 | }
400 | package_units = {
401 | "name": "MultiplicativeExpression",
402 | "operation": [],
403 | "exponential": package_units,
404 | }
405 | package_units = {
406 | "name": "AdditiveExpression",
407 | "operation": [],
408 | "multiplicitive": package_units,
409 | }
410 | package_units = {
411 | "name": "RangeExpression",
412 | "operand": None,
413 | "additive": package_units,
414 | }
415 | package_units = {
416 | "name": "RelationalExpression",
417 | "operation": [],
418 | "range": package_units,
419 | }
420 | package_units = {
421 | "name": "ClassificationExpression",
422 | "operand": [],
423 | "operator": None,
424 | "ownedRelationship": [],
425 | "relational": package_units,
426 | }
427 | package_units = {
428 | "name": "EqualityExpression",
429 | "operation": [],
430 | "classification": package_units,
431 | }
432 | package_units = {
433 | "name": "AndExpression",
434 | "operation": [],
435 | "equality": package_units,
436 | }
437 | package_units = {
438 | "name": "XorExpression",
439 | "operand": [],
440 | "operator": [],
441 | "and": package_units,
442 | }
443 | package_units = {
444 | "name": "OrExpression",
445 | "xor": package_units,
446 | "operand": [],
447 | "operator": [],
448 | }
449 | package_units = {
450 | "name": "ImpliesExpression",
451 | "operand": [],
452 | "operator": [],
453 | "or": package_units,
454 | }
455 | package_units = {
456 | "name": "NullCoalescingExpression",
457 | "implies": package_units,
458 | "operator": [],
459 | "operand": [],
460 | }
461 | package_units = {
462 | "name": "ConditionalExpression",
463 | "operator": None,
464 | "operand": [package_units],
465 | }
466 | package_units = {"name": "OwnedExpression", "expression": package_units}
467 | package_units = {
468 | "name": "SequenceExpression",
469 | "operation": [],
470 | "ownedRelationship": package_units,
471 | }
472 | package_units = [package_units]
473 | operator = ["["]
474 | else:
475 | package_units = []
476 | operator = []
477 |
478 | package = {
479 | "name": "BaseExpression",
480 | "ownedRelationship": {
481 | "name": "LiteralInteger",
482 | "value": str(value.value),
483 | },
484 | }
485 | package = {
486 | "name": "PrimaryExpression",
487 | "operand": package_units,
488 | "base": package,
489 | "operator": operator,
490 | "ownedRelationship1": [],
491 | "ownedRelationship2": [],
492 | }
493 | package = {
494 | "name": "ExtentExpression",
495 | "operator": "",
496 | "ownedRelationship": [],
497 | "primary": package,
498 | }
499 | package = {
500 | "name": "UnaryExpression",
501 | "operand": [],
502 | "operator": None,
503 | "extent": package,
504 | }
505 | package = {
506 | "name": "ExponentiationExpression",
507 | "operand": [],
508 | "operator": [],
509 | "unary": package,
510 | }
511 | package = {
512 | "name": "MultiplicativeExpression",
513 | "operation": [],
514 | "exponential": package,
515 | }
516 | package = {
517 | "name": "AdditiveExpression",
518 | "operation": [],
519 | "multiplicitive": package,
520 | }
521 | package = {
522 | "name": "RangeExpression",
523 | "operand": None,
524 | "additive": package,
525 | }
526 | package = {
527 | "name": "RelationalExpression",
528 | "operation": [],
529 | "range": package,
530 | }
531 | package = {
532 | "name": "ClassificationExpression",
533 | "operand": [],
534 | "operator": None,
535 | "ownedRelationship": [],
536 | "relational": package,
537 | }
538 | package = {
539 | "name": "EqualityExpression",
540 | "operation": [],
541 | "classification": package,
542 | }
543 | package = {
544 | "name": "AndExpression",
545 | "operation": [],
546 | "equality": package,
547 | }
548 | package = {
549 | "name": "XorExpression",
550 | "operand": [],
551 | "operator": [],
552 | "and": package,
553 | }
554 | package = {
555 | "name": "OrExpression",
556 | "xor": package,
557 | "operand": [],
558 | "operator": [],
559 | }
560 | package = {
561 | "name": "ImpliesExpression",
562 | "operand": [],
563 | "operator": [],
564 | "or": package,
565 | }
566 | package = {
567 | "name": "NullCoalescingExpression",
568 | "implies": package,
569 | "operator": [],
570 | "operand": [],
571 | }
572 | package = {
573 | "name": "ConditionalExpression",
574 | "operator": None,
575 | "operand": [package],
576 | }
577 | package = {"name": "OwnedExpression", "expression": package}
578 | package = {
579 | "name": "FeatureValue",
580 | "isDefault": False,
581 | "isEqual": False,
582 | "isInitial": False,
583 | "ownedRelatedElement": package,
584 | }
585 | package = {"name": "ValuePart", "ownedRelationship": [package]}
586 | self.grammar.usage.completion.valuepart = ValuePart(package)
587 | # value.unit
588 |
589 | return self
590 |
591 | def get_value(self):
592 | realpart = (
593 | self.grammar.usage.completion.valuepart.relationships[0]
594 | .element.expression.operands[0]
595 | .implies.orexpression.xor.andexpression.equality.classification.relational.range.additive.left_hand.exponential.unary.extent.primary
596 | )
597 | real = float(realpart.base.relationship.dump())
598 | unit = (
599 | realpart.operand[0]
600 | .relationship.expression.operands[0]
601 | .implies.orexpression.xor.andexpression.equality.classification.relational.range.additive.left_hand.exponential.unary.extent.primary.base.relationship.children[
602 | 0
603 | ]
604 | .memberElement.dump()
605 | )
606 | return real * u.Unit(unit)
607 |
608 |
609 | class Part(Usage):
610 | def __init__(self, definition=False, name=None):
611 | Usage.__init__(self)
612 | if definition:
613 | self.grammar = PartDefinition()
614 | else:
615 | self.grammar = PartUsage()
616 |
617 |
618 | class Item(Usage):
619 | def __init__(self, definition=False, name=None):
620 | Usage.__init__(self)
621 | if definition:
622 | self.grammar = ItemDefinition()
623 | else:
624 | self.grammar = ItemUsage()
625 |
626 |
627 | class Port(Usage):
628 | def __init__(self, definition=False, name=None):
629 | Usage.__init__(self)
630 | if definition:
631 | self.grammar = PortDefinition()
632 | else:
633 | self.grammar = PortUsage()
634 |
635 |
636 | class DefaultReference(Usage):
637 | def __init__(self):
638 | Usage.__init__(self)
639 | self.grammar = DefaultReferenceUsage()
640 |
641 | def set_direction(self, direction):
642 | r = RefPrefix()
643 | if direction == "in":
644 | r.direction.isIn = True
645 | elif direction == "out":
646 | r.direction.isOut = True
647 | elif direction == "inout":
648 | r.direction.isInOut = True
649 | else:
650 | raise ValueError
651 | self.grammar.prefix = r
652 | return self
653 |
654 | def usage_dump(self, child):
655 | # This is a usage.
656 |
657 | self._ensure_body("definition")
658 |
659 | # Add packaging
660 | package = {
661 | "name": "NonOccurrenceUsageElement",
662 | "ownedRelatedElement": self.grammar.get_definition(),
663 | }
664 |
665 | if child == "DefinitionBody":
666 | package = {
667 | "name": "NonOccurrenceUsageMember",
668 | "prefix": None,
669 | "ownedRelatedElement": [package],
670 | }
671 |
672 | package = {"name": "DefinitionBodyItem", "ownedRelationship": [package]}
673 | elif "PackageBody":
674 | package = {"name": "UsageElement", "ownedRelatedElement": package}
675 | package = {
676 | "name": "PackageMember",
677 | "ownedRelatedElement": package,
678 | "prefix": None,
679 | }
680 |
681 | return package
682 |
683 | def _get_definition(self, child=None):
684 | package = self.usage_dump(child)
685 |
686 | if child is None:
687 | package = {
688 | "name": "PackageBodyElement",
689 | "ownedRelationship": [package],
690 | "prefix": None,
691 | }
692 |
693 | # Add the typed by definition to the package output
694 | if self.typedby is not None:
695 | if child is None:
696 | package["ownedRelationship"].insert(
697 | 0, self.typedby._get_definition(child="PackageBody")
698 | )
699 | elif child == "PackageBody":
700 | package = [self.typedby._get_definition(child="PackageBody"), package]
701 | else:
702 | package["ownedRelationship"].insert(
703 | 0, self.typedby._get_definition(child=child)["ownedRelationship"][0]
704 | )
705 |
706 | return package
707 |
708 | # def dump(self, child=None):
709 | # package = self.usage_dump(child)
710 |
711 | # if child is None:
712 | # package = {
713 | # "name": "PackageBodyElement",
714 | # "ownedRelationship": [package],
715 | # "prefix": None,
716 | # }
717 |
718 | # # Add the typed by definition to the package output
719 | # if self.typedby is not None:
720 | # if child is None:
721 | # package["ownedRelationship"].insert(
722 | # 0, self.typedby.dump(child="PackageBody")
723 | # )
724 | # elif child == "PackageBody":
725 | # package = [self.typedby.dump(child="PackageBody"), package]
726 | # else:
727 | # package["ownedRelationship"].insert(
728 | # 0, self.typedby.dump(child=child)["ownedRelationship"][0]
729 | # )
730 |
731 | # return package
732 |
--------------------------------------------------------------------------------
/tests/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Westfall-io/sysml2py/b1e59714c239394cacd8542e8b4ae343aa15e843/tests/.DS_Store
--------------------------------------------------------------------------------
/tests/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Westfall-io/sysml2py/b1e59714c239394cacd8542e8b4ae343aa15e843/tests/__init__.py
--------------------------------------------------------------------------------
/tests/class_test.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | """
4 | Created on Tue Jul 11 16:46:28 2023
5 |
6 | @author: christophercox
7 | """
8 |
9 | import pytest
10 |
11 | from sysml2py.formatting import classtree
12 | from sysml2py import Package, Item, Model, Attribute, Part, Port
13 | from sysml2py import load_grammar as loads
14 |
15 |
16 | def test_package():
17 | p = classtree(Package()._get_definition()).dump()
18 |
19 | text = """package ;"""
20 | q = classtree(loads(text)).dump()
21 |
22 | assert p == q
23 |
24 |
25 | def test_package_name():
26 | name = "Rocket"
27 | p = classtree(Package()._set_name(name)._get_definition()).dump()
28 |
29 | text = "package " + name + ";"
30 | q = classtree(loads(text)).dump()
31 |
32 | assert p == q
33 |
34 |
35 | def test_package_shortname():
36 | name = "'3.1'"
37 | p = classtree(Package()._set_name(name, short=True)._get_definition()).dump()
38 |
39 | text = "package <" + name + ">;"
40 | q = classtree(loads(text)).dump()
41 |
42 | assert p == q
43 |
44 |
45 | def test_package_setbothnames():
46 | name = "Rocket"
47 | shortname = "'3.1'"
48 | p = classtree(
49 | Package()._set_name(name)._set_name(shortname, short=True)._get_definition()
50 | ).dump()
51 |
52 | text = "package <" + shortname + "> " + name + ";"
53 | q = classtree(loads(text)).dump()
54 |
55 | assert p == q
56 |
57 |
58 | def test_package_getname():
59 | name = "Rocket"
60 | p = Package()._set_name(name)
61 | assert p._get_name() == name
62 |
63 |
64 | def test_package_addchild():
65 | p1 = Package()._set_name("Rocket")
66 | p2 = Package()._set_name("Engine")
67 | p1._set_child(p2)
68 | p = classtree(p1._get_definition()).dump()
69 |
70 | text = """package Rocket {
71 | package Engine;
72 | }"""
73 |
74 | q = classtree(loads(text)).dump()
75 |
76 | assert p == q
77 |
78 |
79 | def test_package_get_child():
80 | p1 = Package()._set_name("Rocket")
81 | p2 = Package()._set_name("Engine")
82 | p1._set_child(p2)
83 | p = classtree(p1._get_child("Rocket.Engine")._get_definition()).dump()
84 |
85 | text = """package Engine;"""
86 |
87 | q = classtree(loads(text)).dump()
88 |
89 | assert p == q
90 |
91 |
92 | def test_package_get_child_method2():
93 | p1 = Package()._set_name("Rocket")
94 | p2 = Package()._set_name("Engine")
95 | p1._set_child(p2)
96 | p = classtree(p1._get_child("Engine")._get_definition()).dump()
97 |
98 | text = """package Engine;"""
99 |
100 | q = classtree(loads(text)).dump()
101 |
102 | assert p == q
103 |
104 |
105 | def test_package_typed_child():
106 | p1 = Package()._set_name("Rocket")
107 | i1 = Item(definition=True)._set_name("Fuel")
108 | i2 = Item()._set_name("Hydrogen")
109 | p1._set_child(i2)
110 | i2._set_typed_by(i1)
111 | p = classtree(p1._get_definition()).dump()
112 |
113 | text = """package Rocket {
114 | item def Fuel ;
115 | item Hydrogen : Fuel;
116 | }"""
117 |
118 | q = classtree(loads(text)).dump()
119 |
120 | assert p == q
121 |
122 |
123 | def test_package_load_grammar():
124 | p = Package()
125 |
126 | text = """package Rocket {
127 | item def Fuel ;
128 | item Hydrogen : Fuel;
129 | }"""
130 | q = Model().load(text)
131 | p.load_from_grammar(q._get_child("Rocket")._get_grammar())
132 |
133 | assert p.dump() == q.dump()
134 |
135 |
136 | def test_model_cannot_dump_error():
137 | m = Model()
138 | with pytest.raises(ValueError, match="Base Model has no elements."):
139 | m.dump()
140 |
141 |
142 | def test_model_load_error_not_package_def():
143 | text = """item def Fuel ;"""
144 | with pytest.raises(
145 | ValueError, match="Base Model must be encapsulated by a package."
146 | ):
147 | Model().load(text)
148 |
149 |
150 | def test_model_load_error_not_package_usage():
151 | text = """item Fuel ;"""
152 | with pytest.raises(
153 | ValueError, match="Base Model must be encapsulated by a package."
154 | ):
155 | Model().load(text)
156 |
157 |
158 | def test_model_add_child():
159 | m = Model()
160 | p1 = Package()._set_name("Rocket")
161 | p2 = Package()._set_name("Payload")
162 | m._set_child(p1)
163 | m._set_child(p2)
164 |
165 | text = """package Rocket;
166 | package Payload;"""
167 | q = classtree(loads(text))
168 | assert m.dump() == q.dump()
169 |
170 |
171 | def test_model_get_child():
172 | m = Model()
173 | p1 = Package()._set_name("Rocket")
174 | p2 = Package()._set_name("Payload")
175 | m._set_child(p1)
176 | m._set_child(p2)
177 | m2 = m._get_child("Rocket")
178 |
179 | text = """package Rocket;"""
180 | q = classtree(loads(text))
181 | assert m2.dump() == q.dump()
182 |
183 |
184 | def test_model_load():
185 | p1 = Package()._set_name("Rocket")
186 | i1 = Item(definition=True)._set_name("Fuel")
187 | i2 = Item()._set_name("Hydrogen")
188 | p1._set_child(i2)
189 | i2._set_typed_by(i1)
190 | p = classtree(p1._get_definition())
191 |
192 | text = """package Rocket {
193 | item def Fuel ;
194 | item Hydrogen : Fuel;
195 | }"""
196 |
197 | q = Model().load(text)
198 |
199 | assert p.dump() == q.dump()
200 |
201 |
202 | def test_item():
203 | i1 = Item()
204 | text = """item;"""
205 | i2 = classtree(loads(text))
206 |
207 | assert i1.dump() == i2.dump()
208 |
209 |
210 | def test_item_def():
211 | i1 = Item(definition=True)
212 | text = """item def;"""
213 | i2 = classtree(loads(text))
214 |
215 | assert i1.dump() == i2.dump()
216 |
217 |
218 | def test_item_name():
219 | i1 = Item()._set_name("Fuel")
220 | text = """item Fuel;"""
221 | i2 = classtree(loads(text))
222 |
223 | assert i1.dump() == i2.dump()
224 |
225 |
226 | def test_item_shortname():
227 | i1 = Item()._set_name("'3.1'", short=True)
228 | text = """item <'3.1'>;"""
229 | i2 = classtree(loads(text))
230 |
231 | assert i1.dump() == i2.dump()
232 |
233 |
234 | def test_item_getname():
235 | name = "Fuel"
236 | i1 = Item()._set_name(name)
237 |
238 | assert i1._get_name() == name
239 |
240 |
241 | def test_item_setchild():
242 | i1 = Item()._set_name("Fuel")
243 | ic1 = Item()
244 | i1._set_child(ic1)
245 | text = """item Fuel {
246 | item;
247 | }"""
248 | i2 = classtree(loads(text))
249 |
250 | assert i1.dump() == i2.dump()
251 |
252 |
253 | def test_item_getchild():
254 | i1 = Item()._set_name("Fuel")
255 | ic1 = Item()._set_name("Fuel_child")
256 | i1._set_child(ic1)
257 | text = """item Fuel_child;"""
258 | i2 = classtree(loads(text))
259 |
260 | assert i1._get_child("Fuel.Fuel_child").dump() == i2.dump()
261 |
262 |
263 | def test_item_getchild_skipelement():
264 | i1 = Item()._set_name("Fuel")
265 | ic1 = Item()._set_name("Fuel_child")
266 | i1._set_child(ic1)
267 | text = """item Fuel_child;"""
268 | i2 = classtree(loads(text))
269 |
270 | assert i1._get_child("Fuel_child").dump() == i2.dump()
271 |
272 |
273 | def test_item_getchild_threelevel():
274 | i1 = Item()._set_name("Fuel")
275 | ic1 = Item()._set_name("child")
276 | ic2 = Item()._set_name("subchild")
277 | i1._set_child(ic1)
278 | ic1._set_child(ic2)
279 | text = """item subchild;"""
280 | i2 = classtree(loads(text))
281 |
282 | assert i1._get_child("Fuel.child.subchild").dump() == i2.dump()
283 |
284 |
285 | def test_item_getchild_error_int():
286 | i1 = Item()._set_name("Fuel")
287 | ic1 = Item()._set_name("Fuel_child")
288 | i1._set_child(ic1)
289 | with pytest.raises(TypeError):
290 | i1._get_child(1)
291 |
292 |
293 | def test_item_getchild_error_str():
294 | i1 = Item()._set_name("Fuel")
295 | ic1 = Item()._set_name("Fuel_child")
296 | i1._set_child(ic1)
297 | assert i1._get_child("Fuel.error") == None
298 |
299 |
300 | def test_item_typedby():
301 | p1 = Package()._set_name("Store")
302 | i1 = Item()._set_name("apple")
303 | i2 = Item(definition=True)._set_name("Fruit")
304 | p1._set_child(i1)
305 | i1._set_typed_by(i2)
306 |
307 | text = """package Store {
308 | item def Fruit ;
309 | item apple : Fruit;
310 | }"""
311 | p2 = classtree(loads(text))
312 |
313 | assert p1.dump() == p2.dump()
314 |
315 |
316 | def test_item_typedby_invalidusage_twousage():
317 | i1 = Item()._set_name("apple")
318 | i2 = Item()._set_name("Fruit")
319 | with pytest.raises(ValueError):
320 | i1._set_typed_by(i2)
321 |
322 |
323 | def test_item_typedby_invalidusage_twodef():
324 | i1 = Item(definition=True)._set_name("apple")
325 | i2 = Item(definition=True)._set_name("Fruit")
326 | with pytest.raises(ValueError):
327 | i1._set_typed_by(i2)
328 |
329 |
330 | def test_part_load_grammar():
331 | p = Part()
332 |
333 | text = """package Rocket {
334 | package EngineAssembly;
335 | part Tank {
336 | item def Fuel ;
337 | item Hydrogen : Fuel;
338 | }
339 | }"""
340 | q = Model().load(text)._get_child("Rocket.Tank")
341 | p.load_from_grammar(q._get_grammar())
342 |
343 | assert p.dump() == q.dump()
344 |
345 |
346 | def test_part():
347 | i1 = Part()
348 | text = """part;"""
349 | i2 = classtree(loads(text))
350 |
351 | assert i1.dump() == i2.dump()
352 |
353 |
354 | def test_part_def():
355 | i1 = Part(definition=True)
356 | text = """part def;"""
357 | i2 = classtree(loads(text))
358 |
359 | assert i1.dump() == i2.dump()
360 |
361 |
362 | def test_part_name():
363 | i1 = Part()._set_name("Fuel")
364 | text = """part Fuel;"""
365 | i2 = classtree(loads(text))
366 |
367 | assert i1.dump() == i2.dump()
368 |
369 |
370 | def test_part_shortname():
371 | i1 = Part()._set_name("'3.1'", short=True)
372 | text = """part <'3.1'>;"""
373 | i2 = classtree(loads(text))
374 |
375 | assert i1.dump() == i2.dump()
376 |
377 |
378 | def test_part_getname():
379 | name = "Fuel"
380 | i1 = Part()._set_name(name)
381 |
382 | assert i1._get_name() == name
383 |
384 |
385 | def test_part_setchild():
386 | i1 = Part()._set_name("Fuel")
387 | ic1 = Part()
388 | i1._set_child(ic1)
389 | text = """part Fuel {
390 | part;
391 | }"""
392 | i2 = classtree(loads(text))
393 |
394 | assert i1.dump() == i2.dump()
395 |
396 |
397 | def test_part_getchild():
398 | i1 = Part()._set_name("Fuel")
399 | ic1 = Part()._set_name("Fuel_child")
400 | i1._set_child(ic1)
401 | text = """part Fuel_child;"""
402 | i2 = classtree(loads(text))
403 |
404 | assert i1._get_child("Fuel.Fuel_child").dump() == i2.dump()
405 |
406 |
407 | def test_part_getchild_error_int():
408 | i1 = Part()._set_name("Fuel")
409 | ic1 = Part()._set_name("Fuel_child")
410 | i1._set_child(ic1)
411 | with pytest.raises(TypeError):
412 | i1._get_child(1)
413 |
414 |
415 | def test_part_getchild_error_str():
416 | i1 = Part()._set_name("Fuel")
417 | ic1 = Part()._set_name("Fuel_child")
418 | i1._set_child(ic1)
419 | assert i1._get_child("Fuel.error") == None
420 |
421 |
422 | def test_part_typedby():
423 | p1 = Package()._set_name("Store")
424 | i1 = Part()._set_name("apple")
425 | i2 = Part(definition=True)._set_name("Fruit")
426 | p1._set_child(i1)
427 | i1._set_typed_by(i2)
428 |
429 | text = """package Store {
430 | part def Fruit ;
431 | part apple : Fruit;
432 | }"""
433 | p2 = classtree(loads(text))
434 |
435 | assert p1.dump() == p2.dump()
436 |
437 |
438 | def test_part_typedby_invalidusage_twousage():
439 | i1 = Part()._set_name("apple")
440 | i2 = Part()._set_name("Fruit")
441 | with pytest.raises(ValueError):
442 | i1._set_typed_by(i2)
443 |
444 |
445 | def test_part_typedby_invalidusage_twodef():
446 | i1 = Part(definition=True)._set_name("apple")
447 | i2 = Part(definition=True)._set_name("Fruit")
448 | with pytest.raises(ValueError):
449 | i1._set_typed_by(i2)
450 |
451 |
452 | def test_port():
453 | o1 = Port()
454 | text = """port;"""
455 | o2 = classtree(loads(text))
456 |
457 | assert o1.dump() == o2.dump()
458 |
459 |
460 | def test_port_def():
461 | o1 = Port(definition=True)
462 | text = """port def;"""
463 | o2 = classtree(loads(text))
464 |
465 | assert o1.dump() == o2.dump()
466 |
467 |
468 | def test_port_directed_in():
469 | o1 = Port()._set_name("FuelHose")
470 | o1.add_directed_feature("in", "Fuel")
471 | text = """port FuelHose {
472 | in Fuel ;
473 | }"""
474 | o2 = classtree(loads(text))
475 | assert o1.dump() == o2.dump()
476 |
477 |
478 | def test_port_directed_out():
479 | o1 = Port()._set_name("FuelHose")
480 | o1.add_directed_feature("out", "Fuel")
481 | text = """port FuelHose {
482 | out Fuel ;
483 | }"""
484 | o2 = classtree(loads(text))
485 | assert o1.dump() == o2.dump()
486 |
487 |
488 | def test_port_directed_inout():
489 | o1 = Port()._set_name("FuelHose")
490 | o1.add_directed_feature("inout", "Fuel")
491 | text = """port FuelHose {
492 | inout Fuel ;
493 | }"""
494 | o2 = classtree(loads(text))
495 | assert o1.dump() == o2.dump()
496 |
497 |
498 | def test_port_directed_error():
499 | o1 = Port()
500 | with pytest.raises(ValueError):
501 | o1.add_directed_feature("error", "Fuel")
502 |
503 |
504 | # This test doesn't work right now
505 | # def test_item_def_subchild():
506 | # i = Item(definition=True)._set_name("Engine")
507 | # import astropy.units as u
508 |
509 | # a = Attribute()._set_name("mass")
510 | # a.set_value(100 * u.kg)
511 | # i._set_child(a)
512 |
513 | # text = """item Engine {
514 | # attribute mass= 100.0 [kg];
515 | # }"""
516 |
517 | # q = classtree(loads(text))
518 |
519 | # assert i.dump() == q.dump()
520 |
521 |
522 | def test_attribute_definition():
523 | import astropy.units as u
524 |
525 | a = Attribute(definition=True)._set_name("mass")
526 |
527 | text = """attribute def mass;"""
528 |
529 | q = classtree(loads(text))
530 |
531 | assert a.dump() == q.dump()
532 |
533 |
534 | def test_attribute_units():
535 | import astropy.units as u
536 |
537 | a = Attribute()._set_name("mass")
538 | a.set_value(100 * u.kg)
539 |
540 | text = """attribute mass= 100.0 [kg];"""
541 |
542 | q = classtree(loads(text))
543 |
544 | assert a.dump() == q.dump()
545 |
546 |
547 | def test_attribute_getunits():
548 | import astropy.units as u
549 |
550 | value = 100 * u.kg
551 |
552 | a = Attribute()._set_name("mass")
553 | a.set_value(value)
554 |
555 | assert value == a.get_value()
556 |
557 |
558 | def test_attribute_nounits():
559 | a = Attribute()._set_name("mass")
560 | a.set_value(100)
561 |
562 | text = """attribute mass= 100.0;"""
563 |
564 | q = classtree(loads(text))
565 |
566 | assert a.dump() == q.dump()
567 |
--------------------------------------------------------------------------------
/tests/conftest.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | """
4 | Created on Tue Jul 11 22:49:00 2023
5 |
6 | @author: christophercox
7 | """
8 |
9 | import pytest
10 |
11 |
12 | @pytest.fixture
13 | def single_package():
14 | return """package;"""
15 |
--------------------------------------------------------------------------------
/tests/functions.py:
--------------------------------------------------------------------------------
1 | import re
2 | import string
3 |
4 |
5 | def remove_comments(string):
6 | pattern = r"(\".*?\"|\'.*?\')|(//[^\r\n]*$)"
7 | # first group captures quoted strings (double or single)
8 | # second group captures comments (//single-line or /* multi-line */)
9 | regex = re.compile(pattern, re.MULTILINE | re.DOTALL)
10 |
11 | def _replacer(match):
12 | # if the 2nd group (capturing comments) is not None,
13 | # it means we have captured a non-quoted (real) comment string.
14 | if match.group(2) is not None:
15 | return "" # so we will return empty to remove the comment
16 | else: # otherwise, we will return the 1st group
17 | return match.group(1) # captured quoted-string
18 |
19 | return regex.sub(_replacer, string)
20 |
21 |
22 | def strip_ws(text):
23 | text = remove_comments(text)
24 | text = text.replace("specializes", ":>")
25 | text = text.replace("subsets", ":>")
26 | text = text.replace("redefines", ":>>")
27 | return text.translate(str.maketrans("", "", string.whitespace))
28 |
--------------------------------------------------------------------------------
/tests/main_test.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | """
4 | Created on Mon May 29 23:20:18 2023
5 |
6 | @author: christophercox
7 | """
8 | import pytest
9 |
10 | from sysml2py import load, loads, load_grammar
11 | from sysml2py.formatting import classtree
12 |
13 | from textx import TextXSyntaxError
14 |
15 | from .functions import strip_ws
16 |
17 |
18 | def test_grammar_load_fromfile(single_package):
19 | with open("temp.txt", "w") as f:
20 | f.write(single_package)
21 | f.close()
22 |
23 | f = open("temp.txt", "r")
24 | grammar = load_grammar(f)
25 | assert strip_ws(classtree(grammar).dump()) == strip_ws(single_package)
26 |
27 |
28 | def test_grammar_invalid_input():
29 | with pytest.raises(TypeError):
30 | load_grammar({})
31 |
32 |
33 | def test_load_fromfile(single_package):
34 | with open("temp.txt", "w") as f:
35 | f.write(single_package)
36 | f.close()
37 |
38 | f = open("temp.txt", "r")
39 | model = load(f)
40 | assert strip_ws(model.dump()) == strip_ws(single_package)
41 |
42 |
43 | def test_load_fromfile_error(single_package):
44 | with pytest.raises(TypeError):
45 | load("string")
46 |
47 |
48 | def test_load_fromstr(single_package):
49 | model = loads(single_package)
50 | assert strip_ws(model.dump()) == strip_ws(single_package)
51 |
52 |
53 | def test_load_fromstr_error(single_package):
54 | with pytest.raises(TypeError):
55 | loads({})
56 |
57 |
58 | def test_invalid_sysml():
59 | with pytest.raises(TextXSyntaxError):
60 | loads("error")
61 |
--------------------------------------------------------------------------------