end-of-line -> x0A | x0Dx0A // LF or CR+LF input-char -> x00 ... xFF // any 8-bit character, value 0 to 255, ISO-8859-1 input-line -> input-char* comment -> `#` input-line // from # to the end EOL -> comment? end-of-line lower-case -> `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` upper-case -> `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` euro-lower -> `à` | `á` | `â` | `ä` | `å` | `æ` | `ç` | `è` | `é` | `ê` | `ë` | `ì` | `í` | `î` | `ï` | `ð` | `ñ` | `ò` | `ó` | `ô` | `õ` | `ö` | `ø` | `ù` | `ú` | `û` | `ü` | `ý` | `þ` euro-upper -> `À` | `Á` | `Â` | `Ä` | `Å` | `Æ` | `Ç` | `È` | `É` | `Ê` | `Ë` | `Ì` | `Í` | `Î` | `Ï` | `Ð` | `Ñ` | `Ò` | `Ó` | `Ô` | `Õ` | `Ö` | `Ø` | `Ù` | `Ú` | `Û` | `Ü` | `Ý` | `Þ` euro-additional-lower -> `ß` | `ÿ` underscore -> `_` letter -> underscore | lower-case | upper-case | euro-lower | euro-upper | euro-additional-lower decimal-digit -> `0` | `1` | `2` | `3` | `4` | `5` | `6` | `7` | `8` | `9` identifier -> letter { letter | decimal-digit }* // not reserved-words, case is significant // reserved words are any case - - - reserved-words -> abstract | alias | and | array | attrib | bit | byte | break | case | contained | continue | default | each | else | enables | end | exit | expose | false | final | flags | for | funct | if | include | inherits | int | interface | long | method | mode | not | null | object | or | pragma | predef | private | real | repeat | return | set | static | string | struct | switch | true | ubyte | uint| ulong | until | ushort | while| `_` abstract -> `abstract` alias -> `alias` and -> `and` array -> `array` attrib -> `attrib` bit -> `bit` byte -> `byte` break -> `break` case -> `case` contained -> `contained` continue -> `continue` default -> `default` each -> `each` else -> `else` enables -> `enables` end -> `end` exit -> `exit` expose -> `expose` extends -> `extends` false -> `false` final -> `final` flags -> `flags` for -> `for` funct -> `funct` if -> `if` inherits -> `inherits` int -> `int` interface -> `interface` long -> `long` method -> `method` mode -> `mode` not -> `not` null -> `null` object -> `object` or -> `or` pragma -> `pragma` predef -> `predef` private -> `private` real -> `real` repeat -> `repeat` return -> `return` set -> `set` short -> `short` signal -> `signal` static -> `static` string -> `string` struct -> `struct` switch -> `switch` true -> `true` ubyte -> `ubyte` uint -> `uint` ulong -> `ulong` until -> `until` ushort -> `ushort` when -> `when` while -> `while' this -> `_` hex-digit -> decimal-digit | `a` | `b` | `c` | `d` | `e` | `f` | `A` | `B` | `C` | `D` | `E` | `F` binary-bit -> `0` | `1` decimal-integer-constant -> decimal-digit+ suffix? // fits a size hexadecimal-integer-constant -> { `0x` | `0X` } { hex-digit }1-16 suffix? binary-integer-constant -> { `0b` | `0B` } { binary-bit }1-64 suffix? suffix -> { signed-suffix | unsigned-suffix } bit-length signed-suffix -> `s` | `S` unsigned-suffix -> `u` | `U` bit-length -> `1` | `8` | `16` | `32` | `64` // signed with 1 is invalid true-const -> true false-const -> false null-const -> null logical-value -> true-const | false-const | null-const real-const -> decimal-digit+ `.` decimal-digit+ exponent? // limited to 28 significant digits exponent -> { `e` | `E` } { `+` | `-` }? decimal-digit decimal-digit? decimal-digit? decimal-digit? // limited by hardware integer-constant -> decimal-integer-constant | hexadecimal-integer-constant numeric-constant -> integer-constant | real-constant apostrophe -> `'` quote -> `"` simple-string-const -> apostrophe input-char+ apostrophe // embedded apostrophe is \' insert -> `{` expression `}` // evaluates to a string hex-character -> { `\x` | `\X` } hex-digit hex-digit entity-chars -> { `\h(` | `\H(` } entity-name-list `)` // names from ISO-8859-1 standard 1-byte values escape-char -> `\{` | `\n` | `\r` | `\t` | `\\` | ``"` | hex-character | entity-chars insertable-string-const -> quote { escape-char | insert | input-char }* quote // inserts allowed in curly braces and allows escaped chars multi-line-string-const -> `<<` end-of-line { escape-char | insert | input-char | end-of-line }* end-of-line `>>` // keeps all shown in braces slash -> `/` pattern-string-const -> slash input-char* slash string-const -> simple-string-const | insertable-string-const | multi-line-string-const | pattern-string-cost constant -> numeric-constant | true-const | false-const | null-const | predef-const | flags-const | string-const add-op -> `+` sub-op -> `-` mult-op -> `*` div-op -> `/` remainder-op -> `%` shift-op -> `*>` | `<*` power-op -> `^` concat-op -> `||` binary-bit-and -> `&` binary-bit-or -> `|` binary-bit-exor -> `~` binary-op -> add-op | sub-op | mult-op | div-op | shift-op | power-op | concat-op | binary-bit-and | binary-bit-or | binary-bit-exor | remainder-op unary-plus -> `+` unary-minus -> `-` unary-comp -> `~` unary-op -> unary-plus | unary-minus | unary-comp selector -> `.` assign-op -> `=` op-assign-op -> binary-op`=` // no space before = selector-assign-op -> selector`=` // no space before = equality -> `=?` inequality -> `\=` less-than -> `<` greater -> `>` less-or-equal -> `<=` greater-or-equal -> `<=` comparison-op -> equality | inequality | less-than | greater | less-or-equal | greater-or-equal equality-op -> equality | inequality and-op -> and // reserved word or-op -> or // reserved word not-op -> not // reserved word postfix-plus -> `++` postfix-minus -> `--` postfix-incrementor -> postfix-plus | postfix-minus swap-op -> `<>` definable-binary-op -> add-op | sub-op | mul-op | div-op | power-op | concat-op | binary-bit-and | binary-bit-or | binary-bit-exor definable-unary-op -> unary-plus | unary-minus | unary-comp definable-comparison-op -> comparison-op predef-const-id -> identifier predef-const-spec -> predef-const-id { `=` decimal-integer-constant }? predef-type -> identifier // not otherwise used in this namespace predef-const -> predef-const-id | predef-type selector predef-const-id predef-declaration -> private? final? predef predef-type extends? predef-const-spec { `,` predef-const-spec }* // each predef-const-id is unique flags-type -> identifier // not otherwise used in this namespace flags-declaration -> private? flags flags-type predef-type-name flags-value -> flags-type `(` predef-list `,`? `)` predef-list-item -> predef-const-id { `=` logical-expression }? predef-list -> predef-list-item { `,` predef-list-item }* attrib-name -> identifier short-string -> { `+` | `-` }? string-const attrib-decl -> private? attrib type-name attrib-name { short_string }? { `=` attrib-expression }? attrib-expression -> // to be defined as a basic arithmetic expression with only attrib-name and constant values integer-type-name -> signed-integer-type-name | unsigned-integer-type-name signed-integer-type-name -> int | int selector bit-length | long | short | byte // bit-length is not 1 unsigned-integer-type-name -> uint | uint selector bit-length | ulong | ushort | ubyte | bit basic-type-name -> integer-type-name | real | string | real selector scale scale -> `0` ... `99` type-name -> basic-type-name | predef-type | flags-type | object-type | struct-type | alias-type type -> type-name | type-name selector attrib-name | this-type array-name -> identifier // declared as an array index-type -> int | string | predef-type fixed-size -> decimal-constant | variable | `(` arith-expr `)` // expression or variable is type int (value is 0 or higher) integer-variable -> identifier // a variable of type int or uint array-keyword-with-index-spec -> array { selector index-type }? array-decl -> array-keyword-with-index-spec { `*` fixed-size }? alias-decl -> private? alias alias-type type array-decl? alias-type -> identifier variable -> identifier | struct-name selector identifier | object-name selector identifier array-ref -> array-name | object-ref selector array-name | struct-ref selector array-name array-of-arrays-ref -> array-of-arrays-name | object-ref selector array-of-arrays-name | struct-ref selector array-of-arrays-name array-of-arrays-name -> identifier index-const -> decimal-const | string-const | predef-const array_element-init -> { index-const `=` }? non-assign-expression array-initializer -> array-keyword-with-index-spec `(` `)` | array-keyword-with-index-spec `(` array_element-init { `,` array_element-init }* `,`? `)` item -> variable { `=` non-assign-expression }? | array-decl array-name { `=` array-initializer }? | array-decl array-decl array-of-arrays-name item-decl -> type item { `,` item }* struct-decl -> private? struct struct-type EOL { item-decl EOL }+ end struct // the items declared are variables, arrays, or structs (objects not allowed) struct-type -> identifier struct-member -> variable | array-name struct-value -> struct `(` struct-member `=` expression { `,` struct-member `=` expression }* `)` // things that can be assigned a value arith-left-value -> variable | array-element | expose-set-ref flags-left-value -> variable | array-element | expose-set-ref | flags-element flaqs-element -> flags-left-value selector flags-const-id predef-left-value -> variable | array-element | expose-set-ref string-left-value -> variable | array-element | expose-set-ref left-value -> arith-left-value | flags-left-value | predef-left-value | string-left-value | flaqs-element arith-primary -> variable | array-element | numeric-constant | function-call | expose-return-ref | type-cast | `(` arith-expr `)` // numeric type unary-part -> arith-primary | unary-op arith-primary factor -> unary-part | factor power-op unary-part term -> factor | array | term { mult-op | div-op | binary-bit-and | shift-op | remainder-op } factor arith-expr -> term | arith-expr { add-op | sub-op | binary-bit-or | binary-bit-exor } term // the array-element subscript is parenthesized if it is an incrementor and the array-element is an array-ref (array of arrays base) - - array-subscript -> arith-primary | arith-left-value postfix-incrementor | string-primary array-element -> array-ref selector array-subscript array-ref -> array-name | object-ref selector array-ref | array-element // the last case is special flags-expr -> variable | array | array-element | flags-element | flags-const | function-call | expose-return-ref | flags-value | `(` flags-expr `)` predef-expr -> variable | array | array-element | predef-const | function-call | expose-return-ref | type-cast | `(` predef-expr `)` // type predef string-primary -> variable | array | array-element | string-const | function-call | expose-return-ref | type-cast | `(` string-expr `)` // all of type string substring -> string-primary selector string-selection string-selection -> arith-primary | arith-left-value postfix-incrementor string-expr -> string-primary | substring | string-expr concat-op string-primary arith-relation -> arith-expr comparison-op arith-expr string-relation -> string-expr comparison-op string-expr predef-relation -> predef-expr equality-op predef-expr flags-relation -> flags-expr equality-op flags-expr array-relation -> array-ref equality-op array-ref object-relation -> object-ref equality-op object-ref relation -> arith-relation | string-relation | predef-relation | flags-relation | array-relation | object-relation logical-primary-> logical-value | variable | function-call | flags-element | `(` logical-expression `)` logical-secondary -> logical-primary | not-op logical-primary | relation logical-factor -> logical-secondary | logical-factor and-op logical-secondary logical-term-> logical-factor | logical-term or-op logical-factor logical-expression -> logical-term type-cast -> primary selector type primary -> logical-primary | string-primary | flags-expr | predef-expr | arith-primary | `(` relation `)` | type-cast expression -> logical-expression | string-expr | predef-expr | flags-expr | arith-expr assignment -> left-value { assign-op | op-assign-op } expression | postfix-incrementor array-assignment -> array-ref assign-op { array-expr | array-ref } selector-assignment -> { object-ref | struct-ref | array-ref | left-value } selector-assign-op { funct-call | mode-call } error-condition -> object-name // of type: _ErrorCondition assign-stmt -> assignment | array-assignment | selector-assignment exit-stmt -> exit continue-stmt -> continue break-stmt -> break return-stmt -> return expression? repeat-stmt -> repeat signal-stmt -> signal error-condition swap-stmt -> left-value swap-op left-value // the two sides must be compatible type and/or 'kind' // a 'construct' is a statement occupying multiple lines switch-construct -> switch-line case-construct* default-construct? end switch when=block? switch-line -> switch { arith-expr | predef-expr | string-expr } // expressions are not array-valued case-construct -> case-line { statement EOL }* { continue-stmt EOL}? case-const -> integer-const | predef-const | string-const range-const -> integer-const | string-const case-value -> case-const | case-range case-range -> range-const `:` range-const? | `:` range-const // not allowed for predef constants case-value-list -> case-value { `,` case-value }* case-line -> case case-value-list EOL default-construct -> default-line { statement EOL }* // no continue statement default-line -> default EOL if-construct -> if-test follow-stmt else-construct? if-test -> if { integer-expression | logical-expression } simple-stmt -> exit-stmt | break-stmt | return-stmt | repeat-stmt | signal-stmt | continue-stmt follow-stmt -> simple-stmt | block | empty-block | one-statement-block empty-stmt -> `{` `}` one-statement-block -> `{` { simple-stmt | incrementation } `}` // may not be a construct block -> EOL? `{` EOL { statement EOL | declaration EOL }* `}` block-stmt -> block when-block? | empty-stmt when-block -> when block declaration -> predef-declaration | flags-declaration | object-construct | procedure-def | attrib-decl | alias-decl | pragma | interface-construct else-construct -> else else-follow-stmt else-follow-stmt -> statement for-construct -> for for-parameters for-block for-parameters -> for-incremental-conditions | for-array-conditions | for-object-conditions | for-flags-conditions for-incremental-conditions -> assignment-part? { { while | until } test-expression }? { final incrementation }? assignment-part -> { type? variable `=` expression } | method-call | assignment | array-assignment test-expression -> logical-expression incrementation -> variable { `++` | `--` } | method-call | assignment | array-assignment key -> variable temp-var - variable for-array-conditions -> each { array-ref | string-variable | string-const } { key `=` }? temp-var for-flags-conditions -> each flags-expr key `=` temp-var for-object-conditions -> each object-item temp-var // the object enables _Selectable object-item -> variable | array-element for-block -> block final-block? when-block? final-block -> final block statement -> assign-stmt | swap-stmt | method-call | for-construct | switch-construct | if-construct | exit-stmt | return-stmt | repeat-stmt | continue-stmt | break-stmt | signal-stmt | block-stmt | empty-stmt function-args -> `!` | parenthesized-expression-list expression-list -> expression { `,` expression }* parenthesized-expression-list -> `(` expression-list `)` function-call -> { any-object-ref selector }? function-name function-args method-call -> { any-object-ref selector }? method-name expression-list? mode-call -> { object-ref selector }? mode-name parenthesized-expression-list? any-object-ref -> object-type | object-ref | array-ref | array-element | variable | constant | expose-return-ref | `(` expression `)` expose-decl -> expose type { variable | array-decl } set-phrase* return-phrase? // any order for set and return internal-item - > variable | array-element | array | struct | struct-name selector struct-member set-phrase -> set { internal-item `=` expression | method-call } return-phrase -> return expression this-object -> this this-type -> this // a second meaning for the reserved word expose-proto -> expose type { variable | array-decl } set? return? // any order for set and return interface-construct -> interface interface-name param-type-part? enables-part? EOL interface-body EOL end interface interface-decl -> { procedure_proto | expose_proto } EOL interface-body -> interface-decl+ param-type-part -> `[` param-type-list `]` param-type-list -> param-type { `,` param-type }* enables-part -> enables interface-name-list interface-name-list -> interface-name { `,` interface-name }* interface-name -> identifier procedure-body -> { declaration EOL | statement EOL | construct EOL }* constructor -> static? default method EOL procedure-body EOL end method finalizer -> final method EOL procedure-body EOL end method object-construct -> final? contained? private? object object-type { enables interface-name-list }? { inherits inherited-object }? EOL object-body EOL end object inherited-object -> object-type param-type -> identifier object-name -> identifier | this-object object-decl -> private? item-decl | expose-decl | abstract expose-proto | abstract procedure-proto | private? procedure-def | define-op | constructor | finalizer object-body -> { object-decl EOL }+ object-ref -> object-type | this-object procedure-proto -> method-proto | mode-proto | funct-proto procedure-def -> method-def | mode-def | funct-def | define-op // friendly-procedure-def -> ???? base-type -> type | null | type `[` param-type-implemented `]` args-spec -> `(` arg { `,` arg }* `)` arg -> type ref? arg-name { array-decl }0-2 // can omit arg-name in a prototype (no body) arg-name -> identifier param-type-implemented -> param-type `=` actual-types-supported { `,` param-type `=` actual-types-supported }+ actual-types-supported -> `*` | type+ method-proto -> base-type method method-name args-spec? method-name -> identifier funct-proto -> base-type funct funct-name args-spec? return-spec funct-name -> identifier return-spec -> return result-decl result-decl -> return-type item return-type -> type mode-proto -> base-type mode mode-name args-spec? mode-name -> identifier method-def -> { private | final | abstract }? set? method-proto EOL procedure-body EOL end method when-block? funct-def -> { private | final | abstract }? set? funct-proto EOL procedure-body EOL end funct when-block? mode-def -> { private | final | abstract }? mode-proto EOL procedure-body EOL end mode when-block? define-binary-op -> type-name funct definable-binary-op `(` type-name variable `)` return-spec // all three types the same define-unary-op -> type-name funct definable-unary-op return-spec // types the same define-compare-op -> type-name funct definable-compare-op `(` type-name variable `)` return-spec // first two types the same, return type is int define-type-cast -> type-name funct new-type return-spec new-type -> type-name define-op -> { define-binary-op | define-unary-op | define-compare-op | define-type-cast } EOL procedure-body default-object -> default object EOL default-object-body EOL end object default-object-decl -> default-object-expose | default-object-method-def | default-object-funct-def default-object-body -> { default-object-decl EOL }+ default-object-expose -> expose basic-type-name named-constant return constant // actually a constant expression named-constant -> identifier default-object-method-def -> default-method-proto EOL procedure-body EOL end method default-object-funct-def -> default-funct-proto EOL procedure-body EOL end funct default-method-proto -> null method method-name args-spec? default-funct-proto -> null funct funct-name args-spec? return-spec