Quotations for the original syntax of OCaml 3.09 with Camlp5

Warning: This is a legacy page that is only available for historical reasons. I stopped developing OCamlp5 (called OCamlp4 at that time) in spring 2007 when Nicolas Pouillard announced a rewrite of Camlp5 on the OCaml list.

Warning II: This page describes version 0.2. It has not been updated for version 0.3 yet (and history proved that this was the right decision).

This page documents the quotation system in original syntax for OCaml abstract syntax trees for OCaml 3.09 with Camlp5. For this purpose I simply annotate the complete ocaml grammar with the quotations. For convenience this page contains also those parts of the grammar that are not yet supported or that are not relevant (through the order is different).

Page Navigation

Jump to

Conventions

A typical quotation description look like this:

       | pattern as  value-name
<:patt< $patt$ as $[lid]:id$ >>; id : string

The form of the quotation is given below the grammar rule. I hope it is mostly self-explanatory. Of course you can fill the place of the anti-quotation with more concrete syntax. The type of the anti-quotation is given after the semicolon if it is not obvious, like for $patt$. For the second anti-quotation the anti-quotation name lid is given in brackets because the name is optional. In many cases the anti-quotation name is required and without it the quotation parser will fail.

A note on syntactic sugar

There are a number of cases, where for different ocaml input phrases the compiler generates the same internal ast. For instance, both 2 + 3 and (+) 2 3 are internally represented with the same (nested) application ast node. The ocaml reference manual does not document syntac sugar, it often provides different grammar rules for what is the same thing internally.

This has some consequences for the quotation expander:

Syntactic sugar is also responsible for the most prominent quotation inconvenience: There is no quotation like <:expr< [ $list:els$ ] >>. The reason is, that a list like [ 1; 2 ] is expanded into 1 :: 2 :: [], which is internally represented like (::)(1, (::)(2, [])) (the last expression gives a syntax error because :: is a keyword and not an infix operator).

List of all quotations forms

6.11 Module expressions (module implementations)

definition ::= let [rec] let-binding  { and let-binding }
<:str_item< let $opt:rec$ $list:bindings$ >>; rec : bool, bindings : (pattern * expr) list
  | external value-name :  typexpr =  external-declaration
<:str_item< external $[lid:]lid$ : $ptype$ = $list:strings$ >>; lid : string, ptype : ptyp, strings : string list
<:str_item< external ( +++ ): $ptype$ = $list:strings$ >>; ptype : ptyp, strings : string list
  | type-definition
<:str_item< type $list:typedefs$ >>; typedefs : typedef list
  | exception-definition
  | class-definition
<:str_item< class $list:cdefs$ >>; cdefs : class_expr MLast.class_infos list
<:str_item< class $cdef$ and $cdef$ ... >>; cdef : class_expr MLast.class_infos
<:str_item< class $opt:vir$ [ [ $list:ctps$ ] ] $[lid:]id$ $[pat:]p$ ... = $cexpr$ and ... >>; vir : bool; ctps: (string * (bool * bool)) list; id : string; $p$ : pattern; cexpr : class_expr
  | classtype-definition
<:str_item< class type $list:ctdefs$ >>; ctdefs: class_type MLast.class_infos list
<:str_item< class type $ctdef$ and $ctdef$ ... >>; ctdef : class_type MLast.class_infos
<:str_item< class type $opt:vir$ [ [ $list:ctps$ ] ] $[lid:]id$ = $class_type$ and ... >>; vir: bool; ctps : (string * (bool * bool)) list; id : string; class_type : class-type
  | module module-name  { ( module-name :  module-type ) }  [ : module-type ] =  module-expr
<:str_item< module $[uid:]id$ = $[mexpr:]me$ >>; id : string, me : module_expr
<:str_item< module $[uid:]id$ : $[mtyp:]mt$ = $[mexpr:]me$ >>; id : string, mt : module_type, me : module_expr
<:str_item< module $[uid:]id$( $[uid:]id$ : $[mtyp:]mt) ... = $[mexpr:]me$ >>; id : string, mt : module_type, me : module_expr
<:str_item< module $[uid:]id$( $[uid:]id$ : $[mtyp:]mt) ... : $[mtyp:]mt$ = $[mexpr:]me$ >>; id : string, mt : module_type, me : module_expr
  | module type modtype-name =  module-type
<:str_item< module type $[uid:]id$ = $[mtyp:]mt$ >>; id : string, mt : module_type
  | open module-path
<:str_item< open $mod_ident$ >>; mod_ident : string list
<:str_item< open $uid:id$ . $uid:id$ ... >>; id : string
  | include module-expr
<:str_item< include $[mexpr:]:me$ >>; me : module_expr
  | module rec module-name :  module-type =  module-expr  { and module-name:  module-type =  module-expr }
<:str_item< module rec $list:mods$ >>; mods : (string * module_type * module_expr) list
  | expr
<:str_item< $exp:expr$ >>

module-expr ::= module-path
<:module_expr< $uid:id$ >>; id : string
<:module_expr< $mexpr$ . $mexpr$ >>
  | struct { definition  [;;] } end
<:module_expr< struct $list:str_items$ >>; str_items : str_item list
  | functor ( module-name :  module-type ) ->  module-expr
<:module_expr< functor ( $[uid:]id$ : $[mtyp:]mt$ ) : $mexpr$ >>; id : string, mt : module_type
  | module-expr (  module-expr )
<:module_expr< $mexpr$ $mexpr$ >>
  | ( module-expr )
<:module_expr< ( $mexpr$ ) >>
  | ( module-expr :  module-type )
<:module_expr< ( $mexpr$ : $[mtyp:]mt$ ) >>; mt : module_type

6.7 Expressions

expr ::= value-path
<:expr< $expr$ . $expr$ >>
<:expr< $uid:id$ . $uid:id$ ... $uid:id$ >>; id : string
<:expr< $uid:id$ . $uid:id$ ... $lid:id$ >>; id : string
  | constant
<:expr< $int:s$ >>; s : string
<:expr< $int32:s$ >>; s : string
<:expr< $int64:s$ >>; s : string
<:expr< $nativeint:s$ >>; s : string
<:expr< $flo:s$ >>; s : string
<:expr< $chr:s$ >>; s : string
<:expr< $str:s$ >>; s : string
polymorphic variants are on the todo list
  | ( expr )
<:expr< ( $expr$ ) >>
  | begin expr end
<:expr< begin $expr$ end >>
  | ( expr :  typexpr )
<:expr< ( $expr$ : $[ptyp:]ptyp$ ) >>; ptyp : ptyp
  | expr ,  expr  { , expr }
<:expr< $expr$, $expr$, ... >>
<:expr< $tup:exprs$ >>; exprs : expr list
  | constr  expr
see the rules for function application and values
  | `tag-name  expr
on the todo list
  | expr ::  expr
<:expr< $expr$ :: $expr$ >>
  | [ expr  { ; expr } ]
<:expr< [ $expr$; $expr$; ... ] >>
<:expr< [] >>
  | [| expr  { ; expr } |]
<:expr< [| $list:exprs$ |] >>; exprs : expr list
<:expr< [| $expr$; $expr$; ... |] >>
<:expr< [| |] >>
  | { field =  expr  { ; field =  expr } }
<:expr< { $list:lel$ } >>; lel : (patt * expr) list
<:expr< { $patt$ = $expr$; $uid:id$ . $uid:id$ . $lid:id$ = $expr$ } >>; patt: patt, id : string
  | { expr with  field =  expr  { ; field =  expr } }
<:expr< { $expr$ with $list:lel$ } >>; lel : (patt * expr) list
<:expr< { $expr$ with $patt$ = $expr$; $uid:id$ . $uid:id$ . $lid:id$ = $expr$ } >>; patt: patt, id : string
  | expr  { argument }+
<:expr< $expr$ $expr$ >>
  | prefix-symbol  expr
<:expr< prefix-symbol $expr$ >>
  | expr  infix-op  expr
<:expr< $expr$ infix-op $expr$ >>
  | expr .  field
<:expr< $expr$ . $expr$ >>
  | expr .  field <-  expr
<:expr< $expr$ . $expr$ <- $expr$ >>
  | expr .(  expr )
<:expr< $expr$ .( $expr$ ) >>
  | expr .(  expr ) <-  expr
<:expr< $expr$ .( $expr$ ) <- $expr$ >>
  | expr .[  expr ]
<:expr< $expr$ .[ $expr$ ] >>
  | expr .[  expr ] <-  expr
<:expr< $expr$ .[ $expr$ ] <- $expr$ >>
  | expr .{  expr }
<:expr< $expr$ .{ $expr$ } >>
<:expr< $expr$ .{ $expr$, $expr$ } >>
<:expr< $expr$ .{ $expr$, $expr$, $expr$ } >>
<:expr< $expr$ .{ $tup:exprs$ } >>; exprs : expr list
  | expr .{  expr } <-  expr
<:expr< $expr$ .{ $expr$ } <- $expr$ >>
<:expr< $expr$ .{ $expr$, $expr$ } <- $expr$ >>
<:expr< $expr$ .{ $expr$, $expr$, $expr$ } <- $expr$ >>
<:expr< $expr$ .{ $tup:exprs$ } <- $expr$ >>; exprs : expr list
  | if expr then  expr  [ else expr ]
<:expr< if $expr$ then $expr$ else $expr$ >>
<:expr< if $expr$ then $expr$ >>
  | while expr do  expr done
<:expr< while $expr$ do $expr$ done >>
  | for ident =  expr  ( to | downto ) expr do  expr done
<:expr< for $lid:id$ = $expr$ to $expr$ do $expr$ done >>; id : string
<:expr< for $lid:id$ = $expr$ downto $expr$ do $expr$ done >>; id : string
<:expr< for $lid:id$ = $expr$ $to:dir$ $expr$ do $expr$ done >>; dir : bool (true = to, false = downto), id : string
  | expr ;  expr
<:expr< $seq:exprs$ >>; exprs: expr list
<:expr< $expr$; $expr$; ... >>
  | match expr with  pattern-matching
<:expr< match $expr$ with [|] $list:matches$ >>; matches : (patt * expr option * expr) list
<:expr< match $expr$ with [|] $patt$ $opt:optex$ -> $expr$ | ... >>; patt : patt, optex: expr option
<:expr< match $expr$ with [|] $patt$ when $expr$ -> $expr$ | ... >>; patt : patt
<:expr< match $expr$ with [|] $patt$ -> $expr$ | ... >>; patt : patt
  | function pattern-matching
<:expr< function [|] $list:matches$ >>; matches : (patt * expr option * expr) list
<:expr< function [|] $patt$ $opt:optex$ -> $expr$ | ... >>; patt : patt, optex: expr option
<:expr< function [|] $patt$ when $expr$ -> $expr$ | ... >>; patt : patt
<:expr< function [|] $patt$ -> $expr$ | ... >>; patt : patt
  | fun multiple-matching
<:expr< fun $patt$ ... -> $expr$ >>; patt : patt
  | try expr with  pattern-matching
<:expr< try $expr$ with [|] $list:matches$ >>; matches : (patt * expr option * expr) list
<:expr< try $expr$ with [|] $patt$ $opt:optex$ -> $expr$ | ... >>; patt : patt, optex: expr option
<:expr< try $expr$ with [|] $patt$ when $expr$ -> $expr$ | ... >>; patt : patt
<:expr< try $expr$ with [|] $patt$ -> $expr$ | ... >>; patt : patt
  | let [rec] let-binding  { and let-binding } in  expr
<:expr< let $opt:rec$ $list:bindings$ in $expr$ >>; rec : bool, bindings : (patt * expr) list
<:expr< let $opt:rec$ $patt$ ... [: $[ptyp:]ptyp$ ] = $expr$ and ... in $expr$ >>; rec : bool, patt : patt, ptyp : ptyp
  | let module module-name  { ( module-name :  module-type ) }  [ : module-type ] =  module-expr in  expr
<:expr< let module $[uid:]id$ = $[mexpr:]me$ in $expr$ >>; id : string, me : module_expr
<:expr< let module $[uid:]id$ : $[mtyp:]mt$ = $[mexpr:]me$ in $expr$ >>; id : string, mt : module_type, me : module_expr
<:expr< let module $[uid:]id$( $[uid:]id$ : $[mtyp:]mt) ... = $[mexpr:]me$ in $expr$ >>; id : string, mt : module_type, me : module_expr
<:expr< let module $[uid:]id$( $[uid:]id$ : $[mtyp:]mt) ... : $[mtyp:]mt$ = $[mexpr:]me$ in $expr$ >>; id : string, mt : module_type, me : module_expr
  | new class-path
<:expr< new $list:ids$ >>; ids : string list
  | object [( pattern  [: typexpr] )]  { class-field } end
<:expr< object ($patt$ : $ptyp$) $list:citems$ >>; selfpatt : patt option; ptyp : ptyp; citems : class_str_item list
<:expr< object ($patt$) $list:citems$ >>; patt : patt; citems : class_str_item list
<:expr< object $opt:selfpatt$ $[cli:]citem$ ... >>; selfpatt : patt option; citem : class-field
<:expr< object $opt:selfpatt$ $list:citems$ >>; selfpatt : patt option; citems : class-field list
  | expr #  method-name
<:expr< $expr$ # $[lid:]id$ >>; id : string
  | inst-var-name
<:expr< $lid:id$ >>; id : string
  | inst-var-name <-  expr
<:expr< $expr$ <- $expr$ >>
  | ( expr :>  typexpr )
<:expr< ( $expr$ :> $[typ:]ptype$ ) >>; ptype : ptype
  | ( expr :  typexpr :>  typexpr )
<:expr< ( $expr$ : $[typ:]ptype$ :> $[typ:]ptype$ ) >>; ptype : ptype
  | {< inst-var-name =  expr  { ; inst-var-name =  expr } >}
<:expr< {< $list:fields$ >} >>; fields : (string * expr) list
<:expr< {< $[lid:]id$ = $expr$; ... >} >>; id : string
  | assert expr
<:expr< assert false >>
<:expr< assert $expr$ >>
  | lazy expr
<:expr< lazy $expr$ >>
argument ::= expr
  | ~ label-name
  | ~ label-name :  expr
  | ? label-name
  | ? label-name :  expr
pattern-matching ::= [ | ] pattern  [when expr] ->  expr  { | pattern  [when expr] ->  expr }
multiple-matching ::= { parameter }+  [when expr] ->  expr
let-binding ::= pattern =  expr
  | value-name  { parameter }  [: typexpr] =  expr
parameter ::= pattern
  | ~ label-name
  | ~ ( label-name  [: typexpr] )
  | ~ label-name :  pattern
  | ? label-name
  | ? ( label-name  [: typexpr]  [= expr] )
  | ? label-name :  pattern
  | ? label-name : (  pattern  [: typexpr]  [= expr] )

6.6 Patterns

pattern ::= value-name
<:patt< $lid:id$ >>; id : string
<:patt< (infix-op) >>
  | _
<:patt< _ >>
  | constant
<:patt< $patt$ . $patt$ >>
<:patt< $uid:id$ >>; id : string
<:patt< $lid:id$ >>; id : string
<:patt< $int:s$ >>; s : string
<:patt< $int32:s$ >>; s : string
<:patt< $int64:s$ >>; s : string
<:patt< $nativeint:s$ >>; s : string
<:patt< $flo:s$ >>; s : string
<:patt< $chr:s$ >>; s : string
<:patt< $str:s$ >>; s : string
<:patt< () >>
polymorphic variants are on the todo list
  | pattern as  value-name
<:patt< $patt$ as $[lid]:id$ >>; id : string
  | ( pattern )
<:patt< ( $patt$ ) >>
  | ( pattern :  typexpr )
<:patt< ( $patt$ : $[ptyp:]ptyp$ ) >>; ptyp : ptyp
  | pattern |  pattern
<:patt< $patt$ | $patt$ >>
  | constr  pattern
<:patt< $patt$ $patt$ >>
  | `tag-name  pattern
  | #typeconstr-name
  | pattern  { , pattern }
<:patt< $patt$, $patt$, ... >>
<:patt< $tup:pl$ >>; pl : patt list
  | char-literal   ..   char-literal
<:patt< $patt$ .. $patt$ >>
  | { field =  pattern  { ; field =  pattern } }
<:patt< { $patt$ = $patt$; ... >>
<:patt< { $list:lblpatts$ } >>; lblpatts : (patt * patt) list
  | [ pattern  { ; pattern } ]
<:patt< [ $patt$; ... ] >>
  | pattern ::  pattern
<:patt< $patt$ :: $patt$ :: $patt$ ... >>
<:patt< $patt$ :: $patt$ >>
  | [| pattern  { ; pattern } |]
<:patt< [| |] >>
<:patt< [| $patt$; ... |] >>
<:patt< [| $list:patts$ >>; patts : patt list

6.8 Type and exception definitions

6.8.1 Type definitions

type-definition ::= type typedef  { and typedef }
typedef ::= [type-params]  typeconstr-name  [type-information]
type abbreviation (lid : string):
<:typedef< type-parameters $[lid:]lid$ = $ptype$ constraints >>
variant type, with lid : string, cdl : (location * string * ptyp list) list:
<:typedef< type-parameters $[lid:]lid$ = $list:cdl$ constraints >>
<:typedef< type-parameters $[lid:]lid$ = private $list:cdl$ constraints >>
<:typedef< type-parameters $[lid:]lid$ = $ptype$ = $list:cdl$ constraints >>
<:typedef< type-parameters $[lid:]lid$ = $ptype$ = private $list:cdl$ constraints >>
record type, with lid : string, labels : (location * string * bool * ptyp) list:
<:typedef< type-parameters $[lid:]lid$ = { $list:labels$ } constraints >>
<:typedef< type-parameters $[lid:]lid$ = private { $list:labels$ } constraints >>
<:typedef< type-parameters $[lid:]lid$ = $ptype$ = { $list:labels$ } constraints >>
<:typedef< type-parameters $[lid:]lid$ = $ptype$ = private { $list:labels$ } constraints >>
abstract type (lid : string):
<:typedef< $[lid:]lid$ constraints >>
<:typedef< [+/-] 'tp $[lid:]lid$ constraints >>
<:typedef< ( [+/-] 'tp1, ... ) $[lid:]lid$ constraints >>
type-information ::= [type-equation]  [type-representation]  { type-constraint }
type-equation ::= = typexpr
type-representation ::= = constr-decl  { | constr-decl }
  | = { field-decl  { ; field-decl } }
 
     Extensions for private types:
  | = private constr-decl  { | constr-decl }
  | = private { field-decl  { ; field-decl } }
 
type-params ::= type-param
  | ( type-param  { , type-param } )
type-param ::= ' ident
  | + ' ident
  | - ' ident
constr-decl ::= constr-name
  | constr-name of  typexpr
field-decl ::= field-name :  poly-typexpr
  | mutable field-name :  poly-typexpr
type-constraint ::= constraint ' ident =  typexpr

Exception definitions

exception-definition ::= exception exception-name  [of typexpr]
<:str_item< exception $[uid:]uid$ [of $list:tl$] >>; uid : string, tl : ptyp list
  | exception exception-name =  constr
<:str_item< exception $[uid:]uid$ = $mod_ident$ >>; uid : string, mod_ident : string list
<:str_item< exception $[uid:]uid$ = $uid:id$ . ... $lid:id$ >>; uid : string, id : string

6.4 Type expressions

typexpr ::= ' ident
<:ptyp< ' $id$ >>; id : string
  | _
<:ptyp< _ >>
  | ( typexpr )
<:ptyp< ( $ptyp$ ) >>
  | [[?]label-name:]  typexpr ->  typexpr
<:ptyp< $t1$ -> $t2$ >>; t1, t2 : ptyp
labels are on the todo list
  | typexpr  { * typexpr }+
<:ptyp< $tup:types$ >>; types: ptyp list
<:ptyp< $ptyp$ * $ptyp$ * ... >>; t : ptyp
  | typeconstr
  | typexpr  typeconstr
<:ptyp< $arg$ $constr$ >>; arg, constr : ptyp
  | ( typexpr  { , typexpr } )  typeconstr
<:ptyp< ( $arg$, $arg$, ... ) $constr$ >>; arg, constr : ptyp
  | typexpr as '  ident
<:ptyp< $ptyp$ as ' $id$ >>; ptyp : ptyp, id : string
  | [ variant-type ]
on the todo list
  | < [..] >
<:ptyp< < > >>
<:ptyp< < .. > >>
  | < method-type  { ; method-type }  [; ..] >
<:ptyp< < $list:fields$ $opt:open$ > >>; fields : (string * ptyp) list, open : bool
<:ptyp< < $list:fields$ [ ; .. ] > >>; fields : (string * ptyp) list
<:ptyp< < $[lid:]id$ : $ptyp$; ... [ ; .. ] > >>; id : string
  | # class-path
<:ptyp< # $list:ids$ >>; ids : string list
  | typexpr #  class-path
<:ptyp< $ptyp$ # $list:ids$ >>; ids : string list
  | ( typexpr  { , typexpr } ) #  class-path
<:ptyp< ( $arg$, $arg$, ... ) # $list:ids$ >>; arg : ptyp, ids : string list
poly-typexpr ::= typexpr
  | { ' ident }+ .  typexpr
<:ptyp< '$id$ '$id$ ... . $ptyp$ >>; id : string, ptyp : ptyp
<;ptyp< $list:typevars$ . $ptyp$ >>; typevars : string list, ptyp : ptyp
method-type ::= method-name :  poly-typexpr

Variant types

variant-type ::= [ | ] tag-spec  { | tag-spec }
  | > [ tag-spec ]  { | tag-spec }
  | < [ | ] tag-spec-full  { | tag-spec-full }  [ > { `tag-name }+ ]
tag-spec ::= `tag-name  [ of typexpr ]
  | typexpr
tag-spec-full ::= `tag-name  [ of typexpr ]  { & typexpr }
  | typexpr

6.10 Module types (module specifications)

module-type ::= modtype-path
<:module_type< $uid:id$ >>; id : string
<:module_type< $lid:id$ >>; id : string
<:module_type< $mt$ ( $mt$ ) >>; mt : module_type
<:module_type< $mt$ . $mt$ >>; mt : module_type
  | sig { specification  [;;] } end
<:module_type< sig $[sigi:]si$ ... end >>; si : sig_item
<:module_type< sig $list:sis$ ... end >>; sis : sig_item list
  | functor ( module-name :  module-type ) ->  module-type
<:module_type< functor( $[uid:]id$ : $mt$ ) -> $mt$ >>; id : string
  | module-type with  mod-constraint  { and mod-constraint }
<:module_type< $mt$ with $list:wcl$ >>; wcl : with_constr list
  | ( module-type )
<:module_type< ( $mt$ ) >>
specification ::= val value-name :  typexpr
<:sig_item< val $[lid:]id$ : $[ptyp:]type$ >>; id : string; type : ptyp
<:sig_item< val (infix-op) : $[ptyp:]type$ >>; type : ptyp
  | external value-name :  typexpr =  external-declaration
<:sig_item< external (infix-op) : $[ptyp:]t$ = $list:strings$ >>; t : ptype, strings : string list
<:sig_item< external $[lid:]id$ : $[ptyp:]t$ = $list:strings$ >>; id : string, t : ptype, strings : string list
  | type-definition
<:sig_item< type $list:typedefs$ >>; typedefs : typedef list
  | exception constr-decl
<:sig_item< exception $[uid:]id$ >>; id : string
<:sig_item< exception $[uid:]id$ of $[ptyp:]t$ * ... >>; id : string, t : ptype
<:sig_item< exception $[uid:]id$ of $list:tl$ >>; id : string, tl : ptype list
  | class-specification
<:sig_item< class $list:ctdefs$ >>; ctdefs: class_type MLast.class_infos list
<:sig_item< class $ctdef$ and $ctdef$ ... >>; ctdef : class_type MLast.class_infos
<:sig_item< class $opt:vir$ [ [ $list:ctps$ ] ] $[lid:]id$ : $class_type$ and ... >>; vir: bool; ctps : (string * (bool * bool)) list; id : string; class_type : class-type
  | classtype-definition
<:sig_item< class type $list:ctdefs$ >>; ctdefs: class_type MLast.class_infos list
<:sig_item< class type $ctdef$ and $ctdef$ ... >>; ctdef : class_type MLast.class_infos
<:sig_item< class type $opt:vir$ [ [ $list:ctps$ ] ] $[lid:]id$ = $class_type$ and ... >>; vir: bool; ctps : (string * (bool * bool)) list; id : string; class_type : class-type
  | module module-name :  module-type
<:sig_item< module $[uid:]id$ : $[mtyp:]mt$ >>; id : string, mt : module_type
  | module module-name  { ( module-name :  module-type ) } :  module-type
<:sig_item< module $[uid:]id$( $[uid:]id$ : $[mtyp:]mt$ ) ... : $[mtyp:]mt$ >>; id : string, mt : module_type
  | module type modtype-name
<:sig_item< module type $[uid:]id$ >>; id : string
  | module type modtype-name =  module-type
<:sig_item< module type $[uid:]id$ = $[mtyp:]mt$ >>; id : string, mt : module_type
  | open module-path
<:sig_item< open $uid:id$ . $uid:id$ ... >>; id : string
<:sig_item< open $mod_ident$ >>; mod_ident : string list
  | include module-type
<:sig_item< include $[mtyp:]mt$ >>; mt : module_type
  | module rec module-name :  module-type  { and module-name:  module-type }
<:sig_item< module rec $list:mods$ >>; mods : (string * module_type) list
 
mod-constraint ::= type [type-parameters]  typeconstr =  typexpr
<:with_constr< type type-parameters $mod_ident$ = $[ptyp:]ptyp$ >>; mod_ident : string list, ptyp : ptype
  | module module-path =  extended-module-path
<:with_constr< module $mod_ident$ = $[mexp:]me$ >>; mod_ident : string list, me : module_expr

6.9.2 Class expressions

class-expr ::= class-path
<:class_expr< $list:class_longident$ >>; class_longident : string list
  | [ typexpr  {, typexpr} ]  class-path
<:class_expr< [ $list:ptyps$ ] $list:class_longident$ >>; ptyps : ptyp list, class_longident : string list
  | ( class-expr )
<:class_expr< ( $class_expr$ ) >>
  | ( class-expr :  class-type )
<:class_expr< ( $class_expr$ : $class_type$ ) >>; class_type : class_type
  | class-expr  {argument}+
<:class_expr< $class_expr$ $[exp:]expr$ >>; expr : expr
  | fun {parameter}+ ->  class-expr
<:class_expr< fun $[pat:]patt$ ... -> $class_expr$ >>; patt : patt
  | let [rec] let-binding  {and let-binding} in  class-expr
<:class_expr< let $opt:rec$ $list:bindings$ in $class_expr$ >>; rec : bool, bindings : (patt * expr) list
<:class_expr< let $opt:rec$ $patt$ ... [: $[ptyp:]ptyp$ ] = $expr$ and ... in $class_expr$ >>; rec : bool, patt : patt, ptyp : ptyp
  | object [( pattern  [: typexpr] )]  { class-field } end
<:class_expr< object ($patt$ : $ptyp$) $list:citems$ >>; selfpatt : patt option; ptyp : ptyp; citems : class_str_item list
<:class_expr< object ($patt$) $list:citems$ >>; patt : patt; citems : class_str_item list
<:class_expr< object $opt:selfpatt$ $[cli:]citem$ ... >>; selfpatt : patt option; citem : class-field
<:class_expr< object $opt:selfpatt$ $list:citems$ >>; selfpatt : patt option; citems : class-field list
class-field ::= inherit class-expr  [as value-name]
<:class_str_item< inherit $class_expr$ $opt:olid$ >>; olid : string option
<:class_str_item< inherit $class_expr$ as $[lid:]lid$ >>; lid : string option
<:class_str_item< inherit $class_expr$ >>
  | val [mutable] inst-var-name  [: typexpr] =  expr
<:class_str_item< val $opt:mf$ $[lid:]lid$ [ : $[typ:]ptyp$ ] = $expr$ >>; mf : bool, ptyp : ptyp, expr : expr
<:class_str_item< val mutable $[lid:]lid$ [ : $[typ:]ptyp$ ] = $expr$ >>; ptyp : ptyp, expr : expr
<:class_str_item< val $[lid:]lid$ [ : $[typ:]ptyp$ ] = $expr$ >>; ptyp : ptyp, expr : expr
  | val [mutable] inst-var-name  : typexpr  :> typexpr =  expr
<:class_str_item< val $opt:mf$ $[lid:]lid$ : $[typ:]ptyp$ :> $[typ:]ptyp$ = $expr$ >>; mf : bool, ptyp : ptyp, expr : expr
<:class_str_item< val mutable $[lid:]lid$ : $[typ:]ptyp$ :> $[typ:]ptyp$ = $expr$ >>; ptyp : ptyp, expr : expr
<:class_str_item< val $[lid:]lid$ : $[typ:]ptyp$ :> $[typ:]ptyp$ = $expr$ >>; ptyp : ptyp, expr : expr
  | val [mutable] inst-var-name  :> typexpr =  expr
<:class_str_item< val $opt:mf$ $[lid:]lid$ :> $[typ:]ptyp$ = $expr$ >>; mf : bool, ptyp : ptyp, expr : expr
<:class_str_item< val mutable $[lid:]lid$ :> $[typ:]ptyp$ = $expr$ >>; ptyp : ptyp, expr : expr
<:class_str_item< val $[lid:]lid$ :> $[typ:]ptyp$ = $expr$ >>; ptyp : ptyp, expr : expr
  | method [private] method-name  {parameter}  [: typexpr] =  expr
<:class_str_item< method $opt:priv$ $[lid:]id$ = $[exp:]expr$ >>; priv : bool; id : string; expr : expr
<:class_str_item< method $opt:priv$ $[lid:]id$ $[patt:]patt$ ... [ : $typ:ptyp$ ] = $[exp:]expr$ >>; priv : bool; id : string; patt : patt; ptyp : ptyp; expr : expr
  | method [private] method-name :  poly-typexpr =  expr
<:class_str_item< method $opt:priv$ $[lid:]id$ $opt:optyp$ = $[exp:]expr$ >>; priv : bool; id : string; optyp : ptyp option; expr : expr
<:class_str_item< method $opt:priv$ $[lid:]id$ : $[typ:]ptyp$ = $[exp:]expr$ >>; priv : bool; id : string; ptyp : ptyp; expr : expr
  | method [private] virtual method-name :  poly-typexpr
<:class_str_item< method $opt:priv$ virtual $[lid:]id$ : $[typ:]ptyp$ >>; priv : bool; id : string; ptyp : ptyp
  | constraint typexpr =  typexpr
<:class_str_item< constraint $[typ:]ptyp$ = $[typ:]ptyp$ >>; ptyp : ptyp
  | initializer expr
<:class_str_item< initializer $[exp:]expr$ >>; expr : expr

6.9.1 Class types

class-type ::=  
  | class-body-type
  | [[?]labeltypexpr ->  class-type
<:class_type< $[typ:]ptype$ -> $class_type$ >>; ptype : ptype
class-body-type ::= object [( typexpr )]  {class-field-spec} end
<:class_type< object $opt:selftype$ $list:sigitems$ >>; selftype : ptype option, sigitems : class_sig_item list
<:class_type< object [ ( $[ptyp:]selftype$ ) ] $sigitem$ ... >>; selftype : ptyp, sigitem : class_sig_item
  | class-path
<:class_type< $list:ids$ >>; ids : string list
  | [ typexpr  {, typexpr} ]  class-path
<:class_type< [ $list:args$ ] $list:ids$ >>; args : ptype list; ids : string list
class-field-spec ::= inherit class-type
<:class_sig_item< inherit $cltyp$ >>; cltyp : class_type
  | val [mutable] inst-var-name :  typexpr
<:class_sig_item< val $opt:mf$ $[lid:]id$ : $[typ:]ptyp$ >>; mf : bool; id : string; ptyp : ptyp
  | method [private] method-name :  poly-typexpr
<:class_sig_item< method $opt:priv$ virtual $[lid:]id$ : $[typ:]ptyp$ >>; priv : bool; id : string; ptyp : ptyp
  | method [private] virtual method-name :  poly-typexpr
<:class_sig_item< method $opt:priv$ $[lid:]id$ : $[typ:]ptyp$ >>; priv : bool; id : string; ptyp : ptyp
  | constraint typexpr =  typexpr
<:class_sig_item< constraint $[ptyp:]ptyp$ = $[ptyp:]ptyp$ >>; ptyp : ptyp

6.3 Names

Naming objects

value-name ::= lowercase-ident
  | ( operator-name )
operator-name ::= prefix-symbol | infix-op
infix-op ::= infix-symbol
  | * | = | or | & | :=
  | mod | land | lor | lxor | lsl | lsr | asr
constr-name ::= capitalized-ident
  | false
  | true
  | [ ]
  | ( )
  | ::
exception-name ::= capitalized-ident
label-name ::= lowercase-ident
tag-name ::= capitalized-ident
typeconstr-name ::= lowercase-ident
field-name ::= lowercase-ident
module-name ::= capitalized-ident
modtype-name ::= ident
class-name ::= lowercase-ident
inst-var-name ::= lowercase-ident
method-name ::= lowercase-ident

Referring to named objects

value-path ::= value-name
  | module-path .  value-name
constr ::= constr-name
  | module-path .  capitalized-ident
typeconstr ::= typeconstr-name
  | extended-module-path .  typeconstr-name
<:ptyp< $lid:id$ >>; id : string (lowercase)
<:ptyp< $uid:id$ >>; id : string (uppercase)
<:ptyp< $module$ . $item$ >>; modult, item : ptyp
<:ptyp< $arg$ $constr$ >>; arg, constr : ptyp
<:ptyp< $functor$ ( $module$ ) >>; functor, module : ptyp
field ::= field-name
  | module-path .  field-name
module-path ::= module-name
  | module-path .  module-name
extended-module-path ::= module-name
  | extended-module-path .  module-name
  | extended-module-path (  extended-module-path )
modtype-path ::= modtype-name
  | extended-module-path .  modtype-name
class-path ::= class-name
  | module-path .  class-name

Remaining grammar rules

There are no quotation forms below this point. The following material is included for convenience only.

6.1 Lexical conventions

Identifiers

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

Integer literals

integer-literal ::= [-] (0...9) { 0...9| _ }
  | [-] (0x| 0X) (0...9| A...F| a...f) { 0...9| A...F| a...f| _ }
  | [-] (0o| 0O) (0...7) { 0...7| _ }
  | [-] (0b| 0B) (0...1) { 0...1| _ }

Extensions for int32, int64 and nativeint Integer literals

int32-literal ::= integer-literal l
int64-literal ::= integer-literal L
nativeint-literal ::= integer-literal n

Floating-point literals

float-literal ::= [-] (0...9) { 0...9| _ } [. { 0...9| _ }] [(e| E) [+| -] (0...9) { 0...9| _ }]

Character literals

char-literal ::= ' regular-char '
  | ' escape-sequence '
escape-sequence ::= \ (\ | " | ' | n | t | b | r)
  | \ (0...9) (0...9) (0...9)
  | \x (0...9| A...F| a...f) (0...9| A...F| a...f)

String literals

string-literal ::= " { string-character } "
string-character ::= regular-char-str
  | escape-sequence

Naming labels

label ::= ~ (a ... z) { letter| 0...9| _| ' } :
optlabel ::= ? (a ... z) { letter| 0...9| _| ' } :

Prefix and infix symbols

infix-symbol ::= (= | < | > | @ | ^ | | | & | + | - | * | / | $ | %) { operator-char }
prefix-symbol ::= (! | ? | ~) { operator-char }
operator-char ::= ! | $ | % | & | * | + | - | . | / | : | < | = | > | ? | @ | ^ | | | ~

Line number directives

linenum-directive ::= # {0 ... 9}+
  | # {0 ... 9}+ " { string-character } "

6.5 Constants

constant ::= integer-literal   
  | int32-literal
  | int64-literal
  | nativeint-literal    
  | float-literal
  | char-literal
  | string-literal
  | constr
  | `tag-name

6.9 Classes

6.9.2 Class expressions

Method definition

expr ::= ...
  | inst-var-name <-  expr
  | {< [ inst-var-name =  expr  { ; inst-var-name =  expr } ] >}

6.9.3 Class definitions

class-definition ::= class class-binding  { and class-binding }
class-binding ::= [virtual] [[ type-parameters ]]  class-name  {parameter}  [: class-type] =  class-expr
type-parameters ::= ' ident  { , ' ident }

6.9.4 Class specification

class-specification ::= class class-spec  { and class-spec }
class-spec ::= [virtual] [[ type-parameters ]]  class-name :  class-type

6.9.5 Class type definitions

classtype-definition ::= class type classtype-def  { and classtype-def }
classtype-def ::= [virtual] [[ type-parameters ]]  class-name =  class-body-type

6.12 Compilation units

unit-interface ::= { specification  [;;] }
unit-implementation ::= { definition  [;;] }

9. The toplevel system (ocaml)

toplevel-input ::= { toplevel-phrase } ;;
toplevel-phrase ::= toplevel-definition
  | expr
  | # ident  directive-argument
toplevel-definition ::= let [rec] let-binding  { and let-binding }
  | external value-name :  typexpr =  external-declaration
  | type-definition
  | exception-definition
  | module module-name  [ : module-type ] =  module-expr
  | module type modtype-name =  module-type
  | open module-path
directive-argument ::= nothing
  | string-literal
  | integer-literal
  | value-path


last modified on 20 Sep 2011 by Hendrik