Skip to content

Commit 6a15cba

Browse files
v4.1.0
Improved parser for KerML, SysMLv2 - Added support for subsetting and other means for typing in KerML - Semantic Actions separeted from recursive descent productions
1 parent 4e06b1a commit 6a15cba

File tree

373 files changed

+9104
-7667
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

373 files changed

+9104
-7667
lines changed

build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget
1616
* - also set the value standalone according to your setup
1717
*/
1818
group = "com.github.tukcps"
19-
version = "4.0.7" // must be number.number.number
19+
version = "4.1.0" // must be number.number.number
2020
val aaddVersion = "0.1.11"
21-
val sysmlapiVersion = "3.9.4"
21+
val sysmlapiVersion = "3.9.5"
2222
val useMavenAADD = true
2323
val useMavenSysMLAPI = true
2424

doc/SysMDLanguageExtensions.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ constraint-propagation semantics are built-in and considered from ground up.
8282

8383
```
8484
attribute x: Real = 0.0 .. 0.1; // or: ... = oneOf(0.0 .. 0.1); with oneOf: Range -> Real
85-
attribute y: Real(0.0 .. 0.1); // or: y { inv bounds { y >= 0.0 and y <= 0.1} }
85+
attribute y: RealInRange {:>> range = "0.0 .. 0.1";} // or: y { inv bounds { y >= 0.0 and y <= 0.1} }
8686
```
8787

8888
_Note, that for the sake of interoperability, we in the next releases we will focus on the standard-compliant version and deprecate non-compliant

doc/Time.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ Time can be presented in the following units: second (s), minute (min), hour (h)
99

1010
Examples:
1111
```
12-
t1: Real(20..50)[s] = 10.0 [s].
13-
t2: Real(20..50)[min] = 10.0 [min].
12+
t1: Real = 10.0 [s] {:>> unit = "s"; :>> range = "20..50";}
13+
t2: Real = 10.0 [min] {:>> unit = "min"; :>> range = "20..50";}
1414
```
1515

1616
## Date

install/1-SysMD-Kickstart/SysMD-Modeling.md

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Initially, there are only the KerML standard libraries.
2020
### Import of namespaces
2121
Other namespaces can be imported to simplify the notations.
2222
For example, the standard package ```ScalarValues``` introduces standard data types like:
23+
2324
- Real
2425
- Boolean
2526
- Integer
@@ -30,7 +31,8 @@ By importing the namespace of the package ```ScalarValues``` we can access it
3031
by its simple name as follows:
3132
```SysML::kickstart
3233
private import ScalarValues::*; // Allows us shortcuts to Real, Integer, etc.
33-
private import SI::*; // Allows us shortcuts to Domains
34+
private import SI::*; // Allows us shortcuts to Domains
35+
private import Ranges::*; // Allows us to specify constraints & co/contravariance
3436
attribute r: Real = oneOf(2.0 .. 3.0); // assigns r a value, constraine to the range 2 to 3.
3537
attribute i: Integer = 2; // assigns i the value 2.
3638
```
@@ -53,18 +55,18 @@ It provides additional means to add constraints to numbers; the constraints can
5355
```Markdown
5456
library package Ranges {
5557
// Abstract concept of a Range from which a Real is chosen
56-
datatype InRange {
57-
feature min: ScalarValues::Real;
58-
feature max: ScalarValues::Real;
59-
inv { (min <= self) and (self <= max) }
58+
abstract datatype InRange {
59+
feature range: Ranges::Range; // Models a range
60+
inv { (that.min <= self) and (that <= range.max) }
6061
}
61-
datatype AllInRange :> InRange;
62+
abstract datatype AllInRange :> InRange; // ...
63+
abstract datatype QuantityInRange :> InRange; // ...
6264
}
6365
```
6466
These constraints are used to represent and propagate constraints, where
6567

66-
- _min_ is a known lower bound,
67-
- _max_ is a known upper bound,
68+
- _range_ bounds the range of a Number (e.g. Integer, Real) to the given range.
69+
6870
- _AllInRange_ specifies that the constraint system shall be satisfied for all values in the range _min .. max_.
6971

7072
Below, we give some simple examples.
@@ -84,7 +86,7 @@ part rangeExample {
8486
attribute height: Length = oneOf(10.0 .. 100.0 [cm]);
8587
attribute width: Length = oneOf(1.0 .. 1.1 [m]);
8688
attribute length: Length = oneOf(1.0 .. 1.1 [m]);
87-
attribute volume: Volume = height * width * length {
89+
attribute volume: Volume, Ranges::QuantityInRange = height * width * length {
8890
:>> range = "1000.0 .. 2000.0";
8991
:>> unit = "l";
9092
}
@@ -141,10 +143,10 @@ Units are converted automatically before computations are done, and the consiste
141143
the unit left of a dependency, and the unit right of it must be convertible into each other.
142144
```SysML::kickstart
143145
package unitsExample {
144-
attribute t: Time [s] = 1.0 [s];
145-
attribute v: Speed [m/s] = 3.0 [m/s];
146-
attribute g: Acceleration [m/s^2] = 4.0 [m/s^2];
147-
attribute s: Speed [m/s] = sqrt(sqr(v)+sqr(g)*sqr(t));
146+
attribute t: Time = 1.0 [s];
147+
attribute v: Speed = 3.0 [m/s];
148+
attribute g: Acceleration = 4.0 [m/s^2];
149+
attribute s: Speed = sqrt(sqr(v)+sqr(g)*sqr(t));
148150
}
149151
```
150152
Play with the units, e.g., by changing the unit after the type declaration or try ms instead of s.
@@ -153,7 +155,7 @@ For date and time, the ISO format is supported.
153155
We can add and subtract times in this format.
154156
```SysML::kickstart::unitsExample
155157
attribute date: Time [DateTime] = DateTime("2021-10-10T03:00:00");
156-
attribute time: Time [a] = 1.0 a;
158+
attribute time: Time = 1.0 a {:>> unit="a";}
157159
attribute dateResult: Time [DateTime] = date + time;
158160
```
159161
### Vectors
@@ -163,17 +165,17 @@ operations like the angle or cross-product.
163165
Here is an example for defining vectors:
164166
```SysML::kickstart
165167
package vectors {
166-
attribute a: Mass(0.0..1.0,1.0..2.0) [kg] = (0.5,1.5) kg;
168+
attribute a: Mass = (0.5,1.5) kg {:>> range="0.0..1.0,1.0..2.0";}
167169
attribute b: Mass = (0.5,1.5) kg;
168-
attribute c: Mass(-5.0..-1.0,-1.0..2.0, 2.0..4.0) [kg] = (-5.0, -1.0, 3.0) kg;
170+
attribute c: Mass = (-5.0, -1.0, 3.0) kg {:>> range="-5.0..-1.0,-1.0..2.0, 2.0..4.0";}
169171
}
170172
```
171173
In the next example, there is a calculation with Vectors with the cross-product and angle.
172174
```SysML::kickstart::vectors
173-
attribute a2: Real(1..1,5..5,10..10);
174-
attribute b2: Real(5..5,1..1,10..10);
175+
attribute a2: Real, InRange {:>> range="1..1,5..5,10..10";}
176+
attribute b2: Real, InRange {:>> range="5..5,1..1,10..10";}
175177
attribute c2: Real = a2 cross b2;
176-
attribute d2: Quantity [°] = angle(a2,b2);
178+
attribute d2: Quantity = angle(a2,b2) {:>>unit="°";}
177179
```
178180
## Types and Functions in Expressions
179181
SysMD supports the following types:
@@ -249,13 +251,13 @@ vehicles via its path as shown in the example below.
249251
```SysML::kickstart
250252
package carParts {
251253
part def Body {
252-
attribute mass: Mass(300.0) [kg];
254+
attribute mass: Mass {:>> range="300.0";}
253255
}
254256
part def Engine {
255-
attribute mass: Mass(300.0) [kg];
257+
attribute mass: Mass {:>> range="300.0";}
256258
}
257259
part def Wheel {
258-
attribute mass: Mass(50.0) [kg];
260+
attribute mass: Mass {:>> range="50.0";}
259261
}
260262
}
261263
```
@@ -291,14 +293,14 @@ Specializations inherit features.
291293
// We consider a vehicle to be anything that has at least one wheel.
292294
// The bySubclasses determines a consistent value for mass with min diameter.
293295
part def Vehicle {
294-
attribute mass: Mass(0..1000) [kg] = bySpecializations(mass);
296+
attribute mass: Mass = bySpecializations(mass) {:>> range ="0..1000";}
295297
part wheels: carParts::Wheel[1 .. *];
296298
}
297299
298300
// A car is a vehicle with Body and Engine.
299301
// the sumOverParts determines a consistent minimal range consistent with parts.
300302
part def Car :> Vehicle {
301-
attribute redefines mass: Mass(0 .. 1000)[kg] = sumOverParts(mass);
303+
attribute redefines mass: Mass = sumOverParts(mass) {:>> range ="0 .. 1000";}
302304
part wheels: carParts::Wheel[4 .. 10];
303305
part body: carParts::Body;
304306
part engine: carParts::Engine;
@@ -321,7 +323,7 @@ Boolean properties. They may also have a physical unit. Then, we specify:
321323

322324
There is also a possibility to define user defined functions with any number of input variables .
323325
These functions can be defined once and used multiple times.
324-
```SysML::Global::kickstart
326+
```SysML::kickstart
325327
package CalculationExample {
326328
// Definition of a Calculation
327329
calc def calcEnergy {

install/3-SysMLv2Tutorial/sysml.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,8 @@ package stateMachineExample {
287287
}
288288
```
289289
While no calculations are yet done by SysMD for state machines, one can render it.
290-
Navigate in the hasA tree to the state status and right-click on it.
290+
Navigate in the hasA tree to the state ```tutorial::sysml::stateMachineExample::part1::status```.
291+
Right-click on it.
291292
Select render graph, and the following automata graph will be shown:
292293

293294
![Graph](Files/statemachine.png){width=400 height=220}

src/main/kotlin/com/github/tukcps/sysmd/Main.kt

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,12 @@ val logger: Logger = LoggerFactory.getLogger("SysMD Notebook")
1818

1919
fun main(args: Array<String>) {
2020

21-
SplashScreen.show()
21+
SplashScreen.show("headless" in args)
2222

2323
SpringApplicationBuilder(
2424
SysMdRunner::class.java,
25-
) .headless(false)
25+
) .headless("headless" in args)
2626
.run(*args)
27-
2827
}
2928

3029
/**
@@ -35,20 +34,10 @@ fun main(args: Array<String>) {
3534
*/
3635
object SplashScreen {
3736

38-
// Prevent splash screen during unit tests or for server mode ...
39-
private fun isRunningTest(): Boolean {
40-
try {
41-
Class.forName("org.junit.Test")
42-
} catch (e: ClassNotFoundException) {
43-
return false
44-
}
45-
return true
46-
}
47-
4837
private var splashScreen: JFrame? = null
4938

50-
fun show() {
51-
if (!isRunningTest()) {
39+
fun show(headless: Boolean) {
40+
if (!headless) {
5241
splashScreen = JFrame("SysMD Notebook Splash Screen")
5342
splashScreen?.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
5443
splashScreen?.setSize(1000, 800)

src/main/kotlin/com/github/tukcps/sysmd/SysMdRunner.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import com.github.tukcps.sysmd.exports.Exporter
1414
import com.github.tukcps.sysmd.exports.UcbDataPack
1515
import com.github.tukcps.sysmd.generated.resources.Res
1616
import com.github.tukcps.sysmd.generated.resources.SysMD_Icon
17+
import com.github.tukcps.sysmd.model.kerml.Feature
1718
import com.github.tukcps.sysmd.model.sysml.StateUsage
1819
import com.github.tukcps.sysmd.rest.RESTRepository
1920
import com.github.tukcps.sysmd.services.session.SessionManager
@@ -104,7 +105,7 @@ open class SysMdRunner: CommandLineRunner {
104105
if ("headless" !in args)
105106
try {
106107
init()
107-
logger.info("Starting SysMD ${AppTheme.version} with options '$args'")
108+
logger.info("Starting SysMD ${AppTheme.version} with options ${args.toList()}")
108109
val sysMdViewModel = SysMDViewModel(session)
109110
application {
110111
val showDialog = remember { mutableStateOf(false) }
@@ -173,7 +174,7 @@ open class SysMdRunner: CommandLineRunner {
173174
var ucbData: UcbDataPack? = null
174175
val systemcExporter = Exporter()
175176
try {
176-
systemcExporter.analyzeSysMD(elementToSystemC?.value!!)
177+
systemcExporter.analyzeSysMD(elementToSystemC?.value!! as Feature)
177178
ucbData = systemcExporter.getUCBData()
178179
openUCB.value = true
179180
} catch (e: Exception) {

src/main/kotlin/com/github/tukcps/sysmd/compiler/HoodSysmlParser.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,5 @@ class HoodSysmlParser {
2828
fun getActionUsages(owner: Element): List<ActionUsage> =
2929
owner.getOwnedElementsOfType<ActionUsage>()
3030

31-
fun getOwner(it: Element) = it.owner.ref
31+
fun getOwner(it: Element) = it.owner
3232
}

src/main/kotlin/com/github/tukcps/sysmd/compiler/KerML.kt

Lines changed: 21 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,10 @@ import com.github.tukcps.sysmd.compiler.parser.kerml.QualifiedName
99
import com.github.tukcps.sysmd.compiler.parser.util.ParserProductionRules
1010
import com.github.tukcps.sysmd.compiler.scanner.Token
1111
import com.github.tukcps.sysmd.compiler.scanner.Token.Kind.*
12-
import com.github.tukcps.sysmd.compiler.semantics.SemanticActions
12+
import com.github.tukcps.sysmd.compiler.semantics.ActionsContext
1313
import com.github.tukcps.sysmd.exceptions.Issue
1414
import com.github.tukcps.sysmd.exceptions.SyntaxError
1515
import com.github.tukcps.sysmd.exceptions.SysMDException
16-
import com.github.tukcps.sysmd.model.kerml.TextualRepresentation
1716
import com.github.tukcps.sysmd.model.util.QualifiedName
1817
import com.github.tukcps.sysmd.quantities.Quantity
1918
import com.github.tukcps.sysmd.services.session.Session
@@ -46,36 +45,30 @@ open class KerML(
4645
keywords: Map<String, Token.Kind> = Token.kerMLKeywords,
4746
) : ParserProductionRules(keywords = keywords) {
4847

49-
var semantics: SemanticActions = SemanticActions(model, compiler = this)
48+
var semantics = ActionsContext(model, compiler = this)
5049

5150
/**
52-
* Parses the body of the textual representation while considering the owner prefix.
53-
*/
54-
@Deprecated("Use parse with string input instead")
55-
fun parse(textualRepresentation: TextualRepresentation) {
56-
this.input = textualRepresentation.body
57-
semantics.initOwners(textualRepresentation.getOwnerPrefix())
58-
parse()
59-
}
60-
61-
/**
62-
* Parses an input directly.
63-
* No TextualRepresentation is needed, and no annotations, etc.
51+
* Parses an input directly given as a CharSequence.
6452
* @param input the char sequence that is parsed
6553
* @param ownerQualifiedName the qualified name of the package that gives the scope.
6654
*/
6755
fun parse(
6856
input: CharSequence,
69-
ownerQualifiedName: QualifiedName = "Global",
57+
ownerQualifiedName: QualifiedName = "",
7058
){
7159
this.input = input
72-
semantics.initOwners(ownerQualifiedName)
60+
semantics.initOwningNamespaces(ownerQualifiedName)
7361
parse()
7462
}
7563

7664

77-
// Re-definition of the Parser template's error message function
78-
override var error = fun(message: String) { model.status.error(message = message, this) }
65+
/**
66+
* Re-definition of the Parser template's error message function.
67+
* error is a lambda that is used for error reporting.
68+
*/
69+
override var error = fun(message: String) {
70+
model.status.error(message = message, this, element = semantics.element())
71+
}
7972

8073
/**
8174
* RootNamespace :- ( NamespaceBodyElement )* EOF
@@ -86,20 +79,20 @@ open class KerML(
8679
NamespaceBodyElement() // KerML textual
8780
} catch (exception: Exception) {
8881
handleError(exception)
89-
semantics.initOwners("Global")
82+
semantics.initOwningNamespaces("Global")
9083
}
9184
}
9285
try {
9386
EOF.consume()
9487
} catch (exception: Exception) {
9588
handleError(exception)
96-
semantics.initOwners("Global")
89+
semantics.initOwningNamespaces("Global")
9790
}
9891
}
9992

10093

10194
/**
102-
* QualifiedNameList :- QualifiedName ("," QualifiedName )*
95+
* QualifiedNameList :- QualifiedName ("," QualifiedName )*
10396
* Semantics: returns a list of identifications that have been parsed.
10497
*/
10598
fun QualifiedNameList(): MutableList<QualifiedName> {
@@ -170,13 +163,13 @@ open class KerML(
170163
} else
171164
model.status.fatal(exception.message?: "Unknown error", this, cause = exception)
172165
// Skip input until we get the next DOT (=end of triple) or RCURBRACE or EOF.
173-
var nested = 0;
166+
var nested = 0
174167
while (
175168
(token.kind != SEMICOLON || nested > 0)
176169
&& token.kind != EOF
177170
&& (token.kind != RCURBRACE || nested <= 0)) {
178-
if (token.kind == LCURBRACE) nested = nested+1;
179-
if (token.kind == RCURBRACE) nested = nested-1;
171+
if (token.kind == LCURBRACE) nested = nested+1
172+
if (token.kind == RCURBRACE) nested = nested-1
180173
consume()
181174
}
182175
// If parser skips right curly brace, we need to also pop one from the owner stack.
@@ -190,14 +183,14 @@ open class KerML(
190183
internal fun handleSyntaxError(message: String) {
191184
model.status.error(message, this, semantics.namespace, Issue.Kind.ERROR_SYNTACTICAL)
192185
// Skip input until we get the next DOT (=end of triple) or RCURBRACE or EOF.
193-
var nested = 0;
186+
var nested = 0
194187
while (
195188
(token.kind != SEMICOLON || nested > 0)
196189
&& token.kind != EOF
197190
&& (token.kind != RCURBRACE || nested <= 0)
198191
) {
199-
if (token.kind == LCURBRACE) nested = nested+1;
200-
if (token.kind == RCURBRACE) nested = nested-1;
192+
if (token.kind == LCURBRACE) nested = nested+1
193+
if (token.kind == RCURBRACE) nested = nested-1
201194
consume()
202195
}
203196
// If parser skips right curly brace, we need to also pop one from the owner stack.

0 commit comments

Comments
 (0)