diff --git a/bench/good/ocaml.mly b/bench/good/ocaml.mly
index 600e08232222d7ef97f439332263a3082b5e7cff..1cc2dea085b170b4cb8c7dd446faf046c76fcf70 100644
--- a/bench/good/ocaml.mly
+++ b/bench/good/ocaml.mly
@@ -1,6 +1,6 @@
 /***********************************************************************/
 /*                                                                     */
-/*                           Objective Caml                            */
+/*                                OCaml                                */
 /*                                                                     */
 /*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         */
 /*                                                                     */
@@ -10,8 +10,6 @@
 /*                                                                     */
 /***********************************************************************/
 
-/* $Id: parser.mly,v 1.121 2004/10/06 13:06:11 garrigue Exp $ */
-
 /* The parser definition */
 
 %{
@@ -19,40 +17,41 @@ open Location
 open Asttypes
 open Longident
 open Parsetree
-
-let mktyp d =
-  { ptyp_desc = d; ptyp_loc = symbol_rloc() }
-let mkpat d =
-  { ppat_desc = d; ppat_loc = symbol_rloc() }
-let mkexp d =
-  { pexp_desc = d; pexp_loc = symbol_rloc() }
-let mkmty d =
-  { pmty_desc = d; pmty_loc = symbol_rloc() }
-let mksig d =
-  { psig_desc = d; psig_loc = symbol_rloc() }
-let mkmod d =
-  { pmod_desc = d; pmod_loc = symbol_rloc() }
-let mkstr d =
-  { pstr_desc = d; pstr_loc = symbol_rloc() }
-let mkfield d =
-  { pfield_desc = d; pfield_loc = symbol_rloc() }
-let mkclass d =
-  { pcl_desc = d; pcl_loc = symbol_rloc() }
-let mkcty d =
-  { pcty_desc = d; pcty_loc = symbol_rloc() }
+open Ast_helper
+open Docstrings
+
+let mktyp d = Typ.mk ~loc:(symbol_rloc()) d
+let mkpat d = Pat.mk ~loc:(symbol_rloc()) d
+let mkexp d = Exp.mk ~loc:(symbol_rloc()) d
+let mkmty d = Mty.mk ~loc:(symbol_rloc()) d
+let mksig d = Sig.mk ~loc:(symbol_rloc()) d
+let mkmod d = Mod.mk ~loc:(symbol_rloc()) d
+let mkstr d = Str.mk ~loc:(symbol_rloc()) d
+let mkclass d = Cl.mk ~loc:(symbol_rloc()) d
+let mkcty d = Cty.mk ~loc:(symbol_rloc()) d
+let mkctf ?attrs ?docs d =
+  Ctf.mk ~loc:(symbol_rloc()) ?attrs ?docs d
+let mkcf ?attrs ?docs d =
+  Cf.mk ~loc:(symbol_rloc()) ?attrs ?docs d
+
+let mkrhs rhs pos = mkloc rhs (rhs_loc pos)
 
 let reloc_pat x = { x with ppat_loc = symbol_rloc () };;
 let reloc_exp x = { x with pexp_loc = symbol_rloc () };;
 
 let mkoperator name pos =
-  { pexp_desc = Pexp_ident(Lident name); pexp_loc = rhs_loc pos }
+  let loc = rhs_loc pos in
+  Exp.mk ~loc (Pexp_ident(mkloc (Lident name) loc))
+
+let mkpatvar name pos =
+  Pat.mk ~loc:(rhs_loc pos) (Ppat_var (mkrhs name pos))
 
 (*
   Ghost expressions and patterns:
-  expressions and patterns that do not appear explicitely in the
+  expressions and patterns that do not appear explicitly in the
   source file they have the loc_ghost flag set to true.
   Then the profiler will not try to instrument them and the
-  -stypes option will not try to display their type.
+  -annot option will not try to display their type.
 
   Every grammar rule that generates an element with a location must
   make at most one non-ghost element, the topmost one.
@@ -64,19 +63,17 @@ let mkoperator name pos =
   AST node, then the location must be real; in all other cases,
   it must be ghost.
 *)
-let ghexp d = { pexp_desc = d; pexp_loc = symbol_gloc () };;
-let ghpat d = { ppat_desc = d; ppat_loc = symbol_gloc () };;
-let ghtyp d = { ptyp_desc = d; ptyp_loc = symbol_gloc () };;
+let ghexp d = Exp.mk ~loc:(symbol_gloc ()) d
+let ghpat d = Pat.mk ~loc:(symbol_gloc ()) d
+let ghtyp d = Typ.mk ~loc:(symbol_gloc ()) d
+let ghloc d = { txt = d; loc = symbol_gloc () }
+let ghstr d = Str.mk ~loc:(symbol_gloc()) d
 
-let mkassert e =
-  match e with
-  | {pexp_desc = Pexp_construct (Lident "false", None, false) } ->
-         mkexp (Pexp_assertfalse)
-  | _ -> mkexp (Pexp_assert (e))
-;;
+let ghunit () =
+  ghexp (Pexp_construct (mknoloc (Lident "()"), None))
 
 let mkinfix arg1 name arg2 =
-  mkexp(Pexp_apply(mkoperator name 2, ["", arg1; "", arg2]))
+  mkexp(Pexp_apply(mkoperator name 2, [Nolabel, arg1; Nolabel, arg2]))
 
 let neg_float_string f =
   if String.length f > 0 && f.[0] = '-'
@@ -93,50 +90,68 @@ let mkuminus name arg =
       mkexp(Pexp_constant(Const_int64(Int64.neg n)))
   | "-", Pexp_constant(Const_nativeint n) ->
       mkexp(Pexp_constant(Const_nativeint(Nativeint.neg n)))
-  | _, Pexp_constant(Const_float f) ->
+  | ("-" | "-."), Pexp_constant(Const_float f) ->
       mkexp(Pexp_constant(Const_float(neg_float_string f)))
   | _ ->
-      mkexp(Pexp_apply(mkoperator ("~" ^ name) 1, ["", arg]))
+      mkexp(Pexp_apply(mkoperator ("~" ^ name) 1, [Nolabel, arg]))
+
+let mkuplus name arg =
+  let desc = arg.pexp_desc in
+  match name, desc with
+  | "+", Pexp_constant(Const_int _)
+  | "+", Pexp_constant(Const_int32 _)
+  | "+", Pexp_constant(Const_int64 _)
+  | "+", Pexp_constant(Const_nativeint _)
+  | ("+" | "+."), Pexp_constant(Const_float _) -> mkexp desc
+  | _ ->
+      mkexp(Pexp_apply(mkoperator ("~" ^ name) 1, [Nolabel, arg]))
 
-let rec mktailexp = function
+let mkexp_cons consloc args loc =
+  Exp.mk ~loc (Pexp_construct(mkloc (Lident "::") consloc, Some args))
+
+let mkpat_cons consloc args loc =
+  Pat.mk ~loc (Ppat_construct(mkloc (Lident "::") consloc, Some args))
+
+let rec mktailexp nilloc = function
     [] ->
-      ghexp(Pexp_construct(Lident "[]", None, false))
+      let loc = { nilloc with loc_ghost = true } in
+      let nil = { txt = Lident "[]"; loc = loc } in
+      Exp.mk ~loc (Pexp_construct (nil, None))
   | e1 :: el ->
-      let exp_el = mktailexp el in
-      let l = {loc_start = e1.pexp_loc.loc_start;
+      let exp_el = mktailexp nilloc el in
+      let loc = {loc_start = e1.pexp_loc.loc_start;
                loc_end = exp_el.pexp_loc.loc_end;
                loc_ghost = true}
       in
-      let arg = {pexp_desc = Pexp_tuple [e1; exp_el]; pexp_loc = l} in
-      {pexp_desc = Pexp_construct(Lident "::", Some arg, false); pexp_loc = l}
+      let arg = Exp.mk ~loc (Pexp_tuple [e1; exp_el]) in
+      mkexp_cons {loc with loc_ghost = true} arg loc
 
-let rec mktailpat = function
+let rec mktailpat nilloc = function
     [] ->
-      ghpat(Ppat_construct(Lident "[]", None, false))
+      let loc = { nilloc with loc_ghost = true } in
+      let nil = { txt = Lident "[]"; loc = loc } in
+      Pat.mk ~loc (Ppat_construct (nil, None))
   | p1 :: pl ->
-      let pat_pl = mktailpat pl in
-      let l = {loc_start = p1.ppat_loc.loc_start;
+      let pat_pl = mktailpat nilloc pl in
+      let loc = {loc_start = p1.ppat_loc.loc_start;
                loc_end = pat_pl.ppat_loc.loc_end;
                loc_ghost = true}
       in
-      let arg = {ppat_desc = Ppat_tuple [p1; pat_pl]; ppat_loc = l} in
-      {ppat_desc = Ppat_construct(Lident "::", Some arg, false); ppat_loc = l}
+      let arg = Pat.mk ~loc (Ppat_tuple [p1; pat_pl]) in
+      mkpat_cons {loc with loc_ghost = true} arg loc
 
-let ghstrexp e =
-  { pstr_desc = Pstr_eval e; pstr_loc = {e.pexp_loc with loc_ghost = true} }
+let mkstrexp e attrs =
+  { pstr_desc = Pstr_eval (e, attrs); pstr_loc = e.pexp_loc }
 
-let array_function str name =
-  Ldot(Lident str, (if !Clflags.fast then "unsafe_" ^ name else name))
+let mkexp_constraint e (t1, t2) =
+  match t1, t2 with
+  | Some t, None -> ghexp(Pexp_constraint(e, t))
+  | _, Some t -> ghexp(Pexp_coerce(e, t1, t))
+  | None, None -> assert false
 
-let rec deep_mkrangepat c1 c2 =
-  if c1 = c2 then ghpat(Ppat_constant(Const_char c1)) else
-  ghpat(Ppat_or(ghpat(Ppat_constant(Const_char c1)),
-                deep_mkrangepat (Char.chr(Char.code c1 + 1)) c2))
-
-let rec mkrangepat c1 c2 =
-  if c1 > c2 then mkrangepat c2 c1 else
-  if c1 = c2 then mkpat(Ppat_constant(Const_char c1)) else
-  reloc_pat (deep_mkrangepat c1 c2)
+let array_function par assign=
+  let op = if assign then par^"<-" else par in
+  ghloc ( Lident op )
 
 let syntax_error () =
   raise Syntaxerr.Escape_error
@@ -145,44 +160,244 @@ let unclosed opening_name opening_num closing_name closing_num =
   raise(Syntaxerr.Error(Syntaxerr.Unclosed(rhs_loc opening_num, opening_name,
                                            rhs_loc closing_num, closing_name)))
 
-let bigarray_function str name =
-  Ldot(Ldot(Lident "Bigarray", str), name)
+let expecting pos nonterm =
+    raise Syntaxerr.(Error(Expecting(rhs_loc pos, nonterm)))
+
+let not_expecting pos nonterm =
+    raise Syntaxerr.(Error(Not_expecting(rhs_loc pos, nonterm)))
+
+let bigarray_function order assign =
+  let op =
+    match order with
+      | 1 -> ".{}"
+      | 2 -> ".{,}"
+      | 3 -> ".{,,}"
+      | _ -> ".{,..,}"
+  in
+  let op= if assign then op^"<-" else op in
+  ghloc ( Lident op )
 
 let bigarray_untuplify = function
-    { pexp_desc = Pexp_tuple explist} -> explist
+    { pexp_desc = Pexp_tuple explist; pexp_loc = _ } -> explist
   | exp -> [exp]
 
 let bigarray_get arr arg =
+  let get order = bigarray_function order false in
   match bigarray_untuplify arg with
     [c1] ->
-      mkexp(Pexp_apply(ghexp(Pexp_ident(bigarray_function "Array1" "get")),
-                       ["", arr; "", c1]))
+      mkexp(Pexp_apply(ghexp(Pexp_ident(get 1)),
+                       [Nolabel, arr; Nolabel, c1]))
   | [c1;c2] ->
-      mkexp(Pexp_apply(ghexp(Pexp_ident(bigarray_function "Array2" "get")),
-                       ["", arr; "", c1; "", c2]))
+      mkexp(Pexp_apply(ghexp(Pexp_ident(get 2)),
+                       [Nolabel, arr; Nolabel, c1; Nolabel, c2]))
   | [c1;c2;c3] ->
-      mkexp(Pexp_apply(ghexp(Pexp_ident(bigarray_function "Array3" "get")),
-                       ["", arr; "", c1; "", c2; "", c3]))
+      mkexp(Pexp_apply(ghexp(Pexp_ident(get 3)),
+                       [Nolabel, arr; Nolabel, c1; Nolabel, c2; Nolabel, c3]))
   | coords ->
-      mkexp(Pexp_apply(ghexp(Pexp_ident(bigarray_function "Genarray" "get")),
-                       ["", arr; "", ghexp(Pexp_array coords)]))
+      mkexp(Pexp_apply(ghexp(Pexp_ident(get 0)),
+                       [Nolabel, arr; Nolabel, ghexp(Pexp_array coords)]))
 
 let bigarray_set arr arg newval =
+  let set order = bigarray_function order true in
   match bigarray_untuplify arg with
     [c1] ->
-      mkexp(Pexp_apply(ghexp(Pexp_ident(bigarray_function "Array1" "set")),
-                       ["", arr; "", c1; "", newval]))
+      mkexp(Pexp_apply(ghexp(Pexp_ident(set 1)),
+                       [Nolabel, arr; Nolabel, c1; Nolabel, newval]))
   | [c1;c2] ->
-      mkexp(Pexp_apply(ghexp(Pexp_ident(bigarray_function "Array2" "set")),
-                       ["", arr; "", c1; "", c2; "", newval]))
+      mkexp(Pexp_apply(ghexp(Pexp_ident(set 2)),
+                       [Nolabel, arr; Nolabel, c1; Nolabel, c2;
+                        Nolabel, newval]))
   | [c1;c2;c3] ->
-      mkexp(Pexp_apply(ghexp(Pexp_ident(bigarray_function "Array3" "set")),
-                       ["", arr; "", c1; "", c2; "", c3; "", newval]))
+      mkexp(Pexp_apply(ghexp(Pexp_ident(set 3)),
+                       [Nolabel, arr; Nolabel, c1; Nolabel, c2; Nolabel, c3;
+                        Nolabel, newval]))
   | coords ->
-      mkexp(Pexp_apply(ghexp(Pexp_ident(bigarray_function "Genarray" "set")),
-                       ["", arr; 
-                        "", ghexp(Pexp_array coords);
-                        "", newval]))
+      mkexp(Pexp_apply(ghexp(Pexp_ident(set 0)),
+                       [Nolabel, arr;
+                        Nolabel, ghexp(Pexp_array coords);
+                        Nolabel, newval]))
+
+let lapply p1 p2 =
+  if !Clflags.applicative_functors
+  then Lapply(p1, p2)
+  else raise (Syntaxerr.Error(Syntaxerr.Applicative_path (symbol_rloc())))
+
+let exp_of_label lbl pos =
+  mkexp (Pexp_ident(mkrhs (Lident(Longident.last lbl)) pos))
+
+let pat_of_label lbl pos =
+  mkpat (Ppat_var (mkrhs (Longident.last lbl) pos))
+
+let check_variable vl loc v =
+  if List.mem v vl then
+    raise Syntaxerr.(Error(Variable_in_scope(loc,v)))
+
+let varify_constructors var_names t =
+  let rec loop t =
+    let desc =
+      match t.ptyp_desc with
+      | Ptyp_any -> Ptyp_any
+      | Ptyp_var x ->
+          check_variable var_names t.ptyp_loc x;
+          Ptyp_var x
+      | Ptyp_arrow (label,core_type,core_type') ->
+          Ptyp_arrow(label, loop core_type, loop core_type')
+      | Ptyp_tuple lst -> Ptyp_tuple (List.map loop lst)
+      | Ptyp_constr( { txt = Lident s }, []) when List.mem s var_names ->
+          Ptyp_var s
+      | Ptyp_constr(longident, lst) ->
+          Ptyp_constr(longident, List.map loop lst)
+      | Ptyp_object (lst, o) ->
+          Ptyp_object
+            (List.map (fun (s, attrs, t) -> (s, attrs, loop t)) lst, o)
+      | Ptyp_class (longident, lst) ->
+          Ptyp_class (longident, List.map loop lst)
+      | Ptyp_alias(core_type, string) ->
+          check_variable var_names t.ptyp_loc string;
+          Ptyp_alias(loop core_type, string)
+      | Ptyp_variant(row_field_list, flag, lbl_lst_option) ->
+          Ptyp_variant(List.map loop_row_field row_field_list,
+                       flag, lbl_lst_option)
+      | Ptyp_poly(string_lst, core_type) ->
+          List.iter (check_variable var_names t.ptyp_loc) string_lst;
+          Ptyp_poly(string_lst, loop core_type)
+      | Ptyp_package(longident,lst) ->
+          Ptyp_package(longident,List.map (fun (n,typ) -> (n,loop typ) ) lst)
+      | Ptyp_extension (s, arg) ->
+          Ptyp_extension (s, arg)
+    in
+    {t with ptyp_desc = desc}
+  and loop_row_field  =
+    function
+      | Rtag(label,attrs,flag,lst) ->
+          Rtag(label,attrs,flag,List.map loop lst)
+      | Rinherit t ->
+          Rinherit (loop t)
+  in
+  loop t
+
+let mk_newtypes newtypes exp =
+  List.fold_right (fun newtype exp -> mkexp (Pexp_newtype (newtype, exp)))
+    newtypes exp
+
+let wrap_type_annotation newtypes core_type body =
+  let exp = mkexp(Pexp_constraint(body,core_type)) in
+  let exp = mk_newtypes newtypes exp in
+  (exp, ghtyp(Ptyp_poly(newtypes,varify_constructors newtypes core_type)))
+
+let wrap_exp_attrs body (ext, attrs) =
+  (* todo: keep exact location for the entire attribute *)
+  let body = {body with pexp_attributes = attrs @ body.pexp_attributes} in
+  match ext with
+  | None -> body
+  | Some id -> ghexp(Pexp_extension (id, PStr [mkstrexp body []]))
+
+let mkexp_attrs d attrs =
+  wrap_exp_attrs (mkexp d) attrs
+
+let text_str pos = Str.text (rhs_text pos)
+let text_sig pos = Sig.text (rhs_text pos)
+let text_cstr pos = Cf.text (rhs_text pos)
+let text_csig pos = Ctf.text (rhs_text pos)
+let text_def pos = [Ptop_def (Str.text (rhs_text pos))]
+
+let extra_text text pos items =
+  let pre_extras = rhs_pre_extra_text pos in
+  let post_extras = rhs_post_extra_text pos in
+    text pre_extras @ items @ text post_extras
+
+let extra_str pos items = extra_text Str.text pos items
+let extra_sig pos items = extra_text Sig.text pos items
+let extra_cstr pos items = extra_text Cf.text pos items
+let extra_csig pos items = extra_text Ctf.text pos items
+let extra_def pos items =
+  extra_text (fun txt -> [Ptop_def (Str.text txt)]) pos items
+
+type let_binding =
+  { lb_pattern: pattern;
+    lb_expression: expression;
+    lb_attributes: attributes;
+    lb_docs: docs Lazy.t;
+    lb_text: text Lazy.t;
+    lb_loc: Location.t; }
+
+type let_bindings =
+  { lbs_bindings: let_binding list;
+    lbs_rec: rec_flag;
+    lbs_extension: string Asttypes.loc option;
+    lbs_attributes: attributes;
+    lbs_loc: Location.t }
+
+let mklb (p, e) attrs =
+  { lb_pattern = p;
+    lb_expression = e;
+    lb_attributes = attrs;
+    lb_docs = symbol_docs_lazy ();
+    lb_text = symbol_text_lazy ();
+    lb_loc = symbol_rloc (); }
+
+let mklbs (ext, attrs) rf lb =
+  { lbs_bindings = [lb];
+    lbs_rec = rf;
+    lbs_extension = ext ;
+    lbs_attributes = attrs;
+    lbs_loc = symbol_rloc (); }
+
+let addlb lbs lb =
+  { lbs with lbs_bindings = lb :: lbs.lbs_bindings }
+
+let val_of_let_bindings lbs =
+  let str =
+    match lbs.lbs_bindings with
+    | [ {lb_pattern = { ppat_desc = Ppat_any; ppat_loc = _ }; _} as lb ] ->
+        let exp = wrap_exp_attrs lb.lb_expression
+                    (None, lbs.lbs_attributes) in
+        mkstr (Pstr_eval (exp, lb.lb_attributes))
+    | bindings ->
+        if lbs.lbs_attributes <> [] then
+          raise Syntaxerr.(Error(Not_expecting(lbs.lbs_loc, "attributes")));
+        let bindings =
+          List.map
+            (fun lb ->
+               Vb.mk ~loc:lb.lb_loc ~attrs:lb.lb_attributes
+                 ~docs:(Lazy.force lb.lb_docs)
+                 ~text:(Lazy.force lb.lb_text)
+                 lb.lb_pattern lb.lb_expression)
+            bindings
+        in
+        mkstr(Pstr_value(lbs.lbs_rec, List.rev bindings))
+  in
+  match lbs.lbs_extension with
+  | None -> str
+  | Some id -> ghstr (Pstr_extension((id, PStr [str]), []))
+
+let expr_of_let_bindings lbs body =
+  let bindings =
+    List.map
+      (fun lb ->
+         if lb.lb_attributes <> [] then
+           raise Syntaxerr.(Error(Not_expecting(lb.lb_loc, "item attribute")));
+         Vb.mk ~loc:lb.lb_loc lb.lb_pattern lb.lb_expression)
+      lbs.lbs_bindings
+  in
+    mkexp_attrs (Pexp_let(lbs.lbs_rec, List.rev bindings, body))
+      (lbs.lbs_extension, lbs.lbs_attributes)
+
+let class_of_let_bindings lbs body =
+  let bindings =
+    List.map
+      (fun lb ->
+         if lb.lb_attributes <> [] then
+           raise Syntaxerr.(Error(Not_expecting(lb.lb_loc, "item attribute")));
+         Vb.mk ~loc:lb.lb_loc lb.lb_pattern lb.lb_expression)
+      lbs.lbs_bindings
+  in
+    if lbs.lbs_extension <> None then
+      raise Syntaxerr.(Error(Not_expecting(lbs.lbs_loc, "extension")));
+    if lbs.lbs_attributes <> [] then
+      raise Syntaxerr.(Error(Not_expecting(lbs.lbs_loc, "attributes")));
+    mkclass(Pcl_let (lbs.lbs_rec, List.rev bindings, body))
+
 %}
 
 /* Tokens */
@@ -193,6 +408,7 @@ let bigarray_set arr arg newval =
 %token AS
 %token ASSERT
 %token BACKQUOTE
+%token BANG
 %token BAR
 %token BARBAR
 %token BARRBRACKET
@@ -246,11 +462,16 @@ let bigarray_set arr arg newval =
 %token LBRACKETBAR
 %token LBRACKETLESS
 %token LBRACKETGREATER
+%token LBRACKETPERCENT
+%token LBRACKETPERCENTPERCENT
 %token LESS
 %token LESSMINUS
 %token LET
 %token <string> LIDENT
 %token LPAREN
+%token LBRACKETAT
+%token LBRACKETATAT
+%token LBRACKETATATAT
 %token MATCH
 %token METHOD
 %token MINUS
@@ -260,17 +481,20 @@ let bigarray_set arr arg newval =
 %token MUTABLE
 %token <nativeint> NATIVEINT
 %token NEW
+%token NONREC
 %token OBJECT
 %token OF
 %token OPEN
 %token <string> OPTLABEL
 %token OR
 /* %token PARSER */
+%token PERCENT
 %token PLUS
+%token PLUSDOT
+%token PLUSEQ
 %token <string> PREFIXOP
 %token PRIVATE
 %token QUESTION
-%token QUESTIONQUESTION
 %token QUOTE
 %token RBRACE
 %token RBRACKET
@@ -279,9 +503,10 @@ let bigarray_set arr arg newval =
 %token SEMI
 %token SEMISEMI
 %token SHARP
+%token <string> SHARPOP
 %token SIG
 %token STAR
-%token <string> STRING
+%token <string * string option> STRING
 %token STRUCT
 %token THEN
 %token TILDE
@@ -296,6 +521,10 @@ let bigarray_set arr arg newval =
 %token WHEN
 %token WHILE
 %token WITH
+%token <string * Location.t> COMMENT
+%token <Docstrings.docstring> DOCSTRING
+
+%token EOL
 
 /* Precedences and associativities.
 
@@ -341,21 +570,26 @@ The precedences must be listed from low to high.
 %nonassoc below_EQUAL
 %left     INFIXOP0 EQUAL LESS GREATER   /* expr (e OP e OP e) */
 %right    INFIXOP1                      /* expr (e OP e OP e) */
+%nonassoc below_LBRACKETAT
+%nonassoc LBRACKETAT
+%nonassoc LBRACKETATAT
 %right    COLONCOLON                    /* expr (e :: e :: e) */
-%left     INFIXOP2 PLUS MINUS MINUSDOT  /* expr (e OP e OP e) */
-%left     INFIXOP3 STAR                 /* expr (e OP e OP e) */
+%left     INFIXOP2 PLUS PLUSDOT MINUS MINUSDOT PLUSEQ /* expr (e OP e OP e) */
+%left     PERCENT INFIXOP3 STAR                 /* expr (e OP e OP e) */
 %right    INFIXOP4                      /* expr (e OP e OP e) */
-%nonassoc prec_unary_minus              /* unary - */
+%nonassoc prec_unary_minus prec_unary_plus /* unary - */
 %nonassoc prec_constant_constructor     /* cf. simple_expr (C versus C x) */
 %nonassoc prec_constr_appl              /* above AS BAR COLONCOLON COMMA */
 %nonassoc below_SHARP
 %nonassoc SHARP                         /* simple_expr/toplevel_directive */
+%left     SHARPOP
 %nonassoc below_DOT
 %nonassoc DOT
 /* Finally, the first tokens of simple_expr are above everything else. */
-%nonassoc BACKQUOTE BEGIN CHAR FALSE FLOAT INT INT32 INT64
+%nonassoc BACKQUOTE BANG BEGIN CHAR FALSE FLOAT INT INT32 INT64
           LBRACE LBRACELESS LBRACKET LBRACKETBAR LIDENT LPAREN
           NEW NATIVEINT PREFIXOP STRING TRUE UIDENT
+          LBRACKETPERCENT LBRACKETPERCENTPERCENT
 
 
 /* Entry points */
@@ -368,54 +602,109 @@ The precedences must be listed from low to high.
 %type <Parsetree.toplevel_phrase> toplevel_phrase
 %start use_file                         /* for the #use directive */
 %type <Parsetree.toplevel_phrase list> use_file
-
+%start parse_core_type
+%type <Parsetree.core_type> parse_core_type
+%start parse_expression
+%type <Parsetree.expression> parse_expression
+%start parse_pattern
+%type <Parsetree.pattern> parse_pattern
 %%
 
 /* Entry points */
 
 implementation:
-    structure EOF                        { $1 }
+    structure EOF                        { extra_str 1 $1 }
 ;
 interface:
-    signature EOF                        { List.rev $1 }
+    signature EOF                        { extra_sig 1 $1 }
 ;
 toplevel_phrase:
-    top_structure SEMISEMI               { Ptop_def $1 }
-  | seq_expr SEMISEMI                    { Ptop_def[ghstrexp $1] }
+    top_structure SEMISEMI               { Ptop_def (extra_str 1 $1) }
   | toplevel_directive SEMISEMI          { $1 }
   | EOF                                  { raise End_of_file }
 ;
 top_structure:
-    structure_item                       { [$1] }
-  | structure_item top_structure         { $1 :: $2 }
+    seq_expr post_item_attributes
+      { (text_str 1) @ [mkstrexp $1 $2] }
+  | top_structure_tail
+      { $1 }
+;
+top_structure_tail:
+    /* empty */                          { [] }
+  | structure_item top_structure_tail    { (text_str 1) @ $1 :: $2 }
 ;
 use_file:
+    use_file_body                        { extra_def 1 $1 }
+;
+use_file_body:
     use_file_tail                        { $1 }
-  | seq_expr use_file_tail               { Ptop_def[ghstrexp $1] :: $2 }
+  | seq_expr post_item_attributes use_file_tail
+      { (text_def 1) @ Ptop_def[mkstrexp $1 $2] :: $3 }
 ;
 use_file_tail:
-    EOF                                         { [] }
-  | SEMISEMI EOF                                { [] }
-  | SEMISEMI seq_expr use_file_tail             { Ptop_def[ghstrexp $2] :: $3 }
-  | SEMISEMI structure_item use_file_tail       { Ptop_def[$2] :: $3 }
-  | SEMISEMI toplevel_directive use_file_tail   { $2 :: $3 }
-  | structure_item use_file_tail                { Ptop_def[$1] :: $2 }
-  | toplevel_directive use_file_tail            { $1 :: $2 }
+    EOF
+      { [] }
+  | SEMISEMI EOF
+      { text_def 1 }
+  | SEMISEMI seq_expr post_item_attributes use_file_tail
+      {  mark_rhs_docs 2 3;
+        (text_def 1) @ (text_def 2) @ Ptop_def[mkstrexp $2 $3] :: $4 }
+  | SEMISEMI structure_item use_file_tail
+      { (text_def 1) @ (text_def 2) @ Ptop_def[$2] :: $3 }
+  | SEMISEMI toplevel_directive use_file_tail
+      {  mark_rhs_docs 2 3;
+        (text_def 1) @ (text_def 2) @ $2 :: $3 }
+  | structure_item use_file_tail
+      { (text_def 1) @ Ptop_def[$1] :: $2 }
+  | toplevel_directive use_file_tail
+      { mark_rhs_docs 1 1;
+        (text_def 1) @ $1 :: $2 }
+;
+parse_core_type:
+    core_type EOF { $1 }
+;
+parse_expression:
+    seq_expr EOF { $1 }
+;
+parse_pattern:
+    pattern EOF { $1 }
 ;
 
 /* Module expressions */
 
+functor_arg:
+    LPAREN RPAREN
+      { mkrhs "*" 2, None }
+  | LPAREN functor_arg_name COLON module_type RPAREN
+      { mkrhs $2 2, Some $4 }
+;
+
+functor_arg_name:
+    UIDENT     { $1 }
+  | UNDERSCORE { "_" }
+;
+
+functor_args:
+    functor_args functor_arg
+      { $2 :: $1 }
+  | functor_arg
+      { [ $1 ] }
+;
+
 module_expr:
     mod_longident
-      { mkmod(Pmod_ident $1) }
+      { mkmod(Pmod_ident (mkrhs $1 1)) }
   | STRUCT structure END
-      { mkmod(Pmod_structure($2)) }
+      { mkmod(Pmod_structure(extra_str 2 $2)) }
   | STRUCT structure error
       { unclosed "struct" 1 "end" 3 }
-  | FUNCTOR LPAREN UIDENT COLON module_type RPAREN MINUSGREATER module_expr
-      { mkmod(Pmod_functor($3, $5, $8)) }
+  | FUNCTOR functor_args MINUSGREATER module_expr
+      { List.fold_left (fun acc (n, t) -> mkmod(Pmod_functor(n, t, acc)))
+                       $4 $2 }
   | module_expr LPAREN module_expr RPAREN
       { mkmod(Pmod_apply($1, $3)) }
+  | module_expr LPAREN RPAREN
+      { mkmod(Pmod_apply($1, mkmod (Pmod_structure []))) }
   | module_expr LPAREN module_expr error
       { unclosed "(" 2 ")" 4 }
   | LPAREN module_expr COLON module_type RPAREN
@@ -426,139 +715,242 @@ module_expr:
       { $2 }
   | LPAREN module_expr error
       { unclosed "(" 1 ")" 3 }
+  | LPAREN VAL expr RPAREN
+      { mkmod(Pmod_unpack $3) }
+  | LPAREN VAL expr COLON package_type RPAREN
+      { mkmod(Pmod_unpack(
+              ghexp(Pexp_constraint($3, ghtyp(Ptyp_package $5))))) }
+  | LPAREN VAL expr COLON package_type COLONGREATER package_type RPAREN
+      { mkmod(Pmod_unpack(
+              ghexp(Pexp_coerce($3, Some(ghtyp(Ptyp_package $5)),
+                                    ghtyp(Ptyp_package $7))))) }
+  | LPAREN VAL expr COLONGREATER package_type RPAREN
+      { mkmod(Pmod_unpack(
+              ghexp(Pexp_coerce($3, None, ghtyp(Ptyp_package $5))))) }
+  | LPAREN VAL expr COLON error
+      { unclosed "(" 1 ")" 5 }
+  | LPAREN VAL expr COLONGREATER error
+      { unclosed "(" 1 ")" 5 }
+  | LPAREN VAL expr error
+      { unclosed "(" 1 ")" 4 }
+  | module_expr attribute
+      { Mod.attr $1 $2 }
+  | extension
+      { mkmod(Pmod_extension $1) }
 ;
+
 structure:
-    structure_tail                              { $1 }
-  | seq_expr structure_tail                     { ghstrexp $1 :: $2 }
+    seq_expr post_item_attributes structure_tail
+      { mark_rhs_docs 1 2;
+        (text_str 1) @ mkstrexp $1 $2 :: $3 }
+  | structure_tail { $1 }
 ;
 structure_tail:
-    /* empty */                                 { [] }
-  | SEMISEMI                                    { [] }
-  | SEMISEMI seq_expr structure_tail            { ghstrexp $2 :: $3 }
-  | SEMISEMI structure_item structure_tail      { $2 :: $3 }
-  | structure_item structure_tail               { $1 :: $2 }
+    /* empty */          { [] }
+  | SEMISEMI structure   { (text_str 1) @ $2 }
+  | structure_item structure_tail { (text_str 1) @ $1 :: $2 }
 ;
 structure_item:
-    LET rec_flag let_bindings
-      { match $3 with
-          [{ppat_desc = Ppat_any}, exp] -> mkstr(Pstr_eval exp)
-        | _ -> mkstr(Pstr_value($2, List.rev $3)) }
-  | EXTERNAL val_ident_colon core_type EQUAL primitive_declaration
-      { mkstr(Pstr_primitive($2, {pval_type = $3; pval_prim = $5})) }
-  | TYPE type_declarations
-      { mkstr(Pstr_type(List.rev $2)) }
-  | EXCEPTION UIDENT constructor_arguments
-      { mkstr(Pstr_exception($2, $3)) }
-  | EXCEPTION UIDENT EQUAL constr_longident
-      { mkstr(Pstr_exn_rebind($2, $4)) }
-  | MODULE UIDENT module_binding
-      { mkstr(Pstr_module($2, $3)) }
-  | MODULE REC module_rec_bindings
-      { mkstr(Pstr_recmodule(List.rev $3)) }
-  | MODULE TYPE ident EQUAL module_type
-      { mkstr(Pstr_modtype($3, $5)) }
-  | OPEN mod_longident
-      { mkstr(Pstr_open $2) }
-  | CLASS class_declarations
-      { mkstr(Pstr_class (List.rev $2)) }
-  | CLASS TYPE class_type_declarations
-      { mkstr(Pstr_class_type (List.rev $3)) }
-  | INCLUDE module_expr
-      { mkstr(Pstr_include $2) }
-;
-module_binding:
+    let_bindings
+      { val_of_let_bindings $1 }
+  | primitive_declaration
+      { mkstr (Pstr_primitive $1) }
+  | value_description
+      { mkstr (Pstr_primitive $1) }
+  | type_declarations
+      { let (nr, l) = $1 in mkstr(Pstr_type (nr, List.rev l)) }
+  | str_type_extension
+      { mkstr(Pstr_typext $1) }
+  | str_exception_declaration
+      { mkstr(Pstr_exception $1) }
+  | module_binding
+      { mkstr(Pstr_module $1) }
+  | rec_module_bindings
+      { mkstr(Pstr_recmodule(List.rev $1)) }
+  | module_type_declaration
+      { mkstr(Pstr_modtype $1) }
+  | open_statement { mkstr(Pstr_open $1) }
+  | class_declarations
+      { mkstr(Pstr_class (List.rev $1)) }
+  | class_type_declarations
+      { mkstr(Pstr_class_type (List.rev $1)) }
+  | str_include_statement
+      { mkstr(Pstr_include $1) }
+  | item_extension post_item_attributes
+      { mkstr(Pstr_extension ($1, (add_docs_attrs (symbol_docs ()) $2))) }
+  | floating_attribute
+      { mark_symbol_docs ();
+        mkstr(Pstr_attribute $1) }
+;
+str_include_statement:
+    INCLUDE module_expr post_item_attributes
+      { Incl.mk $2 ~attrs:$3
+                ~loc:(symbol_rloc()) ~docs:(symbol_docs ()) }
+;
+module_binding_body:
     EQUAL module_expr
       { $2 }
   | COLON module_type EQUAL module_expr
       { mkmod(Pmod_constraint($4, $2)) }
-  | LPAREN UIDENT COLON module_type RPAREN module_binding
-      { mkmod(Pmod_functor($2, $4, $6)) }
+  | functor_arg module_binding_body
+      { mkmod(Pmod_functor(fst $1, snd $1, $2)) }
 ;
-module_rec_bindings:
-    module_rec_binding                            { [$1] }
-  | module_rec_bindings AND module_rec_binding    { $3 :: $1 }
+module_binding:
+    MODULE UIDENT module_binding_body post_item_attributes
+      { Mb.mk (mkrhs $2 2) $3 ~attrs:$4
+              ~loc:(symbol_rloc ()) ~docs:(symbol_docs ()) }
+;
+rec_module_bindings:
+    rec_module_binding                            { [$1] }
+  | rec_module_bindings and_module_binding        { $2 :: $1 }
 ;
-module_rec_binding:
-    UIDENT COLON module_type EQUAL module_expr    { ($1, $3, $5) }
+rec_module_binding:
+    MODULE REC UIDENT module_binding_body post_item_attributes
+      { Mb.mk (mkrhs $3 3) $4 ~attrs:$5
+              ~loc:(symbol_rloc ()) ~docs:(symbol_docs ()) }
+;
+and_module_binding:
+    AND UIDENT module_binding_body post_item_attributes
+      { Mb.mk (mkrhs $2 2) $3 ~attrs:$4 ~loc:(symbol_rloc ())
+               ~text:(symbol_text ()) ~docs:(symbol_docs ()) }
 ;
 
 /* Module types */
 
 module_type:
     mty_longident
-      { mkmty(Pmty_ident $1) }
+      { mkmty(Pmty_ident (mkrhs $1 1)) }
   | SIG signature END
-      { mkmty(Pmty_signature(List.rev $2)) }
+      { mkmty(Pmty_signature (extra_sig 2 $2)) }
   | SIG signature error
       { unclosed "sig" 1 "end" 3 }
-  | FUNCTOR LPAREN UIDENT COLON module_type RPAREN MINUSGREATER module_type
+  | FUNCTOR functor_args MINUSGREATER module_type
       %prec below_WITH
-      { mkmty(Pmty_functor($3, $5, $8)) }
+      { List.fold_left (fun acc (n, t) -> mkmty(Pmty_functor(n, t, acc)))
+                       $4 $2 }
   | module_type WITH with_constraints
       { mkmty(Pmty_with($1, List.rev $3)) }
+  | MODULE TYPE OF module_expr %prec below_LBRACKETAT
+      { mkmty(Pmty_typeof $4) }
+/*  | LPAREN MODULE mod_longident RPAREN
+      { mkmty (Pmty_alias (mkrhs $3 3)) } */
   | LPAREN module_type RPAREN
       { $2 }
   | LPAREN module_type error
       { unclosed "(" 1 ")" 3 }
+  | extension
+      { mkmty(Pmty_extension $1) }
+  | module_type attribute
+      { Mty.attr $1 $2 }
 ;
 signature:
-    /* empty */                                 { [] }
-  | signature signature_item                    { $2 :: $1 }
-  | signature signature_item SEMISEMI           { $2 :: $1 }
+    /* empty */          { [] }
+  | SEMISEMI signature   { (text_sig 1) @ $2 }
+  | signature_item signature { (text_sig 1) @ $1 :: $2 }
 ;
 signature_item:
-    VAL val_ident_colon core_type
-      { mksig(Psig_value($2, {pval_type = $3; pval_prim = []})) }
-  | EXTERNAL val_ident_colon core_type EQUAL primitive_declaration
-      { mksig(Psig_value($2, {pval_type = $3; pval_prim = $5})) }
-  | TYPE type_declarations
-      { mksig(Psig_type(List.rev $2)) }
-  | EXCEPTION UIDENT constructor_arguments
-      { mksig(Psig_exception($2, $3)) }
-  | MODULE UIDENT module_declaration
-      { mksig(Psig_module($2, $3)) }
-  | MODULE REC module_rec_declarations
-      { mksig(Psig_recmodule(List.rev $3)) }
-  | MODULE TYPE ident
-      { mksig(Psig_modtype($3, Pmodtype_abstract)) }
-  | MODULE TYPE ident EQUAL module_type
-      { mksig(Psig_modtype($3, Pmodtype_manifest $5)) }
-  | OPEN mod_longident
-      { mksig(Psig_open $2) }
-  | INCLUDE module_type
-      { mksig(Psig_include $2) }
-  | CLASS class_descriptions
-      { mksig(Psig_class (List.rev $2)) }
-  | CLASS TYPE class_type_declarations
-      { mksig(Psig_class_type (List.rev $3)) }
-;
-
-module_declaration:
+    value_description
+      { mksig(Psig_value $1) }
+  | primitive_declaration
+      { mksig(Psig_value $1) }
+  | type_declarations
+      { let (nr, l) = $1 in mksig(Psig_type (nr, List.rev l)) }
+  | sig_type_extension
+      { mksig(Psig_typext $1) }
+  | sig_exception_declaration
+      { mksig(Psig_exception $1) }
+  | module_declaration
+      { mksig(Psig_module $1) }
+  | module_alias
+      { mksig(Psig_module $1) }
+  | rec_module_declarations
+      { mksig(Psig_recmodule (List.rev $1)) }
+  | module_type_declaration
+      { mksig(Psig_modtype $1) }
+  | open_statement
+      { mksig(Psig_open $1) }
+  | sig_include_statement
+      { mksig(Psig_include $1) }
+  | class_descriptions
+      { mksig(Psig_class (List.rev $1)) }
+  | class_type_declarations
+      { mksig(Psig_class_type (List.rev $1)) }
+  | item_extension post_item_attributes
+      { mksig(Psig_extension ($1, (add_docs_attrs (symbol_docs ()) $2))) }
+  | floating_attribute
+      { mark_symbol_docs ();
+        mksig(Psig_attribute $1) }
+;
+open_statement:
+  | OPEN override_flag mod_longident post_item_attributes
+      { Opn.mk (mkrhs $3 3) ~override:$2 ~attrs:$4
+          ~loc:(symbol_rloc()) ~docs:(symbol_docs ()) }
+;
+sig_include_statement:
+    INCLUDE module_type post_item_attributes %prec below_WITH
+      { Incl.mk $2 ~attrs:$3
+                ~loc:(symbol_rloc()) ~docs:(symbol_docs ()) }
+;
+module_declaration_body:
     COLON module_type
       { $2 }
-  | LPAREN UIDENT COLON module_type RPAREN module_declaration
-      { mkmty(Pmty_functor($2, $4, $6)) }
-;
-module_rec_declarations:
-    module_rec_declaration                              { [$1] }
-  | module_rec_declarations AND module_rec_declaration  { $3 :: $1 }
+  | LPAREN UIDENT COLON module_type RPAREN module_declaration_body
+      { mkmty(Pmty_functor(mkrhs $2 2, Some $4, $6)) }
+  | LPAREN RPAREN module_declaration_body
+      { mkmty(Pmty_functor(mkrhs "*" 1, None, $3)) }
 ;
-module_rec_declaration:
-    UIDENT COLON module_type                            { ($1, $3) }
+module_declaration:
+    MODULE UIDENT module_declaration_body post_item_attributes
+      { Md.mk (mkrhs $2 2) $3 ~attrs:$4
+          ~loc:(symbol_rloc()) ~docs:(symbol_docs ()) }
+;
+module_alias:
+    MODULE UIDENT EQUAL mod_longident post_item_attributes
+      { Md.mk (mkrhs $2 2)
+          (Mty.alias ~loc:(rhs_loc 4) (mkrhs $4 4)) ~attrs:$5
+             ~loc:(symbol_rloc()) ~docs:(symbol_docs ()) }
+;
+rec_module_declarations:
+    rec_module_declaration                          { [$1] }
+  | rec_module_declarations and_module_declaration  { $2 :: $1 }
+;
+rec_module_declaration:
+    MODULE REC UIDENT COLON module_type post_item_attributes
+      { Md.mk (mkrhs $3 3) $5 ~attrs:$6
+              ~loc:(symbol_rloc()) ~docs:(symbol_docs ()) }
+;
+and_module_declaration:
+    AND UIDENT COLON module_type post_item_attributes
+      { Md.mk (mkrhs $2 2) $4 ~attrs:$5 ~loc:(symbol_rloc())
+              ~text:(symbol_text()) ~docs:(symbol_docs()) }
+;
+module_type_declaration_body:
+    /* empty */               { None }
+  | EQUAL module_type         { Some $2 }
+;
+module_type_declaration:
+    MODULE TYPE ident module_type_declaration_body post_item_attributes
+      { Mtd.mk (mkrhs $3 3) ?typ:$4 ~attrs:$5
+          ~loc:(symbol_rloc()) ~docs:(symbol_docs ()) }
 ;
-
 /* Class expressions */
 
 class_declarations:
-    class_declarations AND class_declaration    { $3 :: $1 }
-  | class_declaration                           { [$1] }
+    class_declaration                           { [$1] }
+  | class_declarations and_class_declaration    { $2 :: $1 }
 ;
 class_declaration:
-    virtual_flag class_type_parameters LIDENT class_fun_binding
-      { let params, variance = List.split (fst $2) in
-        {pci_virt = $1; pci_params = params, snd $2;
-         pci_name = $3; pci_expr = $4; pci_variance = variance;
-         pci_loc = symbol_rloc ()} }
+    CLASS virtual_flag class_type_parameters LIDENT class_fun_binding
+    post_item_attributes
+      { Ci.mk (mkrhs $4 4) $5 ~virt:$2 ~params:$3 ~attrs:$6
+              ~loc:(symbol_rloc ()) ~docs:(symbol_docs ()) }
+;
+and_class_declaration:
+    AND virtual_flag class_type_parameters LIDENT class_fun_binding
+    post_item_attributes
+      { Ci.mk (mkrhs $4 4) $5 ~virt:$2 ~params:$3
+         ~attrs:$6 ~loc:(symbol_rloc ())
+         ~text:(symbol_text ()) ~docs:(symbol_docs ()) }
 ;
 class_fun_binding:
     EQUAL class_expr
@@ -569,8 +961,8 @@ class_fun_binding:
       { let (l,o,p) = $1 in mkclass(Pcl_fun(l, o, p, $2)) }
 ;
 class_type_parameters:
-    /*empty*/                                   { [], symbol_gloc () }
-  | LBRACKET type_parameter_list RBRACKET       { List.rev $2, symbol_rloc () }
+    /*empty*/                                   { [] }
+  | LBRACKET type_parameter_list RBRACKET       { List.rev $2 }
 ;
 class_fun_def:
     labeled_simple_pattern MINUSGREATER class_expr
@@ -585,16 +977,20 @@ class_expr:
       { $2 }
   | class_simple_expr simple_labeled_expr_list
       { mkclass(Pcl_apply($1, List.rev $2)) }
-  | LET rec_flag let_bindings IN class_expr
-      { mkclass(Pcl_let ($2, List.rev $3, $5)) }
+  | let_bindings IN class_expr
+      { class_of_let_bindings $1 $3 }
+  | class_expr attribute
+      { Cl.attr $1 $2 }
+  | extension
+      { mkclass(Pcl_extension $1) }
 ;
 class_simple_expr:
     LBRACKET core_type_comma_list RBRACKET class_longident
-      { mkclass(Pcl_constr($4, List.rev $2)) }
+      { mkclass(Pcl_constr(mkloc $4 (rhs_loc 4), List.rev $2)) }
   | class_longident
-      { mkclass(Pcl_constr($1, [])) }
+      { mkclass(Pcl_constr(mkrhs $1 1, [])) }
   | OBJECT class_structure END
-      { mkclass(Pcl_structure($2)) }
+      { mkclass(Pcl_structure $2) }
   | OBJECT class_structure error
       { unclosed "object" 1 "end" 3 }
   | LPAREN class_expr COLON class_type RPAREN
@@ -607,8 +1003,8 @@ class_simple_expr:
       { unclosed "(" 1 ")" 3 }
 ;
 class_structure:
-    class_self_pattern class_fields
-      { $1, List.rev $2 }
+  |  class_self_pattern class_fields
+       { Cstr.mk $1 (extra_cstr 2 (List.rev $2)) }
 ;
 class_self_pattern:
     LPAREN pattern RPAREN
@@ -621,45 +1017,66 @@ class_self_pattern:
 class_fields:
     /* empty */
       { [] }
-  | class_fields INHERIT class_expr parent_binder
-      { Pcf_inher ($3, $4) :: $1 }
-  | class_fields VAL value
-      { Pcf_val $3 :: $1 }
-  | class_fields virtual_method
-      { Pcf_virt $2 :: $1 }
-  | class_fields concrete_method
-      { Pcf_meth $2 :: $1 }
-  | class_fields CONSTRAINT constrain
-      { Pcf_cstr $3 :: $1 }
-  | class_fields INITIALIZER seq_expr
-      { Pcf_init $3 :: $1 }
+  | class_fields class_field
+      { $2 :: (text_cstr 2) @ $1 }
+;
+class_field:
+  | INHERIT override_flag class_expr parent_binder post_item_attributes
+      { mkcf (Pcf_inherit ($2, $3, $4)) ~attrs:$5 ~docs:(symbol_docs ()) }
+  | VAL value post_item_attributes
+      { mkcf (Pcf_val $2) ~attrs:$3 ~docs:(symbol_docs ()) }
+  | METHOD method_ post_item_attributes
+      { mkcf (Pcf_method $2) ~attrs:$3 ~docs:(symbol_docs ()) }
+  | CONSTRAINT constrain_field post_item_attributes
+      { mkcf (Pcf_constraint $2) ~attrs:$3 ~docs:(symbol_docs ()) }
+  | INITIALIZER seq_expr post_item_attributes
+      { mkcf (Pcf_initializer $2) ~attrs:$3 ~docs:(symbol_docs ()) }
+  | item_extension post_item_attributes
+      { mkcf (Pcf_extension $1) ~attrs:$2 ~docs:(symbol_docs ()) }
+  | floating_attribute
+      { mark_symbol_docs ();
+        mkcf (Pcf_attribute $1) }
 ;
 parent_binder:
     AS LIDENT
           { Some $2 }
   | /* empty */
-          {None}
+          { None }
 ;
 value:
-        mutable_flag label EQUAL seq_expr
-          { $2, $1, $4, symbol_rloc () }
-      | mutable_flag label type_constraint EQUAL seq_expr
-          { $2, $1, (let (t, t') = $3 in ghexp(Pexp_constraint($5, t, t'))),
-            symbol_rloc () }
-;
-virtual_method:
-    METHOD PRIVATE VIRTUAL label COLON poly_type
-      { $4, Private, $6, symbol_rloc () }
-  | METHOD VIRTUAL private_flag label COLON poly_type
-      { $4, $3, $6, symbol_rloc () }
-;
-concrete_method :
-    METHOD private_flag label strict_binding
-      { $3, $2, ghexp(Pexp_poly ($4, None)), symbol_rloc () }
-  | METHOD private_flag label COLON poly_type EQUAL seq_expr
-      { $3, $2, ghexp(Pexp_poly($7,Some $5)), symbol_rloc () }
-  | METHOD private_flag LABEL poly_type EQUAL seq_expr
-      { $3, $2, ghexp(Pexp_poly($6,Some $4)), symbol_rloc () }
+/* TODO: factorize these rules (also with method): */
+    override_flag MUTABLE VIRTUAL label COLON core_type
+      { if $1 = Override then syntax_error ();
+        mkloc $4 (rhs_loc 4), Mutable, Cfk_virtual $6 }
+  | VIRTUAL mutable_flag label COLON core_type
+      { mkrhs $3 3, $2, Cfk_virtual $5 }
+  | override_flag mutable_flag label EQUAL seq_expr
+      { mkrhs $3 3, $2, Cfk_concrete ($1, $5) }
+  | override_flag mutable_flag label type_constraint EQUAL seq_expr
+      {
+       let e = mkexp_constraint $6 $4 in
+       mkrhs $3 3, $2, Cfk_concrete ($1, e)
+      }
+;
+method_:
+/* TODO: factorize those rules... */
+    override_flag PRIVATE VIRTUAL label COLON poly_type
+      { if $1 = Override then syntax_error ();
+        mkloc $4 (rhs_loc 4), Private, Cfk_virtual $6 }
+  | override_flag VIRTUAL private_flag label COLON poly_type
+      { if $1 = Override then syntax_error ();
+        mkloc $4 (rhs_loc 4), $3, Cfk_virtual $6 }
+  | override_flag private_flag label strict_binding
+      { mkloc $3 (rhs_loc 3), $2,
+        Cfk_concrete ($1, ghexp(Pexp_poly ($4, None))) }
+  | override_flag private_flag label COLON poly_type EQUAL seq_expr
+      { mkloc $3 (rhs_loc 3), $2,
+        Cfk_concrete ($1, ghexp(Pexp_poly($7, Some $5))) }
+  | override_flag private_flag label COLON TYPE lident_list
+    DOT core_type EQUAL seq_expr
+      { let exp, poly = wrap_type_annotation $6 $8 $10 in
+        mkloc $3 (rhs_loc 3), $2,
+        Cfk_concrete ($1, ghexp(Pexp_poly(exp, Some poly))) }
 ;
 
 /* Class types */
@@ -667,34 +1084,33 @@ concrete_method :
 class_type:
     class_signature
       { $1 }
-  | QUESTION LIDENT COLON simple_core_type_or_tuple MINUSGREATER class_type
-      { mkcty(Pcty_fun("?" ^ $2 ,
-                       {ptyp_desc = Ptyp_constr(Lident "option", [$4]);
-                        ptyp_loc = $4.ptyp_loc},
-                       $6)) }
+  | QUESTION LIDENT COLON simple_core_type_or_tuple MINUSGREATER
+    class_type
+      { mkcty(Pcty_arrow(Optional $2 , $4, $6)) }
   | OPTLABEL simple_core_type_or_tuple MINUSGREATER class_type
-      { mkcty(Pcty_fun("?" ^ $1 ,
-                       {ptyp_desc = Ptyp_constr(Lident "option", [$2]);
-                        ptyp_loc = $2.ptyp_loc},
-                       $4)) }
+      { mkcty(Pcty_arrow(Optional $1, $2, $4)) }
   | LIDENT COLON simple_core_type_or_tuple MINUSGREATER class_type
-      { mkcty(Pcty_fun($1, $3, $5)) }
+      { mkcty(Pcty_arrow(Labelled $1, $3, $5)) }
   | simple_core_type_or_tuple MINUSGREATER class_type
-      { mkcty(Pcty_fun("", $1, $3)) }
-;
+      { mkcty(Pcty_arrow(Nolabel, $1, $3)) }
+ ;
 class_signature:
     LBRACKET core_type_comma_list RBRACKET clty_longident
-      { mkcty(Pcty_constr ($4, List.rev $2)) }
+      { mkcty(Pcty_constr (mkloc $4 (rhs_loc 4), List.rev $2)) }
   | clty_longident
-      { mkcty(Pcty_constr ($1, [])) }
+      { mkcty(Pcty_constr (mkrhs $1 1, [])) }
   | OBJECT class_sig_body END
       { mkcty(Pcty_signature $2) }
   | OBJECT class_sig_body error
       { unclosed "object" 1 "end" 3 }
+  | class_signature attribute
+      { Cty.attr $1 $2 }
+  | extension
+      { mkcty(Pcty_extension $1) }
 ;
 class_sig_body:
     class_self_type class_sig_fields
-      { $1, List.rev $2 }
+      { Csig.mk $1 (extra_csig 2 (List.rev $2)) }
 ;
 class_self_type:
     LPAREN core_type RPAREN
@@ -704,44 +1120,73 @@ class_self_type:
 ;
 class_sig_fields:
     /* empty */                                 { [] }
-  | class_sig_fields INHERIT class_signature    { Pctf_inher $3 :: $1 }
-  | class_sig_fields VAL value_type             { Pctf_val   $3 :: $1 }
-  | class_sig_fields virtual_method             { Pctf_virt  $2 :: $1 }
-  | class_sig_fields method_type                { Pctf_meth  $2 :: $1 }
-  | class_sig_fields CONSTRAINT constrain       { Pctf_cstr  $3 :: $1 }
+| class_sig_fields class_sig_field     { $2 :: (text_csig 2) @ $1 }
+;
+class_sig_field:
+    INHERIT class_signature post_item_attributes
+      { mkctf (Pctf_inherit $2) ~attrs:$3 ~docs:(symbol_docs ()) }
+  | VAL value_type post_item_attributes
+      { mkctf (Pctf_val $2) ~attrs:$3 ~docs:(symbol_docs ()) }
+  | METHOD private_virtual_flags label COLON poly_type post_item_attributes
+      {
+       let (p, v) = $2 in
+       mkctf (Pctf_method ($3, p, v, $5)) ~attrs:$6 ~docs:(symbol_docs ())
+      }
+  | CONSTRAINT constrain_field post_item_attributes
+      { mkctf (Pctf_constraint $2) ~attrs:$3 ~docs:(symbol_docs ()) }
+  | item_extension post_item_attributes
+      { mkctf (Pctf_extension $1) ~attrs:$2 ~docs:(symbol_docs ()) }
+  | floating_attribute
+      { mark_symbol_docs ();
+        mkctf(Pctf_attribute $1) }
 ;
 value_type:
-    mutable_flag label COLON core_type
-      { $2, $1, Some $4, symbol_rloc () }
-;
-method_type:
-    METHOD private_flag label COLON poly_type
-      { $3, $2, $5, symbol_rloc () }
+    VIRTUAL mutable_flag label COLON core_type
+      { $3, $2, Virtual, $5 }
+  | MUTABLE virtual_flag label COLON core_type
+      { $3, Mutable, $2, $5 }
+  | label COLON core_type
+      { $1, Immutable, Concrete, $3 }
 ;
 constrain:
-        core_type EQUAL core_type          { $1, $3, symbol_rloc () }
+        core_type EQUAL core_type          { $1, $3, symbol_rloc() }
+;
+constrain_field:
+        core_type EQUAL core_type          { $1, $3 }
 ;
 class_descriptions:
-    class_descriptions AND class_description    { $3 :: $1 }
-  | class_description                           { [$1] }
+    class_description                           { [$1] }
+  | class_descriptions and_class_description    { $2 :: $1 }
 ;
 class_description:
-    virtual_flag class_type_parameters LIDENT COLON class_type
-      { let params, variance = List.split (fst $2) in
-        {pci_virt = $1; pci_params = params, snd $2;
-         pci_name = $3; pci_expr = $5; pci_variance = variance;
-         pci_loc = symbol_rloc ()} }
+    CLASS virtual_flag class_type_parameters LIDENT COLON class_type
+    post_item_attributes
+      { Ci.mk (mkrhs $4 4) $6 ~virt:$2 ~params:$3 ~attrs:$7
+              ~loc:(symbol_rloc ()) ~docs:(symbol_docs ()) }
+;
+and_class_description:
+    AND virtual_flag class_type_parameters LIDENT COLON class_type
+    post_item_attributes
+      { Ci.mk (mkrhs $4 4) $6 ~virt:$2 ~params:$3
+              ~attrs:$7 ~loc:(symbol_rloc ())
+              ~text:(symbol_text ()) ~docs:(symbol_docs ()) }
 ;
 class_type_declarations:
-    class_type_declarations AND class_type_declaration  { $3 :: $1 }
-  | class_type_declaration                              { [$1] }
+    class_type_declaration                              { [$1] }
+  | class_type_declarations and_class_type_declaration  { $2 :: $1 }
 ;
 class_type_declaration:
-    virtual_flag class_type_parameters LIDENT EQUAL class_signature
-      { let params, variance = List.split (fst $2) in
-        {pci_virt = $1; pci_params = params, snd $2;
-         pci_name = $3; pci_expr = $5; pci_variance = variance;
-         pci_loc = symbol_rloc ()} }
+    CLASS TYPE virtual_flag class_type_parameters LIDENT EQUAL
+    class_signature post_item_attributes
+      { Ci.mk (mkrhs $5 5) $7 ~virt:$3 ~params:$4 ~attrs:$8
+              ~loc:(symbol_rloc ()) ~docs:(symbol_docs ()) }
+;
+and_class_type_declaration:
+    AND virtual_flag class_type_parameters LIDENT EQUAL
+    class_signature post_item_attributes
+      { Ci.mk (mkrhs $4 4) $6 ~virt:$2 ~params:$3
+         ~attrs:$7 ~loc:(symbol_rloc ())
+         ~text:(symbol_text ()) ~docs:(symbol_docs ()) }
 ;
 
 /* Core expressions */
@@ -753,24 +1198,25 @@ seq_expr:
 ;
 labeled_simple_pattern:
     QUESTION LPAREN label_let_pattern opt_default RPAREN
-      { ("?" ^ fst $3, $4, snd $3) }
+      { (Optional (fst $3), $4, snd $3) }
   | QUESTION label_var
-      { ("?" ^ fst $2, None, snd $2) }
+      { (Optional (fst $2), None, snd $2) }
   | OPTLABEL LPAREN let_pattern opt_default RPAREN
-      { ("?" ^ $1, $4, $3) }
+      { (Optional $1, $4, $3) }
   | OPTLABEL pattern_var
-      { ("?" ^ $1, None, $2) }
+      { (Optional $1, None, $2) }
   | TILDE LPAREN label_let_pattern RPAREN
-      { (fst $3, None, snd $3) }
+      { (Labelled (fst $3), None, snd $3) }
   | TILDE label_var
-      { (fst $2, None, snd $2) }
+      { (Labelled (fst $2), None, snd $2) }
   | LABEL simple_pattern
-      { ($1, None, $2) }
+      { (Labelled $1, None, $2) }
   | simple_pattern
-      { ("", None, $1) }
+      { (Nolabel, None, $1) }
 ;
 pattern_var:
-    LIDENT    { mkpat(Ppat_var $1) }
+    LIDENT            { mkpat(Ppat_var (mkrhs $1 1)) }
+  | UNDERSCORE        { mkpat Ppat_any }
 ;
 opt_default:
     /* empty */                         { None }
@@ -783,7 +1229,7 @@ label_let_pattern:
       { let (lab, pat) = $1 in (lab, mkpat(Ppat_constraint(pat, $3))) }
 ;
 label_var:
-    LIDENT    { ($1, mkpat(Ppat_var $1)) }
+    LIDENT    { ($1, mkpat(Ppat_var (mkrhs $1 1))) }
 ;
 let_pattern:
     pattern
@@ -796,38 +1242,44 @@ expr:
       { $1 }
   | simple_expr simple_labeled_expr_list
       { mkexp(Pexp_apply($1, List.rev $2)) }
-  | LET rec_flag let_bindings IN seq_expr
-      { mkexp(Pexp_let($2, List.rev $3, $5)) }
-  | LET MODULE UIDENT module_binding IN seq_expr
-      { mkexp(Pexp_letmodule($3, $4, $6)) }
-  | FUNCTION opt_bar match_cases
-      { mkexp(Pexp_function("", None, List.rev $3)) }
-  | FUN labeled_simple_pattern fun_def
-      { let (l,o,p) = $2 in mkexp(Pexp_function(l, o, [p, $3])) }
-  | MATCH seq_expr WITH opt_bar match_cases
-      { mkexp(Pexp_match($2, List.rev $5)) }
-  | TRY seq_expr WITH opt_bar match_cases
-      { mkexp(Pexp_try($2, List.rev $5)) }
-  | TRY seq_expr WITH error
+  | let_bindings IN seq_expr
+      { expr_of_let_bindings $1 $3 }
+  | LET MODULE ext_attributes UIDENT module_binding_body IN seq_expr
+      { mkexp_attrs (Pexp_letmodule(mkrhs $4 4, $5, $7)) $3 }
+  | LET OPEN override_flag ext_attributes mod_longident IN seq_expr
+      { mkexp_attrs (Pexp_open($3, mkrhs $5 5, $7)) $4 }
+  | FUNCTION ext_attributes opt_bar match_cases
+      { mkexp_attrs (Pexp_function(List.rev $4)) $2 }
+  | FUN ext_attributes labeled_simple_pattern fun_def
+      { let (l,o,p) = $3 in
+        mkexp_attrs (Pexp_fun(l, o, p, $4)) $2 }
+  | FUN ext_attributes LPAREN TYPE lident_list RPAREN fun_def
+      { mkexp_attrs (mk_newtypes $5 $7).pexp_desc $2 }
+  | MATCH ext_attributes seq_expr WITH opt_bar match_cases
+      { mkexp_attrs (Pexp_match($3, List.rev $6)) $2 }
+  | TRY ext_attributes seq_expr WITH opt_bar match_cases
+      { mkexp_attrs (Pexp_try($3, List.rev $6)) $2 }
+  | TRY ext_attributes seq_expr WITH error
       { syntax_error() }
   | expr_comma_list %prec below_COMMA
       { mkexp(Pexp_tuple(List.rev $1)) }
   | constr_longident simple_expr %prec below_SHARP
-      { mkexp(Pexp_construct($1, Some $2, false)) }
+      { mkexp(Pexp_construct(mkrhs $1 1, Some $2)) }
   | name_tag simple_expr %prec below_SHARP
       { mkexp(Pexp_variant($1, Some $2)) }
-  | IF seq_expr THEN expr ELSE expr
-      { mkexp(Pexp_ifthenelse($2, $4, Some $6)) }
-  | IF seq_expr THEN expr
-      { mkexp(Pexp_ifthenelse($2, $4, None)) }
-  | WHILE seq_expr DO seq_expr DONE
-      { mkexp(Pexp_while($2, $4)) }
-  | FOR val_ident EQUAL seq_expr direction_flag seq_expr DO seq_expr DONE
-      { mkexp(Pexp_for($2, $4, $6, $5, $8)) }
+  | IF ext_attributes seq_expr THEN expr ELSE expr
+      { mkexp_attrs(Pexp_ifthenelse($3, $5, Some $7)) $2 }
+  | IF ext_attributes seq_expr THEN expr
+      { mkexp_attrs (Pexp_ifthenelse($3, $5, None)) $2 }
+  | WHILE ext_attributes seq_expr DO seq_expr DONE
+      { mkexp_attrs (Pexp_while($3, $5)) $2 }
+  | FOR ext_attributes pattern EQUAL seq_expr direction_flag seq_expr DO
+    seq_expr DONE
+      { mkexp_attrs(Pexp_for($3, $5, $7, $6, $9)) $2 }
   | expr COLONCOLON expr
-      { mkexp(Pexp_construct(Lident "::",
-                             Some(ghexp(Pexp_tuple[$1;$3])),
-                             false)) }
+      { mkexp_cons (rhs_loc 2) (ghexp(Pexp_tuple[$1;$3])) (symbol_rloc()) }
+  | LPAREN COLONCOLON RPAREN LPAREN expr COMMA expr RPAREN
+      { mkexp_cons (rhs_loc 2) (ghexp(Pexp_tuple[$5;$7])) (symbol_rloc()) }
   | expr INFIXOP0 expr
       { mkinfix $1 $2 $3 }
   | expr INFIXOP1 expr
@@ -840,12 +1292,18 @@ expr:
       { mkinfix $1 $2 $3 }
   | expr PLUS expr
       { mkinfix $1 "+" $3 }
+  | expr PLUSDOT expr
+      { mkinfix $1 "+." $3 }
+  | expr PLUSEQ expr
+      { mkinfix $1 "+=" $3 }
   | expr MINUS expr
       { mkinfix $1 "-" $3 }
   | expr MINUSDOT expr
       { mkinfix $1 "-." $3 }
   | expr STAR expr
       { mkinfix $1 "*" $3 }
+  | expr PERCENT expr
+      { mkinfix $1 "%" $3 }
   | expr EQUAL expr
       { mkinfix $1 "=" $3 }
   | expr LESS expr
@@ -864,58 +1322,70 @@ expr:
       { mkinfix $1 ":=" $3 }
   | subtractive expr %prec prec_unary_minus
       { mkuminus $1 $2 }
+  | additive expr %prec prec_unary_plus
+      { mkuplus $1 $2 }
   | simple_expr DOT label_longident LESSMINUS expr
-      { mkexp(Pexp_setfield($1, $3, $5)) }
+      { mkexp(Pexp_setfield($1, mkrhs $3 3, $5)) }
   | simple_expr DOT LPAREN seq_expr RPAREN LESSMINUS expr
-      { mkexp(Pexp_apply(ghexp(Pexp_ident(array_function "Array" "set")),
-                         ["",$1; "",$4; "",$7])) }
+      { mkexp(Pexp_apply(ghexp(Pexp_ident(array_function ".()" true)),
+                         [Nolabel,$1; Nolabel,$4; Nolabel,$7])) }
   | simple_expr DOT LBRACKET seq_expr RBRACKET LESSMINUS expr
-      { mkexp(Pexp_apply(ghexp(Pexp_ident(array_function "String" "set")),
-                         ["",$1; "",$4; "",$7])) }
+      { mkexp(Pexp_apply(ghexp(Pexp_ident(array_function ".[]" true)),
+                         [Nolabel,$1; Nolabel,$4; Nolabel,$7])) }
   | simple_expr DOT LBRACE expr RBRACE LESSMINUS expr
       { bigarray_set $1 $4 $7 }
   | label LESSMINUS expr
-      { mkexp(Pexp_setinstvar($1, $3)) }
-  | ASSERT simple_expr %prec below_SHARP
-      { mkassert $2 }
-  | LAZY simple_expr %prec below_SHARP
-      { mkexp (Pexp_lazy ($2)) }
-  | OBJECT class_structure END
-      { mkexp (Pexp_object($2)) }
-  | OBJECT class_structure error
-      { unclosed "object" 1 "end" 3 }
+      { mkexp(Pexp_setinstvar(mkrhs $1 1, $3)) }
+  | ASSERT ext_attributes simple_expr %prec below_SHARP
+      { mkexp_attrs (Pexp_assert $3) $2 }
+  | LAZY ext_attributes simple_expr %prec below_SHARP
+      { mkexp_attrs (Pexp_lazy $3) $2 }
+  | OBJECT ext_attributes class_structure END
+      { mkexp_attrs (Pexp_object $3) $2 }
+  | OBJECT ext_attributes class_structure error
+      { unclosed "object" 1 "end" 4 }
+  | expr attribute
+      { Exp.attr $1 $2 }
 ;
 simple_expr:
     val_longident
-      { mkexp(Pexp_ident $1) }
+      { mkexp(Pexp_ident (mkrhs $1 1)) }
   | constant
       { mkexp(Pexp_constant $1) }
   | constr_longident %prec prec_constant_constructor
-      { mkexp(Pexp_construct($1, None, false)) }
+      { mkexp(Pexp_construct(mkrhs $1 1, None)) }
   | name_tag %prec prec_constant_constructor
       { mkexp(Pexp_variant($1, None)) }
   | LPAREN seq_expr RPAREN
       { reloc_exp $2 }
   | LPAREN seq_expr error
       { unclosed "(" 1 ")" 3 }
-  | BEGIN seq_expr END
-      { reloc_exp $2 }
-  | BEGIN END
-      { mkexp (Pexp_construct (Lident "()", None, false)) }
-  | BEGIN seq_expr error
+  | BEGIN ext_attributes seq_expr END
+      { wrap_exp_attrs (reloc_exp $3) $2 (* check location *) }
+  | BEGIN ext_attributes END
+      { mkexp_attrs (Pexp_construct (mkloc (Lident "()") (symbol_rloc ()),
+                               None)) $2 }
+  | BEGIN ext_attributes seq_expr error
       { unclosed "begin" 1 "end" 3 }
   | LPAREN seq_expr type_constraint RPAREN
-      { let (t, t') = $3 in mkexp(Pexp_constraint($2, t, t')) }
+      { mkexp_constraint $2 $3 }
   | simple_expr DOT label_longident
-      { mkexp(Pexp_field($1, $3)) }
+      { mkexp(Pexp_field($1, mkrhs $3 3)) }
+  | mod_longident DOT LPAREN seq_expr RPAREN
+      { mkexp(Pexp_open(Fresh, mkrhs $1 1, $4)) }
+  | mod_longident DOT LPAREN RPAREN
+      { mkexp(Pexp_open(Fresh, mkrhs $1 1,
+                        mkexp(Pexp_construct(mkrhs (Lident "()") 1, None)))) }
+  | mod_longident DOT LPAREN seq_expr error
+      { unclosed "(" 3 ")" 5 }
   | simple_expr DOT LPAREN seq_expr RPAREN
-      { mkexp(Pexp_apply(ghexp(Pexp_ident(array_function "Array" "get")),
-                         ["",$1; "",$4])) }
+      { mkexp(Pexp_apply(ghexp(Pexp_ident(array_function ".()" false)),
+                         [Nolabel,$1; Nolabel,$4])) }
   | simple_expr DOT LPAREN seq_expr error
       { unclosed "(" 3 ")" 5 }
   | simple_expr DOT LBRACKET seq_expr RBRACKET
-      { mkexp(Pexp_apply(ghexp(Pexp_ident(array_function "String" "get")),
-                         ["",$1; "",$4])) }
+      { mkexp(Pexp_apply(ghexp(Pexp_ident(array_function ".[]" false)),
+                         [Nolabel,$1; Nolabel,$4])) }
   | simple_expr DOT LBRACKET seq_expr error
       { unclosed "[" 3 "]" 5 }
   | simple_expr DOT LBRACE expr RBRACE
@@ -923,31 +1393,76 @@ simple_expr:
   | simple_expr DOT LBRACE expr_comma_list error
       { unclosed "{" 3 "}" 5 }
   | LBRACE record_expr RBRACE
-      { let (exten, fields) = $2 in mkexp(Pexp_record(fields, exten)) }
+      { let (exten, fields) = $2 in mkexp (Pexp_record(fields, exten)) }
   | LBRACE record_expr error
       { unclosed "{" 1 "}" 3 }
+  | mod_longident DOT LBRACE record_expr RBRACE
+      { let (exten, fields) = $4 in
+        let rec_exp = mkexp(Pexp_record(fields, exten)) in
+        mkexp(Pexp_open(Fresh, mkrhs $1 1, rec_exp)) }
+  | mod_longident DOT LBRACE record_expr error
+      { unclosed "{" 3 "}" 5 }
   | LBRACKETBAR expr_semi_list opt_semi BARRBRACKET
-      { mkexp(Pexp_array(List.rev $2)) }
+      { mkexp (Pexp_array(List.rev $2)) }
   | LBRACKETBAR expr_semi_list opt_semi error
       { unclosed "[|" 1 "|]" 4 }
   | LBRACKETBAR BARRBRACKET
-      { mkexp(Pexp_array []) }
+      { mkexp (Pexp_array []) }
+  | mod_longident DOT LBRACKETBAR expr_semi_list opt_semi BARRBRACKET
+      { mkexp(Pexp_open(Fresh, mkrhs $1 1, mkexp(Pexp_array(List.rev $4)))) }
+  | mod_longident DOT LBRACKETBAR BARRBRACKET
+      { mkexp(Pexp_open(Fresh, mkrhs $1 1, mkexp(Pexp_array []))) }
+  | mod_longident DOT LBRACKETBAR expr_semi_list opt_semi error
+      { unclosed "[|" 3 "|]" 6 }
   | LBRACKET expr_semi_list opt_semi RBRACKET
-      { reloc_exp (mktailexp (List.rev $2)) }
+      { reloc_exp (mktailexp (rhs_loc 4) (List.rev $2)) }
   | LBRACKET expr_semi_list opt_semi error
       { unclosed "[" 1 "]" 4 }
+  | mod_longident DOT LBRACKET expr_semi_list opt_semi RBRACKET
+      { let list_exp = reloc_exp (mktailexp (rhs_loc 6) (List.rev $4)) in
+        mkexp(Pexp_open(Fresh, mkrhs $1 1, list_exp)) }
+  | mod_longident DOT LBRACKET RBRACKET
+      { mkexp(Pexp_open(Fresh, mkrhs $1 1,
+                        mkexp(Pexp_construct(mkrhs (Lident "[]") 1, None)))) }
+  | mod_longident DOT LBRACKET expr_semi_list opt_semi error
+      { unclosed "[" 3 "]" 6 }
   | PREFIXOP simple_expr
-      { mkexp(Pexp_apply(mkoperator $1 1, ["",$2])) }
-  | NEW class_longident
-      { mkexp(Pexp_new($2)) }
-  | LBRACELESS field_expr_list opt_semi GREATERRBRACE
-      { mkexp(Pexp_override(List.rev $2)) }
-  | LBRACELESS field_expr_list opt_semi error
+      { mkexp(Pexp_apply(mkoperator $1 1, [Nolabel,$2])) }
+  | BANG simple_expr
+      { mkexp(Pexp_apply(mkoperator "!" 1, [Nolabel,$2])) }
+  | NEW ext_attributes class_longident
+      { mkexp_attrs (Pexp_new(mkrhs $3 3)) $2 }
+  | LBRACELESS field_expr_list GREATERRBRACE
+      { mkexp (Pexp_override $2) }
+  | LBRACELESS field_expr_list error
       { unclosed "{<" 1 ">}" 4 }
   | LBRACELESS GREATERRBRACE
-      { mkexp(Pexp_override []) }
+      { mkexp (Pexp_override [])}
+  | mod_longident DOT LBRACELESS field_expr_list GREATERRBRACE
+      { mkexp(Pexp_open(Fresh, mkrhs $1 1, mkexp (Pexp_override $4)))}
+  | mod_longident DOT LBRACELESS GREATERRBRACE
+      { mkexp(Pexp_open(Fresh, mkrhs $1 1, mkexp (Pexp_override [])))}
+  | mod_longident DOT LBRACELESS field_expr_list error
+      { unclosed "{<" 3 ">}" 6 }
   | simple_expr SHARP label
       { mkexp(Pexp_send($1, $3)) }
+  | simple_expr SHARPOP simple_expr
+      { mkinfix $1 $2 $3 }
+  | LPAREN MODULE module_expr RPAREN
+      { mkexp (Pexp_pack $3) }
+  | LPAREN MODULE module_expr COLON package_type RPAREN
+      { mkexp (Pexp_constraint (ghexp (Pexp_pack $3),
+                                ghtyp (Ptyp_package $5))) }
+  | LPAREN MODULE module_expr COLON error
+      { unclosed "(" 1 ")" 5 }
+  | mod_longident DOT LPAREN MODULE module_expr COLON package_type RPAREN
+      { mkexp(Pexp_open(Fresh, mkrhs $1 1,
+        mkexp (Pexp_constraint (ghexp (Pexp_pack $5),
+                                ghtyp (Ptyp_package $7))))) }
+  | mod_longident DOT LPAREN MODULE module_expr COLON error
+      { unclosed "(" 3 ")" 7 }
+  | extension
+      { mkexp (Pexp_extension $1) }
 ;
 simple_labeled_expr_list:
     labeled_simple_expr
@@ -957,77 +1472,117 @@ simple_labeled_expr_list:
 ;
 labeled_simple_expr:
     simple_expr %prec below_SHARP
-      { ("", $1) }
+      { (Nolabel, $1) }
   | label_expr
       { $1 }
 ;
 label_expr:
     LABEL simple_expr %prec below_SHARP
-      { ($1, $2) }
+      { (Labelled $1, $2) }
   | TILDE label_ident
-      { $2 }
+      { (Labelled (fst $2), snd $2) }
   | QUESTION label_ident
-      { ("?" ^ fst $2, snd $2) }
+      { (Optional (fst $2), snd $2) }
   | OPTLABEL simple_expr %prec below_SHARP
-      { ("?" ^ $1, $2) }
+      { (Optional $1, $2) }
 ;
 label_ident:
-    LIDENT   { ($1, mkexp(Pexp_ident(Lident $1))) }
+    LIDENT   { ($1, mkexp(Pexp_ident(mkrhs (Lident $1) 1))) }
 ;
-let_bindings:
-    let_binding                                 { [$1] }
-  | let_bindings AND let_binding                { $3 :: $1 }
+lident_list:
+    LIDENT                            { [$1] }
+  | LIDENT lident_list                { $1 :: $2 }
 ;
-let_binding:
+let_binding_body:
     val_ident fun_binding
-      { ({ppat_desc = Ppat_var $1; ppat_loc = rhs_loc 1}, $2) }
+      { (mkpatvar $1 1, $2) }
+  | val_ident COLON typevar_list DOT core_type EQUAL seq_expr
+      { (ghpat(Ppat_constraint(mkpatvar $1 1,
+                               ghtyp(Ptyp_poly(List.rev $3,$5)))),
+         $7) }
+  | val_ident COLON TYPE lident_list DOT core_type EQUAL seq_expr
+      { let exp, poly = wrap_type_annotation $4 $6 $8 in
+        (ghpat(Ppat_constraint(mkpatvar $1 1, poly)), exp) }
   | pattern EQUAL seq_expr
       { ($1, $3) }
+  | simple_pattern_not_ident COLON core_type EQUAL seq_expr
+      { (ghpat(Ppat_constraint($1, $3)), $5) }
+;
+let_bindings:
+    let_binding                                 { $1 }
+  | let_bindings and_let_binding                { addlb $1 $2 }
+;
+let_binding:
+    LET ext_attributes rec_flag let_binding_body post_item_attributes
+      { mklbs $2 $3 (mklb $4 $5) }
+;
+and_let_binding:
+    AND let_binding_body post_item_attributes
+      { mklb $2 $3 }
 ;
 fun_binding:
     strict_binding
       { $1 }
   | type_constraint EQUAL seq_expr
-      { let (t, t') = $1 in ghexp(Pexp_constraint($3, t, t')) }
+      { mkexp_constraint $3 $1 }
 ;
 strict_binding:
     EQUAL seq_expr
       { $2 }
   | labeled_simple_pattern fun_binding
-      { let (l, o, p) = $1 in ghexp(Pexp_function(l, o, [p, $2])) }
+      { let (l, o, p) = $1 in ghexp(Pexp_fun(l, o, p, $2)) }
+  | LPAREN TYPE lident_list RPAREN fun_binding
+      { mk_newtypes $3 $5 }
 ;
 match_cases:
-    pattern match_action                        { [$1, $2] }
-  | match_cases BAR pattern match_action        { ($3, $4) :: $1 }
+    match_case { [$1] }
+  | match_cases BAR match_case { $3 :: $1 }
 ;
-fun_def:
-    match_action                                { $1 }
-  | labeled_simple_pattern fun_def
-      { let (l,o,p) = $1 in ghexp(Pexp_function(l, o, [p, $2])) }
+match_case:
+    pattern MINUSGREATER seq_expr
+      { Exp.case $1 $3 }
+  | pattern WHEN seq_expr MINUSGREATER seq_expr
+      { Exp.case $1 ~guard:$3 $5 }
 ;
-match_action:
+fun_def:
     MINUSGREATER seq_expr                       { $2 }
-  | WHEN seq_expr MINUSGREATER seq_expr         { mkexp(Pexp_when($2, $4)) }
+/* Cf #5939: we used to accept (fun p when e0 -> e) */
+  | labeled_simple_pattern fun_def
+      {
+       let (l,o,p) = $1 in
+       ghexp(Pexp_fun(l, o, p, $2))
+      }
+  | LPAREN TYPE lident_list RPAREN fun_def
+      { mk_newtypes $3 $5 }
 ;
 expr_comma_list:
     expr_comma_list COMMA expr                  { $3 :: $1 }
   | expr COMMA expr                             { [$3; $1] }
 ;
 record_expr:
-    simple_expr WITH lbl_expr_list opt_semi     { (Some $1, List.rev $3) }
-  | lbl_expr_list opt_semi                      { (None, List.rev $1) }
+    simple_expr WITH lbl_expr_list              { (Some $1, $3) }
+  | lbl_expr_list                               { (None, $1) }
 ;
 lbl_expr_list:
+     lbl_expr { [$1] }
+  |  lbl_expr SEMI lbl_expr_list { $1 :: $3 }
+  |  lbl_expr SEMI { [$1] }
+;
+lbl_expr:
     label_longident EQUAL expr
-      { [$1,$3] }
-  | lbl_expr_list SEMI label_longident EQUAL expr
-      { ($3, $5) :: $1 }
+      { (mkrhs $1 1,$3) }
+  | label_longident
+      { (mkrhs $1 1, exp_of_label $1 1) }
 ;
 field_expr_list:
+    field_expr opt_semi { [$1] }
+  | field_expr SEMI field_expr_list { $1 :: $3 }
+;
+field_expr:
     label EQUAL expr
-      { [$1,$3] }
-  | field_expr_list SEMI label EQUAL expr
-      { ($3, $5) :: $1 }
+      { (mkrhs $1 1, $3) }
+  | label
+      { (mkrhs $1 1, exp_of_label (Lident $1) 1) }
 ;
 expr_semi_list:
     expr                                        { [$1] }
@@ -1047,40 +1602,58 @@ pattern:
     simple_pattern
       { $1 }
   | pattern AS val_ident
-      { mkpat(Ppat_alias($1, $3)) }
+      { mkpat(Ppat_alias($1, mkrhs $3 3)) }
+  | pattern AS error
+      { expecting 3 "identifier" }
   | pattern_comma_list  %prec below_COMMA
       { mkpat(Ppat_tuple(List.rev $1)) }
   | constr_longident pattern %prec prec_constr_appl
-      { mkpat(Ppat_construct($1, Some $2, false)) }
+      { mkpat(Ppat_construct(mkrhs $1 1, Some $2)) }
   | name_tag pattern %prec prec_constr_appl
       { mkpat(Ppat_variant($1, Some $2)) }
   | pattern COLONCOLON pattern
-      { mkpat(Ppat_construct(Lident "::", Some(ghpat(Ppat_tuple[$1;$3])),
-                             false)) }
+      { mkpat_cons (rhs_loc 2) (ghpat(Ppat_tuple[$1;$3])) (symbol_rloc()) }
+  | pattern COLONCOLON error
+      { expecting 3 "pattern" }
+  | LPAREN COLONCOLON RPAREN LPAREN pattern COMMA pattern RPAREN
+      { mkpat_cons (rhs_loc 2) (ghpat(Ppat_tuple[$5;$7])) (symbol_rloc()) }
+  | LPAREN COLONCOLON RPAREN LPAREN pattern COMMA pattern error
+      { unclosed "(" 4 ")" 8 }
   | pattern BAR pattern
       { mkpat(Ppat_or($1, $3)) }
+  | pattern BAR error
+      { expecting 3 "pattern" }
+  | LAZY simple_pattern
+      { mkpat(Ppat_lazy $2) }
+  | EXCEPTION pattern %prec prec_constr_appl
+      { mkpat(Ppat_exception $2) }
+  | pattern attribute
+      { Pat.attr $1 $2 }
 ;
 simple_pattern:
     val_ident %prec below_EQUAL
-      { mkpat(Ppat_var $1) }
+      { mkpat(Ppat_var (mkrhs $1 1)) }
+  | simple_pattern_not_ident { $1 }
+;
+simple_pattern_not_ident:
   | UNDERSCORE
       { mkpat(Ppat_any) }
   | signed_constant
       { mkpat(Ppat_constant $1) }
-  | CHAR DOTDOT CHAR
-      { mkrangepat $1 $3 }
+  | signed_constant DOTDOT signed_constant
+      { mkpat(Ppat_interval ($1, $3)) }
   | constr_longident
-      { mkpat(Ppat_construct($1, None, false)) }
+      { mkpat(Ppat_construct(mkrhs $1 1, None)) }
   | name_tag
       { mkpat(Ppat_variant($1, None)) }
   | SHARP type_longident
-      { mkpat(Ppat_type $2) }
-  | LBRACE lbl_pattern_list opt_semi RBRACE
-      { mkpat(Ppat_record(List.rev $2)) }
-  | LBRACE lbl_pattern_list opt_semi error
-      { unclosed "{" 1 "}" 4 }
+      { mkpat(Ppat_type (mkrhs $2 2)) }
+  | LBRACE lbl_pattern_list RBRACE
+      { let (fields, closed) = $2 in mkpat(Ppat_record(fields, closed)) }
+  | LBRACE lbl_pattern_list error
+      { unclosed "{" 1 "}" 3 }
   | LBRACKET pattern_semi_list opt_semi RBRACKET
-      { reloc_pat (mktailpat (List.rev $2)) }
+      { reloc_pat (mktailpat (rhs_loc 4) (List.rev $2)) }
   | LBRACKET pattern_semi_list opt_semi error
       { unclosed "[" 1 "]" 4 }
   | LBRACKETBAR pattern_semi_list opt_semi BARRBRACKET
@@ -1097,45 +1670,90 @@ simple_pattern:
       { mkpat(Ppat_constraint($2, $4)) }
   | LPAREN pattern COLON core_type error
       { unclosed "(" 1 ")" 5 }
+  | LPAREN pattern COLON error
+      { expecting 4 "type" }
+  | LPAREN MODULE UIDENT RPAREN
+      { mkpat(Ppat_unpack (mkrhs $3 3)) }
+  | LPAREN MODULE UIDENT COLON package_type RPAREN
+      { mkpat(Ppat_constraint(mkpat(Ppat_unpack (mkrhs $3 3)),
+                              ghtyp(Ptyp_package $5))) }
+  | LPAREN MODULE UIDENT COLON package_type error
+      { unclosed "(" 1 ")" 6 }
+  | extension
+      { mkpat(Ppat_extension $1) }
 ;
 
 pattern_comma_list:
     pattern_comma_list COMMA pattern            { $3 :: $1 }
   | pattern COMMA pattern                       { [$3; $1] }
+  | pattern COMMA error                         { expecting 3 "pattern" }
 ;
 pattern_semi_list:
     pattern                                     { [$1] }
   | pattern_semi_list SEMI pattern              { $3 :: $1 }
 ;
 lbl_pattern_list:
-    label_longident EQUAL pattern               { [($1, $3)] }
-  | lbl_pattern_list SEMI label_longident EQUAL pattern { ($3, $5) :: $1 }
+    lbl_pattern { [$1], Closed }
+  | lbl_pattern SEMI { [$1], Closed }
+  | lbl_pattern SEMI UNDERSCORE opt_semi { [$1], Open }
+  | lbl_pattern SEMI lbl_pattern_list
+      { let (fields, closed) = $3 in $1 :: fields, closed }
+;
+lbl_pattern:
+    label_longident EQUAL pattern
+      { (mkrhs $1 1,$3) }
+  | label_longident
+      { (mkrhs $1 1, pat_of_label $1 1) }
+;
+
+/* Value descriptions */
+
+value_description:
+    VAL val_ident COLON core_type post_item_attributes
+      { Val.mk (mkrhs $2 2) $4 ~attrs:$5
+               ~loc:(symbol_rloc()) ~docs:(symbol_docs ()) }
 ;
 
 /* Primitive declarations */
 
+primitive_declaration_body:
+    STRING                                      { [fst $1] }
+  | STRING primitive_declaration_body           { fst $1 :: $2 }
+;
 primitive_declaration:
-    STRING                                      { [$1] }
-  | STRING primitive_declaration                { $1 :: $2 }
+    EXTERNAL val_ident COLON core_type EQUAL primitive_declaration_body
+    post_item_attributes
+      { Val.mk (mkrhs $2 2) $4 ~prim:$6 ~attrs:$7
+               ~loc:(symbol_rloc ()) ~docs:(symbol_docs ()) }
 ;
 
 /* Type declarations */
 
 type_declarations:
-    type_declaration                            { [$1] }
-  | type_declarations AND type_declaration      { $3 :: $1 }
+    type_declaration
+      { let (nonrec_flag, ty) = $1 in (nonrec_flag, [ty]) }
+  | type_declarations and_type_declaration
+      { let (nonrec_flag, tys) = $1 in (nonrec_flag, $2 :: tys) }
 ;
 
 type_declaration:
-    type_parameters LIDENT type_kind constraints
-      { let (params, variance) = List.split $1 in
-        let (kind, manifest) = $3 in
-        ($2, {ptype_params = params;
-              ptype_cstrs = List.rev $4;
-              ptype_kind = kind;
-              ptype_manifest = manifest;
-              ptype_variance = variance;
-              ptype_loc = symbol_rloc()}) }
+    TYPE nonrec_flag optional_type_parameters LIDENT type_kind constraints
+    post_item_attributes
+      { let (kind, priv, manifest) = $5 in
+        let ty =
+          Type.mk (mkrhs $4 4) ~params:$3 ~cstrs:(List.rev $6) ~kind
+            ~priv ?manifest ~attrs:$7
+            ~loc:(symbol_rloc ()) ~docs:(symbol_docs ())
+        in
+          ($2, ty) }
+;
+and_type_declaration:
+    AND optional_type_parameters LIDENT type_kind constraints
+    post_item_attributes
+      { let (kind, priv, manifest) = $4 in
+          Type.mk (mkrhs $3 3) ~params:$2 ~cstrs:(List.rev $5)
+            ~kind ~priv ?manifest ~attrs:$6 ~loc:(symbol_rloc ())
+            ~text:(symbol_text ()) ~docs:(symbol_docs ()) }
 ;
 constraints:
         constraints CONSTRAINT constrain        { $3 :: $1 }
@@ -1143,56 +1761,190 @@ constraints:
 ;
 type_kind:
     /*empty*/
-      { (Ptype_abstract, None) }
+      { (Ptype_abstract, Public, None) }
   | EQUAL core_type
-      { (Ptype_abstract, Some $2) }
+      { (Ptype_abstract, Public, Some $2) }
+  | EQUAL PRIVATE core_type
+      { (Ptype_abstract, Private, Some $3) }
   | EQUAL constructor_declarations
-      { (Ptype_variant(List.rev $2, Public), None) }
+      { (Ptype_variant(List.rev $2), Public, None) }
   | EQUAL PRIVATE constructor_declarations
-      { (Ptype_variant(List.rev $3, Private), None) }
-  | EQUAL private_flag BAR constructor_declarations
-      { (Ptype_variant(List.rev $4, $2), None) }
-  | EQUAL private_flag LBRACE label_declarations opt_semi RBRACE
-      { (Ptype_record(List.rev $4, $2), None) }
-  | EQUAL core_type EQUAL private_flag opt_bar constructor_declarations
-      { (Ptype_variant(List.rev $6, $4), Some $2) }
-  | EQUAL core_type EQUAL private_flag LBRACE label_declarations opt_semi RBRACE
-      { (Ptype_record(List.rev $6, $4), Some $2) }
+      { (Ptype_variant(List.rev $3), Private, None) }
+  | EQUAL DOTDOT
+      { (Ptype_open, Public, None) }
+  | EQUAL private_flag LBRACE label_declarations RBRACE
+      { (Ptype_record $4, $2, None) }
+  | EQUAL core_type EQUAL private_flag constructor_declarations
+      { (Ptype_variant(List.rev $5), $4, Some $2) }
+  | EQUAL core_type EQUAL DOTDOT
+      { (Ptype_open, Public, Some $2) }
+  | EQUAL core_type EQUAL private_flag LBRACE label_declarations RBRACE
+      { (Ptype_record $6, $4, Some $2) }
+;
+optional_type_parameters:
+    /*empty*/                                   { [] }
+  | optional_type_parameter                     { [$1] }
+  | LPAREN optional_type_parameter_list RPAREN  { List.rev $2 }
+;
+optional_type_parameter:
+    type_variance optional_type_variable        { $2, $1 }
+;
+optional_type_parameter_list:
+    optional_type_parameter                              { [$1] }
+  | optional_type_parameter_list COMMA optional_type_parameter    { $3 :: $1 }
+;
+optional_type_variable:
+    QUOTE ident                                 { mktyp(Ptyp_var $2) }
+  | UNDERSCORE                                  { mktyp(Ptyp_any) }
 ;
+
+
 type_parameters:
     /*empty*/                                   { [] }
   | type_parameter                              { [$1] }
   | LPAREN type_parameter_list RPAREN           { List.rev $2 }
 ;
 type_parameter:
-    type_variance QUOTE ident                   { $3, $1 }
+    type_variance type_variable                   { $2, $1 }
 ;
 type_variance:
-    /* empty */                                 { false, false }
-  | PLUS                                        { true, false }
-  | MINUS                                       { false, true }
+    /* empty */                                 { Invariant }
+  | PLUS                                        { Covariant }
+  | MINUS                                       { Contravariant }
+;
+type_variable:
+    QUOTE ident                                 { mktyp(Ptyp_var $2) }
 ;
 type_parameter_list:
     type_parameter                              { [$1] }
   | type_parameter_list COMMA type_parameter    { $3 :: $1 }
 ;
 constructor_declarations:
-    constructor_declaration                     { [$1] }
-  | constructor_declarations BAR constructor_declaration { $3 :: $1 }
+    constructor_declaration                              { [$1] }
+  | bar_constructor_declaration                          { [$1] }
+  | constructor_declarations bar_constructor_declaration { $2 :: $1 }
 ;
 constructor_declaration:
-    constr_ident constructor_arguments          { ($1, $2, symbol_rloc()) }
+  | constr_ident generalized_constructor_arguments attributes
+      {
+       let args,res = $2 in
+       Type.constructor (mkrhs $1 1) ~args ?res ~attrs:$3
+         ~loc:(symbol_rloc()) ~info:(symbol_info ())
+      }
+;
+bar_constructor_declaration:
+  | BAR constr_ident generalized_constructor_arguments attributes
+      {
+       let args,res = $3 in
+       Type.constructor (mkrhs $2 2) ~args ?res ~attrs:$4
+         ~loc:(symbol_rloc()) ~info:(symbol_info ())
+      }
+;
+str_exception_declaration:
+  | sig_exception_declaration                    { $1 }
+  | EXCEPTION constr_ident EQUAL constr_longident attributes
+    post_item_attributes
+      { Te.rebind (mkrhs $2 2) (mkrhs $4 4) ~attrs:($5 @ $6)
+          ~loc:(symbol_rloc()) ~docs:(symbol_docs ()) }
+;
+sig_exception_declaration:
+  | EXCEPTION constr_ident generalized_constructor_arguments attributes
+    post_item_attributes
+      { let args, res = $3 in
+          Te.decl (mkrhs $2 2) ~args ?res ~attrs:($4 @ $5)
+            ~loc:(symbol_rloc()) ~docs:(symbol_docs ()) }
+;
+generalized_constructor_arguments:
+    /*empty*/                     { (Pcstr_tuple [],None) }
+  | OF constructor_arguments      { ($2,None) }
+  | COLON constructor_arguments MINUSGREATER simple_core_type
+                                  { ($2,Some $4) }
+  | COLON simple_core_type
+                                  { (Pcstr_tuple [],Some $2) }
 ;
+
 constructor_arguments:
-    /*empty*/                                   { [] }
-  | OF core_type_list                           { List.rev $2 }
+  | core_type_list                   { Pcstr_tuple (List.rev $1) }
+  | LBRACE label_declarations RBRACE { Pcstr_record $2 }
 ;
 label_declarations:
     label_declaration                           { [$1] }
-  | label_declarations SEMI label_declaration   { $3 :: $1 }
+  | label_declaration_semi                      { [$1] }
+  | label_declaration_semi label_declarations   { $1 :: $2 }
 ;
 label_declaration:
-    mutable_flag label COLON poly_type          { ($2, $1, $4, symbol_rloc()) }
+    mutable_flag label COLON poly_type_no_attr attributes
+      {
+       Type.field (mkrhs $2 2) $4 ~mut:$1 ~attrs:$5
+         ~loc:(symbol_rloc()) ~info:(symbol_info ())
+      }
+;
+label_declaration_semi:
+    mutable_flag label COLON poly_type_no_attr attributes SEMI attributes
+      {
+       let info =
+         match rhs_info 5 with
+         | Some _ as info_before_semi -> info_before_semi
+         | None -> symbol_info ()
+       in
+       Type.field (mkrhs $2 2) $4 ~mut:$1 ~attrs:($5 @ $7)
+         ~loc:(symbol_rloc()) ~info
+      }
+;
+
+/* Type Extensions */
+
+str_type_extension:
+  TYPE nonrec_flag optional_type_parameters type_longident
+  PLUSEQ private_flag str_extension_constructors post_item_attributes
+      { if $2 <> Recursive then not_expecting 2 "nonrec flag";
+        Te.mk (mkrhs $4 4) (List.rev $7) ~params:$3 ~priv:$6
+          ~attrs:$8 ~docs:(symbol_docs ()) }
+;
+sig_type_extension:
+  TYPE nonrec_flag optional_type_parameters type_longident
+  PLUSEQ private_flag sig_extension_constructors post_item_attributes
+      { if $2 <> Recursive then not_expecting 2 "nonrec flag";
+        Te.mk (mkrhs $4 4) (List.rev $7) ~params:$3 ~priv:$6
+          ~attrs:$8 ~docs:(symbol_docs ()) }
+;
+str_extension_constructors:
+    extension_constructor_declaration                     { [$1] }
+  | bar_extension_constructor_declaration                 { [$1] }
+  | extension_constructor_rebind                          { [$1] }
+  | bar_extension_constructor_rebind                      { [$1] }
+  | str_extension_constructors bar_extension_constructor_declaration
+      { $2 :: $1 }
+  | str_extension_constructors bar_extension_constructor_rebind
+      { $2 :: $1 }
+;
+sig_extension_constructors:
+    extension_constructor_declaration                     { [$1] }
+  | bar_extension_constructor_declaration                 { [$1] }
+  | sig_extension_constructors bar_extension_constructor_declaration
+      { $2 :: $1 }
+;
+extension_constructor_declaration:
+  | constr_ident generalized_constructor_arguments attributes
+      { let args, res = $2 in
+        Te.decl (mkrhs $1 1) ~args ?res ~attrs:$3
+          ~loc:(symbol_rloc()) ~info:(symbol_info ()) }
+;
+bar_extension_constructor_declaration:
+  | BAR constr_ident generalized_constructor_arguments attributes
+      { let args, res = $3 in
+        Te.decl (mkrhs $2 2) ~args ?res ~attrs:$4
+           ~loc:(symbol_rloc()) ~info:(symbol_info ()) }
+;
+extension_constructor_rebind:
+  | constr_ident EQUAL constr_longident attributes
+      { Te.rebind (mkrhs $1 1) (mkrhs $3 3) ~attrs:$4
+          ~loc:(symbol_rloc()) ~info:(symbol_info ()) }
+;
+bar_extension_constructor_rebind:
+  | BAR constr_ident EQUAL constr_longident attributes
+      { Te.rebind (mkrhs $2 2) (mkrhs $4 4) ~attrs:$5
+          ~loc:(symbol_rloc()) ~info:(symbol_info ()) }
 ;
 
 /* "with" constraints (additional type equations over signature components) */
@@ -1202,18 +1954,32 @@ with_constraints:
   | with_constraints AND with_constraint        { $3 :: $1 }
 ;
 with_constraint:
-    TYPE type_parameters label_longident EQUAL core_type constraints
-      { let params, variance = List.split $2 in
-        ($3, Pwith_type {ptype_params = params;
-                         ptype_cstrs = List.rev $6;
-                         ptype_kind = Ptype_abstract;
-                         ptype_manifest = Some $5;
-                         ptype_variance = variance;
-                         ptype_loc = symbol_rloc()}) }
+    TYPE type_parameters label_longident with_type_binder core_type_no_attr
+    constraints
+      { Pwith_type
+          (mkrhs $3 3,
+           (Type.mk (mkrhs (Longident.last $3) 3)
+              ~params:$2
+              ~cstrs:(List.rev $6)
+              ~manifest:$5
+              ~priv:$4
+              ~loc:(symbol_rloc()))) }
     /* used label_longident instead of type_longident to disallow
        functor applications in type path */
+  | TYPE type_parameters label COLONEQUAL core_type_no_attr
+      { Pwith_typesubst
+          (Type.mk (mkrhs $3 3)
+             ~params:$2
+             ~manifest:$5
+             ~loc:(symbol_rloc())) }
   | MODULE mod_longident EQUAL mod_ext_longident
-      { ($2, Pwith_module $4) }
+      { Pwith_module (mkrhs $2 2, mkrhs $4 4) }
+  | MODULE UIDENT COLONEQUAL mod_ext_longident
+      { Pwith_modsubst (mkrhs $2 2, mkrhs $4 4) }
+;
+with_type_binder:
+    EQUAL          { Public }
+  | EQUAL PRIVATE  { Private }
 ;
 
 /* Polymorphic types */
@@ -1224,14 +1990,26 @@ typevar_list:
 ;
 poly_type:
         core_type
-          { mktyp(Ptyp_poly([], $1)) }
+          { $1 }
       | typevar_list DOT core_type
           { mktyp(Ptyp_poly(List.rev $1, $3)) }
 ;
+poly_type_no_attr:
+        core_type_no_attr
+          { $1 }
+      | typevar_list DOT core_type_no_attr
+          { mktyp(Ptyp_poly(List.rev $1, $3)) }
+;
 
 /* Core types */
 
 core_type:
+    core_type_no_attr
+      { $1 }
+  | core_type attribute
+      { Typ.attr $1 $2 }
+;
+core_type_no_attr:
     core_type2
       { $1 }
   | core_type2 AS QUOTE ident
@@ -1241,17 +2019,13 @@ core_type2:
     simple_core_type_or_tuple
       { $1 }
   | QUESTION LIDENT COLON core_type2 MINUSGREATER core_type2
-      { mktyp(Ptyp_arrow("?" ^ $2 ,
-               {ptyp_desc = Ptyp_constr(Lident "option", [$4]);
-                ptyp_loc = $4.ptyp_loc}, $6)) }
+      { mktyp(Ptyp_arrow(Optional $2 , $4, $6)) }
   | OPTLABEL core_type2 MINUSGREATER core_type2
-      { mktyp(Ptyp_arrow("?" ^ $1 ,
-               {ptyp_desc = Ptyp_constr(Lident "option", [$2]);
-                ptyp_loc = $2.ptyp_loc}, $4)) }
+      { mktyp(Ptyp_arrow(Optional $1 , $2, $4)) }
   | LIDENT COLON core_type2 MINUSGREATER core_type2
-      { mktyp(Ptyp_arrow($1, $3, $5)) }
+      { mktyp(Ptyp_arrow(Labelled $1, $3, $5)) }
   | core_type2 MINUSGREATER core_type2
-      { mktyp(Ptyp_arrow("", $1, $3)) }
+      { mktyp(Ptyp_arrow(Nolabel, $1, $3)) }
 ;
 
 simple_core_type:
@@ -1260,41 +2034,61 @@ simple_core_type:
   | LPAREN core_type_comma_list RPAREN %prec below_SHARP
       { match $2 with [sty] -> sty | _ -> raise Parse_error }
 ;
+
 simple_core_type2:
     QUOTE ident
       { mktyp(Ptyp_var $2) }
   | UNDERSCORE
       { mktyp(Ptyp_any) }
   | type_longident
-      { mktyp(Ptyp_constr($1, [])) }
+      { mktyp(Ptyp_constr(mkrhs $1 1, [])) }
   | simple_core_type2 type_longident
-      { mktyp(Ptyp_constr($2, [$1])) }
+      { mktyp(Ptyp_constr(mkrhs $2 2, [$1])) }
   | LPAREN core_type_comma_list RPAREN type_longident
-      { mktyp(Ptyp_constr($4, List.rev $2)) }
+      { mktyp(Ptyp_constr(mkrhs $4 4, List.rev $2)) }
   | LESS meth_list GREATER
-      { mktyp(Ptyp_object $2) }
+      { let (f, c) = $2 in mktyp(Ptyp_object (f, c)) }
   | LESS GREATER
-      { mktyp(Ptyp_object []) }
-  | SHARP class_longident opt_present
-      { mktyp(Ptyp_class($2, [], $3)) }
-  | simple_core_type2 SHARP class_longident opt_present
-      { mktyp(Ptyp_class($3, [$1], $4)) }
-  | LPAREN core_type_comma_list RPAREN SHARP class_longident opt_present
-      { mktyp(Ptyp_class($5, List.rev $2, $6)) }
+      { mktyp(Ptyp_object ([], Closed)) }
+  | SHARP class_longident
+      { mktyp(Ptyp_class(mkrhs $2 2, [])) }
+  | simple_core_type2 SHARP class_longident
+      { mktyp(Ptyp_class(mkrhs $3 3, [$1])) }
+  | LPAREN core_type_comma_list RPAREN SHARP class_longident
+      { mktyp(Ptyp_class(mkrhs $5 5, List.rev $2)) }
   | LBRACKET tag_field RBRACKET
-      { mktyp(Ptyp_variant([$2], true, None)) }
+      { mktyp(Ptyp_variant([$2], Closed, None)) }
+/* PR#3835: this is not LR(1), would need lookahead=2
+  | LBRACKET simple_core_type RBRACKET
+      { mktyp(Ptyp_variant([$2], Closed, None)) }
+*/
   | LBRACKET BAR row_field_list RBRACKET
-      { mktyp(Ptyp_variant(List.rev $3, true, None)) }
+      { mktyp(Ptyp_variant(List.rev $3, Closed, None)) }
   | LBRACKET row_field BAR row_field_list RBRACKET
-      { mktyp(Ptyp_variant($2 :: List.rev $4, true, None)) }
+      { mktyp(Ptyp_variant($2 :: List.rev $4, Closed, None)) }
   | LBRACKETGREATER opt_bar row_field_list RBRACKET
-      { mktyp(Ptyp_variant(List.rev $3, false, None)) }
+      { mktyp(Ptyp_variant(List.rev $3, Open, None)) }
   | LBRACKETGREATER RBRACKET
-      { mktyp(Ptyp_variant([], false, None)) }
+      { mktyp(Ptyp_variant([], Open, None)) }
   | LBRACKETLESS opt_bar row_field_list RBRACKET
-      { mktyp(Ptyp_variant(List.rev $3, true, Some [])) }
+      { mktyp(Ptyp_variant(List.rev $3, Closed, Some [])) }
   | LBRACKETLESS opt_bar row_field_list GREATER name_tag_list RBRACKET
-      { mktyp(Ptyp_variant(List.rev $3, true, Some (List.rev $5))) }
+      { mktyp(Ptyp_variant(List.rev $3, Closed, Some (List.rev $5))) }
+  | LPAREN MODULE package_type RPAREN
+      { mktyp(Ptyp_package $3) }
+  | extension
+      { mktyp (Ptyp_extension $1) }
+;
+package_type:
+    mty_longident { (mkrhs $1 1, []) }
+  | mty_longident WITH package_type_cstrs { (mkrhs $1 1, $3) }
+;
+package_type_cstr:
+    TYPE label_longident EQUAL core_type { (mkrhs $2 2, $4) }
+;
+package_type_cstrs:
+    package_type_cstr { [$1] }
+  | package_type_cstr AND package_type_cstrs { $1::$3 }
 ;
 row_field_list:
     row_field                                   { [$1] }
@@ -1302,32 +2096,28 @@ row_field_list:
 ;
 row_field:
     tag_field                                   { $1 }
-  | simple_core_type2                           { Rinherit $1 }
+  | simple_core_type                            { Rinherit $1 }
 ;
 tag_field:
-    name_tag OF opt_ampersand amper_type_list
-      { Rtag ($1, $3, List.rev $4) }
-  | name_tag
-      { Rtag ($1, true, []) }
+    name_tag OF opt_ampersand amper_type_list attributes
+      { Rtag ($1, $5, $3, List.rev $4) }
+  | name_tag attributes
+      { Rtag ($1, $2, true, []) }
 ;
 opt_ampersand:
     AMPERSAND                                   { true }
   | /* empty */                                 { false }
 ;
 amper_type_list:
-    core_type                                   { [$1] }
-  | amper_type_list AMPERSAND core_type         { $3 :: $1 }
-;
-opt_present:
-    LBRACKETGREATER name_tag_list RBRACKET      { List.rev $2 }
-  | /* empty */                                 { [] }
+    core_type_no_attr                           { [$1] }
+  | amper_type_list AMPERSAND core_type_no_attr { $3 :: $1 }
 ;
 name_tag_list:
     name_tag                                    { [$1] }
   | name_tag_list name_tag                      { $2 :: $1 }
 ;
 simple_core_type_or_tuple:
-    simple_core_type                            { $1 }
+    simple_core_type { $1 }
   | simple_core_type STAR core_type_list
       { mktyp(Ptyp_tuple($1 :: List.rev $3)) }
 ;
@@ -1340,12 +2130,12 @@ core_type_list:
   | core_type_list STAR simple_core_type        { $3 :: $1 }
 ;
 meth_list:
-    field SEMI meth_list                        { $1 :: $3 }
-  | field opt_semi                              { [$1] }
-  | DOTDOT                                      { [mkfield Pfield_var] }
+    field SEMI meth_list                     { let (f, c) = $3 in ($1 :: f, c) }
+  | field opt_semi                              { [$1], Closed }
+  | DOTDOT                                      { [], Open }
 ;
 field:
-    label COLON poly_type                       { mkfield(Pfield($1, $3)) }
+    label COLON poly_type_no_attr attributes    { ($1, $4, $3) }
 ;
 label:
     LIDENT                                      { $1 }
@@ -1354,22 +2144,28 @@ label:
 /* Constants */
 
 constant:
-    INT                                         { Const_int $1 }
-  | CHAR                                        { Const_char $1 }
-  | STRING                                      { Const_string $1 }
-  | FLOAT                                       { Const_float $1 }
-  | INT32                                       { Const_int32 $1 }
-  | INT64                                       { Const_int64 $1 }
-  | NATIVEINT                                   { Const_nativeint $1 }
+    INT                               { Const_int $1 }
+  | CHAR                              { Const_char $1 }
+  | STRING                            { let (s, d) = $1 in Const_string (s, d) }
+  | FLOAT                             { Const_float $1 }
+  | INT32                             { Const_int32 $1 }
+  | INT64                             { Const_int64 $1 }
+  | NATIVEINT                         { Const_nativeint $1 }
 ;
 signed_constant:
-    constant                                    { $1 }
-  | MINUS INT                                   { Const_int(- $2) }
-  | MINUS FLOAT                                 { Const_float("-" ^ $2) }
-  | MINUS INT32                                 { Const_int32(Int32.neg $2) }
-  | MINUS INT64                                 { Const_int64(Int64.neg $2) }
-  | MINUS NATIVEINT                             { Const_nativeint(Nativeint.neg $2) }
+    constant                               { $1 }
+  | MINUS INT                              { Const_int(- $2) }
+  | MINUS FLOAT                            { Const_float("-" ^ $2) }
+  | MINUS INT32                            { Const_int32(Int32.neg $2) }
+  | MINUS INT64                            { Const_int64(Int64.neg $2) }
+  | MINUS NATIVEINT                        { Const_nativeint(Nativeint.neg $2) }
+  | PLUS INT                               { Const_int $2 }
+  | PLUS FLOAT                             { Const_float $2 }
+  | PLUS INT32                             { Const_int32 $2 }
+  | PLUS INT64                             { Const_int64 $2 }
+  | PLUS NATIVEINT                         { Const_nativeint $2 }
 ;
+
 /* Identifiers and long identifiers */
 
 ident:
@@ -1379,11 +2175,9 @@ ident:
 val_ident:
     LIDENT                                      { $1 }
   | LPAREN operator RPAREN                      { $2 }
-;
-val_ident_colon:
-    LIDENT COLON                                { $1 }
-  | LPAREN operator RPAREN COLON                { $2 }
-  | LABEL                                       { $1 }
+  | LPAREN operator error                       { unclosed "(" 1 ")" 3 }
+  | LPAREN error                                { expecting 2 "operator" }
+  | LPAREN MODULE error                         { expecting 3 "module-expr" }
 ;
 operator:
     PREFIXOP                                    { $1 }
@@ -1392,7 +2186,10 @@ operator:
   | INFIXOP2                                    { $1 }
   | INFIXOP3                                    { $1 }
   | INFIXOP4                                    { $1 }
+  | SHARPOP                                     { $1 }
+  | BANG                                        { "!" }
   | PLUS                                        { "+" }
+  | PLUSDOT                                     { "+." }
   | MINUS                                       { "-" }
   | MINUSDOT                                    { "-." }
   | STAR                                        { "*" }
@@ -1404,12 +2201,33 @@ operator:
   | AMPERSAND                                   { "&" }
   | AMPERAMPER                                  { "&&" }
   | COLONEQUAL                                  { ":=" }
+  | PLUSEQ                                      { "+=" }
+  | PERCENT                                     { "%" }
+  | index_operator                              { $1 }
+;
+index_operator:
+    DOT index_operator_core opt_assign_arrow { $2^$3 }
+;
+index_operator_core:
+  | LPAREN RPAREN                               { ".()" }
+  | LBRACKET RBRACKET                           { ".[]" }
+  | LBRACE RBRACE                               { ".{}" }
+  | LBRACE COMMA  RBRACE                        { ".{,}" }
+  | LBRACE COMMA COMMA RBRACE                   { ".{,,}" }
+  | LBRACE COMMA DOTDOT COMMA RBRACE            { ".{,..,}"}
+;
+
+opt_assign_arrow:
+                                                { "" }
+  | LESSMINUS                                   { "<-" }
 ;
+
 constr_ident:
     UIDENT                                      { $1 }
 /*  | LBRACKET RBRACKET                           { "[]" } */
   | LPAREN RPAREN                               { "()" }
   | COLONCOLON                                  { "::" }
+/*  | LPAREN COLONCOLON RPAREN                    { "::" } */
   | FALSE                                       { "false" }
   | TRUE                                        { "true" }
 ;
@@ -1440,7 +2258,7 @@ mod_longident:
 mod_ext_longident:
     UIDENT                                      { Lident $1 }
   | mod_ext_longident DOT UIDENT                { Ldot($1, $3) }
-  | mod_ext_longident LPAREN mod_ext_longident RPAREN { Lapply($1, $3) }
+  | mod_ext_longident LPAREN mod_ext_longident RPAREN { lapply $1 $3 }
 ;
 mty_longident:
     ident                                       { Lident $1 }
@@ -1459,9 +2277,10 @@ class_longident:
 
 toplevel_directive:
     SHARP ident                 { Ptop_dir($2, Pdir_none) }
-  | SHARP ident STRING          { Ptop_dir($2, Pdir_string $3) }
+  | SHARP ident STRING          { Ptop_dir($2, Pdir_string (fst $3)) }
   | SHARP ident INT             { Ptop_dir($2, Pdir_int $3) }
   | SHARP ident val_longident   { Ptop_dir($2, Pdir_ident $3) }
+  | SHARP ident mod_longident   { Ptop_dir($2, Pdir_ident $3) }
   | SHARP ident FALSE           { Ptop_dir($2, Pdir_bool false) }
   | SHARP ident TRUE            { Ptop_dir($2, Pdir_bool true) }
 ;
@@ -1475,6 +2294,10 @@ rec_flag:
     /* empty */                                 { Nonrecursive }
   | REC                                         { Recursive }
 ;
+nonrec_flag:
+    /* empty */                                 { Recursive }
+  | NONREC                                      { Nonrecursive }
+;
 direction_flag:
     TO                                          { Upto }
   | DOWNTO                                      { Downto }
@@ -1491,6 +2314,17 @@ virtual_flag:
     /* empty */                                 { Concrete }
   | VIRTUAL                                     { Virtual }
 ;
+private_virtual_flags:
+    /* empty */  { Public, Concrete }
+  | PRIVATE { Private, Concrete }
+  | VIRTUAL { Public, Virtual }
+  | PRIVATE VIRTUAL { Private, Virtual }
+  | VIRTUAL PRIVATE { Private, Virtual }
+;
+override_flag:
+    /* empty */                                 { Fresh }
+  | BANG                                        { Override }
+;
 opt_bar:
     /* empty */                                 { () }
   | BAR                                         { () }
@@ -1503,4 +2337,104 @@ subtractive:
   | MINUS                                       { "-" }
   | MINUSDOT                                    { "-." }
 ;
+additive:
+  | PLUS                                        { "+" }
+  | PLUSDOT                                     { "+." }
+;
+
+/* Attributes and extensions */
+
+single_attr_id:
+    LIDENT { $1 }
+  | UIDENT { $1 }
+  | AND { "and" }
+  | AS { "as" }
+  | ASSERT { "assert" }
+  | BEGIN { "begin" }
+  | CLASS { "class" }
+  | CONSTRAINT { "constraint" }
+  | DO { "do" }
+  | DONE { "done" }
+  | DOWNTO { "downto" }
+  | ELSE { "else" }
+  | END { "end" }
+  | EXCEPTION { "exception" }
+  | EXTERNAL { "external" }
+  | FALSE { "false" }
+  | FOR { "for" }
+  | FUN { "fun" }
+  | FUNCTION { "function" }
+  | FUNCTOR { "functor" }
+  | IF { "if" }
+  | IN { "in" }
+  | INCLUDE { "include" }
+  | INHERIT { "inherit" }
+  | INITIALIZER { "initializer" }
+  | LAZY { "lazy" }
+  | LET { "let" }
+  | MATCH { "match" }
+  | METHOD { "method" }
+  | MODULE { "module" }
+  | MUTABLE { "mutable" }
+  | NEW { "new" }
+  | NONREC { "nonrec" }
+  | OBJECT { "object" }
+  | OF { "of" }
+  | OPEN { "open" }
+  | OR { "or" }
+  | PRIVATE { "private" }
+  | REC { "rec" }
+  | SIG { "sig" }
+  | STRUCT { "struct" }
+  | THEN { "then" }
+  | TO { "to" }
+  | TRUE { "true" }
+  | TRY { "try" }
+  | TYPE { "type" }
+  | VAL { "val" }
+  | VIRTUAL { "virtual" }
+  | WHEN { "when" }
+  | WHILE { "while" }
+  | WITH { "with" }
+/* mod/land/lor/lxor/lsl/lsr/asr are not supported for now */
+;
+
+attr_id:
+    single_attr_id { mkloc $1 (symbol_rloc()) }
+  | single_attr_id DOT attr_id { mkloc ($1 ^ "." ^ $3.txt) (symbol_rloc())}
+;
+attribute:
+  LBRACKETAT attr_id payload RBRACKET { ($2, $3) }
+;
+post_item_attribute:
+  LBRACKETATAT attr_id payload RBRACKET { ($2, $3) }
+;
+floating_attribute:
+  LBRACKETATATAT attr_id payload RBRACKET { ($2, $3) }
+;
+post_item_attributes:
+    /* empty */  { [] }
+  | post_item_attribute post_item_attributes { $1 :: $2 }
+;
+attributes:
+    /* empty */{ [] }
+  | attribute attributes { $1 :: $2 }
+;
+ext_attributes:
+    /* empty */  { None, [] }
+  | attribute attributes { None, $1 :: $2 }
+  | PERCENT attr_id attributes { Some $2, $3 }
+;
+extension:
+  LBRACKETPERCENT attr_id payload RBRACKET { ($2, $3) }
+;
+item_extension:
+  LBRACKETPERCENTPERCENT attr_id payload RBRACKET { ($2, $3) }
+;
+payload:
+    structure { PStr $1 }
+  | COLON core_type { PTyp $2 }
+  | QUESTION pattern { PPat ($2, None) }
+  | QUESTION pattern WHEN seq_expr { PPat ($2, Some $4) }
+;
 %%