Appendix H: Lexical Reference
The chapters teach constructs. This appendix covers the smaller rules underneath them – how names, literals, and comments are actually written – and in particular the two forms the chapters use without stopping to explain: root-qualified names and quoted names.
Names
An ordinary name is an identifier: CoffeeMachine, grindSize, waterTank.
The book’s convention, and a common one, is UpperCamelCase for definitions and
lowerCamelCase for usages and attributes. Nothing in the language enforces
that, but a reader scanning a model relies on it.
Qualified and root-qualified names
<Package>::<Member>
$::<Package>::<Member>
part grinder : CoffeeMachineDomain::Definitions::Grinder;
A qualified name walks down from a visible namespace. Reach for one when a bare name would be ambiguous across packages.
Prefixing $:: makes it a root-qualified name: lookup starts at the model
root rather than the enclosing scope. It is the escape hatch for the case where
a local name shadows the one you meant.
Quoted names, for names that are not identifiers
<'<short-name>'> '<long name>'
requirement def <'REQ-TEMP-01'> 'Extraction Temperature' {
doc /* Water temperature shall remain within operating range. */
}
Read it as: this requirement’s short name is REQ-TEMP-01 and its name is
Extraction Temperature.
A name in single quotes is an unrestricted name, and it may contain
characters an identifier cannot – spaces, hyphens, punctuation. Angle brackets
declare a short name, which is why requirement identifiers like REQ-TEMP-01
are written <'REQ-TEMP-01'>: the hyphens would otherwise be read as
subtraction. To put a quote inside such a name, escape it: 'REQ\'TEMP-02'.
This is the form Chapter 10 and Chapter 11 use for requirement identifiers.
Use quoted names where they earn their keep – requirements and cases that carry an external identifier or a human-readable title – and plain identifiers everywhere else.
Literals
attribute grindSize : Real = 0.4;
attribute enabled : Boolean = true;
attribute label : String = "Main Grinder";
- Booleans are
trueandfalse. - Strings are double-quoted.
- Reals may lead with a dot –
.5is valid – and may use scientific notation:1e3,9.8e-2. nullis the null literal.()is an equivalent spelling of the same empty value, which is worth recognising when you meet it in library sources.*is the infinity literal. It is what makes[0..*]mean “any number of” in a multiplicity, and it is the same token as multiplication – position tells them apart.
Comments, and why doc is different
part def Brewer {
doc /* Heats and pressurizes water for extraction. */
//* A note to whoever is editing this file next.
attribute waterTemp : Real = 93.0;
}
doc creates a documentation element in the model. It survives into the
model itself, so tools can show it on hover, carry it into a generated document,
and export it through the API.
//* notes do not. Per the specification’s own grammar they are hidden
tokens, discarded during parsing in the same way whitespace is. They never
become part of the model.
So the choice is not stylistic. If the sentence explains what an element is,
it belongs in doc, where a reviewer who never opens the source file will still
see it. If it is a message to the next person editing the file, //* is right.
The most common mistake here is writing model meaning into a note and then wondering why it does not appear anywhere in the tooling.
Marking the language of documentation
part def Brewer {
doc locale "en-GB" /* Heats and pressurises water for extraction. */
}
A doc may carry a locale – a string naming the natural language the
documentation is written in. It is optional, and worth setting on a model whose
documentation is translated or whose readership is mixed, because it lets a tool
pick the right text rather than guessing. Comments take the same modifier.
Embedding another language
The specification also provides a way to carry a fragment of some other language inside a model element:
[rep <name>] language "<language-name>" /* <the fragment> */
This is a textual representation (SysML §8.2.2.4.3). The intent is that a constraint expressed in OCL, a formula in MathML, or a snippet of source can travel with the element it belongs to, tagged with what language it is in, so a tool that understands that language can pick it up and one that does not can leave it alone.
Not available in sysml-rs. The parser does not accept this form. Worse, a
repline without the string is absorbed as a pair of ordinary names rather than reported as an error, so it fails quietly. The construct is in the specification and in the grammar; it is simply not implemented here, and this book does not use it.