(***********************************************************************)
(*                                                                     *)
(*                                OCaml                                *)
(*                                                                     *)
               , projet Cristal , INRIA Rocquencourt         
(*                                                                     *)
   Copyright 1996 Institut National de Recherche en Informatique et   
   en Automatique .   All rights reserved .   This file is distributed    
   under the terms of the Q Public License version 1.0 .               
(*                                                                     *)
(***********************************************************************)

(** Abstract syntax tree produced by parsing *)

open Asttypes

* { 2 Extension points }

type attribute = string loc * payload
       (* [@id ARG]
          [@@id ARG]

          Metadata containers passed around within the AST.
          The compiler ignores unknown attributes.
       *)

and extension = string loc * payload
      (* [%id ARG]
         [%%id ARG]

         Sub-language placeholder -- rejected by the typechecker.
      *)

and attributes = attribute list

and payload =
  | PStr of structure
  | PTyp of core_type  (* : T *)
  | PPat of pattern * expression option  (* ? P  or  ? P when E *)

* { 2 Core language }

(* Type expressions *)

and core_type =
    {
     ptyp_desc: core_type_desc;
     ptyp_loc: Location.t;
     ptyp_attributes: attributes; (* ... [@id1] [@id2] *)
    }

and core_type_desc =
  | Ptyp_any
        (*  _ *)
  | Ptyp_var of string
        (* 'a *)
  | Ptyp_arrow of label * core_type * core_type
        (* T1 -> T2       (label = "")
           ~l:T1 -> T2    (label = "l")
           ?l:T1 -> T2    (label = "?l")
         *)
  | Ptyp_tuple of core_type list
  T1 * ... * Tn 

            Invariant : n > = 2 
        

           Invariant: n >= 2
        *)
  | Ptyp_constr of Longident.t loc * core_type list
        (* tconstr
           T tconstr
           (T1, ..., Tn) tconstr
         *)
  | Ptyp_object of (string * attributes * core_type) list * closed_flag
        (* < l1:T1; ...; ln:Tn >     (flag = Closed)
           < l1:T1; ...; ln:Tn; .. > (flag = Open)
         *)
  | Ptyp_class of Longident.t loc * core_type list
  # tconstr 
            T # tconstr 
            ( T1 , ... , Tn ) # tconstr 
         
           T #tconstr
           (T1, ..., Tn) #tconstr
         *)
  | Ptyp_alias of core_type * string
        (* T as 'a *)
  | Ptyp_variant of row_field list * closed_flag * label list option
        (* [ `A|`B ]         (flag = Closed; labels = None)
           [> `A|`B ]        (flag = Open;   labels = None)
           [< `A|`B ]        (flag = Closed; labels = Some [])
           [< `A|`B > `X `Y ](flag = Closed; labels = Some ["X";"Y"])
         *)
  | Ptyp_poly of string list * core_type
  ' a1 ... ' an . T 

            Can only appear in the following context : 

            - As the core_type of a Ppat_constraint node corresponding 
              to a constraint on a let - binding : let x : ' a1 ... ' an . T 
              = e ... 

            - Under Cfk_virtual for methods ( not values ) . 

            - As the core_type of a Pctf_method node . 

            - As the core_type of a Pexp_poly node . 

            - As the pld_type field of a label_declaration . 

            - As a core_type of a Ptyp_object node . 
         

           Can only appear in the following context:

           - As the core_type of a Ppat_constraint node corresponding
             to a constraint on a let-binding: let x : 'a1 ... 'an. T
             = e ...

           - Under Cfk_virtual for methods (not values).

           - As the core_type of a Pctf_method node.

           - As the core_type of a Pexp_poly node.

           - As the pld_type field of a label_declaration.

           - As a core_type of a Ptyp_object node.
         *)

  | Ptyp_package of package_type
        (* (module S) *)
  | Ptyp_extension of extension
        (* [%id] *)

and package_type = Longident.t loc * (Longident.t loc * core_type) list
      (*
        (module S)
        (module S with type t1 = T1 and ... and tn = Tn)
       *)

and row_field =
  | Rtag of label * attributes * bool * core_type list
  [ ` A ]                    ( true ,   [ ] ) 
            [ ` A of T ]               ( false , [ T ] ) 
            [ ` A of T1 & .. & Tn ]    ( false , [ T1; ... Tn ] ) 
            [ ` A of & T1 & .. & Tn ] ( true ,   [ T1; ... Tn ] ) 

           - The 2nd field is true if the tag contains a 
             constant ( empty ) constructor . 
           - ' & ' occurs when several types are used for the same constructor 
             ( see 4.2 in the manual ) 

           - TODO : switch to a record representation , and keep location 
        
           [`A of T]              ( false, [T] )
           [`A of T1 & .. & Tn]   ( false, [T1;...Tn] )
           [`A of & T1 & .. & Tn] ( true,  [T1;...Tn] )

          - The 2nd field is true if the tag contains a
            constant (empty) constructor.
          - '&' occurs when several types are used for the same constructor
            (see 4.2 in the manual)

          - TODO: switch to a record representation, and keep location
        *)
  | Rinherit of core_type
        (* [ T ] *)

(* Patterns *)

and pattern =
    {
     ppat_desc: pattern_desc;
     ppat_loc: Location.t;
     ppat_attributes: attributes; (* ... [@id1] [@id2] *)
    }

and pattern_desc =
  | Ppat_any
        (* _ *)
  | Ppat_var of string loc
        (* x *)
  | Ppat_alias of pattern * string loc
        (* P as 'a *)
  | Ppat_constant of constant
  1 , ' a ' , " true " , 1.0 , 1l , 1L , 1n
  | Ppat_interval of constant * constant
        (* 'a'..'z'

           Other forms of interval are recognized by the parser
           but rejected by the type-checker. *)
  | Ppat_tuple of pattern list
  ( P1 , ... , Pn ) 

            Invariant : n > = 2 
        

           Invariant: n >= 2
        *)
  | Ppat_construct of Longident.t loc * pattern option
  C                 None 
            C P               Some P 
            C ( P1 , ... , Pn )   Some ( Ppat_tuple [ P1 ; ... ; Pn ] ) 
         
           C P              Some P
           C (P1, ..., Pn)  Some (Ppat_tuple [P1; ...; Pn])
         *)
  | Ppat_variant of label * pattern option
        (* `A             (None)
           `A P           (Some P)
         *)
  | Ppat_record of (Longident.t loc * pattern) list * closed_flag
  { l1 = P1 ; ... ; ln = Pn }      ( flag = Closed ) 
            { l1 = P1 ; ... ; ln = Pn ; _ }    ( flag = Open ) 

            Invariant : n > 0 
         
           { l1=P1; ...; ln=Pn; _}   (flag = Open)

           Invariant: n > 0
         *)
  | Ppat_array of pattern list
        (* [| P1; ...; Pn |] *)
  | Ppat_or of pattern * pattern
  P1 | P2
  | Ppat_constraint of pattern * core_type
        (* (P : T) *)
  | Ppat_type of Longident.t loc
        (* #tconst *)
  | Ppat_lazy of pattern
        (* lazy P *)
  | Ppat_unpack of string loc
        (* (module P)
           Note: (module P : S) is represented as
           Ppat_constraint(Ppat_unpack, Ptyp_package)
         *)
  | Ppat_exception of pattern
        (* exception P *)
  | Ppat_extension of extension
        (* [%id] *)

(* Value expressions *)

and expression =
    {
     pexp_desc: expression_desc;
     pexp_loc: Location.t;
     pexp_attributes: attributes; (* ... [@id1] [@id2] *)
    }

and expression_desc =
  | Pexp_ident of Longident.t loc
        (* x
           M.x
         *)
  | Pexp_constant of constant
  1 , ' a ' , " true " , 1.0 , 1l , 1L , 1n
  | Pexp_let of rec_flag * value_binding list * expression
  let P1 = E1 and ... and Pn = EN in E        ( flag =  ) 
            let rec P1 = E1 and ... and Pn = EN in E    ( flag = Recursive ) 
         
           let rec P1 = E1 and ... and Pn = EN in E   (flag = Recursive)
         *)
  | Pexp_function of case list
        (* function P1 -> E1 | ... | Pn -> En *)
  | Pexp_fun of label * expression option * pattern * expression
  fun P - > E1                           ( lab = " " , None ) 
            fun ~l :P - > E1                        ( lab = " l " , None ) 
            fun ? l :P - > E1                        ( lab = " ? l " , None ) 
            fun ? l:(P = E0 ) - > E1                 ( lab = " ? l " , Some E0 ) 

            Notes : 
            - If E0 is provided , lab must start with ' ? ' . 
            - " fun P1 P2 .. Pn - > E1 " is represented as nested Pexp_fun . 
            - " let f P = E " is represented using Pexp_fun . 
         
           fun ~l:P -> E1                       (lab = "l", None)
           fun ?l:P -> E1                       (lab = "?l", None)
           fun ?l:(P = E0) -> E1                (lab = "?l", Some E0)

           Notes:
           - If E0 is provided, lab must start with '?'.
           - "fun P1 P2 .. Pn -> E1" is represented as nested Pexp_fun.
           - "let f P = E" is represented using Pexp_fun.
         *)
  | Pexp_apply of expression * (label * expression) list
  E0 ~l1 : E1 ... ~ln : En 
            li can be empty ( non labeled argument ) or start with ' ? ' 
            ( optional argument ) . 

            Invariant : n > 0 
         
           li can be empty (non labeled argument) or start with '?'
           (optional argument).

           Invariant: n > 0
         *)
  | Pexp_match of expression * case list
  match E0 with P1 - > E1 | ... | Pn - > En
  | Pexp_try of expression * case list
  try E0 with P1 - > E1 | ... | Pn - > En
  | Pexp_tuple of expression list
  ( E1 , ... , En ) 

            Invariant : n > = 2 
        

           Invariant: n >= 2
        *)
  | Pexp_construct of Longident.t loc * expression option
        (* C                None
           C E              Some E
           C (E1, ..., En)  Some (Pexp_tuple[E1;...;En])
        *)
  | Pexp_variant of label * expression option
        (* `A             (None)
           `A E           (Some E)
         *)
  | Pexp_record of (Longident.t loc * expression) list * expression option
  { l1 = P1 ; ... ; ln = Pn }      ( None ) 
            { E0 with l1 = P1 ; ... ; ln = Pn }    ( Some E0 ) 

            Invariant : n > 0 
         
           { E0 with l1=P1; ...; ln=Pn }   (Some E0)

           Invariant: n > 0
         *)
  | Pexp_field of expression * Longident.t loc
        (* E.l *)
  | Pexp_setfield of expression * Longident.t loc * expression
  E1.l < - E2
  | Pexp_array of expression list
        (* [| E1; ...; En |] *)
  | Pexp_ifthenelse of expression * expression * expression option
  if E1 then E2 else E3
  | Pexp_sequence of expression * expression
        (* E1; E2 *)
  | Pexp_while of expression * expression
        (* while E1 do E2 done *)
  | Pexp_for of
      pattern *  expression * expression * direction_flag * expression
  for i = E1 to E2 do E3 done       ( flag = Upto ) 
            for i = E1 downto E2 do E3 done   ( flag =  ) 
         
           for i = E1 downto E2 do E3 done  (flag = Downto)
         *)
  | Pexp_constraint of expression * core_type
        (* (E : T) *)
  | Pexp_coerce of expression * core_type option * core_type
        (* (E :> T)        (None, T)
           (E : T0 :> T)   (Some T0, T)
         *)
  | Pexp_send of expression * string
        (*  E # m *)
  | Pexp_new of Longident.t loc
        (* new M.c *)
  | Pexp_setinstvar of string loc * expression
        (* x <- 2 *)
  | Pexp_override of (string loc * expression) list
  { < x1 = E1 ; ... ;    > }
  | Pexp_letmodule of string loc * module_expr * expression
        (* let module M = ME in E *)
  | Pexp_assert of expression
        (* assert E
           Note: "assert false" is treated in a special way by the
           type-checker. *)
  | Pexp_lazy of expression
        (* lazy E *)
  | Pexp_poly of expression * core_type option
  Used for method bodies . 

            Can only be used as the expression under  
            for methods ( not values ) .

           Can only be used as the expression under Cfk_concrete
           for methods (not values). *)
  | Pexp_object of class_structure
        (* object ... end *)
  | Pexp_newtype of string * expression
        (* fun (type t) -> E *)
  | Pexp_pack of module_expr
        (* (module ME)

           (module ME : S) is represented as
           Pexp_constraint(Pexp_pack, Ptyp_package S) *)
  | Pexp_open of override_flag * Longident.t loc * expression
        (* let open M in E
           let! open M in E
        *)
  | Pexp_extension of extension
        (* [%id] *)

and case =   (* (P -> E) or (P when E0 -> E) *)
    {
     pc_lhs: pattern;
     pc_guard: expression option;
     pc_rhs: expression;
    }

(* Value descriptions *)

and value_description =
    {
     pval_name: string loc;
     pval_type: core_type;
     pval_prim: string list;
     pval_attributes: attributes;  (* ... [@@id1] [@@id2] *)
     pval_loc: Location.t;
    }


   val x : T                             ( prim = [ ] ) 
   external x : T = " s1 " ... " sn "        ( prim = [ " s1"; ... "sn " ] ) 

   Note : when used under Pstr_primitive , prim can not be empty 

  val x: T                            (prim = [])
  external x: T = "s1" ... "sn"       (prim = ["s1";..."sn"])

  Note: when used under Pstr_primitive, prim cannot be empty
*)

(* Type declarations *)

and type_declaration =
    {
     ptype_name: string loc;
     ptype_params: (core_type * variance) list;
           (* ('a1,...'an) t; None represents  _*)
     ptype_cstrs: (core_type * core_type * Location.t) list;
  ... constraint T1 = T1 '   ... constraint    
     ptype_kind: type_kind;
     ptype_private: private_flag;   (* = private ... *)
     ptype_manifest: core_type option;  (* = T *)
     ptype_attributes: attributes;   (* ... [@@id1] [@@id2] *)
     ptype_loc: Location.t;
    }

(*
  type t                     (abstract, no manifest)
  type t = T0                (abstract, manifest=T0)
  type t = C of T | ...      (variant,  no manifest)
  type t = T0 = C of T | ... (variant,  manifest=T0)
  type t = {l: T; ...}       (record,   no manifest)
  type t = T0 = {l : T; ...} (record,   manifest=T0)
  type t = ..                (open,     no manifest)
*)

and type_kind =
  | Ptype_abstract
  | Ptype_variant of constructor_declaration list
        (* Invariant: non-empty list *)
  | Ptype_record of label_declaration list
        (* Invariant: non-empty list *)
  | Ptype_open

and label_declaration =
    {
     pld_name: string loc;
     pld_mutable: mutable_flag;
     pld_type: core_type;
     pld_loc: Location.t;
     pld_attributes: attributes; (* l [@id1] [@id2] : T *)
    }

(*  { ...; l: T; ... }            (mutable=Immutable)
    { ...; mutable l: T; ... }    (mutable=Mutable)

    Note: T can be a Ptyp_poly.
*)

and constructor_declaration =
    {
     pcd_name: string loc;
     pcd_args: core_type list;
     pcd_res: core_type option;
     pcd_loc: Location.t;
     pcd_attributes: attributes; (* C [@id1] [@id2] of ... *)
    }
(*
  | C of T1 * ... * Tn     (res = None)
  | C: T0                  (args = [], res = Some T0)
  | C: T1 * ... * Tn -> T0 (res = Some T0)
*)

and type_extension =
    {
     ptyext_path: Longident.t loc;
     ptyext_params: (core_type * variance) list;
     ptyext_constructors: extension_constructor list;
     ptyext_private: private_flag;
     ptyext_attributes: attributes;   (* ... [@@id1] [@@id2] *)
    }
(*
  type t += ...
*)

and extension_constructor =
    {
     pext_name: string loc;
     pext_kind : extension_constructor_kind;
     pext_loc : Location.t;
     pext_attributes: attributes; (* C [@id1] [@id2] of ... *)
    }

and extension_constructor_kind =
    Pext_decl of core_type list * core_type option
      (*
         | C of T1 * ... * Tn     ([T1; ...; Tn], None)
         | C: T0                  ([], Some T0)
         | C: T1 * ... * Tn -> T0 ([T1; ...; Tn], Some T0)
       *)
  | Pext_rebind of Longident.t loc
      (*
         | C = D
       *)

* { 2 Class language }

(* Type expressions for the class language *)

and class_type =
    {
     pcty_desc: class_type_desc;
     pcty_loc: Location.t;
     pcty_attributes: attributes; (* ... [@id1] [@id2] *)
    }

and class_type_desc =
  | Pcty_constr of Longident.t loc * core_type list
        (* c
           ['a1, ..., 'an] c *)
  | Pcty_signature of class_signature
        (* object ... end *)
  | Pcty_arrow of label * core_type * class_type
        (* T -> CT       (label = "")
           ~l:T -> CT    (label = "l")
           ?l:T -> CT    (label = "?l")
         *)
  | Pcty_extension of extension
        (* [%id] *)

and class_signature =
    {
     pcsig_self: core_type;
     pcsig_fields: class_type_field list;
    }
(* object('selfpat) ... end
   object ... end             (self = Ptyp_any)
 *)

and class_type_field =
    {
     pctf_desc: class_type_field_desc;
     pctf_loc: Location.t;
     pctf_attributes: attributes; (* ... [@@id1] [@@id2] *)
    }

and class_type_field_desc =
  | Pctf_inherit of class_type
        (* inherit CT *)
  | Pctf_val of (string * mutable_flag * virtual_flag * core_type)
        (* val x: T *)
  | Pctf_method  of (string * private_flag * virtual_flag * core_type)
        (* method x: T

           Note: T can be a Ptyp_poly.
         *)
  | Pctf_constraint  of (core_type * core_type)
        (* constraint T1 = T2 *)
  | Pctf_attribute of attribute
        (* [@@@id] *)
  | Pctf_extension of extension
        (* [%%id] *)

and 'a class_infos =
    {
     pci_virt: virtual_flag;
     pci_params: (core_type * variance) list;
     pci_name: string loc;
     pci_expr: 'a;
     pci_loc: Location.t;
     pci_attributes: attributes;  (* ... [@@id1] [@@id2] *)
    }
(* class c = ...
   class ['a1,...,'an] c = ...
   class virtual c = ...

   Also used for "class type" declaration.
*)

and class_description = class_type class_infos

and class_type_declaration = class_type class_infos

(* Value expressions for the class language *)

and class_expr =
    {
     pcl_desc: class_expr_desc;
     pcl_loc: Location.t;
     pcl_attributes: attributes; (* ... [@id1] [@id2] *)
    }

and class_expr_desc =
  | Pcl_constr of Longident.t loc * core_type list
        (* c
           ['a1, ..., 'an] c *)
  | Pcl_structure of class_structure
        (* object ... end *)
  | Pcl_fun of label * expression option * pattern * class_expr
        (* fun P -> CE                          (lab = "", None)
           fun ~l:P -> CE                       (lab = "l", None)
           fun ?l:P -> CE                       (lab = "?l", None)
           fun ?l:(P = E0) -> CE                (lab = "?l", Some E0)
         *)
  | Pcl_apply of class_expr * (label * expression) list
        (* CE ~l1:E1 ... ~ln:En
           li can be empty (non labeled argument) or start with '?'
           (optional argument).

           Invariant: n > 0
         *)
  | Pcl_let of rec_flag * value_binding list * class_expr
  let P1 = E1 and ... and Pn = EN in CE       ( flag =  ) 
            let rec P1 = E1 and ... and Pn = EN in CE   ( flag = Recursive ) 
         
           let rec P1 = E1 and ... and Pn = EN in CE  (flag = Recursive)
         *)
  | Pcl_constraint of class_expr * class_type
        (* (CE : CT) *)
  | Pcl_extension of extension
        (* [%id] *)

and class_structure =
    {
     pcstr_self: pattern;
     pcstr_fields: class_field list;
    }
(* object(selfpat) ... end
   object ... end           (self = Ppat_any)
 *)

and class_field =
    {
     pcf_desc: class_field_desc;
     pcf_loc: Location.t;
     pcf_attributes: attributes; (* ... [@@id1] [@@id2] *)
    }

and class_field_desc =
  | Pcf_inherit of override_flag * class_expr * string option
        (* inherit CE
           inherit CE as x
           inherit! CE
           inherit! CE as x
         *)
  | Pcf_val of (string loc * mutable_flag * class_field_kind)
        (* val x = E
           val virtual x: T
         *)
  | Pcf_method of (string loc * private_flag * class_field_kind)
  method x = E             ( E can be a Pexp_poly ) 
            method virtual x : T      ( T can be a Ptyp_poly ) 
         
           method virtual x: T     (T can be a Ptyp_poly)
         *)
  | Pcf_constraint of (core_type * core_type)
        (* constraint T1 = T2 *)
  | Pcf_initializer of expression
        (* initializer E *)
  | Pcf_attribute of attribute
        (* [@@@id] *)
  | Pcf_extension of extension
        (* [%%id] *)

and class_field_kind =
  | Cfk_virtual of core_type
  | Cfk_concrete of override_flag * expression

and class_declaration = class_expr class_infos

* { 2 Module language }

(* Type expressions for the module language *)

and module_type =
    {
     pmty_desc: module_type_desc;
     pmty_loc: Location.t;
     pmty_attributes: attributes; (* ... [@id1] [@id2] *)
    }

and module_type_desc =
  | Pmty_ident of Longident.t loc
        (* S *)
  | Pmty_signature of signature
        (* sig ... end *)
  | Pmty_functor of string loc * module_type option * module_type
  functor(X :  ) - > MT2
  | Pmty_with of module_type * with_constraint list
        (* MT with ... *)
  | Pmty_typeof of module_expr
        (* module type of ME *)
  | Pmty_extension of extension
        (* [%id] *)
  | Pmty_alias of Longident.t loc
        (* (module M) *)

and signature = signature_item list

and signature_item =
    {
     psig_desc: signature_item_desc;
     psig_loc: Location.t;
    }

and signature_item_desc =
  | Psig_value of value_description

            x : T 
           external x : T = " s1 " ... " sn " 
         
          val x: T
          external x: T = "s1" ... "sn"
         *)
  | Psig_type of type_declaration list
        (* type t1 = ... and ... and tn = ... *)
  | Psig_typext of type_extension
        (* type t1 += ... *)
  | Psig_exception of extension_constructor
        (* exception C of T *)
  | Psig_module of module_declaration
        (* module X : MT *)
  | Psig_recmodule of module_declaration list
  module rec X1 :  and ... and Xn : MTn
  | Psig_modtype of module_type_declaration
        (* module type S = MT
           module type S *)
  | Psig_open of open_description
        (* open X *)
  | Psig_include of include_description
  include MT
  | Psig_class of class_description list
        (* class c1 : ... and ... and cn : ... *)
  | Psig_class_type of class_type_declaration list
        (* class type ct1 = ... and ... and ctn = ... *)
  | Psig_attribute of attribute
        (* [@@@id] *)
  | Psig_extension of extension * attributes
        (* [%%id] *)

and module_declaration =
    {
     pmd_name: string loc;
     pmd_type: module_type;
     pmd_attributes: attributes; (* ... [@@id1] [@@id2] *)
     pmd_loc: Location.t;
    }
(* S : MT *)

and module_type_declaration =
    {
     pmtd_name: string loc;
     pmtd_type: module_type option;
     pmtd_attributes: attributes; (* ... [@@id1] [@@id2] *)
     pmtd_loc: Location.t;
    }
  S = MT 
    S        ( abstract module type declaration , pmtd_type = None ) 

   S       (abstract module type declaration, pmtd_type = None)
*)

and open_description =
    {
     popen_lid: Longident.t loc;
     popen_override: override_flag;
     popen_loc: Location.t;
     popen_attributes: attributes;
    }
(* open! X - popen_override = Override (silences the 'used identifier
                              shadowing' warning)
   open  X - popen_override = Fresh
 *)

and 'a include_infos =
    {
     pincl_mod: 'a;
     pincl_loc: Location.t;
     pincl_attributes: attributes;
    }

and include_description = module_type include_infos
  include MT

and include_declaration = module_expr include_infos
(* include ME *)

and with_constraint =
  | Pwith_type of Longident.t loc * type_declaration
        (* with type X.t = ...

           Note: the last component of the longident must match
           the name of the type_declaration. *)
  | Pwith_module of Longident.t loc * Longident.t loc
        (* with module X.Y = Z *)
  | Pwith_typesubst of type_declaration
        (* with type t := ... *)
  | Pwith_modsubst of string loc * Longident.t loc
        (* with module X := Z *)

(* Value expressions for the module language *)

and module_expr =
    {
     pmod_desc: module_expr_desc;
     pmod_loc: Location.t;
     pmod_attributes: attributes; (* ... [@id1] [@id2] *)
    }

and module_expr_desc =
  | Pmod_ident of Longident.t loc
        (* X *)
  | Pmod_structure of structure
        (* struct ... end *)
  | Pmod_functor of string loc * module_type option * module_expr
  functor(X :  ) - > ME
  | Pmod_apply of module_expr * module_expr
        (* ME1(ME2) *)
  | Pmod_constraint of module_expr * module_type
        (* (ME : MT) *)
  | Pmod_unpack of expression
  (  E )
  | Pmod_extension of extension
        (* [%id] *)

and structure = structure_item list

and structure_item =
    {
     pstr_desc: structure_item_desc;
     pstr_loc: Location.t;
    }

and structure_item_desc =
  | Pstr_eval of expression * attributes
        (* E *)
  | Pstr_value of rec_flag * value_binding list
  let P1 = E1 and ... and Pn = EN        ( flag =  ) 
            let rec P1 = E1 and ... and Pn = EN    ( flag = Recursive ) 
         
           let rec P1 = E1 and ... and Pn = EN   (flag = Recursive)
         *)
  | Pstr_primitive of value_description
        (* external x: T = "s1" ... "sn" *)
  | Pstr_type of type_declaration list
        (* type t1 = ... and ... and tn = ... *)
  | Pstr_typext of type_extension
        (* type t1 += ... *)
  | Pstr_exception of extension_constructor
  exception C of T 
            exception C = 
           exception C = M.X *)
  | Pstr_module of module_binding
        (* module X = ME *)
  | Pstr_recmodule of module_binding list
        (* module rec X1 = ME1 and ... and Xn = MEn *)
  | Pstr_modtype of module_type_declaration
        (* module type S = MT *)
  | Pstr_open of open_description
        (* open X *)
  | Pstr_class of class_declaration list
        (* class c1 = ... and ... and cn = ... *)
  | Pstr_class_type of class_type_declaration list
        (* class type ct1 = ... and ... and ctn = ... *)
  | Pstr_include of include_declaration
        (* include ME *)
  | Pstr_attribute of attribute
        (* [@@@id] *)
  | Pstr_extension of extension * attributes
        (* [%%id] *)

and value_binding =
  {
    pvb_pat: pattern;
    pvb_expr: expression;
    pvb_attributes: attributes;
    pvb_loc: Location.t;
  }

and module_binding =
    {
     pmb_name: string loc;
     pmb_expr: module_expr;
     pmb_attributes: attributes;
     pmb_loc: Location.t;
    }
(* X = ME *)

* { 2 Toplevel }

  Toplevel phrases

type toplevel_phrase =
  | Ptop_def of structure
  | Ptop_dir of string * directive_argument
     (* #use, #load ... *)

and directive_argument =
  | Pdir_none
  | Pdir_string of string
  | Pdir_int of int
  | Pdir_ident of Longident.t
  | Pdir_bool of bool

*********************************************************************
                                                                     
                                OCaml                                
                                                                     
                                                                     
                                                                     
*********************************************************************
* Abstract syntax tree produced by parsing 
 [@id ARG]
          [@@id ARG]

          Metadata containers passed around within the AST.
          The compiler ignores unknown attributes.
       
 [%id ARG]
         [%%id ARG]

         Sub-language placeholder -- rejected by the typechecker.
      
 : T 
 ? P  or  ? P when E 
 Type expressions 
 ... [@id1] [@id2] 
  _ 
 'a 
 T1 -> T2       (label = "")
           ~l:T1 -> T2    (label = "l")
           ?l:T1 -> T2    (label = "?l")
         
 tconstr
           T tconstr
           (T1, ..., Tn) tconstr
         
 < l1:T1; ...; ln:Tn >     (flag = Closed)
           < l1:T1; ...; ln:Tn; .. > (flag = Open)
         
 T as 'a 
 [ `A|`B ]         (flag = Closed; labels = None)
           [> `A|`B ]        (flag = Open;   labels = None)
           [< `A|`B ]        (flag = Closed; labels = Some [])
           [< `A|`B > `X `Y ](flag = Closed; labels = Some ["X";"Y"])
         
 (module S) 
 [%id] 

        (module S)
        (module S with type t1 = T1 and ... and tn = Tn)
       
 [ T ] 
 Patterns 
 ... [@id1] [@id2] 
 _ 
 x 
 P as 'a 
 'a'..'z'

           Other forms of interval are recognized by the parser
           but rejected by the type-checker. 
 `A             (None)
           `A P           (Some P)
         
 [| P1; ...; Pn |] 
 (P : T) 
 #tconst 
 lazy P 
 (module P)
           Note: (module P : S) is represented as
           Ppat_constraint(Ppat_unpack, Ptyp_package)
         
 exception P 
 [%id] 
 Value expressions 
 ... [@id1] [@id2] 
 x
           M.x
         
 function P1 -> E1 | ... | Pn -> En 
 C                None
           C E              Some E
           C (E1, ..., En)  Some (Pexp_tuple[E1;...;En])
        
 `A             (None)
           `A E           (Some E)
         
 E.l 
 [| E1; ...; En |] 
 E1; E2 
 while E1 do E2 done 
 (E : T) 
 (E :> T)        (None, T)
           (E : T0 :> T)   (Some T0, T)
         
  E # m 
 new M.c 
 x <- 2 
 let module M = ME in E 
 assert E
           Note: "assert false" is treated in a special way by the
           type-checker. 
 lazy E 
 object ... end 
 fun (type t) -> E 
 (module ME)

           (module ME : S) is represented as
           Pexp_constraint(Pexp_pack, Ptyp_package S) 
 let open M in E
           let! open M in E
        
 [%id] 
 (P -> E) or (P when E0 -> E) 
 Value descriptions 
 ... [@@id1] [@@id2] 
 Type declarations 
 ('a1,...'an) t; None represents  _
 = private ... 
 = T 
 ... [@@id1] [@@id2] 

  type t                     (abstract, no manifest)
  type t = T0                (abstract, manifest=T0)
  type t = C of T | ...      (variant,  no manifest)
  type t = T0 = C of T | ... (variant,  manifest=T0)
  type t = {l: T; ...}       (record,   no manifest)
  type t = T0 = {l : T; ...} (record,   manifest=T0)
  type t = ..                (open,     no manifest)

 Invariant: non-empty list 
 Invariant: non-empty list 
 l [@id1] [@id2] : T 
  { ...; l: T; ... }            (mutable=Immutable)
    { ...; mutable l: T; ... }    (mutable=Mutable)

    Note: T can be a Ptyp_poly.

 C [@id1] [@id2] of ... 

  | C of T1 * ... * Tn     (res = None)
  | C: T0                  (args = [], res = Some T0)
  | C: T1 * ... * Tn -> T0 (res = Some T0)

 ... [@@id1] [@@id2] 

  type t += ...

 C [@id1] [@id2] of ... 

         | C of T1 * ... * Tn     ([T1; ...; Tn], None)
         | C: T0                  ([], Some T0)
         | C: T1 * ... * Tn -> T0 ([T1; ...; Tn], Some T0)
       

         | C = D
       
 Type expressions for the class language 
 ... [@id1] [@id2] 
 c
           ['a1, ..., 'an] c 
 object ... end 
 T -> CT       (label = "")
           ~l:T -> CT    (label = "l")
           ?l:T -> CT    (label = "?l")
         
 [%id] 
 object('selfpat) ... end
   object ... end             (self = Ptyp_any)
 
 ... [@@id1] [@@id2] 
 inherit CT 
 val x: T 
 method x: T

           Note: T can be a Ptyp_poly.
         
 constraint T1 = T2 
 [@@@id] 
 [%%id] 
 ... [@@id1] [@@id2] 
 class c = ...
   class ['a1,...,'an] c = ...
   class virtual c = ...

   Also used for "class type" declaration.

 Value expressions for the class language 
 ... [@id1] [@id2] 
 c
           ['a1, ..., 'an] c 
 object ... end 
 fun P -> CE                          (lab = "", None)
           fun ~l:P -> CE                       (lab = "l", None)
           fun ?l:P -> CE                       (lab = "?l", None)
           fun ?l:(P = E0) -> CE                (lab = "?l", Some E0)
         
 CE ~l1:E1 ... ~ln:En
           li can be empty (non labeled argument) or start with '?'
           (optional argument).

           Invariant: n > 0
         
 (CE : CT) 
 [%id] 
 object(selfpat) ... end
   object ... end           (self = Ppat_any)
 
 ... [@@id1] [@@id2] 
 inherit CE
           inherit CE as x
           inherit! CE
           inherit! CE as x
         
 val x = E
           val virtual x: T
         
 constraint T1 = T2 
 initializer E 
 [@@@id] 
 [%%id] 
 Type expressions for the module language 
 ... [@id1] [@id2] 
 S 
 sig ... end 
 MT with ... 
 module type of ME 
 [%id] 
 (module M) 
 type t1 = ... and ... and tn = ... 
 type t1 += ... 
 exception C of T 
 module X : MT 
 module type S = MT
           module type S 
 open X 
 class c1 : ... and ... and cn : ... 
 class type ct1 = ... and ... and ctn = ... 
 [@@@id] 
 [%%id] 
 ... [@@id1] [@@id2] 
 S : MT 
 ... [@@id1] [@@id2] 
 open! X - popen_override = Override (silences the 'used identifier
                              shadowing' warning)
   open  X - popen_override = Fresh
 
 include ME 
 with type X.t = ...

           Note: the last component of the longident must match
           the name of the type_declaration. 
 with module X.Y = Z 
 with type t := ... 
 with module X := Z 
 Value expressions for the module language 
 ... [@id1] [@id2] 
 X 
 struct ... end 
 ME1(ME2) 
 (ME : MT) 
 [%id] 
 E 
 external x: T = "s1" ... "sn" 
 type t1 = ... and ... and tn = ... 
 type t1 += ... 
 module X = ME 
 module rec X1 = ME1 and ... and Xn = MEn 
 module type S = MT 
 open X 
 class c1 = ... and ... and cn = ... 
 class type ct1 = ... and ... and ctn = ... 
 include ME 
 [@@@id] 
 [%%id] 
 X = ME 
 #use, #load ... 
               , projet Cristal , INRIA Rocquencourt         
   Copyright 1996 Institut National de Recherche en Informatique et   
   en Automatique .   All rights reserved .   This file is distributed    
   under the terms of the Q Public License version 1.0 .               


open Asttypes

* { 2 Extension points }

type attribute = string loc * payload

and extension = string loc * payload

and attributes = attribute list

and payload =
  | PStr of structure

* { 2 Core language }


and core_type =
    {
     ptyp_desc: core_type_desc;
     ptyp_loc: Location.t;
    }

and core_type_desc =
  | Ptyp_any
  | Ptyp_var of string
  | Ptyp_arrow of label * core_type * core_type
  | Ptyp_tuple of core_type list
  T1 * ... * Tn 

            Invariant : n > = 2 
        

           Invariant: n >= 2
        *)
  | Ptyp_constr of Longident.t loc * core_type list
  | Ptyp_object of (string * attributes * core_type) list * closed_flag
  | Ptyp_class of Longident.t loc * core_type list
  # tconstr 
            T # tconstr 
            ( T1 , ... , Tn ) # tconstr 
         
           T #tconstr
           (T1, ..., Tn) #tconstr
         *)
  | Ptyp_alias of core_type * string
  | Ptyp_variant of row_field list * closed_flag * label list option
  | Ptyp_poly of string list * core_type
  ' a1 ... ' an . T 

            Can only appear in the following context : 

            - As the core_type of a Ppat_constraint node corresponding 
              to a constraint on a let - binding : let x : ' a1 ... ' an . T 
              = e ... 

            - Under Cfk_virtual for methods ( not values ) . 

            - As the core_type of a Pctf_method node . 

            - As the core_type of a Pexp_poly node . 

            - As the pld_type field of a label_declaration . 

            - As a core_type of a Ptyp_object node . 
         

           Can only appear in the following context:

           - As the core_type of a Ppat_constraint node corresponding
             to a constraint on a let-binding: let x : 'a1 ... 'an. T
             = e ...

           - Under Cfk_virtual for methods (not values).

           - As the core_type of a Pctf_method node.

           - As the core_type of a Pexp_poly node.

           - As the pld_type field of a label_declaration.

           - As a core_type of a Ptyp_object node.
         *)

  | Ptyp_package of package_type
  | Ptyp_extension of extension

and package_type = Longident.t loc * (Longident.t loc * core_type) list

and row_field =
  | Rtag of label * attributes * bool * core_type list
  [ ` A ]                    ( true ,   [ ] ) 
            [ ` A of T ]               ( false , [ T ] ) 
            [ ` A of T1 & .. & Tn ]    ( false , [ T1; ... Tn ] ) 
            [ ` A of & T1 & .. & Tn ] ( true ,   [ T1; ... Tn ] ) 

           - The 2nd field is true if the tag contains a 
             constant ( empty ) constructor . 
           - ' & ' occurs when several types are used for the same constructor 
             ( see 4.2 in the manual ) 

           - TODO : switch to a record representation , and keep location 
        
           [`A of T]              ( false, [T] )
           [`A of T1 & .. & Tn]   ( false, [T1;...Tn] )
           [`A of & T1 & .. & Tn] ( true,  [T1;...Tn] )

          - The 2nd field is true if the tag contains a
            constant (empty) constructor.
          - '&' occurs when several types are used for the same constructor
            (see 4.2 in the manual)

          - TODO: switch to a record representation, and keep location
        *)
  | Rinherit of core_type


and pattern =
    {
     ppat_desc: pattern_desc;
     ppat_loc: Location.t;
    }

and pattern_desc =
  | Ppat_any
  | Ppat_var of string loc
  | Ppat_alias of pattern * string loc
  | Ppat_constant of constant
  1 , ' a ' , " true " , 1.0 , 1l , 1L , 1n
  | Ppat_interval of constant * constant
  | Ppat_tuple of pattern list
  ( P1 , ... , Pn ) 

            Invariant : n > = 2 
        

           Invariant: n >= 2
        *)
  | Ppat_construct of Longident.t loc * pattern option
  C                 None 
            C P               Some P 
            C ( P1 , ... , Pn )   Some ( Ppat_tuple [ P1 ; ... ; Pn ] ) 
         
           C P              Some P
           C (P1, ..., Pn)  Some (Ppat_tuple [P1; ...; Pn])
         *)
  | Ppat_variant of label * pattern option
  | Ppat_record of (Longident.t loc * pattern) list * closed_flag
  { l1 = P1 ; ... ; ln = Pn }      ( flag = Closed ) 
            { l1 = P1 ; ... ; ln = Pn ; _ }    ( flag = Open ) 

            Invariant : n > 0 
         
           { l1=P1; ...; ln=Pn; _}   (flag = Open)

           Invariant: n > 0
         *)
  | Ppat_array of pattern list
  | Ppat_or of pattern * pattern
  P1 | P2
  | Ppat_constraint of pattern * core_type
  | Ppat_type of Longident.t loc
  | Ppat_lazy of pattern
  | Ppat_unpack of string loc
  | Ppat_exception of pattern
  | Ppat_extension of extension


and expression =
    {
     pexp_desc: expression_desc;
     pexp_loc: Location.t;
    }

and expression_desc =
  | Pexp_ident of Longident.t loc
  | Pexp_constant of constant
  1 , ' a ' , " true " , 1.0 , 1l , 1L , 1n
  | Pexp_let of rec_flag * value_binding list * expression
  let P1 = E1 and ... and Pn = EN in E        ( flag =  ) 
            let rec P1 = E1 and ... and Pn = EN in E    ( flag = Recursive ) 
         
           let rec P1 = E1 and ... and Pn = EN in E   (flag = Recursive)
         *)
  | Pexp_function of case list
  | Pexp_fun of label * expression option * pattern * expression
  fun P - > E1                           ( lab = " " , None ) 
            fun ~l :P - > E1                        ( lab = " l " , None ) 
            fun ? l :P - > E1                        ( lab = " ? l " , None ) 
            fun ? l:(P = E0 ) - > E1                 ( lab = " ? l " , Some E0 ) 

            Notes : 
            - If E0 is provided , lab must start with ' ? ' . 
            - " fun P1 P2 .. Pn - > E1 " is represented as nested Pexp_fun . 
            - " let f P = E " is represented using Pexp_fun . 
         
           fun ~l:P -> E1                       (lab = "l", None)
           fun ?l:P -> E1                       (lab = "?l", None)
           fun ?l:(P = E0) -> E1                (lab = "?l", Some E0)

           Notes:
           - If E0 is provided, lab must start with '?'.
           - "fun P1 P2 .. Pn -> E1" is represented as nested Pexp_fun.
           - "let f P = E" is represented using Pexp_fun.
         *)
  | Pexp_apply of expression * (label * expression) list
  E0 ~l1 : E1 ... ~ln : En 
            li can be empty ( non labeled argument ) or start with ' ? ' 
            ( optional argument ) . 

            Invariant : n > 0 
         
           li can be empty (non labeled argument) or start with '?'
           (optional argument).

           Invariant: n > 0
         *)
  | Pexp_match of expression * case list
  match E0 with P1 - > E1 | ... | Pn - > En
  | Pexp_try of expression * case list
  try E0 with P1 - > E1 | ... | Pn - > En
  | Pexp_tuple of expression list
  ( E1 , ... , En ) 

            Invariant : n > = 2 
        

           Invariant: n >= 2
        *)
  | Pexp_construct of Longident.t loc * expression option
  | Pexp_variant of label * expression option
  | Pexp_record of (Longident.t loc * expression) list * expression option
  { l1 = P1 ; ... ; ln = Pn }      ( None ) 
            { E0 with l1 = P1 ; ... ; ln = Pn }    ( Some E0 ) 

            Invariant : n > 0 
         
           { E0 with l1=P1; ...; ln=Pn }   (Some E0)

           Invariant: n > 0
         *)
  | Pexp_field of expression * Longident.t loc
  | Pexp_setfield of expression * Longident.t loc * expression
  E1.l < - E2
  | Pexp_array of expression list
  | Pexp_ifthenelse of expression * expression * expression option
  if E1 then E2 else E3
  | Pexp_sequence of expression * expression
  | Pexp_while of expression * expression
  | Pexp_for of
      pattern *  expression * expression * direction_flag * expression
  for i = E1 to E2 do E3 done       ( flag = Upto ) 
            for i = E1 downto E2 do E3 done   ( flag =  ) 
         
           for i = E1 downto E2 do E3 done  (flag = Downto)
         *)
  | Pexp_constraint of expression * core_type
  | Pexp_coerce of expression * core_type option * core_type
  | Pexp_send of expression * string
  | Pexp_new of Longident.t loc
  | Pexp_setinstvar of string loc * expression
  | Pexp_override of (string loc * expression) list
  { < x1 = E1 ; ... ;    > }
  | Pexp_letmodule of string loc * module_expr * expression
  | Pexp_assert of expression
  | Pexp_lazy of expression
  | Pexp_poly of expression * core_type option
  Used for method bodies . 

            Can only be used as the expression under  
            for methods ( not values ) .

           Can only be used as the expression under Cfk_concrete
           for methods (not values). *)
  | Pexp_object of class_structure
  | Pexp_newtype of string * expression
  | Pexp_pack of module_expr
  | Pexp_open of override_flag * Longident.t loc * expression
  | Pexp_extension of extension

    {
     pc_lhs: pattern;
     pc_guard: expression option;
     pc_rhs: expression;
    }


and value_description =
    {
     pval_name: string loc;
     pval_type: core_type;
     pval_prim: string list;
     pval_loc: Location.t;
    }


   val x : T                             ( prim = [ ] ) 
   external x : T = " s1 " ... " sn "        ( prim = [ " s1"; ... "sn " ] ) 

   Note : when used under Pstr_primitive , prim can not be empty 

  val x: T                            (prim = [])
  external x: T = "s1" ... "sn"       (prim = ["s1";..."sn"])

  Note: when used under Pstr_primitive, prim cannot be empty
*)


and type_declaration =
    {
     ptype_name: string loc;
     ptype_params: (core_type * variance) list;
     ptype_cstrs: (core_type * core_type * Location.t) list;
  ... constraint T1 = T1 '   ... constraint    
     ptype_kind: type_kind;
     ptype_loc: Location.t;
    }


and type_kind =
  | Ptype_abstract
  | Ptype_variant of constructor_declaration list
  | Ptype_record of label_declaration list
  | Ptype_open

and label_declaration =
    {
     pld_name: string loc;
     pld_mutable: mutable_flag;
     pld_type: core_type;
     pld_loc: Location.t;
    }


and constructor_declaration =
    {
     pcd_name: string loc;
     pcd_args: core_type list;
     pcd_res: core_type option;
     pcd_loc: Location.t;
    }

and type_extension =
    {
     ptyext_path: Longident.t loc;
     ptyext_params: (core_type * variance) list;
     ptyext_constructors: extension_constructor list;
     ptyext_private: private_flag;
    }

and extension_constructor =
    {
     pext_name: string loc;
     pext_kind : extension_constructor_kind;
     pext_loc : Location.t;
    }

and extension_constructor_kind =
    Pext_decl of core_type list * core_type option
  | Pext_rebind of Longident.t loc

* { 2 Class language }


and class_type =
    {
     pcty_desc: class_type_desc;
     pcty_loc: Location.t;
    }

and class_type_desc =
  | Pcty_constr of Longident.t loc * core_type list
  | Pcty_signature of class_signature
  | Pcty_arrow of label * core_type * class_type
  | Pcty_extension of extension

and class_signature =
    {
     pcsig_self: core_type;
     pcsig_fields: class_type_field list;
    }

and class_type_field =
    {
     pctf_desc: class_type_field_desc;
     pctf_loc: Location.t;
    }

and class_type_field_desc =
  | Pctf_inherit of class_type
  | Pctf_val of (string * mutable_flag * virtual_flag * core_type)
  | Pctf_method  of (string * private_flag * virtual_flag * core_type)
  | Pctf_constraint  of (core_type * core_type)
  | Pctf_attribute of attribute
  | Pctf_extension of extension

and 'a class_infos =
    {
     pci_virt: virtual_flag;
     pci_params: (core_type * variance) list;
     pci_name: string loc;
     pci_expr: 'a;
     pci_loc: Location.t;
    }

and class_description = class_type class_infos

and class_type_declaration = class_type class_infos


and class_expr =
    {
     pcl_desc: class_expr_desc;
     pcl_loc: Location.t;
    }

and class_expr_desc =
  | Pcl_constr of Longident.t loc * core_type list
  | Pcl_structure of class_structure
  | Pcl_fun of label * expression option * pattern * class_expr
  | Pcl_apply of class_expr * (label * expression) list
  | Pcl_let of rec_flag * value_binding list * class_expr
  let P1 = E1 and ... and Pn = EN in CE       ( flag =  ) 
            let rec P1 = E1 and ... and Pn = EN in CE   ( flag = Recursive ) 
         
           let rec P1 = E1 and ... and Pn = EN in CE  (flag = Recursive)
         *)
  | Pcl_constraint of class_expr * class_type
  | Pcl_extension of extension

and class_structure =
    {
     pcstr_self: pattern;
     pcstr_fields: class_field list;
    }

and class_field =
    {
     pcf_desc: class_field_desc;
     pcf_loc: Location.t;
    }

and class_field_desc =
  | Pcf_inherit of override_flag * class_expr * string option
  | Pcf_val of (string loc * mutable_flag * class_field_kind)
  | Pcf_method of (string loc * private_flag * class_field_kind)
  method x = E             ( E can be a Pexp_poly ) 
            method virtual x : T      ( T can be a Ptyp_poly ) 
         
           method virtual x: T     (T can be a Ptyp_poly)
         *)
  | Pcf_constraint of (core_type * core_type)
  | Pcf_initializer of expression
  | Pcf_attribute of attribute
  | Pcf_extension of extension

and class_field_kind =
  | Cfk_virtual of core_type
  | Cfk_concrete of override_flag * expression

and class_declaration = class_expr class_infos

* { 2 Module language }


and module_type =
    {
     pmty_desc: module_type_desc;
     pmty_loc: Location.t;
    }

and module_type_desc =
  | Pmty_ident of Longident.t loc
  | Pmty_signature of signature
  | Pmty_functor of string loc * module_type option * module_type
  functor(X :  ) - > MT2
  | Pmty_with of module_type * with_constraint list
  | Pmty_typeof of module_expr
  | Pmty_extension of extension
  | Pmty_alias of Longident.t loc

and signature = signature_item list

and signature_item =
    {
     psig_desc: signature_item_desc;
     psig_loc: Location.t;
    }

and signature_item_desc =
  | Psig_value of value_description

            x : T 
           external x : T = " s1 " ... " sn " 
         
          val x: T
          external x: T = "s1" ... "sn"
         *)
  | Psig_type of type_declaration list
  | Psig_typext of type_extension
  | Psig_exception of extension_constructor
  | Psig_module of module_declaration
  | Psig_recmodule of module_declaration list
  module rec X1 :  and ... and Xn : MTn
  | Psig_modtype of module_type_declaration
  | Psig_open of open_description
  | Psig_include of include_description
  include MT
  | Psig_class of class_description list
  | Psig_class_type of class_type_declaration list
  | Psig_attribute of attribute
  | Psig_extension of extension * attributes

and module_declaration =
    {
     pmd_name: string loc;
     pmd_type: module_type;
     pmd_loc: Location.t;
    }

and module_type_declaration =
    {
     pmtd_name: string loc;
     pmtd_type: module_type option;
     pmtd_loc: Location.t;
    }
  S = MT 
    S        ( abstract module type declaration , pmtd_type = None ) 

   S       (abstract module type declaration, pmtd_type = None)
*)

and open_description =
    {
     popen_lid: Longident.t loc;
     popen_override: override_flag;
     popen_loc: Location.t;
     popen_attributes: attributes;
    }

and 'a include_infos =
    {
     pincl_mod: 'a;
     pincl_loc: Location.t;
     pincl_attributes: attributes;
    }

and include_description = module_type include_infos
  include MT

and include_declaration = module_expr include_infos

and with_constraint =
  | Pwith_type of Longident.t loc * type_declaration
  | Pwith_module of Longident.t loc * Longident.t loc
  | Pwith_typesubst of type_declaration
  | Pwith_modsubst of string loc * Longident.t loc


and module_expr =
    {
     pmod_desc: module_expr_desc;
     pmod_loc: Location.t;
    }

and module_expr_desc =
  | Pmod_ident of Longident.t loc
  | Pmod_structure of structure
  | Pmod_functor of string loc * module_type option * module_expr
  functor(X :  ) - > ME
  | Pmod_apply of module_expr * module_expr
  | Pmod_constraint of module_expr * module_type
  | Pmod_unpack of expression
  (  E )
  | Pmod_extension of extension

and structure = structure_item list

and structure_item =
    {
     pstr_desc: structure_item_desc;
     pstr_loc: Location.t;
    }

and structure_item_desc =
  | Pstr_eval of expression * attributes
  | Pstr_value of rec_flag * value_binding list
  let P1 = E1 and ... and Pn = EN        ( flag =  ) 
            let rec P1 = E1 and ... and Pn = EN    ( flag = Recursive ) 
         
           let rec P1 = E1 and ... and Pn = EN   (flag = Recursive)
         *)
  | Pstr_primitive of value_description
  | Pstr_type of type_declaration list
  | Pstr_typext of type_extension
  | Pstr_exception of extension_constructor
  exception C of T 
            exception C = 
           exception C = M.X *)
  | Pstr_module of module_binding
  | Pstr_recmodule of module_binding list
  | Pstr_modtype of module_type_declaration
  | Pstr_open of open_description
  | Pstr_class of class_declaration list
  | Pstr_class_type of class_type_declaration list
  | Pstr_include of include_declaration
  | Pstr_attribute of attribute
  | Pstr_extension of extension * attributes

and value_binding =
  {
    pvb_pat: pattern;
    pvb_expr: expression;
    pvb_attributes: attributes;
    pvb_loc: Location.t;
  }

and module_binding =
    {
     pmb_name: string loc;
     pmb_expr: module_expr;
     pmb_attributes: attributes;
     pmb_loc: Location.t;
    }

* { 2 Toplevel }

  Toplevel phrases

type toplevel_phrase =
  | Ptop_def of structure
  | Ptop_dir of string * directive_argument

and directive_argument =
  | Pdir_none
  | Pdir_string of string
  | Pdir_int of int
  | Pdir_ident of Longident.t
  | Pdir_bool of bool
