Skip to content
Leon Starr edited this page Jul 27, 2026 · 2 revisions

Unlike program code, models should express the components and behavior of your system as clearly as possible to mere humans. The grammar supports a more natural language friendly way of naming state model elements like transitions, events and states with rules that would horrify most programmers. Within some limits, of course as we do need to ensure the models are unambiguous and executable, unlike natural language.

Our state modeling grammar threads that needle, so before diving in, you may want to review the precise naming rules.

Almost everything you write in an xsm file — a domain, a class, an event, a state, a parameter, a type — is a name. Here's the grammar:

// Elements
name = word (delim word)* r'\?'? // A name is a sequence of one or more words separated by delimiters with optional ?
word = r"[A-Za-z][A-Za-z0-9']*" // Word beginning with an alpha character allowing apostrophe for contractions
delim = r'[ _]' // Delimiter used inside of names
INDENT = "    "  // Need INDENT for clarity and to signal unstructured lines of text
block_end = "--" EOL*  // Signifies end of a block (within section)
rnum = r'O?R[1-9][0-9]*' // Relationship number

Words

A word starts with a letter and continues with letters, digits and apostrophes. So Door, R2, Level2 and driver's are all words. A word may not start with a digit or contain a hyphen.

This means that you can have a state named: Is it there yet? Or you can name an event: Can't close the door

As you can see in the grammar, a question mark may only appear at the end of a name.

Caveat: The above grammar is only for structural model elements and not the action language used inside a state's activity section. The Scrall action language uses a different parser and grammar that employs many punctuation characters as operators and other computational elements. Don't worry, the naming rules aren't that different, but punctuation characters like ' and ? are not available for naming within an activity.

Delimiters

Words within a name are joined by a single space or a single underscore. That's what makes Can't close door one event name rather than three words, and it's why multi-word names read so naturally in this language.

Note, however:

  • One delimiter only. Cannot close door with two spaces is not a name.
  • Spaces and underscores are not equivalent. Are we there? and Are_we_there? both parse, but they are different names. So choose your naming style and stick with it.

The trailing question mark

A name may end in a single ?, which is useful for states that ask something:

state Are we already there?

The ? is part of the name. Any transition targeting that state has to include it.

Capitalization

The grammar doesn't enforce all aspects of this style, but I have adopted a consistent style for naming model elements.

  • Class and domain names get initial caps on each significant word — Accessible Shaft Level.
  • Waiting states are all caps and transient states are mixed case.
  • Keywords are all lowercase and unindented: metadata, domain, class, relationship, events, initial transitions, state, activity, transitions.

Indentation

The INDENT token is exactly four spaces. It's what marks metadata items, event declarations, transitions and Activities body lines, and it's how the grammar distinguishes structure from the unstructured action language text inside an activity. Tabs will not do, and neither will two or six spaces at the structural level — though within an activity body you may indent as deeply as you like past the first four.

Block ends

The -- token, always unindented, closes the Events section, the Initial transitions section and each individual state block. It's the one piece of punctuation doing real structural work in this language.

Comments and blank lines

// Whitespace and comments
EOL = SP* COMMENT? '\n' // end of line: Comments, blank lines, whitespace we can omit from the parser result
COMMENT = '//' r'.*' // Comment slashes don't work if included in the regular expression for some reason
SP = " "

A comment starts with // and runs to the end of the line. Blank lines are fine between sections. Both are discarded by the parser and never appear in the result — with the exception of comments inside an activity body (see Activities), which are just part of the raw action language text and get passed straight through.

Clone this wiki locally