IDL syntax

## 2 IDL syntax

This section describes the syntax of IDL files. IDL syntax is very close to that of C declarations, with extra attributes between brackets adding information to the C types. The following example should give the flavor of the syntax:

            int f([in,string] char * msg);

This reads: ```f` is a function taking a character string as input and returning an `int`''.

### 2.1 Lexical conventions

##### Blanks.

Space, newline, horizontal tabulation, carriage return, line feed and form feed are considered as blanks. Blanks are ignored, but they separate adjacent tokens.

##### Comments.

Both C-style comments `/* ... */` and Java-style comments `// ...` are supported. C-style comments are introduced by `/*` and terminated by `*/`. Java-style comments are introduced by `//` and extend to the end of the line. Comments are treated as blank characters. Comments do not occur inside string or character literals. Nested C-style comments are not supported.

##### Identifiers.

Identifiers have the same syntax as in C.

`ident` | ::= | (`A` ... `Z` | `a` ... `z` | `_`) {`A` ... `Z` | `a` ... `z` | `0` ... `9` | `_`}

##### Literals.

Integer literals, character literals and string literals have the same syntax as in C.

`integer` | ::= | [`-`] {`0` ... `9`} [`-`] `0x` {`0` ... `9` | `a` ... `f` | `A` ... `F`} [`-`] `0` {`0` ... `7`}
`character` | ::= | `'` (`regular-char` | `escape-char`) `'`
`string` | ::= | `"` {`regular-char` | `escape-char`} `"`
`escape-char` | ::= | `\` (`b`| `n`| `r`| `t`)
| | | `\` (`0`...`7`) [`0`...`7`] [`0`...`7`]

##### UUID.

Unique identifiers are composed of 16 hexadecimal digits, in groups of 8, 4, 4, 4 and 12, separated by dashes.

`uuid` | ::= | `hex`8 `-` `hex`4 `-` `hex`4 `-` `hex`4 `-` `hex`4 `hex`4 `hex`4
`hex` | ::= | `0` ... `9` | `a` ... `f` | `A` ... `F`

### 2.2 Limited expressions

Limited expressions are similar to C expressions, with the omission of assignment operators (`=`, `+=`, etc), and the addition of the unsigned (logical) right shift operator `>>>`. Operators have the same precedences and associativities as in C. They are listed below in decreasing priority order.

`lexpr` | ::= | `ident`
| | | `integer`
| | | `character`
| | | `true`
| | | `false`
| | | `string`
| | | `sizeof` `(` `type-expr` `)`
| | | `(` `lexpr` `)`
| | | `lexpr` (`.` | `->`) `ident`
| | | `(` `type-expr` `)` `lexpr`
| | | (`&`| `*`| `!`| `~`| `-`| `+`) `lexpr`
| | | `lexpr` (`*`| `/`| `%`) `lexpr`
| | | `lexpr` (`+`| `-`) `lexpr`
| | | `lexpr` (`<<`| `>>`
| | | `>>>`) `lexpr`
| | | `lexpr` (`==`| `!=`| `>=`| `<=`| `>`| `<`)
| | | `lexpr` (`&`| `^`| `|`) `lexpr`
| | | `lexpr` (`&&`| `||`) `lexpr`
| | | `lexpr` `?` `lexpr` `:` `lexpr`

Constant limited expressions, written `const-lexpr` below, can only reference identifiers that are bound by the IDL `const` declaration.

### 2.3 Attributes

`attributes` | ::= | `[` `attribute` { `,` `attribute` } `]`
`attribute` | ::= | `ident`
| | | `ident` `(` [`lexpr`] { `,` [`lexpr`] } `)`
| | | `ident` `(` `uuid` `)`
| | | `attribute` `*`
| | | `*` `attribute`

Attribute lists are written in brackets `[...]`, and are always optional. Each attribute is identified by a name, and may carry optional arguments. Starred attributes apply to the element type of a pointer or array type, rather than to the pointer or array type itself. The following table summarizes the recognized attributes and their arguments.

Attribute | Context where it can appear
`abstract` | `typedef`
`bigarray` | array type
`blocking` | function declaration
`camlint` | `int` or `long` integer type
`compare``(``fun-name``)` | `typedef`
`c2ml``(``fun-name``)` | `typedef`
`errorcheck``(``fun-name``)` | `typedef`
`errorcode` | `typedef`
`finalize``(``fun-name``)` | `typedef`
`fortran` | array type with `bigarray` attribute
`hash``(``fun-name``)` | `typedef`
`ignore` | any pointer type
`in` | function parameter
`int_default``(` `camlint`| `nativeint`| `int32`| `int64``)` | interface
`int32` | `int` or `long` integer type
`int64` | `int` or `long` integer type
`length_is``(``le`1`,` `le`2`,`...`)` | array type
`long_default``(` `camlint`| `nativeint`| `int32`| `int64``)` | interface
`managed` | array type with `bigarray` attribute
`ml2c``(``fun-name``)` | `typedef`
`mlname(` `fun-or-field-name` `)` | function declaration, `struct` field
`mltype("` `caml-type-expr` `")` | `typedef`
`nativeint` | `int` or `long` integer type
`null_terminated` | array of pointers
`object` | interface
`out` | function parameter
`pointer_default``(` `ref`| `unique`| `ptr``)` | interface
`propget` | function declaration
`propput` | function declaration
`propputref` | function declaration
`ptr` | any pointer type
`ref` | any pointer type
`set` | enum type
`size_is``(``le`1`,` `le`2`,`...`)` | array type
`string` | character array or pointer
`switch_is``(``le``)` | union type or pointer to union
`switch_type``(``ty``)` | union or pointer to union
`unique` | any pointer, array, or bigarray type
`uuid``(` `uuid` `)` | interface

### 2.4 Types and declarators

The declaration of an identifier along with its type is as in C: a type specification comes first, followed by the identifier possibly decorated with `*` and `[...]` to denote pointers and array types. For instance, `int x` declares an identifier `x` of type `int`, while `int (*x)[]` declares an identifier `x` that is a pointer to an array of integers.

`type-spec` | ::= | [`unsigned`| `signed`] (`int`| `short`| `long`| `char`| `hyper`| `long` `long`| `__int64`)
| | | `byte`
| | | `float`
| | | `double`
| | | `boolean`
| | | `void`
| | | `ident`
| | | `wchar_t`
| | | `handle_t`
| | | `struct` `ident`
| | | `union` `ident`
| | | `enum` `ident`
| | | `struct-decl`
| | | `union-decl`
| | | `enum-decl`
`declarator` | ::= | {`*`} `direct-declarator`
`direct-declarator` | ::= | `ident`
| | | `(` `declarator` `)`
| | | `direct-declarator` `[` [`const-lexpr`] `]`

### 2.5 Structures, unions and enumerations

`struct-decl` | ::= | `struct` [`ident`] `{` {`field-decl`} `}`
`field-decl` | ::= | `attributes` `type-spec` `declarator` { `,` `declarator` } `;`
`union-decl` | ::= | `union` [`ident`] `{` {`union-case`} `}`
| | | `union` [`ident`] `switch` `(` `type-spec` `ident` `)` `{` {`union-case`} `}`
`union-case` | ::= | {`case` `ident` `:`}+ [`field-decl`] `;` `default` `:` [`field-decl`] `;`
`enum-decl` | ::= | `enum` [`ident`] `{` `enum-case` {`,` `enum-case`} [`,`] `}`
`enum-case` | ::= | `ident` [`=` `const-lexpr`]

IDL `struct` declarations are like those of C, with the addition of optional attributes on each field. `union` declarations are also as in C, except that each case of an union must be labeled by one or several `case` `ident` `:`. The first form of union declaration assumes that the discriminant of the union is provided separately via a `switch_is` annotation on the union type, while the second form encapsulates the discriminant along with the union itself (like in Pascal's `record case of` construct).

### 2.6 Function declarations

`function-decl` | ::= | `attributes` `type-spec` {`*`} `ident` `(` `params` `)` {`quote``(``ident``,` `string``)`}
`params` | ::= | e
| | | `void`
| | | `param` { `,` `param` }
`param` | ::= | `attributes` `type-spec` `declarator`

Function declarations are like in ANSI C, with the addition of attributes on each parameter and on the function itself. Parameters must be named. The optional `quote` statements following the declaration are user-provided calling sequences and deallocation sequences that replaces the default sequences in the `camlidl`-generated stub code for the function.

### 2.7 Constant definitions

`constant-decl` | ::= | `const` `attributes` `type-spec` {`*`} `ident` `=` `const-lexpr` `;`

A constant declaration associates a name to a limited expression. The limited expression can refer to constant names declared earlier, but cannot refer to other kinds of identifiers. The optional attributes influence the interpretation of the type specification, e.g. `const int x = 3` defines `x` with Caml type `int`, but `const [int64] long x = 5` defines `x` with Caml type `int64`.

### 2.8 IDL files

`file` | ::= | {`decl`}
`decl` | ::= | `function-decl` `;`
| | | `constant-decl` `;`
| | | `struct-decl` `;`
| | | `union-decl` `;`
| | | `enum-decl` `;`
| | | `typedef` `attributes` `type-spec` `declarator` { `,` `declarator` } `;`
| | | `attributes` `interface` `ident` [ `:` `ident` ] `{` {`decl`} `}`
| | | `struct` `ident` `;`
| | | `union` `ident` `;`
| | | `union` `switch` `(` `type-spec` `ident` `)` `;`
| | | `attributes` `interface` `ident` `;`
| | | `import` `string` `;`
| | | `quote` `(` [`ident` `,`] `string` `)`
| | | `cpp_quote` `(` `string` `)`

An IDL file is a sequence of IDL declarations. Declarations include function declarations, constant declarations, type declarations (structs, unions, enums, as well as a C-style `typedef` declaration to name a type expression), and interfaces.
An interface declaration gives a name and attributes to a collection of declarations. For interfaces with the `object` attribute, an optional super-interface can be provided, as in `interface` `intf` `:` `super-intf`. The name of the interface can be used as a type name in the remainder of the file.
Forward declarations of structs, unions and interfaces are supported in the usual C manner, by just giving the name of the struct, union or interface, but not its actual contents.
The `import` statement reads another IDL file and makes available its type and constant declarations in the remainder of the file. No code is generated for the functions and interfaces declared in the imported file. The same file can be imported several times, but is read in only the first time.
The `quote` `(` `ident` `,` `str` `)` diversion copies the string `str` verbatim to one of the files generated by the `camlidl` compiler. The `ident` determines the file where `str` is copied: it can be `ml` for the Caml implementation file (`.ml`), `mli` for the Caml interface file (`.mli`), `mlmli` for both Caml files, `h` for the C header file (`.h`), and `c` for the C source file containing the generated stub code (`.c` file). For backward compatibility, `cpp_quote` `(` `str` `)` is recognized as synonymous for `quote` `(` `h` `,` `str` `)`.