mal-toolbox 1.2.1__tar.gz → 2.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. {mal_toolbox-1.2.1/mal_toolbox.egg-info → mal_toolbox-2.0.0}/PKG-INFO +8 -75
  2. {mal_toolbox-1.2.1 → mal_toolbox-2.0.0}/README.md +5 -74
  3. {mal_toolbox-1.2.1 → mal_toolbox-2.0.0/mal_toolbox.egg-info}/PKG-INFO +8 -75
  4. {mal_toolbox-1.2.1 → mal_toolbox-2.0.0}/mal_toolbox.egg-info/SOURCES.txt +5 -2
  5. {mal_toolbox-1.2.1 → mal_toolbox-2.0.0}/mal_toolbox.egg-info/requires.txt +2 -0
  6. {mal_toolbox-1.2.1 → mal_toolbox-2.0.0}/maltoolbox/__init__.py +2 -2
  7. {mal_toolbox-1.2.1 → mal_toolbox-2.0.0}/maltoolbox/attackgraph/node.py +1 -0
  8. mal_toolbox-2.0.0/maltoolbox/language/compiler/__init__.py +5 -0
  9. mal_toolbox-2.0.0/maltoolbox/language/compiler/distributions.py +158 -0
  10. mal_toolbox-2.0.0/maltoolbox/language/compiler/exceptions.py +37 -0
  11. mal_toolbox-2.0.0/maltoolbox/language/compiler/lang.py +5 -0
  12. mal_toolbox-2.0.0/maltoolbox/language/compiler/mal_analyzer.py +920 -0
  13. mal_toolbox-2.0.0/maltoolbox/language/compiler/mal_compiler.py +1070 -0
  14. {mal_toolbox-1.2.1 → mal_toolbox-2.0.0}/maltoolbox/language/languagegraph.py +6 -5
  15. {mal_toolbox-1.2.1 → mal_toolbox-2.0.0}/pyproject.toml +4 -3
  16. mal_toolbox-1.2.1/maltoolbox/language/compiler/__init__.py +0 -500
  17. mal_toolbox-1.2.1/maltoolbox/language/compiler/mal_lexer.py +0 -232
  18. mal_toolbox-1.2.1/maltoolbox/language/compiler/mal_parser.py +0 -3159
  19. {mal_toolbox-1.2.1 → mal_toolbox-2.0.0}/AUTHORS +0 -0
  20. {mal_toolbox-1.2.1 → mal_toolbox-2.0.0}/LICENSE +0 -0
  21. {mal_toolbox-1.2.1 → mal_toolbox-2.0.0}/mal_toolbox.egg-info/dependency_links.txt +0 -0
  22. {mal_toolbox-1.2.1 → mal_toolbox-2.0.0}/mal_toolbox.egg-info/entry_points.txt +0 -0
  23. {mal_toolbox-1.2.1 → mal_toolbox-2.0.0}/mal_toolbox.egg-info/top_level.txt +0 -0
  24. {mal_toolbox-1.2.1 → mal_toolbox-2.0.0}/maltoolbox/__main__.py +0 -0
  25. {mal_toolbox-1.2.1 → mal_toolbox-2.0.0}/maltoolbox/attackgraph/__init__.py +0 -0
  26. {mal_toolbox-1.2.1 → mal_toolbox-2.0.0}/maltoolbox/attackgraph/analyzers/__init__.py +0 -0
  27. {mal_toolbox-1.2.1 → mal_toolbox-2.0.0}/maltoolbox/attackgraph/attackgraph.py +0 -0
  28. {mal_toolbox-1.2.1 → mal_toolbox-2.0.0}/maltoolbox/exceptions.py +0 -0
  29. {mal_toolbox-1.2.1 → mal_toolbox-2.0.0}/maltoolbox/file_utils.py +0 -0
  30. {mal_toolbox-1.2.1 → mal_toolbox-2.0.0}/maltoolbox/language/__init__.py +0 -0
  31. {mal_toolbox-1.2.1 → mal_toolbox-2.0.0}/maltoolbox/model.py +0 -0
  32. {mal_toolbox-1.2.1 → mal_toolbox-2.0.0}/maltoolbox/patternfinder/__init__.py +0 -0
  33. {mal_toolbox-1.2.1 → mal_toolbox-2.0.0}/maltoolbox/patternfinder/attackgraph_patterns.py +0 -0
  34. {mal_toolbox-1.2.1 → mal_toolbox-2.0.0}/maltoolbox/py.typed +0 -0
  35. {mal_toolbox-1.2.1 → mal_toolbox-2.0.0}/maltoolbox/str_utils.py +0 -0
  36. {mal_toolbox-1.2.1 → mal_toolbox-2.0.0}/maltoolbox/translators/__init__.py +0 -0
  37. {mal_toolbox-1.2.1 → mal_toolbox-2.0.0}/maltoolbox/translators/networkx.py +0 -0
  38. {mal_toolbox-1.2.1 → mal_toolbox-2.0.0}/maltoolbox/translators/updater.py +0 -0
  39. {mal_toolbox-1.2.1 → mal_toolbox-2.0.0}/maltoolbox/visualization/__init__.py +0 -0
  40. {mal_toolbox-1.2.1 → mal_toolbox-2.0.0}/maltoolbox/visualization/draw_io_utils.py +0 -0
  41. {mal_toolbox-1.2.1 → mal_toolbox-2.0.0}/maltoolbox/visualization/graphviz_utils.py +0 -0
  42. {mal_toolbox-1.2.1 → mal_toolbox-2.0.0}/maltoolbox/visualization/neo4j_utils.py +0 -0
  43. {mal_toolbox-1.2.1 → mal_toolbox-2.0.0}/maltoolbox/visualization/utils.py +0 -0
  44. {mal_toolbox-1.2.1 → mal_toolbox-2.0.0}/setup.cfg +0 -0
  45. {mal_toolbox-1.2.1 → mal_toolbox-2.0.0}/tests/test_model.py +0 -0
  46. {mal_toolbox-1.2.1 → mal_toolbox-2.0.0}/tests/test_visualization.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mal-toolbox
3
- Version: 1.2.1
3
+ Version: 2.0.0
4
4
  Summary: A collection of tools used to create MAL models and attack graphs.
5
5
  Author-email: Andrei Buhaiu <buhaiu@kth.se>, Joakim Loxdal <loxdal@kth.se>, Nikolaos Kakouros <nkak@kth.se>, Jakob Nyberg <jaknyb@kth.se>, Giuseppe Nebbione <nebbione@kth.se>, Sandor Berglund <sandor@kth.se>
6
6
  License: Apache Software License
@@ -25,6 +25,8 @@ Requires-Dist: docopt
25
25
  Requires-Dist: PyYAML
26
26
  Requires-Dist: py2neo
27
27
  Requires-Dist: networkx
28
+ Requires-Dist: tree-sitter-mal~=1.0.0
29
+ Requires-Dist: tree-sitter
28
30
  Provides-Extra: dev
29
31
  Requires-Dist: pytest; extra == "dev"
30
32
  Dynamic: license-file
@@ -36,37 +38,9 @@ MAL ([Meta Attack Language](https://mal-lang.org/)) models and attack graphs.
36
38
 
37
39
  Attack graphs can be used to run simulations in [MAL Simulator](https://github.com/mal-lang/mal-simulator) or run your own custom analysis on.
38
40
 
39
- - [MAL Toolbox Documentation](https://mal-lang.org/mal-toolbox/index.html)
41
+ - [MAL Toolbox Documentation](https://github.com/mal-lang/mal-toolbox/wiki)
40
42
  - [MAL Toolbox tutorial](https://github.com/mal-lang/mal-toolbox-tutorial)
41
43
 
42
- ## The Language Module
43
-
44
- The language module provides various tools to process MAL languages.
45
-
46
- ## The Model Module
47
-
48
- With a MAL language a Model (a MAL instance model) can be created either
49
- from a model file or empty.
50
-
51
- The model class will store all of the relevant information to the MAL
52
- instance model, most importantly the assets and their associations.
53
-
54
- Model objects can be used to generate attack graphs with the AttackGraph module.
55
-
56
- ## The Attack Graph Module
57
-
58
- The attack graph module contains tools used to generate attack graphs from
59
- existing MAL instance models and analyse MAL attack graphs. The function used
60
- to generate the attack graph is `generate_graph` and it requires the instance
61
- model and language specification. The resulting attack graph will contain
62
- nodes for each of the attack steps. The structure of the attack node data
63
- class can be seen in `attackgraph/node.py` file. Of note are the lists of
64
- children and parents which allow for easy reference to the other attack step
65
- nodes related and the asset field which will contain the object in the model
66
- instance to which this attack step belongs to, if this information is
67
- available.
68
-
69
-
70
44
  # Usage
71
45
 
72
46
  ## Installation
@@ -147,50 +121,9 @@ Notes:
147
121
  compiler) or a .mal file containing the DSL written in MAL.```
148
122
  ```
149
123
 
150
- ## Code examples / Tutorial
151
-
152
- To find more code examples and tutorials, visit the
153
- [MAL Toolbox Tutorial](https://github.com/mal-lang/mal-toolbox-tutorial/tree/main) repository.
154
-
155
- ### Load a language
156
- ```python
157
-
158
- from maltoolbox.language import LanguageGraph
159
-
160
- # Will load the MAL language (.mal/.mar) or a saved language graph (yml/json)
161
- lang_graph = LanguageGraph.load_from_file(lang_file_path)
162
-
163
- ```
164
-
165
- ### Generate a model
166
- ```python
167
- from maltoolbox.model import Model
168
-
169
- # Create an empty model
170
- instance_model = Model("Example Model", lang_graph)
171
-
172
- # Create and add assets of type supported by the MAL language
173
- asset1 = instance_model.add_asset('Application', 'Application1')
174
- asset2 = instance_model.add_asset('Application', 'Application2')
175
-
176
- # Create association between the assets
177
- asset1.add_associated_assets('appExecutedApps', asset2)
178
- ```
179
-
180
- ## Generate an attack graph
181
-
182
- ```python
183
-
184
- from maltoolbox.attackgraph import AttackGraph
185
-
186
- attack_graph = AttackGraph(lang_graph, model)
187
-
188
- ```
189
-
190
-
191
- ## Contributing
124
+ # Contributing
192
125
 
193
- # CI Pipeline
126
+ ## CI Pipeline
194
127
 
195
128
  Checks are made with:
196
129
 
@@ -200,12 +133,12 @@ Checks are made with:
200
133
 
201
134
  Make sure pipeline passes before PR is marked "Ready for review".
202
135
 
203
- # Tests
136
+ ## Tests
204
137
  There are unit tests inside of ./tests.
205
138
 
206
139
  To run all tests, use the `pytest` command. To run just a specific file or test function use `pytest tests/<filename>` or `pytest -k <function_name>`.
207
140
 
208
- # Making a release
141
+ ## Making a release
209
142
 
210
143
  1. Make a PR with one commit that updates the version number in `pyproject.toml` and `maltoolbox/__init__.py`.
211
144
  Follow [Semantic versioning](https://semver.org/).
@@ -5,37 +5,9 @@ MAL ([Meta Attack Language](https://mal-lang.org/)) models and attack graphs.
5
5
 
6
6
  Attack graphs can be used to run simulations in [MAL Simulator](https://github.com/mal-lang/mal-simulator) or run your own custom analysis on.
7
7
 
8
- - [MAL Toolbox Documentation](https://mal-lang.org/mal-toolbox/index.html)
8
+ - [MAL Toolbox Documentation](https://github.com/mal-lang/mal-toolbox/wiki)
9
9
  - [MAL Toolbox tutorial](https://github.com/mal-lang/mal-toolbox-tutorial)
10
10
 
11
- ## The Language Module
12
-
13
- The language module provides various tools to process MAL languages.
14
-
15
- ## The Model Module
16
-
17
- With a MAL language a Model (a MAL instance model) can be created either
18
- from a model file or empty.
19
-
20
- The model class will store all of the relevant information to the MAL
21
- instance model, most importantly the assets and their associations.
22
-
23
- Model objects can be used to generate attack graphs with the AttackGraph module.
24
-
25
- ## The Attack Graph Module
26
-
27
- The attack graph module contains tools used to generate attack graphs from
28
- existing MAL instance models and analyse MAL attack graphs. The function used
29
- to generate the attack graph is `generate_graph` and it requires the instance
30
- model and language specification. The resulting attack graph will contain
31
- nodes for each of the attack steps. The structure of the attack node data
32
- class can be seen in `attackgraph/node.py` file. Of note are the lists of
33
- children and parents which allow for easy reference to the other attack step
34
- nodes related and the asset field which will contain the object in the model
35
- instance to which this attack step belongs to, if this information is
36
- available.
37
-
38
-
39
11
  # Usage
40
12
 
41
13
  ## Installation
@@ -116,50 +88,9 @@ Notes:
116
88
  compiler) or a .mal file containing the DSL written in MAL.```
117
89
  ```
118
90
 
119
- ## Code examples / Tutorial
120
-
121
- To find more code examples and tutorials, visit the
122
- [MAL Toolbox Tutorial](https://github.com/mal-lang/mal-toolbox-tutorial/tree/main) repository.
123
-
124
- ### Load a language
125
- ```python
126
-
127
- from maltoolbox.language import LanguageGraph
128
-
129
- # Will load the MAL language (.mal/.mar) or a saved language graph (yml/json)
130
- lang_graph = LanguageGraph.load_from_file(lang_file_path)
131
-
132
- ```
133
-
134
- ### Generate a model
135
- ```python
136
- from maltoolbox.model import Model
137
-
138
- # Create an empty model
139
- instance_model = Model("Example Model", lang_graph)
140
-
141
- # Create and add assets of type supported by the MAL language
142
- asset1 = instance_model.add_asset('Application', 'Application1')
143
- asset2 = instance_model.add_asset('Application', 'Application2')
144
-
145
- # Create association between the assets
146
- asset1.add_associated_assets('appExecutedApps', asset2)
147
- ```
148
-
149
- ## Generate an attack graph
150
-
151
- ```python
152
-
153
- from maltoolbox.attackgraph import AttackGraph
154
-
155
- attack_graph = AttackGraph(lang_graph, model)
156
-
157
- ```
158
-
159
-
160
- ## Contributing
91
+ # Contributing
161
92
 
162
- # CI Pipeline
93
+ ## CI Pipeline
163
94
 
164
95
  Checks are made with:
165
96
 
@@ -169,12 +100,12 @@ Checks are made with:
169
100
 
170
101
  Make sure pipeline passes before PR is marked "Ready for review".
171
102
 
172
- # Tests
103
+ ## Tests
173
104
  There are unit tests inside of ./tests.
174
105
 
175
106
  To run all tests, use the `pytest` command. To run just a specific file or test function use `pytest tests/<filename>` or `pytest -k <function_name>`.
176
107
 
177
- # Making a release
108
+ ## Making a release
178
109
 
179
110
  1. Make a PR with one commit that updates the version number in `pyproject.toml` and `maltoolbox/__init__.py`.
180
111
  Follow [Semantic versioning](https://semver.org/).
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mal-toolbox
3
- Version: 1.2.1
3
+ Version: 2.0.0
4
4
  Summary: A collection of tools used to create MAL models and attack graphs.
5
5
  Author-email: Andrei Buhaiu <buhaiu@kth.se>, Joakim Loxdal <loxdal@kth.se>, Nikolaos Kakouros <nkak@kth.se>, Jakob Nyberg <jaknyb@kth.se>, Giuseppe Nebbione <nebbione@kth.se>, Sandor Berglund <sandor@kth.se>
6
6
  License: Apache Software License
@@ -25,6 +25,8 @@ Requires-Dist: docopt
25
25
  Requires-Dist: PyYAML
26
26
  Requires-Dist: py2neo
27
27
  Requires-Dist: networkx
28
+ Requires-Dist: tree-sitter-mal~=1.0.0
29
+ Requires-Dist: tree-sitter
28
30
  Provides-Extra: dev
29
31
  Requires-Dist: pytest; extra == "dev"
30
32
  Dynamic: license-file
@@ -36,37 +38,9 @@ MAL ([Meta Attack Language](https://mal-lang.org/)) models and attack graphs.
36
38
 
37
39
  Attack graphs can be used to run simulations in [MAL Simulator](https://github.com/mal-lang/mal-simulator) or run your own custom analysis on.
38
40
 
39
- - [MAL Toolbox Documentation](https://mal-lang.org/mal-toolbox/index.html)
41
+ - [MAL Toolbox Documentation](https://github.com/mal-lang/mal-toolbox/wiki)
40
42
  - [MAL Toolbox tutorial](https://github.com/mal-lang/mal-toolbox-tutorial)
41
43
 
42
- ## The Language Module
43
-
44
- The language module provides various tools to process MAL languages.
45
-
46
- ## The Model Module
47
-
48
- With a MAL language a Model (a MAL instance model) can be created either
49
- from a model file or empty.
50
-
51
- The model class will store all of the relevant information to the MAL
52
- instance model, most importantly the assets and their associations.
53
-
54
- Model objects can be used to generate attack graphs with the AttackGraph module.
55
-
56
- ## The Attack Graph Module
57
-
58
- The attack graph module contains tools used to generate attack graphs from
59
- existing MAL instance models and analyse MAL attack graphs. The function used
60
- to generate the attack graph is `generate_graph` and it requires the instance
61
- model and language specification. The resulting attack graph will contain
62
- nodes for each of the attack steps. The structure of the attack node data
63
- class can be seen in `attackgraph/node.py` file. Of note are the lists of
64
- children and parents which allow for easy reference to the other attack step
65
- nodes related and the asset field which will contain the object in the model
66
- instance to which this attack step belongs to, if this information is
67
- available.
68
-
69
-
70
44
  # Usage
71
45
 
72
46
  ## Installation
@@ -147,50 +121,9 @@ Notes:
147
121
  compiler) or a .mal file containing the DSL written in MAL.```
148
122
  ```
149
123
 
150
- ## Code examples / Tutorial
151
-
152
- To find more code examples and tutorials, visit the
153
- [MAL Toolbox Tutorial](https://github.com/mal-lang/mal-toolbox-tutorial/tree/main) repository.
154
-
155
- ### Load a language
156
- ```python
157
-
158
- from maltoolbox.language import LanguageGraph
159
-
160
- # Will load the MAL language (.mal/.mar) or a saved language graph (yml/json)
161
- lang_graph = LanguageGraph.load_from_file(lang_file_path)
162
-
163
- ```
164
-
165
- ### Generate a model
166
- ```python
167
- from maltoolbox.model import Model
168
-
169
- # Create an empty model
170
- instance_model = Model("Example Model", lang_graph)
171
-
172
- # Create and add assets of type supported by the MAL language
173
- asset1 = instance_model.add_asset('Application', 'Application1')
174
- asset2 = instance_model.add_asset('Application', 'Application2')
175
-
176
- # Create association between the assets
177
- asset1.add_associated_assets('appExecutedApps', asset2)
178
- ```
179
-
180
- ## Generate an attack graph
181
-
182
- ```python
183
-
184
- from maltoolbox.attackgraph import AttackGraph
185
-
186
- attack_graph = AttackGraph(lang_graph, model)
187
-
188
- ```
189
-
190
-
191
- ## Contributing
124
+ # Contributing
192
125
 
193
- # CI Pipeline
126
+ ## CI Pipeline
194
127
 
195
128
  Checks are made with:
196
129
 
@@ -200,12 +133,12 @@ Checks are made with:
200
133
 
201
134
  Make sure pipeline passes before PR is marked "Ready for review".
202
135
 
203
- # Tests
136
+ ## Tests
204
137
  There are unit tests inside of ./tests.
205
138
 
206
139
  To run all tests, use the `pytest` command. To run just a specific file or test function use `pytest tests/<filename>` or `pytest -k <function_name>`.
207
140
 
208
- # Making a release
141
+ ## Making a release
209
142
 
210
143
  1. Make a PR with one commit that updates the version number in `pyproject.toml` and `maltoolbox/__init__.py`.
211
144
  Follow [Semantic versioning](https://semver.org/).
@@ -22,8 +22,11 @@ maltoolbox/attackgraph/analyzers/__init__.py
22
22
  maltoolbox/language/__init__.py
23
23
  maltoolbox/language/languagegraph.py
24
24
  maltoolbox/language/compiler/__init__.py
25
- maltoolbox/language/compiler/mal_lexer.py
26
- maltoolbox/language/compiler/mal_parser.py
25
+ maltoolbox/language/compiler/distributions.py
26
+ maltoolbox/language/compiler/exceptions.py
27
+ maltoolbox/language/compiler/lang.py
28
+ maltoolbox/language/compiler/mal_analyzer.py
29
+ maltoolbox/language/compiler/mal_compiler.py
27
30
  maltoolbox/patternfinder/__init__.py
28
31
  maltoolbox/patternfinder/attackgraph_patterns.py
29
32
  maltoolbox/translators/__init__.py
@@ -5,6 +5,8 @@ docopt
5
5
  PyYAML
6
6
  py2neo
7
7
  networkx
8
+ tree-sitter-mal~=1.0.0
9
+ tree-sitter
8
10
 
9
11
  [dev]
10
12
  pytest
@@ -1,4 +1,4 @@
1
- # MAL Toolbox v1.2.1
1
+ # MAL Toolbox v2.0.0
2
2
  # Copyright 2025, Andrei Buhaiu.
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -19,7 +19,7 @@
19
19
  """
20
20
 
21
21
  __title__ = "maltoolbox"
22
- __version__ = "1.2.1"
22
+ __version__ = "2.0.0"
23
23
  __authors__ = [
24
24
  "Andrei Buhaiu",
25
25
  "Giuseppe Nebbione",
@@ -28,6 +28,7 @@ class AttackGraphNode:
28
28
  self.lg_attack_step = lg_attack_step
29
29
  self.name = lg_attack_step.name
30
30
  self.type = lg_attack_step.type
31
+ self.causal_mode = self.lg_attack_step.causal_mode
31
32
  self.ttc = ttc_dist if ttc_dist is not None else lg_attack_step.ttc
32
33
  self.tags = lg_attack_step.tags
33
34
  self.detectors = lg_attack_step.detectors
@@ -0,0 +1,5 @@
1
+ from .mal_compiler import MalCompiler
2
+
3
+ __all__ = [
4
+ 'MalCompiler',
5
+ ]
@@ -0,0 +1,158 @@
1
+ class DistributionsException(Exception):
2
+ def __init__(self, error_message):
3
+ self._error_message = error_message
4
+ super().__init__(self._error_message)
5
+
6
+
7
+ class Distributions:
8
+ @staticmethod
9
+ def validate(distribution_name: str, params: list) -> None:
10
+ match distribution_name:
11
+ case 'Bernoulli':
12
+ Bernoulli.validate(params)
13
+ case 'Binomial':
14
+ Binomial.validate(params)
15
+ case 'Exponential':
16
+ Exponential.validate(params)
17
+ case 'Gamma':
18
+ Gamma.validate(params)
19
+ case 'LogNormal':
20
+ LogNormal.validate(params)
21
+ case 'Pareto':
22
+ Pareto.validate(params)
23
+ case 'TruncatedNormal':
24
+ TruncatedNormal.validate(params)
25
+ case 'Uniform':
26
+ Uniform.validate(params)
27
+ case (
28
+ 'Enabled'
29
+ | 'Disabled'
30
+ | 'Zero'
31
+ | 'Infinity'
32
+ | 'EasyAndCertain'
33
+ | 'EasyAndUncertain'
34
+ | 'HardAndCertain'
35
+ | 'HardAndUncertain'
36
+ | 'VeryHardAndCertain'
37
+ | 'VeryHardAndUncertain'
38
+ ):
39
+ Combination.validate(params)
40
+ case _:
41
+ err_msg = f'Distribution {distribution_name} is not supported'
42
+ raise (DistributionsException(err_msg))
43
+
44
+
45
+ class Bernoulli:
46
+ @staticmethod
47
+ def validate(params: list) -> None:
48
+ if not params or len(params) != 1:
49
+ err_msg = 'Expected exactly one parameter (probability), for Bernoulli distribution'
50
+ raise (DistributionsException(err_msg))
51
+ if not 0 <= params[0] <= 1:
52
+ err_msg = f"{params[0]} is not in valid range '0 <= probability <= 1', for Bernoulli distribution"
53
+ raise (DistributionsException(err_msg))
54
+
55
+
56
+ class Binomial:
57
+ @staticmethod
58
+ def validate(params: list) -> None:
59
+ if not params or len(params) != 2:
60
+ err_msg = 'Expected exactly two parameters (trials, probability), for Binomial distribution'
61
+ raise (DistributionsException(err_msg))
62
+ if not 0 <= params[1] <= 1:
63
+ err_msg = f"{params[1]} is not in valid range '0 <= probability <= 1', for Binomial distribution"
64
+ raise (DistributionsException(err_msg))
65
+
66
+
67
+ class Exponential:
68
+ @staticmethod
69
+ def validate(params: list) -> None:
70
+ if not params or len(params) != 1:
71
+ err_msg = (
72
+ 'Expected exactly one parameter (lambda), for Exponential distribution'
73
+ )
74
+ raise (DistributionsException(err_msg))
75
+ if params[0] <= 0:
76
+ err_msg = f"{params[0]} is not in valid range 'lambda > 0', for Exponential distribution"
77
+ raise (DistributionsException(err_msg))
78
+
79
+
80
+ class Gamma:
81
+ @staticmethod
82
+ def validate(params: list) -> None:
83
+ if not params or len(params) != 2:
84
+ err_msg = (
85
+ 'Expected exactly two parameters (shape, scale), for Gamma distribution'
86
+ )
87
+ raise (DistributionsException(err_msg))
88
+ if params[0] <= 0:
89
+ err_msg = (
90
+ f"{params[0]} is not in valid range 'shape > 0', for Gamma distribution"
91
+ )
92
+ raise (DistributionsException(err_msg))
93
+ if params[1] <= 0:
94
+ err_msg = (
95
+ f"{params[1]} is not in valid range 'scale > 0', for Gamma distribution"
96
+ )
97
+ raise (DistributionsException(err_msg))
98
+
99
+
100
+ class LogNormal:
101
+ @staticmethod
102
+ def validate(params: list) -> None:
103
+ if not params or len(params) != 2:
104
+ err_msg = 'Expected exactly two parameters (mean, standardDeviation), for LogNormal distribution'
105
+ raise (DistributionsException(err_msg))
106
+ if params[1] <= 0:
107
+ err_msg = f"{params[1]} is not in valid range 'standardDeviation > 0', for LogNormal distribution"
108
+ raise (DistributionsException(err_msg))
109
+
110
+
111
+ class Pareto:
112
+ @staticmethod
113
+ def validate(params: list) -> None:
114
+ if not params or len(params) != 2:
115
+ err_msg = (
116
+ 'Expected exactly two parameters (min, shape), for Pareto distribution'
117
+ )
118
+ raise (DistributionsException(err_msg))
119
+ if params[0] <= 0:
120
+ err_msg = (
121
+ f"{params[0]} is not in valid range 'min > 0', for Pareto distribution"
122
+ )
123
+ raise (DistributionsException(err_msg))
124
+ if params[1] <= 0:
125
+ err_msg = f"{params[1]} is not in valid range 'shape > 0', for Pareto distribution"
126
+ raise (DistributionsException(err_msg))
127
+
128
+
129
+ class TruncatedNormal:
130
+ @staticmethod
131
+ def validate(params: list) -> None:
132
+ if not params or len(params) != 2:
133
+ err_msg = 'Expected exactly two parameters (mean, standardDeviation), for TruncatedNormal distribution'
134
+ raise (DistributionsException(err_msg))
135
+ if params[1] <= 0:
136
+ err_msg = f"{params[1]} is not in valid range 'standardDeviation > 0', for TruncatedNormal distribution"
137
+ raise (DistributionsException(err_msg))
138
+
139
+
140
+ class Uniform:
141
+ @staticmethod
142
+ def validate(params: list) -> None:
143
+ if not params or len(params) != 2:
144
+ err_msg = (
145
+ 'Expected exactly two parameters (min, max), for Uniform distribution'
146
+ )
147
+ raise (DistributionsException(err_msg))
148
+ if params[0] > params[1]:
149
+ err_msg = f"({params[0]}, {params[1]}) does not meet requirement 'min <= max', for Uniform distribution"
150
+ raise (DistributionsException(err_msg))
151
+
152
+
153
+ class Combination:
154
+ @staticmethod
155
+ def validate(params: list) -> None:
156
+ if params and len(params) != 0:
157
+ err_msg = 'Expected exactly zero parameters, for combination distributions'
158
+ raise (DistributionsException(err_msg))
@@ -0,0 +1,37 @@
1
+ class MalCompilerError(Exception):
2
+ """Base exception for MalCompiler errors."""
3
+
4
+ pass
5
+
6
+
7
+ class MalSyntaxError(MalCompilerError):
8
+ """Raised when syntax error is encountered during compilation."""
9
+
10
+ def __init__(self, message, line=None, column=None):
11
+ self.line = line
12
+ self.column = column
13
+ super().__init__(message)
14
+
15
+
16
+ class MalParseError(MalCompilerError):
17
+ """Raised when parsing fails."""
18
+
19
+ pass
20
+
21
+
22
+ class MalTypeError(MalCompilerError):
23
+ """Raised when type checking fails."""
24
+
25
+ pass
26
+
27
+
28
+ class MalNameError(MalCompilerError):
29
+ """Raised when an undefined name is referenced."""
30
+
31
+ pass
32
+
33
+
34
+ class MalCompilationError(MalCompilerError):
35
+ """Raised when code generation fails."""
36
+
37
+ pass
@@ -0,0 +1,5 @@
1
+ from tree_sitter import Language, Parser
2
+ import tree_sitter_mal as ts_mal
3
+
4
+ MAL_LANGUAGE = Language(ts_mal.language())
5
+ PARSER = Parser(MAL_LANGUAGE)