Appearance
Formal Specification
This page is the formal specification of the Instant Process language. Every node type the language supports is defined here as an EBNF production, accompanied by the constraints that EBNF cannot express on its own (uniqueness, defaulting, semantic restrictions).
Use this page when you need an unambiguous reference: tooling authors, reviewers writing parsers, and anyone integrating with the language. For a friendlier introduction, see the Documentation and the per-node pages.
Notation
The grammar uses the ISO/IEC 14977 EBNF metasymbols:
| Metasymbol | Meaning |
|---|---|
= | Defines a rule (left-hand side is the non-terminal being defined). |
; | Terminates a rule. |
, | Concatenation: items appear in sequence. |
| | Alternation: exactly one of the listed items. |
[ x ] | The item x is optional (zero or one occurrence). |
{ x } | The item x may repeat zero or more times. |
( x ) | Grouping. |
"x" | A literal terminal (case-sensitive). |
(* … *) | A grammar comment; non-normative. |
Whitespace (spaces, tabs) separates tokens but is otherwise insignificant. Each Node production occupies a single logical line; line breaks separate nodes. A # starts a comment that runs to the end of the line; comments are stripped before parsing and are ignored everywhere a token may appear.
Lexical productions
These productions define the basic tokens that node productions are built from.
text
Letter = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J"
| "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T"
| "U" | "V" | "W" | "X" | "Y" | "Z"
| "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j"
| "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t"
| "u" | "v" | "w" | "x" | "y" | "z" ;
Digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
IdChar = Letter | Digit | "_" | "-" ;
Identifier = ( Letter | "_" ) , { IdChar } ;
DescriptionChar = ? any Unicode character except "'" ? ;
Description = "'" , { DescriptionChar } , "'" ;
CommentChar = ? any Unicode character except a line break ? ;
Comment = "#" , { CommentChar } ;
HexDigit = Digit | "a" | "b" | "c" | "d" | "e" | "f"
| "A" | "B" | "C" | "D" | "E" | "F" ;
ProcessId = "'" , 8 * HexDigit , "-" , 4 * HexDigit , "-" , 4 * HexDigit , "-"
, 4 * HexDigit , "-" , 12 * HexDigit , "'" ;Constraints (not expressible in EBNF):
- An
Identifiermust not contain whitespace and must not be enclosed in quotes, those forms are reserved forDescription. - A
Descriptionmust contain at least one character; an empty description ('') is invalid. - A
Commentruns from the#to the end of the line and is discarded before parsing, so it may appear on its own line or after a complete node. It carries no meaning and never becomes part of the process. - A
#inside aDescriptionis an ordinary character, not the start of a comment. - Every node in a process must resolve to a unique identifier across the whole process. See Identifiers for how implicit and explicit identifiers share a namespace.
- A
ProcessIdis the id of a process stored in the drive. It is written between single quotes and must be a well-formed id; the compiler does not check that a process with that id exists.
Node references
A NodeRef is how one node points at another, either by an explicit identifier token or by a description that doubles as an implicit identifier.
text
NodeRef = Identifier | Description ;Constraints:
- A
NodeRefwritten as anIdentifiermatches a node whose explicit identifier is that token. - A
NodeRefwritten as aDescriptionmatches a node whose implicit identifier (its description) is that string. - Every
NodeRefmust resolve to a node or a pool that exists in the same process. ANodeRefthat names a pool is a connection that ends on that pool; see Pool.
Connections (NEXT, NEXT-MESSAGE, NEXT-ASSOCIATION and AND)
A node connects to other nodes with three clauses. The NextClause declares sequence flows, the MessageClause declares message flows and the AssociationClause declares associations. Every node type that carries outgoing connections uses the same clauses. They are defined once here and referenced from each node-type production.
Edge labels
A LinkDescription is an optional label attached to a single edge.
text
LinkDescription = Description ;A single outgoing connection
A NextTarget is one outgoing edge: a target node and an optional edge label.
text
NextTarget = NodeRef , [ LinkDescription ] ;The NEXT clause
A NextClause is either a bare NEXT (which falls through to the next node in the text), or NEXT followed by one or more NextTargets joined by AND. Every edge of a NextClause is a sequence flow.
text
NextClause = "NEXT" , [ NextTarget , { "AND" , NextTarget } ] ;The NEXT-MESSAGE clause
A MessageClause has the shape of a NextClause with the keyword NEXT-MESSAGE in the place of NEXT. Every edge of a MessageClause is a message flow.
text
MessageClause = "NEXT-MESSAGE" , [ NextTarget , { "AND" , NextTarget } ] ;The NEXT-ASSOCIATION clause
An AssociationClause has the shape of a NextClause with the keyword NEXT-ASSOCIATION in the place of NEXT. Every edge of an AssociationClause is an association: a link between a node and information that belongs with it, outside the flow of the process.
text
AssociationClause = "NEXT-ASSOCIATION" , [ NextTarget , { "AND" , NextTarget } ] ;The connections of a node
A node carries one, two or three connection clauses, in any order, with at most one clause of each kind. Each clause has its own AND chain.
text
ConnectionClause = NextClause | MessageClause | AssociationClause ;
Connections = ConnectionClause , [ ConnectionClause ] , [ ConnectionClause ] ;text
GATEWAY 'Approved?' NEXT 'Ship order' 'Yes' AND 'Archive' NEXT-MESSAGE 'Notify customer' 'No' NEXT-ASSOCIATION 'Approval policy'In this line the edges to Ship order and Archive are sequence flows, the edge to Notify customer is a message flow and the edge to Approval policy is an association.
Constraints:
- A
LinkDescriptiononly attaches to aNextTarget(after an explicitNodeRef). A bareNEXT 'Some label'is invalid because the label has no edge to attach to. - When a clause is written bare (
NEXT,NEXT-MESSAGEorNEXT-ASSOCIATIONwith noNextTarget), the connection is created to the next node in the text that takes part in sequence flow.StartNode,LaneNode,PoolNode, andAttachmentNodeare skipped as targets. If no following node exists in the process, the clause is invalid. - Each
NextTargetin anANDchain may carry its own independentLinkDescription. - An
ANDbelongs to the clause it follows. EveryNextTargetis the kind of edge its clause keyword declares, until another clause keyword starts the next clause. - A node carries at most one
NextClause, at most oneMessageClauseand at most oneAssociationClause. A secondNEXT, a secondNEXT-MESSAGEor a secondNEXT-ASSOCIATIONon the same node is invalid. - A bare
NEXT-MESSAGEmakes the fall-through edge a message flow, and a bareNEXT-ASSOCIATIONmakes it an association. When several nodes fall through to the same node, each edge is the kind its own clause declares. - A sequence flow is drawn as a solid line with a filled arrowhead. A message flow is drawn as a dashed line with a small open circle at its source and an open arrowhead at its target. An association is drawn as a dotted line without an arrowhead.
- A message flow and an association take part in layout, side assignment, gateway branch labels and reference resolution exactly as a sequence flow does. The
message-flowandassociationstylesheet selectors colour them; see Stylesheets.
Where an edge attaches
Every edge attaches to one side of a node: left, top, right or bottom.
- Outgoing edges claim their sides first, one edge per side.
- Incoming edges take the sides no outgoing edge of that node uses, one edge per side: the left side while it is free, then the free side each edge approaches from.
- Once every side is taken, further incoming edges share the left side and arrive side by side.
- Edges leaving the same side of the same node share one line, as long as they are all sequence flows, all message flows or all associations. Every other edge runs on its own line, parallel to its neighbours.
Top-level
A process is a sequence of nodes, one per line.
text
Process = { Node } ;
Node = StartNode
| EndNode
| ActivityNode
| EventNode
| GatewayNode
| LaneNode
| PoolNode
| AttachmentNode
| SubprocessNode ;Node specifications
Each section below gives a single-line EBNF production for a node type, followed by the slot-by-slot constraints. The shared rule for every node carrying a description is:
The
Identifierslot is optional. When omitted, the node'sDescriptionis used as its identifier (an implicit identifier). When present, theIdentifierreplaces the implicit identifier, and references must use the explicit token. Prefer the implicit identifier: add an explicitIdentifieronly when two nodes would otherwise resolve to the same identifier (for example duplicate descriptions, or multipleSTARTnodes). See Identifiers.
Start
text
StartNode = "START" , [ Identifier ] , Description , Connections ;Identifier(optional): explicit identifier token. If omitted,Descriptionis used as the implicit identifier.Description(required): human-readable label, in single quotes.Connections(required): outgoing connection(s). A bareNEXT,NEXT-MESSAGEorNEXT-ASSOCIATIONfalls through to the following node. ASTARTline without a connection is a compile error.
See Basic nodes.
End
text
EndKeyword = "END"
| "END-TERMINATE" ;
EndNode = EndKeyword , [ Identifier ] , Description ;EndKeyword(required):ENDis the plain end event.END-TERMINATEis the terminate end event, which ends the whole process at once.Identifier(optional): explicit identifier token.Description(required): human-readable label.- An
Endnode must not haveConnections; end nodes are terminal.
See Basic nodes.
Activity
text
ActivityNode = "ACTIVITY" , [ Identifier ] , Description , [ Connections ] ;Identifier(optional): explicit identifier token.Description(required): human-readable label.Connections(optional): outgoing connection(s).
See Basic nodes.
Event
text
EventKeyword = "EVENT"
| "EVENT-MESSAGE"
| "EVENT-TIMER"
| "EVENT-CONDITIONAL"
| "EVENT-ESCALATION"
| "EVENT-LINK"
| "EVENT-ERROR"
| "EVENT-CANCEL"
| "EVENT-COMPENSATION"
| "EVENT-SIGNAL" ;
EventNode = EventKeyword , [ Identifier ] , Description , [ Connections ] ;EventKeyword(required): selects the event subtype and the BPMN marker drawn inside the circle. The border and the catch or throw direction follow from the connections.Identifier(optional): explicit identifier token.Description(required): human-readable label.Connections(optional): outgoing connection(s).
See Event nodes for the BPMN marker and meaning of each subtype.
Gateway
text
GatewayKeyword = "GATEWAY"
| "GATEWAY-EVENT"
| "GATEWAY-EXCLUSIVE"
| "GATEWAY-PARALLEL"
| "GATEWAY-INCLUSIVE"
| "GATEWAY-COMPLEX" ;
GatewayNode = GatewayKeyword , [ Identifier ] , Description , [ Connections ] ;GatewayKeyword(required): selects the gateway subtype; controls the marker inside the diamond.Identifier(optional): explicit identifier token.Description(required): human-readable label.Connections(optional): outgoing connection(s). Gateways typically useANDto declare multiple branches, each with its ownLinkDescription.
A gateway carries at most three distinct LinkDescription values across its outgoing connections, whatever their kind. A fourth distinct value is an error. Branches that repeat a LinkDescription leave the gateway in the same direction and do not count again. A gateway may have more than three outgoing connections.
A gateway's branches leave on the right, top and bottom sides, one branch per side (see Where an edge attaches). Branches past the three sides leave on the side that fits them best.
See Gateway nodes.
Pool
text
PoolClause = ( "NEXT" | "NEXT-MESSAGE" | "NEXT-ASSOCIATION" ) , NextTarget , { "AND" , NextTarget } ;
PoolConnections = PoolClause , [ PoolClause ] , [ PoolClause ] ;
PoolNode = "POOL" , ( Identifier | Description ) , [ PoolConnections ] ;Identifier(required): the pool's name; doubles as the displayed pool label and as the pool's identifier. Written as a bareIdentifier(e.g.POOL Customer) or as a quotedDescriptionto allow spaces (e.g.POOL 'Web shop').PoolConnections(optional): connections that start on the pool, at most one clause per keyword. Every clause names its targets; a bare clause on aPoolNodeis invalid.- A process uses pools when its first node is a
PoolNode. APoolNodein any other process is invalid. - Every
LaneNodeand every other node after aPoolNodebelongs to that pool until the nextPoolNode. Declaring a pool again returns to it and resumes the lane that was last active in it. - A lane belongs to the pool it is declared in. The same lane name in two pools names two lanes.
- A pool either declares lanes or holds its nodes directly. A
LaneNodeafter a node that sits directly in the pool is invalid. - A pool without lanes and without nodes is valid.
- A pool's identifier shares the namespace of the node identifiers. A pool and a node with the same identifier are invalid.
- A
NodeRefthat names a pool is a connection that ends on the pool. A connection from one pool to another pool is valid. - A connection between a pool and a node inside that pool, a connection from a pool to itself, and a connection between a pool and an
AttachmentNodeare invalid. - A connection whose two ends are in different pools, or of which one end is a pool, is written as a message flow, with
NEXT-MESSAGE. Written withNEXTit is reported as a warning and drawn as a sequence flow. - Pools are drawn stacked top to bottom in the order of their first declaration, separated by a gap. A pool carries its name in a header on the far left, with its lane headers to the right of that header. The lanes of a pool are stacked in the order of their first declaration in that pool.
- A connection to or from a pool meets the border of the pool that faces its other end: the top border when the other end lies above the pool, the bottom border when it lies below. A message flow carries its open arrowhead, or its open circle, on that border.
- The
poolstylesheet selector colours pools; see Stylesheets.
See Links and lanes.
Lane
text
LaneNode = "LANE" , ( Identifier | Description ) ;Identifier(required): the lane's name; doubles as the displayed lane label. Written as a bareIdentifier(a single term with no spaces, e.g.LANE Customer) or as a quotedDescriptionto allow spaces (e.g.LANE 'Sales Team').- A
Lanenode carries no separateDescriptionand noConnections. Subsequent nodes belong to this lane until anotherLaneNodeis encountered. - A later node belongs to an earlier lane only when that lane is declared again.
- In a process that uses pools, a lane belongs to the pool it is declared in.
See Links and lanes.
Attachment
text
AttachmentKeyword = "DATA" | "DATABASE" | "TEXT" ;
AttachmentNode = AttachmentKeyword , [ Identifier ] , Description , [ Connections ] ;AttachmentKeyword(required):DATAfor a generic data artifact (page shape),DATABASEfor a persistent store (cylinder shape),TEXTfor a text annotation (the text inside an open bracket).Identifier(optional): explicit identifier token.Description(required): human-readable label. For a text annotation it is the annotation text.Connections(optional): the node(s) the attachment is associated with. A bareNEXT,NEXT-MESSAGEorNEXT-ASSOCIATIONfalls through to the following node.- Attachments are not part of the sequence flow. Their
Connectionsplace the attachment next to the nodes they name. - An attachment and every node its
Connectionsname belong to the same lane. ANextTargetnaming a node in another lane is invalid. - Every connection of a text annotation is an association, written with
NEXTorNEXT-ASSOCIATION. AMessageClauseon a text annotation is invalid.
See Attachments.
Subprocess
text
ProcessClause = "PROCESS" , ProcessId ;
SubprocessNode = "SUBPROCESS" , [ Identifier ] , Description , ProcessClause , [ Connections ] ;Identifier(optional): explicit identifier token.Description(required): human-readable label. It is the label drawn on the canvas; the referenced process's own name never appears there.ProcessClause(required): names the process this node stands for. A missing clause, or aProcessIdthat is not well-formed, is a compile error on that line.Connections(optional): outgoing connection(s).- A subprocess node takes part in the sequence flow exactly as an
ActivityNodedoes: incoming edges,ANDchains, implicitNEXT,NEXT-MESSAGEandNEXT-ASSOCIATIONfall-through, edge labels, and lane membership. - The compiler resolves nothing: it carries the
ProcessIdthrough as data. A reference to a process that does not exist still compiles.
See Subprocesses.
Semantic constraints summary
Constraints that EBNF cannot express, collected here for tooling authors:
- Identifier uniqueness: every node in a process must resolve to a unique identifier. Implicit and explicit identifiers share the same namespace.
- Implicit identifier defaulting: when a node omits its
Identifier, the value of itsDescriptionis used as the identifier. This is a semantic rule, not a syntactic rewrite. - NodeRef resolution: every
NodeRefmust point to a node declared somewhere in the same process. - Empty NEXT fallback: a
NEXT,NEXT-MESSAGEorNEXT-ASSOCIATIONwith noNodeRefconnects to the next node declared in the source text that takes part in sequence flow;StartNode,LaneNode,PoolNode, andAttachmentNodeare skipped as targets. Several nodes may each carry a bare clause before that target; every one of them connects to it. If no such node exists, the clause is invalid. - LinkDescription placement: a
LinkDescriptionmay only follow a presentNodeRef. A bare quoted string afterNEXT,NEXT-MESSAGE,NEXT-ASSOCIATIONorANDis not a valid link description. - Terminal nodes:
EndNodeandLaneNodemust not carryConnections. - Subprocess reference: a
SubprocessNodemust carry aProcessClause, and itsProcessIdmust be well-formed. The referenced process is resolved outside the compiler; a reference to a process that does not exist, or that the reader cannot open, is not a compile error. A subprocess node whoseProcessIdis the process being edited is reported as a quality finding. - Connection kinds: every edge of a
NextClauseis a sequence flow, every edge of aMessageClauseis a message flow and every edge of anAssociationClauseis an association. A node carries at most one of each clause.NEXT-MESSAGEandNEXT-ASSOCIATIONare reserved words and are never anIdentifier. Every edge of a text annotation is an association, and a text annotation carries noMessageClause. - Pool scoping: a process uses pools when its first node is a
PoolNode.POOLis a reserved word and is never anIdentifier.TEXTis a reserved word and is never anIdentifier. A pool's identifier is unique among the node identifiers. - Pool connections: a
NodeRefmay name a pool. A connection never joins a pool to itself, to a node inside it, or to anAttachmentNode. A sequence flow whose ends are in different pools is reported as a warning. - Minimal explicit identifiers: an explicit
Identifieris only required to disambiguate nodes that would otherwise share an identifier (duplicate descriptions, or multipleSTARTnodes). When a node's description is already unique, omit the explicit token and let the description serve as the identifier.