
ident ::=
  |  (letter | _) { letter | 0...9 | _ | ' }

letter ::=
  |  A ... Z  |  a ... z

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 | _ }

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

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-literal ::=
  |  " { string-character } "

string-character ::=
  |  regular-char-str
  |  escape-sequence

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

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

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

prefix-symbol ::=
  |  (!  |  ?  |  ~) { operator-char }

operator-char ::=
  |  !  |  $  |  %  |  &  |  *  |  +  |  -  |  .  | 
  |  /  |  :  |  <  |  =  |  >  |  ?  |  @  | 
  |  ^  |  |  |  ~

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

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

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

value-path ::=
  |  value-name
  |  module-path . value-name

constr ::=
  |  constr-name
  |  module-path . constr-name

typeconstr ::=
  |  typeconstr-name
  |  extended-module-path . typeconstr-name

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

typexpr ::=
  |  ' ident
  |  _
  |  ( typexpr )
  |  [[?]label-name:] typexpr -> typexpr
  |  typexpr { * typexpr }+
  |  typeconstr
  |  typexpr typeconstr
  |  ( typexpr { , typexpr } ) typeconstr
  |  typexpr as ' ident
  |  variant-type
  |  < [..] >
  |  < method-type { ; method-type } [; ..] >
  |  # class-path
  |  typexpr # class-path
  |  ( typexpr { , typexpr } ) # class-path

poly-typexpr ::=
  |  typexpr
  |  { ' ident }+ . typexpr

method-type ::=
  |  method-name : poly-typexpr

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

constant ::=
  |  integer-literal
  |  float-literal
  |  char-literal
  |  string-literal
  |  constr
  |  false
  |  true
  |  []
  |  ()
  |  `tag-name

pattern ::=
  |  value-name
  |  _
  |  constant
  |  pattern as value-name
  |  ( pattern )
  |  ( pattern : typexpr )
  |  pattern | pattern
  |  constr pattern
  |  `tag-name pattern
  |  #typeconstr-name
  |  pattern { , pattern }
  |  { field = pattern { ; field = pattern } }
  |  [ pattern { ; pattern } ]
  |  pattern :: pattern
  |  [| pattern { ; pattern } |]

expr ::=
  |  value-path
  |  constant
  |  ( expr )
  |  begin expr end
  |  ( expr : typexpr )
  |  expr , expr { , expr }
  |  constr expr
  |  `tag-name expr
  |  expr :: expr
  |  [ expr { ; expr } ]
  |  [| expr { ; expr } |]
  |  { field = expr { ; field = expr } }
  |  { expr with field = expr { ; field = expr } }
  |  expr { argument }+
  |  prefix-symbol expr
  |  expr infix-op expr
  |  expr . field
  |  expr . field <- expr
  |  expr .( expr )
  |  expr .( expr ) <- expr
  |  expr .[ expr ]
  |  expr .[ expr ] <- 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 pattern-matching
  |  function pattern-matching
  |  fun multiple-matching
  |  try expr with pattern-matching
  |  let [rec] let-binding { and let-binding } in expr
  |  new class-path
  |  object [( pattern [: typexpr] )] { class-field } end
  |  expr # method-name
  |  inst-var-name
  |  inst-var-name <- expr
  |  ( expr :> typexpr )
  |  ( expr : typexpr :> typexpr )
  |  {< inst-var-name = expr { ; inst-var-name = expr } >}
  |  assert 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] )

type-definition ::=
  |  type typedef { and typedef }

typedef ::=
  |  [type-params] typeconstr-name [type-information]

type-information ::=
  |  [type-equation] [type-representation] { type-constraint }

type-equation ::=
  |  = typexpr

type-representation ::=
  |  = constr-decl { | constr-decl }
  |  = { 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-definition ::=
  |  exception constr-name [of typexpr]
  |  exception constr-name = constr

class-type ::=
  |  class-body-type
  |  [[?]label-name:] typexpr -> class-type

class-body-type ::=
  |  object [( typexpr )] {class-field-spec} end
  |  class-path
  |  [ typexpr {, typexpr} ] class-path

class-field-spec ::=
  |  inherit class-type
  |  val [mutable] inst-var-name : typexpr
  |  method [private] method-name : poly-typexpr
  |  method [private] virtual method-name : poly-typexpr
  |  constraint typexpr = typexpr

class-expr ::=
  |  class-path
  |  [ typexpr {, typexpr} ] class-path
  |  ( class-expr )
  |  ( class-expr : class-type )
  |  class-expr {argument}+
  |  fun {parameter}+ -> class-expr
  |  let [rec] let-binding {and let-binding} in class-expr
  |  object [( pattern [: typexpr] )] { class-field } end

class-field ::=
  |  inherit class-expr [as value-name]
  |  val [mutable] inst-var-name [: typexpr] = expr
  |  method [private] method-name {parameter} [: typexpr] = expr
  |  method [private] method-name : poly-typexpr = expr
  |  method [private] virtual method-name : poly-typexpr
  |  constraint typexpr = typexpr
  |  initializer expr

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

class-definition ::=
  |  class class-binding { and class-binding }

class-binding ::=
  |  [virtual] [[ type-parameters ]] class-name
  |  {parameter} [: class-type]  = class-expr

type-parameters ::=
  |  ' ident { , ' ident }

class-specification ::=
  |  class class-spec { and class-spec }

class-spec ::=
  |  [virtual] [[ type-parameters ]] class-name : class-type

classtype-definition ::=
  |  class type classtype-def
  |  { and classtype-def }

classtype-def ::=
  |  [virtual] [[ type-parameters ]] class-name = class-body-type

module-type ::=
  |  modtype-path
  |  sig { specification [;;] } end
  |  functor ( module-name : module-type ) -> module-type
  |  module-type with mod-constraint { and mod-constraint }
  |  ( module-type )

mod-constraint ::=
  |  type [type-parameters] typeconstr = typexpr
  |  module module-path = extended-module-path

specification ::=
  |  val value-name : typexpr
  |  external value-name : typexpr = external-declaration
  |  type-definition
  |  exception constr-decl
  |  class-specification
  |  classtype-definition
  |  module module-name : module-type
  |  module module-name { ( module-name : module-type ) }
  |  : module-type
  |  module type modtype-name
  |  module type modtype-name = module-type
  |  open module-path
  |  include module-type

module-expr ::=
  |  module-path
  |  struct { definition [;;] } end
  |  functor ( module-name : module-type ) -> module-expr
  |  module-expr ( module-expr )
  |  ( module-expr )
  |  ( module-expr : module-type )

definition ::=
  |  let [rec] let-binding { and let-binding }
  |  external value-name : typexpr = external-declaration
  |  type-definition
  |  exception-definition
  |  class-definition
  |  classtype-definition
  |  module module-name { ( module-name : module-type ) }
  |  [ : module-type ]  = module-expr
  |  module type modtype-name = module-type
  |  open module-path
  |  include module-expr

unit-interface ::=
  |  { specification [;;] }

unit-implementation ::=
  |  { definition [;;] }

int32-literal ::=
  |  integer-literal l

int64-literal ::=
  |  integer-literal L

nativeint-literal ::=
  |  integer-literal n

type-representation ::=
  |  ...
  |  = private constr-decl { | constr-decl }
  |  = private { field-decl { ; field-decl } }

definition ::=
  |  ...
  |  module rec module-name : module-type = module-expr 
  |  { and module-name: module-type = module-expr }

specification ::=
  |  ...
  |  module rec module-name : module-type
  |  { and module-name: module-type }

type-equation ::=
  |  ...
  |  = private typexpr

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

debug-expr ::=
  |  lowercase-ident
  |  { capitalized-ident . } lowercase-ident
  |  *
  |  $ integer
  |  debug-expr . lowercase-ident
  |  debug-expr .( integer )
  |  debug-expr .[ integer ]
  |  ! debug-expr
  |  ( debug-expr )
