It is MscGen, but not as we know it
SDL has a feature called inline expressions. They allow you to group a bunch of arcs and label them somehow. To define a loop, for instance. Or a conditional statement.
UML2 sequence diagrams have a similar concept called "combined fragments" (see paragraph 14.3.3 of the linked document for details).
Behaviour specification is not a particularly strong suit of interaction diagrams (sequence charts/ diagrams/ collaboration diagrams), as Martin Fowler correctly notes in UML distilled. At this time (November 2015) MscGen does not support them.
Nonetheless inline expressions are damn handy. Hence Xù - a superset of MscGen that includes them.
This is an example of a Xù script describing an interaction that loops over a list of changes and sorts the old ones to a deletion queue, and the rest to a birth queue:
msc {
width=700, hscale=0.8;
a, b [label="change store"], c, d [label="necro queue"],
e [label="natalis queue"];
a =>> b [label="get change list()"];
a alt e [label="changes found"] {
b >> a [label="list of changes"];
a =>> c [label="cull old stuff (list of changes)"];
b loop e [label="for each change"] {
c =>> b [label="get change()"];
b >> c [label="change"];
c alt e [label="change too old"] {
c =>> d [label="queue(change)"];
--- [label="change newer than latest run"];
c =>> e [label="queue(change)"];
--- [label="all other cases"];
||| [label="leave well alone"];
};
};
c >> a [label="done processing"];
--- [label="nothing found"];
b >> a [label="nothing"];
a note a [label="silent exit"];
};
}
Rendered (e.g. with the online interpreter ) this looks like so:
As you can see, the syntax of the inline expressions is very similar to that of regular arcs, the only difference being that inline expressions have a section of arcs, enclosed by curly brackets.
spanarc =
_ from:identifier _ kind:spanarctoken _ to:identifier _ al:("[" al:attributelist "]" {return al})? _ "{" _ arclist:arclist _ "}" _ ";"
To compare, this is how a regular arc looks:
regulararc =
_ from:identifier _ kind:arctoken _ to:identifier _ ("[" attributelist "]")? _ ";"
Some more examples
break {
a => b [label="Can you do this?"];
b >> a [label="Fatal error"];
};
Arguments go into the label as free text.
loop [label="for each grain of sand on the beach"] {
a => beach [label="get grain"];
a => progeny [label="add"];
};
msc {
john, shed, bike;
john alt bike [label="wheather is nice"] {
john =>> shed [label="get(bike)"];
shed >> john [label="bike"];
john =>> bike [label="use"];
--- [label="else"];
||| [label="john stays at home"];
};
}
To separate sections to execute in parallel you can use a comment line, like so:
par {
a => b;
b >> a;
---;
a => c;
c => d;
}
If you're interested in the complete grammar: the parsing expression grammar we use to generate the parser is included in the source.
MscGen uses msc
as a start token. As Xù was designed as an extension
to MscGen the same goes for Xù. If you want to be expressly clear your
script is a Xù script you can also use that:
xu {
arcgradient=20;
a,b,c;
a par c [label="Saying hello"] {
a =>> * [label="hi"];
---;
b =>> * [label="hi"];
---;
c =>> * [label="hi"];
};
a aboxc [label="Now we know each other a bit"];
}
Just like msgenny, Xù supports a "watermark" option: watermark="xù rocks!"
; that puts a watermark diagonally on the rendered chart.
MscGen has an option to automatically wrap text on regular arcs
(wordwraparcs
), which is off by default. Text in any box
(note
, box
, rbox
and abox
) or entity always automatically wraps
to fit into the box.
Both Xù and MsGenny have options to also switch that off - wordwrapboxes
on false makes sure no text in any box gets wrapped. Likewise wordwrapentities
on false makes sure no text in entities gets wrapped.
From version 1.9.0 the xù language supports the title
attribute. In SVG output
the graphics renderer packaged with mscgenjs renders these as <title>
tags.
xu {
a, b;
a => b [
label="the label",
title="The title meister strikes again"
];
a rbox b [
label="this is an rbox",
title="This is a title for an rbox"
];
b =>> b [
label="self reference",
title="Title for a self referencing arc"
];
}
To get fatter lines that indicate an entity (/ lifeline) is 'active', you can use the
boolean activation
attribute (e.g. (activation=on
and activation=off
),
or their activate
and deactivate
short hand.
Note: work in progress - the language supports it, but the graphics renderer does not yet. There'll probably need to be rules in place (either balancing activations/ deactivations or a robust way to stay out of trouble during rendering).
xu {
a, b;
a => b [
label="b gets activated with this call",
activate
];
b >> a [
label="with this return, b gets deactivated",
deactivate
];
}
MsGenny also has support for inline expressions, the if-then-else construct above would look something like this:
john, shed, bike;
john alt bike: weather is nice {
john =>> shed : get(bike);
shed >> john : bike;
john =>> bike : use;
--- : else;
||| : john stays at home;
};
- The command line interface handles by translating inline expressions to horizontal lines ("---")
# translate Xù back to MscGen
mscgen_js --output-type mscgen --input-from funkyInlineThings.xu --output-to funkyFlattenedInlineThings.mscgen
- The on line interpreter, in debug mode, has an Export this chart to Vanilla MscGen option behind the
...
button. - e.g. for the Johnny, bike, shed example
To start the interpreter in debug mode, pass debug=true
to the url:
https://sverweij.github.io/mscgen_js/index.html?debug=true
feature | SDL-RT 2.3 inline expression | UML 2 combined fragment | xù |
---|---|---|---|
Alternatives - if with an optional else | alt | alt, else | alt |
Alternatives - if with noelse | opt | opt | opt |
Break - an exception occurred. After this nothing happens. | exc | break | exc break
|
Parralel - do several things at once | par | par | par |
Weak sequencing - stuff within here can happen in any order across the instances | seq | seq | seq |
Strict sequencing - stuff within here can happen in only this order across the instances | _not available_ | strict | strict |
Negative - this is not happening | _not available_ | neg | neg |
Critical region - this is important, execute at once | _not available_ | critical | critical |
Ignore/ consider | _not available_ | ignore, consider | consider ignore |
Assertion - this stuff must be true | _not available_ | assert | assert |
Loop - repeat this | loop | loop | loop |
Reference - it's not here, but there's a diagram somewhere else detailing this | not available as an "inline expression" but as 'MSC reference' | _not available_ | ref |