directive:
      # open string
   |  # close string
   |  # ident string
implementation:
      {impl-phrase ;;}

impl-phrase:
      expr
   |  value-definition
   |  type-definition
   |  exception-definition
   |  directive

value-definition:
      let [rec] let-binding {and let-binding}
interface:
      {intf-phrase ;;}

intf-phrase:
      value-declaration
   |  type-definition
   |  exception-definition
   |  directive

value-declaration:
      value ident : typexpr {and ident : typexpr}
ident:
      letter {letter | 0...9 | _}

letter:
      A...Z | a...z
integer-literal:
      [-] {0...9}+
   |  [-] (0x | 0X) {0...9 | A...F | a...f}+
   |  [-] (0o | 0O) {0...7}+
   |  [-] (0b | 0B) {0...1}+
float-literal:
      [-] {0...9}+ [. {0...9}] [(e | E) [+ | -] {0...9}+]
char-literal:
      ` regular-char `
   |  ` \ (\ | ` | n | t | b | r) `
   |  ` \ (0...9) (0...9) (0...9) `
string-literal:
      " {string-character} "

string-character:
      regular-char
   |  \ (\ | " | n | t | b | r)
   |  \ (0...9) (0...9) (0...9)
global-name:
      ident
   |  ident __ ident
variable:
      global-name
   |  prefix operator-name

operator-name:
      + | - | * | / | mod | +. | -. | *. | /.
   |  @ | ^ | ! | := | = | <> | == | != | !
   |  < | <= | > | <= | <. | <=. | >. | <=.

cconstr:
      global-name
   |  []
   |  ()

ncconstr:
      global-name
   |  prefix ::

typeconstr:
      global-name

label:
      global-name
typexpr:
      ' ident
   |  ( typexpr )
   |  typexpr -> typexpr
   |  typexpr {* typexpr}+
   |  typeconstr
   |  typexpr typeconstr
   |  ( typexpr {, typexpr} ) typeconstr
constant:
      integer-literal
   |  float-literal
   |  char-literal
   |  string-literal
   |  cconstr
pattern:
      ident
   |  _
   |  pattern as ident
   |  ( pattern )
   |  ( pattern : typexpr )
   |  pattern | pattern
   |  constant
   |  ncconstr pattern
   |  pattern , pattern {, pattern}
   |  { label = pattern {; label = pattern} }
   |  [ ]
   |  [ pattern {; pattern} ]
   |  pattern :: pattern
expr:
      ident
   |  variable
   |  constant
   |  ( expr )
   |  begin expr end
   |  ( expr : typexpr )
   |  expr , expr {, expr}
   |  ncconstr expr
   |  expr :: expr
   |  [ expr {; expr} ]
   |  [| expr {; expr} |]
   |  { label = expr {; label = expr} }
   |  expr expr
   |  prefix-op expr
   |  expr infix-op expr
   |  expr . label
   |  expr . label <- expr
   |  expr .( expr )
   |  expr .( expr ) <- expr
   |  expr & expr
   |  expr or expr
   |  if expr then expr [else expr]
   |  while expr do expr done
   |  for ident = expr (to | downto) expr do expr done
   |  expr ; expr
   |  match expr with simple-matching
   |  fun multiple-matching
   |  function simple-matching
   |  try expr with simple-matching
   |  let [rec] let-binding {and let-binding} in expr

simple-matching:
      pattern -> expr {| pattern -> expr}

multiple-matching:
      pattern-list -> expr {| pattern-list -> expr}

pattern-list:
      pattern {pattern}

let-binding:
      pattern = expr
   |  variable pattern-list = expr

prefix-op:
      - | -. | !

infix-op:
      + | - | * | / | mod | +. | -. | *. | /. | ** | @ | ^ | ! | :=
   |  = | <> | == | != | < | <= | > | >= | <. | <=. | >. | >=.
type-definition:
      type typedef {and typedef}

typedef:
      type-params ident = constr-decl {| constr-decl}
   |  type-params ident = { label-decl {; label-decl} }
   |  type-params ident == typexpr
   |  type-params ident

type-params:
      nothing
   |  ' ident
   |  ( ' ident {, ' ident} )

constr-decl:
      ident
   |  ident of typexpr

label-decl:
      ident : typexpr
   |  mutable ident : typexpr
exception-definition:
      exception constr-decl {and constr-decl}