.. include:: alias.rst .LF file format =============== Introduction ------------ The ``.lf`` file format is a human-readable format for representing |rcm|'s semantics for state machines and all their properties. Its intended use case is the creation and manipulation of state machines using light-weight tools such as a text editor and a command line interface to read, validate and upload state machines to the |core|. .lf files --------- A ``.lf`` file holds a single root state, all its hierarchical child states, as well as all ports, barriers, actions, parameters, variables and results. The name of the file directly acts as the name of that state, e.g. a file called ``Wiggle.lf`` is interpreted as a state machine called 'Wiggle'. State machines can also contain script code, e.g. for actions. Scripts are stored within ``.lf`` files as well, but they are enclosed in special tags (``@{`` as the opening tag and ``}@`` as the closing tag). An example of a state machine representing a simple timer module is given below: .. code-block:: lf Timer { port done service("timer").operation("wait").status == "success" parameterType { float duration; } entry @{ service("timer").operation("wait").call(parameter.duration) }@ clientData { type : "app"; } } Note that the script language for actions (including entry and exit actions) is Lua. In the following sections, we will go over the grammar of the individual elements. Elements of a state machine --------------------------- A state machine consists of several elements. The following figure shows an overview of them. For a simple state only the name of the state machine and the ports are mandatory, all the other elements can be used if necessary. If you want to build a Desk app, a few more elements are necessary which are explained later in the tutorial. .. figure:: _static/statemachine_structure.png :align: center The next code block displays these elements in |lf|. The order of the elements inside the state does not matter. The structure of the child states is similar to the parent state. All the elements can be used, except of the clientData block. .. code-block:: lf App { port Success child("child_state_2").port("success") port Error child("child_state_1").port("error") or child("child_state_2").port("error") clientData { ... } parameterType { ... } resultType { ... } variableType { ... } entry @{ ... }@ action ..condition.. @{ ... }@ action ..condition.. @{ ... }@ exit @{ ... }@ --> child_state_1 { port success ..condition.. -> child_state_2 port error ..condition.. parameterType { ... } resultType { ... } variableType { ... } entry @{ ... }@ action ..condition.. @{ ... }@ action ..condition.. @{ ... }@ exit @{ ... }@ } where { ... } child_state_2 { port success ..condition.. port error ..condition.. parameterType { ... } resultType { ... } variableType { ... } entry @{ ... }@ action ..condition.. @{ ... }@ action ..condition.. @{ ... }@ exit @{ ... }@ } where { ... } } where { ... } Root states ----------- A single ``.lf`` file contains a single root state. Its name must match the filename without the ``.lf`` suffix. The grammar for a root state (i.e. for a complete ``.lf`` file) is given as follows: .. code-block:: bnf ::= The rules for ```` and ```` will be defined in the next section. States ------ A state is a named entity in a hierarchical state machine that can contain other states or barriers. It can be connected to sibling states via ports, and contain actions that are executed upon certain triggers. In |rcm|, the state holds a reference to a single child state or barrier which it treats as its "first" child, i.e. upon executing the state, this "first" child element gets activated. In ``.lf`` files, this attribute is not expressed at the parent state, but the "first" child element is marked by a ``-->`` arrow, marking it as the entry state. A state can be a link state and reference a library, i.e. another state machine, which it links to. Such a link state cannot contain states, barriers, nor actions as these elements are inherited from the linked library. The only elements the link state can contain are ports without a condition that must also be present within the library. .. code-block:: bnf ::= ::= "<-" ::= "<-" ::= epsilon | "-->" ::= epsilon | "where" ::= "{" "}" ::= * ::= | | | | | | | | ::= "{" "}" ::= * ::= | ::= ::= ::= ::= * ::= A-Za-z ::= | 0-9 | "_" Valid state or library identifiers start with a letter and are followed by any number of letters, numbers or underscore. Identifiers are case-sensitive. The ``epsilon`` represents an empty symbol. The rules for ````, ````, ````, ````, ````, ````, ````, ```` and ```` are given in the following sections. Barriers -------- Barriers are child elements of states and represent either: - a synchronization point where incoming port connections from multiple states can be merged onto a single destination state. Execution waits for all incoming ports to activate and transitions to the destination state. This is akin to a ``join`` operation in multi-threaded programs. - a branching point where a single incoming port is mapped onto a number of destination states. In this case, execution starts the execution of the destination states in parallel. This is similar to a ``fork`` operation in multi-threaded programs. Barriers can also be entry nodes of the containing state, i.e. they are the first element to activate when the parent activates. The grammar for barriers is defined as follows: .. code-block:: bnf ::= "barrier" ::= ::= "{" "}" ::= * ::= "->" Actions ------- Actions are functions written in Lua that are executed based on trigger conditions during the execution of the state machines. Special cases are the ``entry`` and ``exit`` actions, which are executed upon entering and leaving a state, respectively. More general ``actions`` have an additional condition expression which must evaluate to true to be executed. The grammar for actions is defined as follows: .. code-block:: bnf ::= | | ::= 'entry'