gsn-model-parser 0.16.10__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- gsn_model_parser-0.16.10/LICENSE +21 -0
- gsn_model_parser-0.16.10/MANIFEST.in +5 -0
- gsn_model_parser-0.16.10/PKG-INFO +155 -0
- gsn_model_parser-0.16.10/README.md +131 -0
- gsn_model_parser-0.16.10/pyproject.toml +47 -0
- gsn_model_parser-0.16.10/setup.cfg +4 -0
- gsn_model_parser-0.16.10/src/gsn_model_parser/__init__.py +5 -0
- gsn_model_parser-0.16.10/src/gsn_model_parser/__main__.py +3 -0
- gsn_model_parser-0.16.10/src/gsn_model_parser/gsn.tx +218 -0
- gsn_model_parser-0.16.10/src/gsn_model_parser/opinion.py +369 -0
- gsn_model_parser-0.16.10/src/gsn_model_parser/parser.py +1099 -0
- gsn_model_parser-0.16.10/src/gsn_model_parser.egg-info/PKG-INFO +155 -0
- gsn_model_parser-0.16.10/src/gsn_model_parser.egg-info/SOURCES.txt +15 -0
- gsn_model_parser-0.16.10/src/gsn_model_parser.egg-info/dependency_links.txt +1 -0
- gsn_model_parser-0.16.10/src/gsn_model_parser.egg-info/entry_points.txt +2 -0
- gsn_model_parser-0.16.10/src/gsn_model_parser.egg-info/requires.txt +1 -0
- gsn_model_parser-0.16.10/src/gsn_model_parser.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Vanderbilt University, ICONS
|
|
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.
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: gsn-model-parser
|
|
3
|
+
Version: 0.16.10
|
|
4
|
+
Summary: Parse Goal Structuring Notation (.gsn) models and propagate subjective-logic opinions
|
|
5
|
+
Author-email: Patrik Meijer <patrik.meijer@vanderbilt.edu>, Mark Wutka <mark.wutka@vanderbilt.edu>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://git-dains-vu.isis.vanderbilt.edu/dains/tools/caid/gsn-domain
|
|
8
|
+
Project-URL: Issues, https://git-dains-vu.isis.vanderbilt.edu/dains/tools/caid/gsn-domain/-/issues
|
|
9
|
+
Keywords: gsn,goal-structuring-notation,assurance,subjective-logic
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Topic :: Scientific/Engineering
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Requires-Dist: textX==4.4.0
|
|
23
|
+
Dynamic: license-file
|
|
24
|
+
|
|
25
|
+
# gsn-model-parser
|
|
26
|
+
|
|
27
|
+
Python parser for Goal Structuring Notation (`.gsn`) models. It loads one or more `.gsn` files from a directory, resolves references, and returns `GSNNode` objects with attributes (including opinions) and content hashes.
|
|
28
|
+
|
|
29
|
+
Requires **Python 3.10+**.
|
|
30
|
+
|
|
31
|
+
## Virtual environment
|
|
32
|
+
|
|
33
|
+
From this directory (`python-model-parser`):
|
|
34
|
+
|
|
35
|
+
```shell
|
|
36
|
+
python3 -m venv venv
|
|
37
|
+
source venv/bin/activate
|
|
38
|
+
pip install -U pip
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Install
|
|
42
|
+
|
|
43
|
+
From PyPI:
|
|
44
|
+
|
|
45
|
+
```shell
|
|
46
|
+
pip install gsn-model-parser
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Editable install from a clone (used for development and tests):
|
|
50
|
+
|
|
51
|
+
```shell
|
|
52
|
+
pip install -e .
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
A release is also published to this project's GitLab PyPI registry. Authenticate with a [personal access token](https://git-dains-vu.isis.vanderbilt.edu/-/user_settings/personal_access_tokens) that has `read_api` and `read_package_registry` (do not commit the token):
|
|
56
|
+
|
|
57
|
+
```shell
|
|
58
|
+
export GSN_DOMAIN_PYPI="https://__token__:${TOKEN}@git-dains-vu.isis.vanderbilt.edu/api/v4/projects/dains%2Ftools%2Fcaid%2Fgsn-domain/packages/pypi/simple"
|
|
59
|
+
pip install gsn-model-parser --index-url "${GSN_DOMAIN_PYPI}" --extra-index-url https://pypi.org/simple
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Build a wheel
|
|
63
|
+
|
|
64
|
+
```shell
|
|
65
|
+
pip install build
|
|
66
|
+
python -m build
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Artifacts land in `dist/` (`gsn_model_parser-*.whl` and `*.tar.gz`). Check the metadata, then upload.
|
|
70
|
+
|
|
71
|
+
Public PyPI (create an API token at <https://pypi.org/manage/account/token/>):
|
|
72
|
+
|
|
73
|
+
```shell
|
|
74
|
+
pip install twine
|
|
75
|
+
python -m twine check dist/*
|
|
76
|
+
python -m twine upload dist/*
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
GitLab CI does this on a version tag (`v0.16.9`). The tag job rewrites `version` in `pyproject.toml` from the tag, builds the artifacts, uploads them to the GitLab PyPI registry, and uploads the same artifacts to public PyPI when the masked CI variable `PYPI_API_TOKEN` is set. Make that variable available to tag pipelines.
|
|
80
|
+
|
|
81
|
+
To upload the same build to the GitLab registry by hand:
|
|
82
|
+
|
|
83
|
+
```shell
|
|
84
|
+
python -m twine upload --repository-url https://git-dains-vu.isis.vanderbilt.edu/api/v4/projects/<project-id>/packages/pypi dist/*
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Usage
|
|
88
|
+
|
|
89
|
+
Parse a directory of `.gsn` files (all files in the folder are one model).
|
|
90
|
+
`get_solved_bys` and `get_in_context_ofs` return the direct children, in source order.
|
|
91
|
+
`ref_goal`, `ref_strategy`, `ref_solution`, `ref_context`, `ref_assumption`, and
|
|
92
|
+
`ref_justification` resolve to the target node, so the same calls continue into a
|
|
93
|
+
node that lives in another namespace. Recurse to walk the whole argument.
|
|
94
|
+
`examples/traverse_model.py` prints this outline for a model directory.
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
from gsn_model_parser import load_model
|
|
98
|
+
|
|
99
|
+
def walk(node, indent=0, seen=None):
|
|
100
|
+
if seen is None:
|
|
101
|
+
seen = set()
|
|
102
|
+
print(f"{' ' * indent}{node.node_type} {node.name}")
|
|
103
|
+
if node.node_id in seen:
|
|
104
|
+
return
|
|
105
|
+
seen.add(node.node_id)
|
|
106
|
+
for context in node.get_in_context_ofs():
|
|
107
|
+
walk(context, indent + 1, seen)
|
|
108
|
+
for child in node.get_solved_bys():
|
|
109
|
+
walk(child, indent + 1, seen)
|
|
110
|
+
|
|
111
|
+
model = load_model("/path/to/sample-models/control-system")
|
|
112
|
+
for root in model.get_roots():
|
|
113
|
+
walk(root)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
#### Compute Propagated Opinions
|
|
117
|
+
`get_propagated_opinion` derives the subjective-logic opinion of a node from its `solvedBy` and `inContextOf` links. On a top-level node that walks the whole argument underneath it. Solutions and assumptions still use their stored opinion; a goal or strategy is computed.
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
from gsn_model_parser import load_model
|
|
121
|
+
|
|
122
|
+
model = load_model("/path/to/sample-models/simple")
|
|
123
|
+
for root in model.get_roots():
|
|
124
|
+
print(root.name, root.get_propagated_opinion())
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
#### Updating Opinions
|
|
128
|
+
``get_gsn_nodes`` still returns the flat node map and a ``persist`` callback:
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
from gsn_model_parser import get_gsn_nodes
|
|
132
|
+
|
|
133
|
+
nodes, persist = get_gsn_nodes("/path/to/sample-models/simple", as_dict=True)
|
|
134
|
+
|
|
135
|
+
for node in nodes.values():
|
|
136
|
+
print(node.name, node.node_type, node.opinion, node.get_content_hash(nodes))
|
|
137
|
+
if node.node_type == 'SolutionNode':
|
|
138
|
+
node.opinion = {'b': 1.0, 'd': 0.0, 'u': 0.0, 'a': 0.5}
|
|
139
|
+
|
|
140
|
+
persist("/path/to/out.gsn") # one combined file
|
|
141
|
+
persist("/path/to/out-dir") # original filenames, one file per source .gsn
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Tests
|
|
145
|
+
|
|
146
|
+
Unit tests parse the sample models under [`../sample-models/`](../sample-models/). From this directory, with the venv activated:
|
|
147
|
+
|
|
148
|
+
```shell
|
|
149
|
+
pip install -e .
|
|
150
|
+
python -m unittest discover -s test -p '*test*.py'
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Grammar
|
|
154
|
+
|
|
155
|
+
The textX grammar [`src/gsn_model_parser/gsn.tx`](src/gsn_model_parser/gsn.tx) tracks [`Assurance.xtext`](../gsn-xtext/edu.vanderbilt.isis.caid.assurancedsl/src/main/java/edu/vanderbilt/isis/caid/assurancedsl/Assurance.xtext). When the `.gsn` language changes, update both.
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# gsn-model-parser
|
|
2
|
+
|
|
3
|
+
Python parser for Goal Structuring Notation (`.gsn`) models. It loads one or more `.gsn` files from a directory, resolves references, and returns `GSNNode` objects with attributes (including opinions) and content hashes.
|
|
4
|
+
|
|
5
|
+
Requires **Python 3.10+**.
|
|
6
|
+
|
|
7
|
+
## Virtual environment
|
|
8
|
+
|
|
9
|
+
From this directory (`python-model-parser`):
|
|
10
|
+
|
|
11
|
+
```shell
|
|
12
|
+
python3 -m venv venv
|
|
13
|
+
source venv/bin/activate
|
|
14
|
+
pip install -U pip
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
From PyPI:
|
|
20
|
+
|
|
21
|
+
```shell
|
|
22
|
+
pip install gsn-model-parser
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Editable install from a clone (used for development and tests):
|
|
26
|
+
|
|
27
|
+
```shell
|
|
28
|
+
pip install -e .
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
A release is also published to this project's GitLab PyPI registry. Authenticate with a [personal access token](https://git-dains-vu.isis.vanderbilt.edu/-/user_settings/personal_access_tokens) that has `read_api` and `read_package_registry` (do not commit the token):
|
|
32
|
+
|
|
33
|
+
```shell
|
|
34
|
+
export GSN_DOMAIN_PYPI="https://__token__:${TOKEN}@git-dains-vu.isis.vanderbilt.edu/api/v4/projects/dains%2Ftools%2Fcaid%2Fgsn-domain/packages/pypi/simple"
|
|
35
|
+
pip install gsn-model-parser --index-url "${GSN_DOMAIN_PYPI}" --extra-index-url https://pypi.org/simple
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Build a wheel
|
|
39
|
+
|
|
40
|
+
```shell
|
|
41
|
+
pip install build
|
|
42
|
+
python -m build
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Artifacts land in `dist/` (`gsn_model_parser-*.whl` and `*.tar.gz`). Check the metadata, then upload.
|
|
46
|
+
|
|
47
|
+
Public PyPI (create an API token at <https://pypi.org/manage/account/token/>):
|
|
48
|
+
|
|
49
|
+
```shell
|
|
50
|
+
pip install twine
|
|
51
|
+
python -m twine check dist/*
|
|
52
|
+
python -m twine upload dist/*
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
GitLab CI does this on a version tag (`v0.16.9`). The tag job rewrites `version` in `pyproject.toml` from the tag, builds the artifacts, uploads them to the GitLab PyPI registry, and uploads the same artifacts to public PyPI when the masked CI variable `PYPI_API_TOKEN` is set. Make that variable available to tag pipelines.
|
|
56
|
+
|
|
57
|
+
To upload the same build to the GitLab registry by hand:
|
|
58
|
+
|
|
59
|
+
```shell
|
|
60
|
+
python -m twine upload --repository-url https://git-dains-vu.isis.vanderbilt.edu/api/v4/projects/<project-id>/packages/pypi dist/*
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Usage
|
|
64
|
+
|
|
65
|
+
Parse a directory of `.gsn` files (all files in the folder are one model).
|
|
66
|
+
`get_solved_bys` and `get_in_context_ofs` return the direct children, in source order.
|
|
67
|
+
`ref_goal`, `ref_strategy`, `ref_solution`, `ref_context`, `ref_assumption`, and
|
|
68
|
+
`ref_justification` resolve to the target node, so the same calls continue into a
|
|
69
|
+
node that lives in another namespace. Recurse to walk the whole argument.
|
|
70
|
+
`examples/traverse_model.py` prints this outline for a model directory.
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
from gsn_model_parser import load_model
|
|
74
|
+
|
|
75
|
+
def walk(node, indent=0, seen=None):
|
|
76
|
+
if seen is None:
|
|
77
|
+
seen = set()
|
|
78
|
+
print(f"{' ' * indent}{node.node_type} {node.name}")
|
|
79
|
+
if node.node_id in seen:
|
|
80
|
+
return
|
|
81
|
+
seen.add(node.node_id)
|
|
82
|
+
for context in node.get_in_context_ofs():
|
|
83
|
+
walk(context, indent + 1, seen)
|
|
84
|
+
for child in node.get_solved_bys():
|
|
85
|
+
walk(child, indent + 1, seen)
|
|
86
|
+
|
|
87
|
+
model = load_model("/path/to/sample-models/control-system")
|
|
88
|
+
for root in model.get_roots():
|
|
89
|
+
walk(root)
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
#### Compute Propagated Opinions
|
|
93
|
+
`get_propagated_opinion` derives the subjective-logic opinion of a node from its `solvedBy` and `inContextOf` links. On a top-level node that walks the whole argument underneath it. Solutions and assumptions still use their stored opinion; a goal or strategy is computed.
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
from gsn_model_parser import load_model
|
|
97
|
+
|
|
98
|
+
model = load_model("/path/to/sample-models/simple")
|
|
99
|
+
for root in model.get_roots():
|
|
100
|
+
print(root.name, root.get_propagated_opinion())
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
#### Updating Opinions
|
|
104
|
+
``get_gsn_nodes`` still returns the flat node map and a ``persist`` callback:
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
from gsn_model_parser import get_gsn_nodes
|
|
108
|
+
|
|
109
|
+
nodes, persist = get_gsn_nodes("/path/to/sample-models/simple", as_dict=True)
|
|
110
|
+
|
|
111
|
+
for node in nodes.values():
|
|
112
|
+
print(node.name, node.node_type, node.opinion, node.get_content_hash(nodes))
|
|
113
|
+
if node.node_type == 'SolutionNode':
|
|
114
|
+
node.opinion = {'b': 1.0, 'd': 0.0, 'u': 0.0, 'a': 0.5}
|
|
115
|
+
|
|
116
|
+
persist("/path/to/out.gsn") # one combined file
|
|
117
|
+
persist("/path/to/out-dir") # original filenames, one file per source .gsn
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Tests
|
|
121
|
+
|
|
122
|
+
Unit tests parse the sample models under [`../sample-models/`](../sample-models/). From this directory, with the venv activated:
|
|
123
|
+
|
|
124
|
+
```shell
|
|
125
|
+
pip install -e .
|
|
126
|
+
python -m unittest discover -s test -p '*test*.py'
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Grammar
|
|
130
|
+
|
|
131
|
+
The textX grammar [`src/gsn_model_parser/gsn.tx`](src/gsn_model_parser/gsn.tx) tracks [`Assurance.xtext`](../gsn-xtext/edu.vanderbilt.isis.caid.assurancedsl/src/main/java/edu/vanderbilt/isis/caid/assurancedsl/Assurance.xtext). When the `.gsn` language changes, update both.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools >= 77.0.3"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "gsn-model-parser"
|
|
7
|
+
version = "0.16.10"
|
|
8
|
+
description = "Parse Goal Structuring Notation (.gsn) models and propagate subjective-logic opinions"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
license-files = ["LICENSE"]
|
|
13
|
+
keywords = ["gsn", "goal-structuring-notation", "assurance", "subjective-logic"]
|
|
14
|
+
authors = [
|
|
15
|
+
{ name = "Patrik Meijer", email = "patrik.meijer@vanderbilt.edu" },
|
|
16
|
+
{ name = "Mark Wutka", email = "mark.wutka@vanderbilt.edu" },
|
|
17
|
+
]
|
|
18
|
+
classifiers = [
|
|
19
|
+
"Development Status :: 4 - Beta",
|
|
20
|
+
"Intended Audience :: Developers",
|
|
21
|
+
"Intended Audience :: Science/Research",
|
|
22
|
+
"Programming Language :: Python :: 3",
|
|
23
|
+
"Programming Language :: Python :: 3.10",
|
|
24
|
+
"Programming Language :: Python :: 3.11",
|
|
25
|
+
"Programming Language :: Python :: 3.12",
|
|
26
|
+
"Programming Language :: Python :: 3.13",
|
|
27
|
+
"Topic :: Scientific/Engineering",
|
|
28
|
+
]
|
|
29
|
+
dependencies = [
|
|
30
|
+
"textX==4.4.0",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
[project.urls]
|
|
34
|
+
Homepage = "https://git-dains-vu.isis.vanderbilt.edu/dains/tools/caid/gsn-domain"
|
|
35
|
+
Issues = "https://git-dains-vu.isis.vanderbilt.edu/dains/tools/caid/gsn-domain/-/issues"
|
|
36
|
+
|
|
37
|
+
[project.scripts]
|
|
38
|
+
gsn-model-parser = "gsn_model_parser.parser:main"
|
|
39
|
+
|
|
40
|
+
[tool.setuptools]
|
|
41
|
+
include-package-data = true
|
|
42
|
+
|
|
43
|
+
[tool.setuptools.packages.find]
|
|
44
|
+
where = ["src"]
|
|
45
|
+
|
|
46
|
+
[tool.setuptools.package-data]
|
|
47
|
+
gsn_model_parser = ["gsn.tx"]
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
AssuranceModel:
|
|
2
|
+
assurancemodels += GSNDefinition*
|
|
3
|
+
;
|
|
4
|
+
|
|
5
|
+
GSNDefinition:
|
|
6
|
+
Goals|Strategies|Contexts|Assumptions|Justifications|Solutions
|
|
7
|
+
;
|
|
8
|
+
|
|
9
|
+
Goals:
|
|
10
|
+
'GOALS' name=ID '{' goals *= GoalNode '}'
|
|
11
|
+
;
|
|
12
|
+
|
|
13
|
+
Strategies:
|
|
14
|
+
'STRATEGIES' name=ID '{' strategies *= StrategyNode '}'
|
|
15
|
+
;
|
|
16
|
+
|
|
17
|
+
Contexts:
|
|
18
|
+
'CONTEXTS' name=ID '{' contexts *= ContextNode '}'
|
|
19
|
+
;
|
|
20
|
+
|
|
21
|
+
Assumptions:
|
|
22
|
+
'ASSUMPTIONS' name=ID '{' assumptions *= AssumptionNode '}'
|
|
23
|
+
;
|
|
24
|
+
|
|
25
|
+
Justifications:
|
|
26
|
+
'JUSTIFICATIONS' name=ID '{' justifications *= JustificationNode '}'
|
|
27
|
+
;
|
|
28
|
+
|
|
29
|
+
Solutions:
|
|
30
|
+
'SOLUTIONS' name=ID '{' solutions *= SolutionNode '}'
|
|
31
|
+
;
|
|
32
|
+
|
|
33
|
+
GoalSupportNodes:
|
|
34
|
+
GoalNode
|
|
35
|
+
| StrategyNode
|
|
36
|
+
| SolutionNode
|
|
37
|
+
| GoalNodeRef
|
|
38
|
+
| StrategyNodeRef
|
|
39
|
+
| SolutionNodeRef
|
|
40
|
+
;
|
|
41
|
+
|
|
42
|
+
StrategySupportNodes:
|
|
43
|
+
GoalNode
|
|
44
|
+
| StrategyNode
|
|
45
|
+
| GoalNodeRef
|
|
46
|
+
| StrategyNodeRef
|
|
47
|
+
;
|
|
48
|
+
|
|
49
|
+
ContextNodes:
|
|
50
|
+
ContextNode
|
|
51
|
+
| ContextNodeRef
|
|
52
|
+
;
|
|
53
|
+
|
|
54
|
+
AssumptionNodes:
|
|
55
|
+
AssumptionNode
|
|
56
|
+
| AssumptionNodeRef
|
|
57
|
+
;
|
|
58
|
+
|
|
59
|
+
JustificationNodes:
|
|
60
|
+
JustificationNode
|
|
61
|
+
| JustificationNodeRef
|
|
62
|
+
;
|
|
63
|
+
|
|
64
|
+
ALLNodes:
|
|
65
|
+
GoalNode
|
|
66
|
+
| StrategyNode
|
|
67
|
+
| SolutionNode
|
|
68
|
+
| ContextNode
|
|
69
|
+
| AssumptionNode
|
|
70
|
+
| JustificationNode
|
|
71
|
+
;
|
|
72
|
+
|
|
73
|
+
GoalNodeRef:
|
|
74
|
+
'ref_goal' ref=[GoalNode:FQN]
|
|
75
|
+
;
|
|
76
|
+
|
|
77
|
+
StrategyNodeRef:
|
|
78
|
+
'ref_strategy' ref=[StrategyNode:FQN]
|
|
79
|
+
;
|
|
80
|
+
|
|
81
|
+
SolutionNodeRef:
|
|
82
|
+
'ref_solution' ref=[SolutionNode:FQN]
|
|
83
|
+
;
|
|
84
|
+
|
|
85
|
+
ContextNodeRef:
|
|
86
|
+
'ref_context' ref=[ContextNode:FQN]
|
|
87
|
+
;
|
|
88
|
+
|
|
89
|
+
AssumptionNodeRef:
|
|
90
|
+
'ref_assumption' ref=[AssumptionNode:FQN]
|
|
91
|
+
;
|
|
92
|
+
|
|
93
|
+
JustificationNodeRef:
|
|
94
|
+
'ref_justification' ref=[JustificationNode:FQN]
|
|
95
|
+
;
|
|
96
|
+
|
|
97
|
+
Number:
|
|
98
|
+
FLOAT | INT
|
|
99
|
+
;
|
|
100
|
+
|
|
101
|
+
Opinion:
|
|
102
|
+
'(' b=Number ',' d=Number ',' u=Number (',' a=Number)? ')'
|
|
103
|
+
;
|
|
104
|
+
|
|
105
|
+
WarrantBlock:
|
|
106
|
+
'warrant' '{'
|
|
107
|
+
('givenTrue' givenTrue=Opinion)?
|
|
108
|
+
('givenFalse' givenFalse=Opinion)?
|
|
109
|
+
'}'
|
|
110
|
+
;
|
|
111
|
+
|
|
112
|
+
GoalChild:
|
|
113
|
+
GoalSupportNodes | ContextNodes | AssumptionNodes | JustificationNodes
|
|
114
|
+
;
|
|
115
|
+
|
|
116
|
+
StrategyChild:
|
|
117
|
+
StrategySupportNodes | ContextNodes | AssumptionNodes | JustificationNodes
|
|
118
|
+
;
|
|
119
|
+
|
|
120
|
+
GoalDetails:
|
|
121
|
+
child=GoalChild
|
|
122
|
+
(warrants=WarrantBlock)?
|
|
123
|
+
;
|
|
124
|
+
|
|
125
|
+
StrategyDetails:
|
|
126
|
+
child=StrategyChild
|
|
127
|
+
(warrants=WarrantBlock)?
|
|
128
|
+
;
|
|
129
|
+
|
|
130
|
+
GoalNode:
|
|
131
|
+
'goal' name=ID '{'
|
|
132
|
+
(details=BaseNode)?
|
|
133
|
+
('status' status=SolutionStatus)?
|
|
134
|
+
(nodedetails *= GoalDetails)
|
|
135
|
+
'}'
|
|
136
|
+
;
|
|
137
|
+
|
|
138
|
+
StrategyNode:
|
|
139
|
+
'strategy' name=ID '{'
|
|
140
|
+
(details=BaseNode)?
|
|
141
|
+
('argument' argumentType=ArgumentType)?
|
|
142
|
+
(nodedetails *= StrategyDetails)
|
|
143
|
+
'}'
|
|
144
|
+
;
|
|
145
|
+
|
|
146
|
+
ContextNode:
|
|
147
|
+
'context' name=ID '{'
|
|
148
|
+
(details=BaseNode)?
|
|
149
|
+
'}'
|
|
150
|
+
;
|
|
151
|
+
|
|
152
|
+
AssumptionNode:
|
|
153
|
+
'assumption' name=ID '{'
|
|
154
|
+
(details=BaseNode)?
|
|
155
|
+
('opinion' opinion=Opinion)?
|
|
156
|
+
'}'
|
|
157
|
+
;
|
|
158
|
+
|
|
159
|
+
JustificationNode:
|
|
160
|
+
'justification' name=ID '{'
|
|
161
|
+
(details=BaseNode)?
|
|
162
|
+
'}'
|
|
163
|
+
;
|
|
164
|
+
|
|
165
|
+
SolutionNode:
|
|
166
|
+
'solution' name=ID '{'
|
|
167
|
+
(details=BaseNode)?
|
|
168
|
+
('status' status=SolutionStatus)?
|
|
169
|
+
('opinion' opinion=Opinion)?
|
|
170
|
+
'}'
|
|
171
|
+
;
|
|
172
|
+
|
|
173
|
+
BaseNode:
|
|
174
|
+
(uuid=UUIDType)?
|
|
175
|
+
(summary=Summary)?
|
|
176
|
+
(info=Description)?
|
|
177
|
+
(labels *= LabelInfo)
|
|
178
|
+
(artifacts *= URI)
|
|
179
|
+
;
|
|
180
|
+
|
|
181
|
+
SolutionStatus:
|
|
182
|
+
'NotReviewed' | 'Approved' | 'Disapproved'
|
|
183
|
+
;
|
|
184
|
+
|
|
185
|
+
ArgumentType:
|
|
186
|
+
'CONJUNCTION' | 'DISJUNCTION' | 'FUSION' | 'DISCOUNT'
|
|
187
|
+
;
|
|
188
|
+
|
|
189
|
+
UUIDType:
|
|
190
|
+
'uuid' info=GUID
|
|
191
|
+
;
|
|
192
|
+
|
|
193
|
+
Summary:
|
|
194
|
+
'summary' info=MLString
|
|
195
|
+
;
|
|
196
|
+
|
|
197
|
+
Description:
|
|
198
|
+
'info' info=MLString
|
|
199
|
+
;
|
|
200
|
+
|
|
201
|
+
LabelInfo:
|
|
202
|
+
'label' name=ID
|
|
203
|
+
;
|
|
204
|
+
|
|
205
|
+
URI:
|
|
206
|
+
'artifact' uri=MLString
|
|
207
|
+
;
|
|
208
|
+
|
|
209
|
+
FQN:
|
|
210
|
+
ID+['.']
|
|
211
|
+
;
|
|
212
|
+
|
|
213
|
+
MLString: data=/(?ms)\"(.*?)\"/;
|
|
214
|
+
GUID: /\{?[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\}?/;
|
|
215
|
+
|
|
216
|
+
Comment:
|
|
217
|
+
/\/\/.*$/
|
|
218
|
+
;
|