Go to the previous, next section.

# Defining Interfaces

Module interfaces may be defined in either the Object Management Group's CORBA OMG IDL, or in ILU's native Interface Specification Language (aka ISL). This document describes the syntax and semantics of ISL, and how to translate OMG IDL interfaces into ISL; see CORBA 2.0 for a specification of the syntax and semantics of OMG IDL.

## General Syntax of ISL

The conventional file suffix for ISL files is ``.isl'`. Some of the ILU tools rely on the name of the file being the same as the name of the interface defined in it, and rely on having only one interface defined in each ``.isl'` file.

An ISL interface contains four kinds of statements: the interface header, type declarations, exception declarations, and constant declarations. Each statement is terminated with a semi-colon.

Many statements in ISL contain lists: lists of the fields in a record, the types in a union, the methods in an object type. All lists in ISL are terminated with an `END` keyword, and the items in the list are separated by commas.

Comments may be placed in an ISL file. They are introduced with the character sequence `(*`, and terminated with `*)`. Comments nest.

### Identifiers

All identifiers that appear in ISL are alphanumeric, begin with an alphabetic character, and may contain hyphens.(1) Differences in case are not sufficient to distinguish between two identifiers; however, the case of an identifier may be preserved in its mapping to a specific programming language.

All ILU type names, exception names, and constant names have two parts, an interface identifier and a local identifier. When writing the full name, the interface identifier comes first, followed by a period, followed by the local identifier. If the interface identifier is ommitted in a name, it defaults to the interface identifier of the most recently encountered interface header.

Interface names, type names, exception names, and constant names occur in different name spaces. Thus is is possible to have a type and an exception with the same name.(2)

### Reserved Words

The following words are reserved words in ISL: `ARRAY`, `ASYNCHRONOUS`, `AUTHENTICATION`, `BOOLEAN`, `BRAND`, `CARDINAL`, `CHARACTER`, `CLASS`, `COLLECTIBLE`, `CONSTANT`, `DEFAULT`, `END`, `ENUMERATION`, `EXCEPTION`, `FALSE`, `FROM`, `FUNCTIONAL`, `IMPORTS`, `IN`, `INOUT`, `INTEGER`, `INTERFACE`, `LIMIT`, `LONG`, `METHODS`, `OBJECT`, `OF`, `OPTIONAL`, `OTHERS`, `OUT`, `RAISES`, `REAL`, `RECORD`, `SEQUENCE`, `SHORT`, `SIBLING`, `SINGLETON`, `SINK`, `SOURCE`, `SUPERCLASS`, `SUPERCLASSES`, `SUPERTYPES`, `TRUE`, `TYPE`, `TYPEID`, `UNION`.

Reserved words may be used as identifiers, by placing them in double quotes, but may not be used as identifiers without quoting.

Other identifiers are worth avoiding, as they may cause problems with specific language implementations. The identifier `t` or `T`, for instance, causes problems with Common Lisp. Language-specific mappings of ISL should try to avoid these problems.

## Statement Syntax

### The Interface Header

Each interface is introduced with exactly one interface header of the form

    INTERFACE interface-name [ BRAND brand ] [ IMPORTS list-of-imported-interfaces END ] ;

The interface-name is used by various language-specific productions to create name spaces in which the types, exceptions, and constants defined in the interface are declared. The optional list-of-imported-interfaces is a comma-separated list of fields, each of the form

    interface-name [ FROM interface-file ]

where interface-file is the typical poorly defined string that names a file for your operating system (in our case, UNIX). Importing an interface allows the current interface to mention the types, exceptions, and constants defined in the imported interface, by referring to them as

    interface-name.type-or-value-name

If the optional "FROM interface-file" is not specified for an imported interface, a sensible site-dependent search policy is followed in an attempt to locate that interface, typically looking down a path (environment variable `ILUPATH` on POSIX systems) of directories for a file with the name ``interface-name.isl'`.

### Type Declarations

In general, a type is defined with a statement of the form

    TYPE type-name = type-reference | construction ;

The form `TYPE type-name = type-reference` is used when you want to rename an existing type to make its usage clear or give it a name in the current interface. A type-reference is just a type-name, or a reference to a type name defined in another interface: interface-name.type-name.

#### Primitive types

The following type "names" are pre-defined:

- `INTEGER,` a 32-bit signed integer value;
- `SHORT INTEGER,` a 16-bit signed integer value;
- `LONG INTEGER,` a 64-bit signed integer value;
- `CARDINAL,` a 32-bit unsigned integer value;
- `SHORT CARDINAL`, a 16-bit unsigned integer value;
- `LONG CARDINAL`, a 64-bit unsigned integer value;
- `BYTE`, an unsigned 8-bit byte value;
- `BOOLEAN`, a logical value either True or False;
- `REAL`, an IEEE 64-bit double-precision floating-point value;
- `SHORT REAL`, an IEEE 32-bit single-precision floating-point value;
- `LONG REAL`, a 128-bit quadruple-precision floating-point value;
- `CHARACTER`, a 16-bit UNICODE/IS-10646 character; and
- `SHORT CHARACTER`, an 8-bit ISO 8859-1 character code (but excluding the octet 8_000).

There is also a special type `NULL`, which cannot be used directly; it has a single value, NULL.

#### Constructor overview

The form ``TYPE` type-name = construction` is used when a user needs to define a new type. Several simple constructors for more complex data types are specified:

- `ARRAY`, a fixed-length N-dimensional array of some specified type;
- `SEQUENCE`, a variable-length one-dimensional array of some specified type;
- `RECORD`, a sequence of typed fields, each of which may be of a different type;
- `UNION`, one of a set of specified types;
- `OPTIONAL`, a union with `NULL`;
- `ENUMERATION`, a type consisting of an explicitly enumerated set of values;
- `OBJECT`, an ILU object type.

In addition, the automatically-imported interface ILU defines the short sequence `CString` of short character.

#### Array Declarations

An `ARRAY` is a fixed-length N-dimensional array of some type. It is defined with a declaration of the form

    TYPE type-name = ARRAY OF dimension-list base-type-reference ;

where dimension-list is a comma-separated list of non-negative integers, each integer specifying the size of a dimension of the array, and base-type-reference is a type-reference to some other ILU type. For example,

    TYPE SymbolTable = ARRAY OF 400 Symbol;
    TYPE Matrix3030 = ARRAY OF 30, 30 REAL;

The total number of elements in the array may not exceed 4294967295 (2^32-1).

#### Sequence Declarations

A sequence is a variable-length one-dimensional array of some type. It is defined with a declaration of the form

    TYPE type-name = [ SHORT ] SEQUENCE OF base-type-reference [ LIMIT size ] ;

where base-type-reference is a type-reference to some other ILU type. If the `LIMIT` parameter size is used, it limits the sequences to having at most size elements; otherwise the sequences are limited to having at most 4294967295 (2^32-1) elements. Use of the `SHORT` modifier is shorthand for a `LIMIT` of 65535 (2^16-1). Use of the `LONG` modifier is not defined for sequences.

#### Generalized Array Declarations

This is a proposed language change, not yet accepted.

The existing language has a weakness: it cannot express coordinated multidimensional variable-length arrays. Coordinated means that there is only one length per dimension, regardless of how many arrays there are at that level. An example is a bitmap of variable height and width: all rows are the same length, and all columns are the same length.

A generalized array type is defined with a declaration of the form

    TYPE type-name = ARRAY dim , ... dim OF base-type-reference ;

where each dim is of the form

    length | [ LIMIT maxlen | SHORT ]

A dimension can be given a fixed length by simply specifying that length. A variable-length dimension is either left blank (meaning the maximum length is 2**32-1), specified as `SHORT` (meaning the maximum length is 2**16-1), or given an explicit maximum length.

Note that putting the dimensions after the `OF` would create a syntactic ambiguity in some cases, concerning grouping of a `SHORT`.

#### Record Declarations

    TYPE type-name = RECORD fields... END ;

where fields is a comma-separated list of field, which has the form

    field-name : field-type-reference

A sample record declaration:

    TYPE Symbol = RECORD
      name : string,
      type : TypeInfo,
      address : cardinal
    END;

#### Union Declarations

A union is a type which may take on values of several different types. To be compliant with the CORBA notion of unions, the union declaration is much more baroque and complicated than it really should be. The declaration has the form:

    TYPE type-name = [ tag-type ] UNION arm-list END [ OTHERS ] ;

where arm-list is a comma-separated list of arm, each of the form:

    [ union-case-name : ] type-name [ arm-valuator ]

where each arm-valuator is either of the form

    = DEFAULT

or of the form

    = value-list END

and where a value-list is a comma-separated list of constant values of the tag type. The tag type must be one of: `SHORT INTEGER`, `SHORT CARDINAL`, `INTEGER`, `CARDINAL`, `BYTE`, `BOOLEAN`, or an enumerated type. (We should also allow `SHORT CHARACTER` and `CHARACTER`.) The tag type is `SHORT INTEGER` if not explicitly specified.

A arm-valuator must be given for either all or none of the arms; if none, the arms are assigned single integral values, starting with 0. arm-valuators must be given if the tag type isn't numeric. All the values appearing in the value-lists of a union must be different from one another. `DEFAULT` can appear in at most one arm of a union type construction. `DEFAULT` and `OTHERS` cannot both appear in the same union.

A union value consists of a tag value, possibly paired with a second value. When the tag value is one that appears in, or is implicitly assigned to, an arm of the union type construction, the second value is of the type named in that arm. Otherwise, the union value is well-formed only if `DEFAULT` or `OTHERS` appears in the union type construction. If an arm is valued with `DEFAULT`, the second value is of that arm's type. If `OTHERS` appears, there is no second value; it is as if there were a default arm of some trivial type (like C's `void` or ML's `unit`).

A simple example:

    TYPE StringOrInt = UNION ilu.CString, CARDINAL END;

A more complex example, that uses an explicit tag type, union case names, and a default arm:

    TYPE ColorType = ENUMERATION RGB, CMY, HSV, YIQ, HLS END;
    TYPE U2 = ColorType
      UNION
        rgb-field : RGBObject = RGB END,
        others : COLORObject = DEFAULT
      END;

The union case name is not guaranteed to be present in language-specific mappings.

ISL unions are logically (and sometimes actually, depending on the programming language) tagged. There is a difference between

    TYPE T1 = UNION Bar, Baz END;
    TYPE T2 = UNION Foo, T1 END;

and

    TYPE T1 = UNION Bar, Baz END;
    TYPE T2 = UNION Foo, Bar, Baz END;

#### Optional Declarations

A variable of type ``OPTIONAL` Foo` can have either a value of `Foo` or of type `NULL`. It is declared with the form

    TYPE type-name = OPTIONAL base-type-reference ;

This should be thought of as roughly equivalent to the declaration

    TYPE type-name = BOOLEAN UNION base-type-reference = TRUE END END OTHERS ;

The difference is that `OPTIONAL` types are logically un-tagged. An optional value is not a pair of (`BOOLEAN`, base-type-reference); rather it is a single value, either a special, distinguished, "null" value or a value of the base-type-reference. There is thus no difference between

    TYPE Bar = OPTIONAL Foo;
    TYPE Baz = OPTIONAL Bar;

and

    TYPE Bar = OPTIONAL Foo;
    TYPE Baz = OPTIONAL Foo;

#### Enumeration Declarations

An enumeration is an abstract type whose values are explicitly enumerated. It is declared with the form

    TYPE type-name = ENUMERATION values... END ;

where values is a comma-separated list of value names, with optional value ID's that are constants of type `SHORT CARDINAL` that specify the value used to represent the enumeration value "on the wire".(3) Use of value ID's is deprecated.

    value-name [ = value-id ]

For example,

    TYPE TapeAction = ENUMERATION
      SkipRecord = 1,
      Rewind = 23,
      Backspace = 49,
      WriteEOF = 0
    END;

All value-names and value-IDs must be unique within an enumeration. If value-IDs are not assigned explicitly, appropriate values will be assigned automatically in some unspecified way. An enumeration may have at most 65535 (2^16-1) values.

#### Object Type Declarations

Object types are described in the following way:

    TYPE type-name = OBJECT
                            [ SINGLETON protocol-description-string ]
                            [ DOCUMENTATION documentation-string ]
                            [ COLLECTIBLE ]
                            [ OPTIONAL ]
                            [ TYPEID type-id-string ]
                            [ SUPERTYPES supertype-list END ]
                            [ METHODS method-list... END ]
                            [ BRAND string-constant ] ;

The keyword `CLASS` is a deprecated synonym for `OBJECT`, and `SUPERCLASSES` is a deprecated synonym for `SUPERTYPES`. Also,

                            [ SUPERCLASS supertype-name ]

is a deprecated equivalent to

                            [ SUPERTYPES supertype-name END ]

The `SINGLETON` keyword specifies that instances of this type are singleton servers, and implies that the discriminator object (the subject of the call) should not be implicitly marshalled as the first argument in an RPC. This is typically used in describing an instance of an existing RPC service, which is to be modelled in ILU. The argument to `SINGLETON` is a string in the form of ILU "protocol-info", which specifies particular protocol-specific parameters to be used in implementing this object type `on the wire'. For example, the Sun RPC calendar manager would use a protocol-description-string of `"sunrpc_2_100068_3"`, indicating that it uses a Sun RPC program number of 100068 and a Sun RPC version of 3.

The optional documentation-string is a quoted string, which is passed on to language-specific bindings where possible, such as with the doc-string capability in Common Lisp.

The `COLLECTIBLE` keyword specifies that instances of this type are meant to be garbage collectible, and that methods necessary for this should be automatically added to its method suite. For an object type to be collectible, all ancestor object types must also be collectible.

The `OPTIONAL` keyword specifies that the language-specific `nil` value may be passed, instead of an instance of this object type, anywhere this object type is used. This is a CORBA mis-feature, and its use is strongly deprecated. Better to explicitly use a different type constructed with the ILU `OPTIONAL` keyword.

The optional supertype-list defines an inheritance relationship between the object types named in the list and the type type-name.

The optional type-id-string can be used to explicitly assign an MSTID for an object type. Doing so effectively seals the object type; that is, changes to the structure of the object type will not be reflected in the MSTID, so version mismatches will not be caught automatically by ILU. This is a dangerous feature (mandated by CORBA).

The string-constant in the `BRAND` clause, if any, contributes an arbitrary tag to the structure of the type; omitting the `BRAND` clause is equivalent to giving one with the empty string. Branding gives the programmer a way to make two types distinct despite their otherwise having the same structure. See an earlier subsection for more details.

The method-list is a comma-separated list of procedure descriptions. All the methods of an object type have distinct names. This means that independently-developed supertypes might not be usable together.

Methods have the syntax:

    [ FUNCTIONAL ] [ ASYNCHRONOUS ] method-name ( [ args... ] )
            [ : return-type-reference ]
            [ RAISES exceptions... END ]
            [ = procedure-id ]
            [ documentation-string ]

where the discriminator (the implicit first argument to the method, the subject of the call, an instance of the object type in question) is not explicitly listed in the signature. Each method has zero or more arguments in a comma-separated list, each element of which is a colon-separated two-ple

    [ argument-direction ] argument-name : [ SIBLING ] argument-type-reference

The `SIBLING` keyword may only appear on arguments of an object type, to indicate that the argument should be a sibling object to the discriminator of the method. The `FUNCTIONAL` keyword indicates that the method, for a given set of arguments, is idempotent (i.e., the side effects of one call are the same as the side effects of more than one call) and will always return the same result (or raise the same exception); this information may be used for caching of return values in the client side stubs. The optional argument-direction information is one of the three keywords `IN`, `OUT`, `INOUT`, specifying whether the parameter is being used as an input parameter, an output parameter, or both.

A method return type is allowed (again separated from the procedure argument list by a colon), and a list of possible exceptions may be specified as a comma-separated list of exception names, bracketed with the keywords RAISES and END.

The optional procedure-id field allows a service description to specify the procedure code that is used in the RPC request packet for this method. Procedure ID's are restricted to the range [0,65279], and must be unique within an interface. This may only be used in methods on objects marked with the `SINGLETON` attribute.

If a method is marked with the `ASYNCHRONOUS` keyword and does not return a value or raise an exception, the RPC method call of a surrogate instance will return after sending the request packet to the RPC partner, as the success of the call does not depend on the completion of the associated code. Other RPC methods will block in such a way as to allow the scheduler to handle other events while it is waiting for the call to complete, if the user has registered the appropriate scheduler hooks with the ILU runtime.

The optional documentation-string is a quoted string, which is passed on to language bindings for which it is meaningful, such as the doc-string capability in Common Lisp.

For example:

    TYPE FancyString = OBJECT
      METHODS
        FUNCTIONAL Length () : cardinal,
        Substring (start : cardinal, end : cardinal) : string
          RAISES StartGreaterThanEnd, StartTooLarge, EndTooLarge END,
        Char (index : cardinal) : character
          RAISES BadIndex END
      END;

Note that the object language in ILU is not intended to be used to fully define an object type, but rather to describe it in a simple language that can be transformed into the different object type definition systems of several other languages.

### Exception Declarations

Exceptions in ILU are raised by ILU methods. They allow error conditions to be signalled back to the calling code. They are declared with a statement of the form:

    EXCEPTION exception-name [ : type-reference ] [ documentation-string ] ;

The optional type-reference part of the declaration allows the exception to have an associated value, to be used in interpretation of the exception. For example, an exception BadFilename might have the type `ilu.CString`, so that the actual bad filename can be associated with the exception:

The optional documentation-string is a quoted string, which is passed on to language bindings for which it is meaningful, such as the doc-string capability in Common Lisp.

    TYPE Filename = ilu.CString;
    EXCEPTION BadFileName : Filename "The value is the bad filename";

Because of the uncertain nature of life in distributed systems, the pre-defined exception `ilu.ProtocolError` (defined in the ILU interface) may be raised by any method, to indicate that the method could not be handled, for some reason. It has the following form:

    TYPE ProtocolErrorDetail = ENUMERATION
                    NoSuchClassAtServer = 1,
                    BrandMismatch = 2,
                    NoSuchMethodOnClass = 3,
                    InvalidArguments = 4,
                    UnknownObjectInstance = 5,
                    UnreachableModule = 6,
                    RequestRejectedByModule = 7,
                    TimeoutOnRequest = 8,
                    UnknownError = 9
            END;

    EXCEPTION ProtocolError : ProtocolErrorDetail;

Signalling of `ProtocolError` is never done by user-written server code; it is reserved to the transport and runtime layers of ILU.

### Constant Declarations

For convenience of interface design, constant values for certain simple types may be defined in ISL with statements of the form

    CONSTANT constant-name : constant-type = constant-value ;

#### Integer, Cardinal, and Byte Constants

A constant-value for types that are sub-types of `INTEGER`, `CARDINAL`, or `BYTE` is specified with the syntax

    [ sign ] [ base-indicator ] digits

where the optional base-indicator allows selection of bases 2, 8, 10 or 16. It is a digit '0' (zero) followed by either the character 'B' for base 2, 'X' for base 16, 'O' (oh) for base 8, or 'D' for base 10. The sign is only valid for subtypes of `INTEGER`; it is either '+' or '-'; if not specified, '+' is assumed. The base-indicator and digits fields are case-insensitive.

#### Real Constants

A constant-value for subtypes of `REAL` has the syntax:

    [ sign ] integer.fraction [ e exponent ]

where integer and fraction are sequences of decimal digits, sign is either '+' or '-' ('+' is the default), and exponent is the power of 10 which the rest of the value is multiplied by (defaults to 0).

#### ilu.CString Constants

A constant-value for a sub-type of `ilu.CString` has the form

    "characters"

where characters are any ISO-Latin-1 characters except for 8_000. The escape character is defined to be '#' (hash). The escape character may occur in the string only in the following ways:

    #" -- a single double-quote character
    ## -- a single escape character
    #hex-digithex-digit -- the octet 16_hex-digithex-digit
    #n -- newline
    #r -- carriage return

#### Examples of Constants

    CONSTANT Newline : byte = 10;
    CONSTANT Pi : short real = 3.14159;
    CONSTANT Big : long real = -1.1349e27;  (*  -1.1349 * 10**27   *)
    TYPE Filename = ilu.CString;
    CONSTANT MyLogin : Filename = "~/.login";
    CONSTANT Prompt : ilu.CString = "OK#n ";
    CONSTANT HeapBound : cardinal = 0xFFFF39a0;
    CONSTANT Pattern1 : cardinal = 0b000001000001;

## ilu.isl

The standard interface `ilu` can be found in the file ``ILUHOME/interfaces/ilu.isl'`; it is maintained as ``ILUHOME/src/stubbers/parser/ilu.isl'`. Here are its contents:

    INTERFACE ilu BRAND "v1";

    TYPE CString = SEQUENCE OF SHORT CHARACTER;

    TYPE ProtocolErrorDetail =
      ENUMERATION
        NoSuchClassAtServer,     (* server doesn't handle specified class *)
        BrandMismatch,           (* versions out of sync *)
        NoSuchMethodOnClass,     (* invalid method, or method not implemented *)
        InvalidArguments,        (* bad arguments passed *)
        UnknownObjectInstance,   (* specified instance not on server *)
        UnreachableModule,       (* no path to handler *)
        RequestRejectedByModule, (* request not looked at, for some reason *)
        TimeoutOnRequest,        (* no response from server within timeout *)
        UnknownError             (* catchall error *)
      END;

    EXCEPTION ProtocolError : ProtocolErrorDetail;

The declarations of `ProtocolErrorDetail` and `ProtocolError` don't belong here, and will be eliminated in favor of a reference manual section explaining the possible errors.

## Using OMG IDL with ILU

ILU allows the use of CORBA OMG IDL (4) instead of ILU ISL. It does this by translating the OMG IDL to its equivalent form in ISL. Most ILU tools will do this automatically, based on whether the suffix of the filename argument is ``.isl'` or ``.idl'`. In addition, the program `idl2isl` can be invoked explicitly to create an ISL version of an OMG IDL interface file. The program idl2isl translates from IDL to ISL. IDL is the Interface Definition Language defined by the Object Management Group.(5)

### Translation

On the whole, the translation from IDL to ISL is a straightforward change of syntax. There are a few cases, however, where a bit more is needed.

#### Anonymous types

OMG IDL allows type declarators to be used in certain places in the syntax (for example, struct members and operation parameters). ISL does not; it requires a type name in the corresponding situations. As a result, it is sometimes necessary for the translator to introduce a name in the ISL output for those types that are anonymous in the OMG IDL input. These names are always of the form `AnonType-nnn-`, where nnn is an integer.

For example, the OMG IDL declaration

    struct str {
    	long	f1;
    	long	f2[5];
    };

is translated into the following ISL:

    TYPE AnonType-1- = ARRAY OF 5 INTEGER;
    TYPE str = RECORD
    	f1 : INTEGER,
    	f2 : AnonType-1-
    	END;

#### Topmodules mode

When the translator is in this mode (which it is by default), only `module` declarations are allowed at the topmost level. Each `module` translates into an `INTERFACE` declaration in ISL, and the declarations inside each `module` go into the corresponding ISL `INTERFACE`.

If the translator is not in this mode, all the declarations in the IDL file go into one ISL `INTERFACE` whose name is taken from the OMG IDL input filename, less the ``.idl'` suffix.

#### Imports mode

When the translator is in this mode (which it is by default), `#include` preprocessor directives are, roughly speaking, turned into ISL `IMPORT` statements. This mode allows for separate compilation (stub generation) of interfaces. There are some restrictions: the `#include` directives must occur before any declarations in the file, and the files that are included must not be fragments. That is, each must consist of a sequence of whole declarations (more specifically, `module` declarations if in `topmodules` mode). The included files may in turn include other files.

If the translator is not in this mode, the input is considered to be the result of preprocessing the file first and textually substituting the included files, following the usual behavior of C and C++ compilers.

#### Unsupported constructs

The IDL types `Object` and `any` are disallowed by the translator. Use of `context` clauses on operations is also prohibited.

### Manual Invocation of `idl2isl`

The program is run automatically as an intermediate step by any of the ILU tools that take ISL files (normally ending in ``.isl'`) if the filename ends in ``.idl'`.

The program may also be run directly, with the following arguments:

    idl2isl { -Wb,toggle | -Wb,!toggle }* source.idl

In this case, it writes the ISL to its standard output. A toggle is set with an argument `-Wb,toggle` and cleared with an argument `-Wb,!toggle`. Toggle settings may also be effected by setting the environment variable ``IDL2ISL_OPTS'` to a comma-separated list of toggle names, each of which is either preceded by a ``!'` character (which clears it) or not (which sets it). Command-line arguments take precedence over the environment variable settings.

The toggles are:

- `dump` (default off): produce a dump of the abstract syntax tree. Used for debugging the translator itself.
- `imports` (default on): set the `imports` mode on (explained below).
- `topmodules` (default on): set the `topmodules` mode on (explained below).

## ISL Grammar

In this grammar, parentheses are used for grouping, vertical-bar indicates selection, braces indicated optionality, quotation marks indicate literal keywords or literal punctuation.

No whitespace is allowed between the parts of a `radix`, `number`, or `quoted-string`. Aside from that, whitespace is used to separate fields where necessary, and excess whitespace is ignored outside of `quoted-string`s.

Three primitives are used:

- name-string, which is a string consisting of decimal digits, upper and lower-case letters, and hyphens, beginning with a letter. It may not be a keyword, unless it is quoted with double-quotes.
- string, which is any sequence of characters.
- digits, which is a sequence of digits drawn from the digits for the particular radix. The default radix is decimal.

    interface = interface-def | interface interface-def

    interface-def = interface-declaration other-declarations

    interface-declaration = "INTERFACE" name-string
                            [ "BRAND" brand-string ]
                            [ "IMPORTS" import-list "END" ]
                            ";"

    import-name = name-string [ "FROM" filename ]

    import-list = import-name | import-list "," import-name

    other-declarations = [ other-declaration other-declarations ]

    other-declaration = constant-decl | exception-decl | type-decl

    constant-decl = "CONSTANT" name-string ":" ( integer-const
                                               | cardinal-const
                                               | boolean-const
                                               | byte-const
                                               | float-const
                                               | string-const ) ";"

    integer-const = [ "SHORT" | "LONG" ] "INTEGER" "=" [ sign ] number

    boolean-const = "BOOLEAN" "=" boolean-value

    cardinal-const = [ "SHORT" | "LONG" ] "CARDINAL" "=" number

    byte-const = "BYTE" "=" number

    float-const = [ "SHORT" | "LONG" ] "REAL" "="
                  [sign] digits [ "." digits ] [ "e" digits ]

    number = [ radix ] digits

    radix = "0" ( binary | octal | hexadecimal )

    binary = "b"

    octal = "o"

    hexadecimal = "x"

    string-const = "ilu.CString" "=" quoted-string

    exception-decl = "EXCEPTION" excp-name [ ":" type ] [ doc-string ] ";"

    excp-name = name-string

    type-decl = "TYPE" name-string "=" ( type | type-cons ) ";"

    type = primitive-type-name | [ name-string "." ] name-string

    primitive-type-name = "BYTE"
                        | [ "SHORT" | "LONG" ] "CARDINAL"
                        | [ "SHORT" | "LONG" ] "INTEGER"
                        | [ "SHORT" | "LONG" ] "REAL"
                        | [ "SHORT" ] "CHARACTER"
                        | "BOOLEAN"

    type-cons =   record-cons
                    | array-cons
                    | sequence-cons
                    | union-cons
                    | optional-cons
                    | enum-cons
                    | object-cons

    record-cons = "RECORD" field-list "END"

    field-list = field | field-list "," field

    field = name-string ":" type

    sequence-cons = [ "SHORT" ] "SEQUENCE" "OF" type [ "LIMIT" number ]

    array-cons = "ARRAY" "OF" dimensions-list type

    dimensions-list = number | dimensions-list "," number

    union-cons = [ int-enum-or-boolean-type ] "UNION" union-field-list "END"

    union-field-list = union-field | union-field-list "," union-field

    union-field = [ field-name-string ":" ] type [ "=" const-list "END" ]

    const-list = const | const-list "," const

    const = number | enum-field-name | boolean-value

    enum-cons = "ENUMERATION" enum-field-list

    enum-field-list = enum-field | enum-field-list "," enum-field

    enum-field = string

    boolean-value = "TRUE" | "FALSE"

    optional-cons = "OPTIONAL" type

    object-cons = "OBJECT" object-attributes

    object-attributes = object-feature | object-attributes object-feature

    object-feature =  "SINGLETON" singleton-protocol-info
                    | "COLLECTIBLE"
                    | "OPTIONAL"
                    | "DOCUMENTATION" doc-string
                    | "TYPEID" type-id-string
                    | "BRAND" brand-string
                    | "SUPERTYPES" supertype-list "END"
                    | "METHODS" method-list "END"

    supertype-list = type | supertype-list "," type

    singleton-protocol-info = quoted-string

    method-list = method | method-list "," method

    method = [ "FUNCTIONAL" | "ASYNCHRONOUS" ] name-string
             arguments [ ":" return-type ] [ "RAISES" exception-list "END"]
             [ doc-string ]

    return-type = type

    exception-list = excp-name | exception-list "," excp-name

    arguments = "(" [ argument-list ] ")"

    argument-list = argument | argument-list "," argument

    argument = [ "IN" | "OUT" | "INOUT" ] name-string ":" [ "SIBLING" ] type

    doc-string = quoted-string

    quoted-string = "\"" string "\""

Go to the previous, next section.