Module Declaration
The declaration of modules is done with an own description language which is similar to the declaration of variables in structured text (ST) code.
Format of the module declaration
A header of the form MODULE<name>
begins the declaration. This is followed by a list of "sections".
Each section is introduced by the keyword SEC
(for "section") and a unique name. The keyword END_SEC
closes the section. The contents of a section contain a list of entries consisting of further sections or so-called definitions.
A definition consists of a name and an optional value and ends with a semicolon.
Comments can be used as in ST code: "//"" for a single line comment and "(*" and "*)" for multiline comments. Whitespace (tabs and spaces) and newline/linefeed can be used to separate the parts of a declaration. Otherwise they are ignored during further processing.
As with ST code, case sensitivity makes no difference.
01 MODULE Persistence IMPLEMENTED_BY PersistenceFB 02 SEC MetaData 03 NAME := TL.ChannelName ; 04 DESC := TL.ChannelDesc ; 05 COLLECTION CATEGORY := ’Persistence’TL.Collection ; 06 ICON_16 := IP.Channel16 ; 07 ICON_32 := IP.Channel32 ; 08 END_SEC 09 SEC Toplevel 10 SEC STANDARD_TASK : LOW 11 NAME := LOW ; 12 DESC := TL.TaskLow ; 13 FLAGS := CREATE_IF_MISSING | READONLY ; 14 END_SEC 15 GVL_NAME := 'GVL_%InstanceName%' ; 16 END_SEC
In line 01 there is the definition of the module name "Persistence". IMPLEMENTED_BY
defines the function block "PersitenceFB" which contains the logic of the module. This function block must derive from IModule
. In line 02 the section MetaData
begins and it ends with line 08. This section contains five definitions. The possibility of nested sections is shown in the section Toplevel
(lines 09–16) which contains the subsection STANDARD_TASK
(line 10).
Syntax of the module declaration
In this section the syntax and the allowed syntactic structure of a module declaration will be explained.
In the following scanner tokens will be written in capitals (example: ID
). Non-terminals of the grammar will be written in curly brackets (example: {Entry}
).
Lexical analysis (scanner)
In the first step so-called tokens (or lexemes) will be created from the characters of the module declaration (example: keywords, constants, identifiers).
Whitespace as well as newline/linefeed characters separate tokens, but will be ignored otherwise. Comments will also be ignored for the further treatment of the declaration. (Comments can be written in a single line (//
") or multiline comments ((*
and *)
) as in to ST language. Multiline comments can be nested.
Basically a token has always a maximal length. For example a123
will be interpreted as an identifier and not as an identifier a
followed by a literal 123
.
The order of the tokens in the list below shows their priority. For example the input MODULE
will be understood as keyword and not as identifier.
Keywords:
MODULE
,SEC
,END_SEC
,IMPORTS
, andIMPLEMENTED_BY
OP: a non-empty sequence of the following characters:
.:,%()[]{}<>|+-*/@!?^°=\~
Note: The comment markers
//
,(*
, and*)
have higher priority than operators. There can be no comment inside an operator no comment can be, example:+//+
will, according to the rule of maximum length, interpreted as an operator and not as+
followed by a comment.LIT: An IEC literal, as it is used in ST, example:
1.4
,tod#12:13:14
. This includes the boolean literalsTRUE
andFALSE
(upper or lower case is not relevant).Note: Untyped literals with a negative sign (
-1
,-3.2
) will be read as two tokens, that is as operator-
followed by an untyped literal. Resulting from this untyped numeric literals can never be negative. Typed literals (INT#-34
) will always be interpreted as one token.ID: a valid IEC identifier (
[a-zA-Z_][a-zA-Z0-9_]*
), whereby two consecutive underlines are not allowed. This includes in contrast to ST also the keywords of ST (i.e.:FUNCTION
,INT
,EXTENDS
, …)SEMICOLON: the character
;
Syntax (parser)
The syntax of the module declaration is defined by the following grammar. µ
is an empty sequence.
{MDecl} ::= MODULE {QID} {ImplSpec} {ImportsSpec} {MBody} {ImplSpec} ::= IMPLEMENTED_BY {QID} | µ {ImportsSpec} ::= IMPORTS {QID} | µ {MBody} ::= {SecList} {SecList} ::= {Modifiers} {Sec} {SecList} | µ {Sec} ::= SEC {QID} {SecTarget} {EntryList} END_SEC {SecTarget} ::= OP(":") {QID} | µ {Modifiers} ::= OP("[") {ModifierList} OP("]") | µ {ModifierList} ::= {QID} OP(",") {ModifierList} | {QID} {EntryList} ::= {Modifiers} {Entry} {EntryList} {Entry} ::= {Sec} | {Def} {Def} ::= {QID} OP(":=") {ValList} SEMICOLON | {QID} SEMICOLON {ValList} ::= {Val} {ValList} | {Val} {Val} ::= ID | LIT | OP {QID} ::= ID | ID OP(".") {QID}
The list of definition values ({ValList}
) must be completed with a semicolon. This simplifies the grammar and avoids ambiguities, because the semicolon cannot be part of a value ({VAL}
), except within a string literal.
The assignment operator (:=
) of definitions ({Def}
) also serves to avoid ambiguities ({QID}
) of definition names and values.
Defined types for definitions
Text: ID.ID (text list name and text list identifier) - see Localization of text list strings
Image: ID.ID (image pool name and image pool identifier)
ID (IEC identifier)
QID (Qualified identifier):
{QID} ::= ID | ID.ID
CategoryPath ::= {StringLiteral} | {CategoryPath}
Cardinality:
[{MIN} .. {MAX}]
|[ {MIN} .. INF [
{MIN}
, and{MAX}
are integer, non-negative literals. If{MAX} != INF
, then{MIN} <= {MAX}
has to apply.StringLiteral: A IEC string literal may contain line breaks.
StdTaskFlags ::= {StdTaskFlag} | {StdTaskFlags} StdTaskFlag ::=
NONE
|CREATE_IF_MISSING
|READONLY
Literal: any IEC literal or QID (for Enum constants)
DTBoolFlag:
µ
(empty sequence) |TRUE
|FALSE
SlotType:
SUBMODULE
|REFERENCE
Pragmas:
[ {PragmaList} ] {PragmaList} ::= {Pragma}
|{Pragma} , {PragmaList} {Pragma} ::= { ( ID
|{StringLiteral}
|{OP2} )+ } {OP2}
: every operator except{, }, [, ]
and,
.InstancePath:
InstancePath ::= {IComp}
|{IComp} . {IComp}
mit{IComp} ::= ID {ArrayAccess}*
und{ArrayAccess} ::= [ {IntList} ]
und{IntList} ::= Int
|Int , {IntList}
TaskRef: Standard_Task. (
Low
|Medium
|High
) |Custom_Task.ID
Instance paths
At some positions in the module declaration instance paths can be defined to address a variable of a function block: For parameters, slots, I/Os, arrays with variable size and instance references.
An instance path is defined as a non empty sequence of components, separated by dots: C1.C2…CN
. A component must either be a IEC identifier or a component followed by an index expression [i1, …, iN]
, where i1
to iN
are integer values.
Instance paths are always relative to the function block which implements the module logic. The first component of the instance path is a member (VAR_INPUT
or VAR_OUTPUT
, depending on the use case) of the function block. In case of additional components in the instance path these components address the variable within the member. Otherwise the member itself is addressed. Instance paths can be restricted to input or output variables (example: for I/Os). For structures these restrictions are not valid. These kind of instance paths are called input instance paths resp. output instance paths.
Localization of text list strings
Texts in modules (example: description of module, name, description of parameter) can be displayed in different languages. These texts are managed in text lists.
The name of the language is of format
<LanguageCode>[-<Country/Region>]
(example:en-US
,de-DE
).<LanguageCode>
is the name of the language according to ISO 639-1 (example:de
oren
).<Country/Region>
is a country code according to ISO 3166.When retrieving a text list entry the system first looks up for the whole language name. If nothing is found it looks up for the
<LanguageCode>
. If this search also fails the default text will be used.
Language | Name of the language |
---|---|
Chinese | zh-CHS |
English | en-US |
French | fr-FR |
German | de-DE |
Italian | it-IT |
Japanese | ja-JP |
Portuguese | pt-PT |
Russian | ru-RU |
Spanish | es-ES |
Deriving module declarations
Analogously to the object oriented inheritance of a function block A from a function block B ("EXTENDS") there is the possibility of deriving module declarations by use of the IMPORTS
keyword. The modifiers UPDATE
and HIDE
are treated specially.
The name of the imported module must be specified with namespace if this module is defined in a different library.
Cyclic imports are not allowed, in particular a module must not import itself. (Example for a cyclic import: module M_1 imports module M_2, M_2 imports M_3, …, M_N imports M_1 again.)
A derived module can be defined without the
IMPLEMENTED_BY
directive. In this case the function block of the base module will be used.If a derived module specifies a function block (by use of
MPLEMENTED_BY
), this function block must derive from the function block of the base module or must be identical to it.A derived module inherits all sections of the base module. It can add new sections or modify existing sections.
A section can be modified in the derived module by using the same name and target extended with the modifier
UPDATE
. In this case, its entries are changed. All missing definitions of the section in the derived module will be taken over from the base module.The modifier
UPDATE
andHIDE
can only be used if the respective section (name and target) is defined in the basic module. Conversely a section, which is defined in the base module can only be used in the derived module if it has theHIDE
orUPDATE
modifier. If there is only theHIDE
modifier in the section and notUPDATE
, then no definitions are allowed.Some entries must be changed in the derived module (example: the description).
MODULE MBase IMPLEMENTED_BY FBBase SEC MetaData DESC := TL.Desc_Base ; END_SEC SEC Parameters SEC Param : paramxIn Variable := xIn ; Name := TL.Param1_Name ; Desc := TL.Param1_Desc ; END_SEC END_SEC MODULE MDerived IMPORTS MBase [UPDATE] SEC MetaData DESC := TL.Desc_Derived ; END_SEC [UPDATE] SEC Parameters [UPDATE,HIDE] SEC Param : paramIn Variable := xIn ; DEFAULT := TRUE ; END_SEC END_SEC
In the example above the parameter paramIn
of the module MBase
is hidden in the derived module MDerived
(by use of the HIDE
modifier), and at the same time a new default value (TRUE
) is set.
Notes to the order of sections and definitions
The order of the sections directly after the module header is irrelevant. Within the sections the order may be very important. For example the order of the slot declarations defines the order of the modules in the module tree.
The order of the definitions is always irrelevant.
The sections of the base modules are always defined before the sections of the module itself.
If a section of the base module is changed by use of
UPDATE
orHIDE
, its order is not affected.It is not possible for a derived module to change the order as defined in the base module.
Auto-completion and "list components"
When start typing in the module editor all available/possible section definitions are shown in an "list components" menu. Only meaningful sections and definitions for the current position are shown. Even if some subsection entries have the same name as subsection entries of other sections, it will try to display only the matching section definitions.
If Return is pressed after completing the first line of a section, then the section will be completed with all necessary definitions/sections and the END_SEC
.
After variable definitions input/output variables are presented by "list components" definitions. Flags or predefined values are also presented in a "list components" selection, which shows the possible flags/values.
After definitions, which use text list entries or image pool entries (example: most times Desc :=
), a "list components" menu including all available and visible text lists or image pools and their entries is presented.
By pressing F2, the corresponding input support can be opened.