@@ -10,6 +10,13 @@ module Parser = Res_parser
1010let mk_loc start_loc end_loc =
1111 Location. {loc_start = start_loc; loc_end = end_loc; loc_ghost = false }
1212
13+ let rec skip_doc_comments p =
14+ match p.Parser. token with
15+ | DocComment _ ->
16+ Parser. next p;
17+ skip_doc_comments p
18+ | _ -> ()
19+
1320type inline_types_context = {
1421 mutable found_inline_types :
1522 (string * Warnings .loc * Parsetree .type_kind ) list ;
@@ -5165,8 +5172,37 @@ and parse_type_representation ?current_type_name_path ?inline_types_context p =
51655172 in
51665173 let kind =
51675174 match p.Parser. token with
5168- | Bar | Uident _ | DocComment _ | At ->
5175+ | Bar | Uident _ | DocComment _ ->
51695176 Parsetree. Ptype_variant (parse_type_constructor_declarations p)
5177+ | At -> (
5178+ (* Attributes can prefix either a variant (constructor list), a record, or an
5179+ open/extensible variant marker (`..`). Peek past attributes and any doc
5180+ comments to decide which kind it is. *)
5181+ let after_attrs =
5182+ Parser. lookahead p (fun state ->
5183+ ignore (parse_attributes state);
5184+ skip_doc_comments state;
5185+ state.Parser. token)
5186+ in
5187+ match after_attrs with
5188+ | Lbrace ->
5189+ (* consume the attributes and any doc comments before the record *)
5190+ ignore (parse_attributes p);
5191+ skip_doc_comments p;
5192+ Parsetree. Ptype_record
5193+ (parse_record_declaration ?current_type_name_path
5194+ ?inline_types_context p)
5195+ | DotDot ->
5196+ (* attributes before an open variant marker; consume attrs/docs then handle `..` *)
5197+ ignore (parse_attributes p);
5198+ skip_doc_comments p;
5199+ Parser. next p;
5200+ (* consume DotDot *)
5201+ Ptype_open
5202+ | _ ->
5203+ (* fall back to variant constructor declarations; leave attributes for the
5204+ constructor parsing so they attach to the first constructor. *)
5205+ Parsetree. Ptype_variant (parse_type_constructor_declarations p))
51705206 | Lbrace ->
51715207 Parsetree. Ptype_record
51725208 (parse_record_declaration ?current_type_name_path ?inline_types_context
@@ -5727,22 +5763,42 @@ and parse_type_equation_and_representation ?current_type_name_path
57275763 let priv, kind = parse_type_representation p in
57285764 (None , priv, kind)
57295765 | At -> (
5730- (* Attribute can start a variant constructor or a type manifest.
5731- Look ahead past attributes; if a constructor -like token follows (Uident not immediately
5732- followed by a Dot, or DotDotDot/Bar/DocComment), treat as variant; otherwise manifest *)
5733- let is_variant_after_attrs =
5766+ (* Attributes can start a representation ( variant/record/open variant) or a manifest.
5767+ Look ahead past attributes (and doc comments). If a representation -like token follows,
5768+ parse it as a representation; otherwise treat as a manifest. *)
5769+ let is_representation_after_attrs =
57345770 Parser. lookahead p (fun state ->
57355771 ignore (parse_attributes state);
5772+ (* optionally skip a run of doc comments before deciding *)
5773+ skip_doc_comments state;
57365774 match state.Parser. token with
5775+ | Lbrace -> (
5776+ (* Disambiguate record declaration vs object type.
5777+ Peek inside the braces; if it looks like an object (String/Dot/DotDot/DotDotDot),
5778+ then this is a manifest type expression, not a representation. If it looks like
5779+ a record field (e.g. Lident or attributes before one), treat as representation. *)
5780+ Parser. next state;
5781+ (* consume Lbrace *)
5782+ ignore (parse_attributes state);
5783+ skip_doc_comments state;
5784+ match state.Parser. token with
5785+ | String _ | Dot | DotDot | DotDotDot ->
5786+ false (* object type => manifest *)
5787+ | _ -> true
5788+ (* record decl => representation *) )
5789+ | Bar -> true (* variant constructor list *)
5790+ | DotDot -> true (* extensible/open variant ".." *)
57375791 | Uident _ -> (
5792+ (* constructor vs module-qualified manifest *)
57385793 Parser. next state;
57395794 match state.Parser. token with
5740- | Dot -> false
5741- | _ -> true )
5742- | DotDotDot | Bar | DocComment _ -> true
5795+ | Dot -> false (* M.t => manifest *)
5796+ | _ -> true
5797+ (* Uident starting a constructor *) )
5798+ | DocComment _ -> true (* doc before constructor list *)
57435799 | _ -> false )
57445800 in
5745- if is_variant_after_attrs then
5801+ if is_representation_after_attrs then
57465802 let priv, kind = parse_type_representation p in
57475803 (None , priv, kind)
57485804 else
0 commit comments