···6969 end
7070 in
7171 loop true 0 empty_body attrs
7272- |> Model.Error.convey_by_exception
7272+ |> Model.Error.to_exception
73737474let read_string parent loc str : Model.Comment.docs_or_stop =
7575 let start_pos = loc.Location.loc_start in
···8181 ~location:start_pos
8282 ~text:str
8383 |> Model.Error.shed_warnings
8484- |> Model.Error.convey_by_exception
8484+ |> Model.Error.to_exception
8585 in
8686 `Docs doc
8787
+4-4
src/loader/loader.ml
···11let read_string parent_definition location text =
22- Model.Error.catch_conveyed_by_exception (fun () ->
22+ Model.Error.catch (fun () ->
33 Attrs.read_string parent_definition location text)
4455···3333 begin match cmt_info.cmt_interface_digest with
3434 | None -> corrupted filename
3535 | Some digest ->
3636- Model.Error.catch_conveyed_by_exception begin fun () ->
3636+ Model.Error.catch begin fun () ->
3737 let name = cmt_info.cmt_modname in
3838 let root = make_root ~module_name:name ~digest in
3939 let (id, doc, items) = Cmti.read_interface root name intf in
···114114 source; interface; hidden; content; expansion = None}
115115116116 | Implementation impl ->
117117- Model.Error.catch_conveyed_by_exception begin fun () ->
117117+ Model.Error.catch begin fun () ->
118118 let name = cmt_info.cmt_modname in
119119 let interface, digest =
120120 match cmt_info.cmt_interface_digest with
···159159 | cmi_info ->
160160 match cmi_info.cmi_crcs with
161161 | (name, Some digest) :: imports when name = cmi_info.cmi_name ->
162162- Model.Error.catch_conveyed_by_exception begin fun () ->
162162+ Model.Error.catch begin fun () ->
163163 let root = make_root ~module_name:name ~digest:digest in
164164 let (id, doc, items) = Cmi.read_interface root name cmi_info.cmi_sign in
165165 let imports =
+13-4
src/model/error.ml
···1818 warnings : t list;
1919}
20202121+let make : string -> Location_.span -> t = fun message location ->
2222+ `With_full_location {location; error = message}
2323+2424+let makef = fun format ->
2525+ (Printf.ksprintf make) format
2626+2127let to_string : t -> string = function
2228 | `With_full_location {location; error} ->
2329 let location_string =
···40464147exception Conveyed_by_exception of t
42484343-let convey_by_exception : ('a, t) result -> 'a = function
4949+let raise_exception : t -> _ = fun error ->
5050+ raise (Conveyed_by_exception error)
5151+5252+let to_exception : ('a, t) result -> 'a = function
4453 | Ok v -> v
4545- | Error e -> raise (Conveyed_by_exception e)
5454+ | Error error -> raise_exception error
46554747-let catch_conveyed_by_exception : (unit -> 'a) -> ('a, t) result = fun f ->
5656+let catch : (unit -> 'a) -> ('a, t) result = fun f ->
4857 try Ok (f ())
4949- with Conveyed_by_exception e -> Error e
5858+ with Conveyed_by_exception error -> Error error
50595160(* TODO This is a temporary measure until odoc is ported to handle warnings
5261 throughout. *)
+26-1
src/model/location_.ml
···44}
5566type span = {
77+ file : string;
78 start : point;
89 end_ : point;
99- file : string;
1010}
11111212type 'a with_location = {
···1717let at : span -> 'a -> 'a with_location = fun location value ->
1818 {location; value}
19192020+let location : 'a with_location -> span = fun {location; _} ->
2121+ location
2222+2023let value : 'a with_location -> 'a = fun {value; _} ->
2124 value
2225···26292730let same : _ with_location -> 'b -> 'b with_location = fun annotated value ->
2831 {annotated with value}
3232+3333+let span : span list -> span = fun spans ->
3434+ match spans with
3535+ | [] ->
3636+ {
3737+ file = "_none_";
3838+ start = {
3939+ line = 1;
4040+ column = 0;
4141+ };
4242+ end_ = {
4343+ line = 1;
4444+ column = 0;
4545+ };
4646+ }
4747+ | first::spans ->
4848+ let last = List.fold_left (fun _ span -> span) first spans in
4949+ {
5050+ file = first.file;
5151+ start = first.start;
5252+ end_ = last.end_;
5353+ }
+2-56
src/parser/helpers.ml
···11-(* This file contains mostly functions from the former [model/attrs.ml], and
22- also some helpers for error handling. It should be reorganized in the
33- future. *)
44-55-type raw_parse_error = {
66- start_offset : int;
77- end_offset : int;
88- text : string;
99-}
1010-1111-exception Parse_error of raw_parse_error
1212-1313-let not_allowed ?suggestion (start_offset, end_offset) ~what ~in_what =
1414- let text = Printf.sprintf "%s is not allowed in %s" what in_what in
1515- let text =
1616- match suggestion with
1717- | None -> text
1818- | Some suggestion ->
1919- Printf.sprintf "%s\nSuggestion: %s" text suggestion
2020- in
2121- raise_notrace (Parse_error {start_offset; end_offset; text})
2222-2323-let must_be_followed_by_whitespace (start_offset, end_offset) ~what =
2424- let text =
2525- Printf.sprintf "%s must be followed by space, a tab, or a new line" what in
2626- raise_notrace (Parse_error {start_offset; end_offset; text})
2727-2828-let cannot_be_empty (start_offset, end_offset) ~what =
2929- raise_notrace
3030- (Parse_error {
3131- start_offset;
3232- end_offset;
3333- text = Printf.sprintf "%s cannot be empty" what
3434- })
3535-3636-let no_leading_whitespace_in_verbatim start_offset =
3737- raise_notrace
3838- (Parse_error {
3939- start_offset;
4040- end_offset = start_offset + 2;
4141- text = "'{v' must be followed by whitespace"
4242- })
4343-4444-let no_trailing_whitespace_in_verbatim end_offset =
4545- raise_notrace
4646- (Parse_error {
4747- start_offset = end_offset - 2;
4848- end_offset = end_offset;
4949- text = "'v}' must be preceded by whitespace"
5050- })
5151-5252-let must_begin_on_its_own_line (start_offset, end_offset) ~what =
5353- let text = Printf.sprintf "%s must begin on its own line" what in
5454- raise_notrace (Parse_error {start_offset; end_offset; text})
5555-5656-11+(* This file contains mostly functions from the former [model/attrs.ml]. It
22+ should be reorganized in the future. *)
573584module Paths = Model.Paths
595
···11+module Location = Model.Location_
22+module Error = Model.Error
33+44+55+66+let bad_markup : string -> Location.span -> Error.t =
77+ Error.makef "'%s': bad markup"
88+99+let bad_section_level : string -> Location.span -> Error.t =
1010+ Error.makef "'%s': bad section level (2-4 allowed)"
1111+1212+let cannot_be_empty : what:string -> Location.span -> Error.t = fun ~what ->
1313+ Error.makef "%s cannot be empty" what
1414+1515+let must_begin_on_its_own_line : what:string -> Location.span -> Error.t =
1616+ fun ~what ->
1717+ Error.makef "%s must begin on its own line" what
1818+1919+let must_be_followed_by_whitespace : what:string -> Location.span -> Error.t =
2020+ fun ~what ->
2121+ Error.makef "%s must be followed by space, a tab, or a new line" what
2222+2323+let not_allowed
2424+ : ?suggestion:string -> what:string -> in_what:string -> Location.span ->
2525+ Error.t =
2626+ fun ?suggestion ~what ~in_what location ->
2727+ let message = Printf.sprintf "%s is not allowed in %s" what in_what in
2828+ let message =
2929+ match suggestion with
3030+ | None -> message
3131+ | Some suggestion -> Printf.sprintf "%s\nSuggestion: %s" message suggestion
3232+ in
3333+ Error.make message location
3434+3535+let no_leading_whitespace_in_verbatim : Location.span -> Error.t =
3636+ Error.make "'{v' must be followed by whitespace"
3737+3838+let no_trailing_whitespace_in_verbatim : Location.span -> Error.t =
3939+ Error.make "'v}' must be preceded by whitespace"
4040+4141+let stray_at : Location.span -> Error.t =
4242+ Error.make "stray '@'"
4343+4444+let stray_cr : Location.span -> Error.t =
4545+ Error.make "stray '\\r' (carriage return character)"
4646+4747+let truncated_before : Location.span -> Error.t =
4848+ Error.make "'@before' expects version number on the same line"
4949+5050+let truncated_param : Location.span -> Error.t =
5151+ Error.make "'@param' expects parameter name on the same line"
5252+5353+let truncated_raise : Location.span -> Error.t =
5454+ Error.make "'@raise' expects exception constructor on the same line"
5555+5656+let truncated_see : Location.span -> Error.t =
5757+ Error.make "'@see' must be followed by <url>, 'file', or \"document title\""
5858+5959+let unknown_tag : string -> Location.span -> Error.t =
6060+ Error.makef "unknown tag '%s'"
6161+6262+let unpaired_right_brace : Location.span -> Error.t =
6363+ Error.make "unpaired '}' (end of markup)"
6464+6565+let unpaired_right_bracket : Location.span -> Error.t =
6666+ Error.make "unpaired ']' (end of code)"
+14-31
src/parser/parser_.ml
···6868 offset_to_location_relative_to_start_of_file
6969 in
70707171- (* The parser signals errors by raising exceptions. These carry byte offsets
7272- into the comment for the start and end of the offending text, and a
7373- description. We need to convert the offsets to locations relative to the
7474- file containing the comment, add the filename, and package the result in
7575- the type of error accepted by the rest of odoc. *)
7676- let convert_parsing_error_to_odoc_error
7777- : Helpers.raw_parse_error -> Model.Error.t = fun error ->
7878-7979- `With_full_location {
8080- location = {
8181- file = location.Lexing.pos_fname;
8282- start = offset_to_location error.start_offset;
8383- end_ = offset_to_location error.end_offset;
8484- };
8585- error = error.text;
8686- }
8787- in
8888-8971 let token_stream =
9072 let lexbuf = Lexing.from_string text in
9191- Stream.from (fun _token_index -> Some (Lexer.token lexbuf))
7373+ let input : Lexer.input =
7474+ {
7575+ file = location.Lexing.pos_fname;
7676+ offset_to_location;
7777+ lexbuf;
7878+ }
7979+ in
8080+ Stream.from (fun _token_index -> Some (Lexer.token input lexbuf))
9281 in
93829494- try
9595- Syntax.parse
9696- ~file:location.Lexing.pos_fname
9797- ~offset_to_location
9898- ~token_stream
9999- |> Semantics.ast_to_comment
8383+ match Syntax.parse token_stream with
8484+ | Error error ->
8585+ {Model.Error.result = Error error; warnings = []}
8686+ | Ok ast ->
8787+ Semantics.ast_to_comment
10088 ~permissive
10189 ~sections_allowed
10290 ~parent_of_sections:containing_definition
103103-104104- with Helpers.Parse_error error ->
105105- {
106106- Model.Error.result = Error (convert_parsing_error_to_odoc_error error);
107107- warnings = [];
108108- }
9191+ ast
109921109311194
+3-7
src/parser/semantics.ml
···1717 if status.permissive then
1818 status.warnings <- message::status.warnings
1919 else
2020- raise_notrace (Error.Conveyed_by_exception message)
2020+ Error.raise_exception message
212122222323···5656 error = "only one title-level heading is allowed";
5757 }
5858 in
5959- raise_notrace (Error.Conveyed_by_exception message)
5959+ Error.raise_exception message
6060 end;
6161 let element = `Heading (`Title, label, content) in
6262 let element = Location.at location element in
···127127 }
128128 in
129129130130- let result =
131131- Error.catch_conveyed_by_exception (fun () ->
132132- top_level_block_elements status ast)
133133- in
134134-130130+ let result = Error.catch (fun () -> top_level_block_elements status ast) in
135131 let warnings = List.rev status.warnings in
136132137133 {Error.result; warnings}
+313-301
src/parser/syntax.ml
···1616 is not explicitly delimited with curly braces.
1717 - [block_element_list] parses a sequence of block elements. A comment is a
1818 sequence of block elements, so [block_element_list] is the top-level
1919- parser. It is also used for list item and tag content.
1919+ parser. It is also used for list item and tag content. *)
20202121- The parser raises exceptions with constructor [Helpers.Parse_error]. These
2222- contain raw byte offsets as locations. These are caught in module [Parser_],
2323- and translated to line/column locations. *)
242125222323+module Location = Model.Location_
2424+module Error = Model.Error
2525+module Comment = Model.Comment
26262727-(* {2 Input} *)
2727+type 'a with_location = 'a Location.with_location
28282929-(* Tokens paired with their start and end byte offsets.
30293131- This type constructor is mainly used as [Token.t stream_head]. However, in
3232- places where only a subset of tokens is allowed, it is used with more
3333- restrictive types, such as [[ `Space | `Single_newline ] stream_head]. *)
3434-type 'token stream_head = (int * int) * 'token
35303636-(* What the parser needs from the outside world. A value of type [input] is
3737- passed around between all the parsing functions.
3131+(* {2 Input} *)
38323939- - [file] is the name of the file containing the comment being parsed. It is
4040- needed to construct locations.
4141- - [offset_to_location] converts byte indexes relative to the start of the
4242- comment to line, column pairs relative to the start of the file containing
4343- the comment.
4444- - [token_stream] is the stream of tokens emitted by the lexer.
3333+type input = (Token.t Location.with_location) Stream.t
45344646- In addition to a value of type [input], some parsing functions also take a
4747- value of type ['a stream_head], for some ['a] that is narrower than [Token.t].
4848- This is done when the stream head has already been examined by the caller, and
4949- it allows a precise and limited set of cases in the function. *)
5050-type input = {
5151- file : string;
5252- offset_to_location : int -> Model.Location_.point;
5353- token_stream : (Token.t stream_head) Stream.t;
5454-}
5555-5656-let junk input =
5757- Stream.junk input.token_stream
3535+let junk = Stream.junk
58365937let peek input =
6060- match Stream.peek input.token_stream with
3838+ match Stream.peek input with
6139 | Some token -> token
6240 | None -> assert false
6341 (* The last token in the stream is always [`End], and it is never consumed by
6442 the parser, so the [None] case is impossible. *)
65436666-let npeek n input =
6767- Stream.npeek n input.token_stream
6868-6969-type 'a with_location = 'a Model.Location_.with_location
7070-7171-let at_token input (start_offset, end_offset) value : _ with_location =
7272- {
7373- location = {
7474- file = input.file;
7575- start = input.offset_to_location start_offset;
7676- end_ = input.offset_to_location end_offset;
7777- };
7878- value;
7979- }
8080-8181-let token_span input (start_offset, _) (_, end_offset) value : _ with_location =
8282- {
8383- location = {
8484- file = input.file;
8585- start = input.offset_to_location start_offset;
8686- end_ = input.offset_to_location end_offset;
8787- };
8888- value;
8989- }
9090-9191-let child_span input (start_offset, end_offset) children value
9292- : _ with_location =
9393- let nested_end_location =
9494- List.fold_left (fun _acc child ->
9595- Some child.Model.Location_.location)
9696- None children
9797- in
9898- match nested_end_location with
9999- | None ->
100100- {
101101- location = {
102102- file = input.file;
103103- start = input.offset_to_location start_offset;
104104- end_ = input.offset_to_location end_offset;
105105- };
106106- value;
107107- }
108108- | Some nested_end_location ->
109109- {
110110- location = {
111111- file = input.file;
112112- start = input.offset_to_location start_offset;
113113- end_ = nested_end_location.end_;
114114- };
115115- value;
116116- }
117117-118118-119119-120120-module Comment = Model.Comment
121121-module Raise = Helpers
4444+let npeek = Stream.npeek
122451234612447···14467 tokens, so "brace \{" becomes [`Word "brace"; `Word "{"].
1456814669 This parser stops on the first non-word token, and does not consume it. *)
147147-let word
148148- : input -> (int * int) ->
149149- Comment.non_link_inline_element with_location =
150150- fun input start_location ->
151151- let rec consume_word_tokens end_location acc =
152152- match peek input with
153153- | l, `Word w ->
7070+let word : input -> Comment.non_link_inline_element with_location =
7171+ fun input ->
7272+ let first_token = peek input in
7373+7474+ let rec consume_word_tokens last_token acc =
7575+ let next_token = peek input in
7676+ match next_token.value with
7777+ | `Word w ->
15478 junk input;
155155- consume_word_tokens l (acc ^ w)
7979+ consume_word_tokens next_token (acc ^ w)
15680157157- | l, `Minus ->
8181+ | `Minus ->
15882 junk input;
159159- consume_word_tokens l (acc ^ "-")
8383+ consume_word_tokens next_token (acc ^ "-")
16084161161- | l, `Plus ->
8585+ | `Plus ->
16286 junk input;
163163- consume_word_tokens l (acc ^ "+")
8787+ consume_word_tokens next_token (acc ^ "+")
1648816589 | _ ->
166166- token_span input start_location end_location (`Word acc)
9090+ let location =
9191+ Location.span [first_token.location; last_token.location] in
9292+ Location.at location (`Word acc)
16793 in
168168- consume_word_tokens start_location ""
9494+9595+ consume_word_tokens first_token ""
1699617097(* Consumes tokens that make up a single non-link inline element:
17198···189116190117 This function consumes exactly the tokens that make up the element. *)
191118let rec non_link_inline_element
192192- : [> ] stream_head -> input ->
119119+ : input -> _ with_location ->
193120 Comment.non_link_inline_element with_location =
194194- fun stream_head input ->
121121+ fun input next_token ->
195122196196- match stream_head with
197197- | l, `Space ->
123123+ match next_token.value with
124124+ | `Space ->
198125 junk input;
199199- at_token input l `Space
126126+ Location.same next_token `Space
200127201201- | l, `Word _
202202- | l, `Minus
203203- | l, `Plus ->
204204- word input l
128128+ | `Word _
129129+ | `Minus
130130+ | `Plus ->
131131+ word input
205132206206- | l, `Code_span c ->
133133+ | `Code_span c ->
207134 junk input;
208208- at_token input l (`Code_span c)
135135+ Location.same next_token (`Code_span c)
209136210210- | l, (`Begin_style s as parent_markup) ->
137137+ | `Begin_style s as parent_markup ->
211138 junk input;
139139+212140 let requires_leading_whitespace =
213141 match s with
214142 | `Superscript | `Subscript -> false
215143 | _ -> true
216144 in
217217- let content, end_location =
145145+ let content, brace_location =
218146 delimited_non_link_inline_element_list
219147 ~parent_markup
220220- ~parent_markup_location:l
148148+ ~parent_markup_location:next_token.location
221149 ~requires_leading_whitespace
222150 input
223151 in
224152 if content = [] then
225225- Raise.cannot_be_empty l ~what:(Token.describe parent_markup);
226226- token_span input l end_location (`Styled (s, content))
153153+ Parse_error.cannot_be_empty
154154+ ~what:(Token.describe parent_markup) next_token.location
155155+ |> Error.raise_exception;
156156+157157+ (`Styled (s, content))
158158+ |> Location.at (Location.span [next_token.location; brace_location])
227159228160(* Consumes tokens that make up a sequence of non-link inline elements. See
229161 function [non_link_inline_element] for a list of what those are.
···251183 generating error messages. *)
252184and delimited_non_link_inline_element_list
253185 : parent_markup:[< Token.t ] ->
254254- parent_markup_location:(int * int) ->
186186+ parent_markup_location:Location.span ->
255187 requires_leading_whitespace:bool ->
256188 input ->
257257- (Comment.non_link_inline_element with_location) list * (int * int) =
189189+ (Comment.non_link_inline_element with_location) list * Location.span =
258190 fun
259191 ~parent_markup
260192 ~parent_markup_location
···267199 let rec consume_non_link_inline_elements
268200 : at_start_of_line:bool ->
269201 (Comment.non_link_inline_element with_location) list ->
270270- (Comment.non_link_inline_element with_location) list * (int * int) =
202202+ (Comment.non_link_inline_element with_location) list * Location.span =
271203 fun ~at_start_of_line acc ->
272204273205 match peek input with
274274- | l, `Right_brace ->
206206+ | {value = `Right_brace; location} ->
275207 junk input;
276276- List.rev acc, l
208208+ List.rev acc, location
277209278210 (* The [`Space] token is not space at the beginning or end of line, because
279211 that is combined into [`Single_newline] or [`Blank_line] tokens. It is
···283215 because that is combined into the [`Right_brace] token by the lexer. So,
284216 it is an internal space, and we want to add it to the non-link inline
285217 element list. *)
286286- | _, `Space
287287- | _, `Word _
288288- | _, `Code_span _
289289- | _, `Begin_style _ as stream_head ->
290290- let acc = (non_link_inline_element stream_head input)::acc in
218218+ | {value = `Space; _}
219219+ | {value = `Word _; _}
220220+ | {value = `Code_span _; _}
221221+ | {value = `Begin_style _; _} as next_token ->
222222+ let acc = (non_link_inline_element input next_token)::acc in
291223 consume_non_link_inline_elements ~at_start_of_line:false acc
292224293293- | l, `Single_newline ->
225225+ | {value = `Single_newline; location} ->
294226 junk input;
295295- let element = at_token input l `Space in
227227+ let element = Location.at location `Space in
296228 consume_non_link_inline_elements ~at_start_of_line:true (element::acc)
297229298298- | l, (`Minus | `Plus as bullet) as stream_head ->
230230+ | {value = `Minus | `Plus as bullet; location} as next_token ->
299231 if not at_start_of_line then
300300- let acc = (non_link_inline_element stream_head input)::acc in
232232+ let acc = (non_link_inline_element input next_token)::acc in
301233 consume_non_link_inline_elements ~at_start_of_line:false acc
302234 else
303235 let suggestion =
···305237 "move %s so it isn't the first thing on the line"
306238 (Token.print bullet)
307239 in
308308- Raise.not_allowed
309309- l
240240+ Parse_error.not_allowed
310241 ~what:(Token.describe bullet)
311242 ~in_what:(Token.describe parent_markup)
312243 ~suggestion
244244+ location
245245+ |> Error.raise_exception
313246314314- | l, token ->
315315- Raise.not_allowed
316316- l ~what:(Token.describe token) ~in_what:(Token.describe parent_markup)
247247+ | other_token ->
248248+ Parse_error.not_allowed
249249+ ~what:(Token.describe other_token.value)
250250+ ~in_what:(Token.describe parent_markup)
251251+ other_token.location
252252+ |> Error.raise_exception
317253 in
318254319319- match peek input with
320320- | _, `Space ->
255255+ let first_token = peek input in
256256+ match first_token.value with
257257+ | `Space ->
321258 junk input;
322259 consume_non_link_inline_elements ~at_start_of_line:false []
323260 (* [~at_start_of_line] is [false] here because the preceding token was some
324261 some markup like '{b', and we didn't move to the next line, so the next
325262 token will not be the first non-whitespace token on its line. *)
326263327327- | _, `Single_newline ->
264264+ | `Single_newline ->
328265 junk input;
329266 consume_non_link_inline_elements ~at_start_of_line:true []
330267331331- | l, `Blank_line ->
268268+ | `Blank_line ->
332269 (* In case the markup is immediately followed by a blank line, the error
333270 message printed by the catch-all case below can be confusing, as it will
334271 suggest that the markup must be followed by a newline (which it is). It
335272 just must not be followed by two newlines. To explain that clearly,
336273 handle that case specifically. *)
337337- Raise.not_allowed
338338- l
274274+ Parse_error.not_allowed
339275 ~what:(Token.describe `Blank_line)
340276 ~in_what:(Token.describe parent_markup)
277277+ first_token.location
278278+ |> Error.raise_exception
341279342342- | l, `Right_brace ->
280280+ | `Right_brace ->
343281 junk input;
344344- [], l
282282+ [], first_token.location
345283346284 | _ ->
347285 if requires_leading_whitespace then
348348- Raise.must_be_followed_by_whitespace
349349- parent_markup_location ~what:(Token.print parent_markup)
286286+ Parse_error.must_be_followed_by_whitespace
287287+ ~what:(Token.print parent_markup) parent_markup_location
288288+ |> Error.raise_exception
350289 else
351290 consume_non_link_inline_elements ~at_start_of_line:false []
352291···384323 then parses a line of inline elements. Afterwards, it looks ahead to the next
385324 line. If that line also begins with an inline element, it parses that line,
386325 and so on. *)
387387-let paragraph
388388- : input -> (int * int) -> Comment.nestable_block_element with_location =
389389- fun input start_offsets ->
326326+let paragraph : input -> Comment.nestable_block_element with_location =
327327+ fun input ->
390328391329 (* Parses a single line of a paragraph, consisting of inline elements. The
392330 only valid ways to end a paragraph line are with [`End], [`Single_newline],
···399337 (Comment.inline_element with_location) list =
400338 fun acc ->
401339 match peek input with
402402- | _, `Space
403403- | _, `Minus
404404- | _, `Plus
405405- | _, `Word _
406406- | _, `Code_span _
407407- | _, `Begin_style _ as stream_head ->
408408- let element = non_link_inline_element stream_head input in
340340+ | {value = `Space; _}
341341+ | {value = `Minus; _}
342342+ | {value = `Plus; _}
343343+ | {value = `Word _; _}
344344+ | {value = `Code_span _; _}
345345+ | {value = `Begin_style _; _} as next_token ->
346346+ let element = non_link_inline_element input next_token in
409347 let acc = (element :> Comment.inline_element with_location)::acc in
410348 paragraph_line acc
411349412412- | l, `Simple_reference r ->
350350+ | {value = `Simple_reference r; location} ->
413351 junk input;
414352 let element =
415415- at_token input l (`Reference (Helpers.read_reference r, [])) in
353353+ Location.at location (`Reference (Helpers.read_reference r, [])) in
416354 paragraph_line (element::acc)
417355418418- | l, (`Begin_reference_with_replacement_text r as parent_markup) ->
356356+ | {value = `Begin_reference_with_replacement_text r as parent_markup;
357357+ location} ->
419358 junk input;
420420- let content, end_location =
359359+360360+ let content, brace_location =
421361 delimited_non_link_inline_element_list
422362 ~parent_markup
423423- ~parent_markup_location:l
363363+ ~parent_markup_location:location
424364 ~requires_leading_whitespace:false
425365 input
426366 in
427367 if content = [] then
428428- Raise.cannot_be_empty l ~what:(Token.describe parent_markup);
429429- let element = `Reference (Helpers.read_reference r, content) in
430430- let element = token_span input l end_location element in
368368+ Parse_error.cannot_be_empty
369369+ ~what:(Token.describe parent_markup) location
370370+ |> Error.raise_exception;
371371+372372+ let element =
373373+ `Reference (Helpers.read_reference r, content)
374374+ |> Location.at (Location.span [location; brace_location])
375375+ in
431376 paragraph_line (element::acc)
432377433433- | l, (`Begin_link_with_replacement_text u as parent_markup) ->
378378+ | {value = `Begin_link_with_replacement_text u as parent_markup;
379379+ location} ->
434380 junk input;
435435- let content, end_location =
381381+382382+ let content, brace_location =
436383 delimited_non_link_inline_element_list
437384 ~parent_markup
438438- ~parent_markup_location:l
385385+ ~parent_markup_location:location
439386 ~requires_leading_whitespace:false
440387 input
441388 in
442442- let element = token_span input l end_location (`Link (u, content)) in
389389+390390+ let element =
391391+ `Link (u, content)
392392+ |> Location.at (Location.span [location; brace_location])
393393+ in
443394 paragraph_line (element::acc)
444395445396 | _ ->
446397 acc
447398 in
448399449449- (* After each row is parsed, decides whether to parse more rows. *)
450450- let rec additional_rows
400400+ (* After each line is parsed, decides whether to parse more lines. *)
401401+ let rec additional_lines
451402 : (Comment.inline_element with_location) list ->
452403 (Comment.inline_element with_location) list =
453404 fun acc ->
454405 match npeek 2 input with
455455- | (l, `Single_newline)::(_, #token_that_begins_a_paragraph_line)::_ ->
406406+ | {value = `Single_newline; location}::
407407+ {value = #token_that_begins_a_paragraph_line; _}::_ ->
456408 junk input;
457457- let acc = (at_token input l `Space)::acc in
409409+ let acc = (Location.at location `Space)::acc in
458410 let acc = paragraph_line acc in
459459- additional_rows acc
411411+ additional_lines acc
460412461413 | _ ->
462414 List.rev acc
463415 in
464416465465- let all_elements = additional_rows (paragraph_line []) in
466466- child_span input start_offsets all_elements (`Paragraph all_elements)
417417+ let elements = paragraph_line [] |> additional_lines in
418418+ `Paragraph elements
419419+ |> Location.at (Location.span (List.map Location.location elements))
467420468421469422···600553 parent_markup:[< Token.t | `Comment ] ->
601554 input ->
602555 (block with_location) list *
603603- stops_at_which_tokens stream_head *
556556+ stops_at_which_tokens with_location *
604557 where_in_line =
605558 fun context ~parent_markup input ->
606559···609562 where_in_line ->
610563 (block with_location) list ->
611564 (block with_location) list *
612612- stops_at_which_tokens stream_head *
565565+ stops_at_which_tokens with_location *
613566 where_in_line =
614567 fun ~parsed_a_tag where_in_line acc ->
615568···619572 | _ -> Token.describe token
620573 in
621574622622- let raise_if_after_text (l, token) =
575575+ let raise_if_after_text {Location.location; value = token} =
623576 if where_in_line = `After_text then
624624- Raise.must_begin_on_its_own_line l ~what:(describe token)
577577+ Parse_error.must_begin_on_its_own_line ~what:(describe token) location
578578+ |> Error.raise_exception
625579 in
626580627627- let raise_if_after_tags (l, token) =
581581+ let raise_if_after_tags {Location.location; value = token} =
628582 if parsed_a_tag then
629583 let suggestion =
630584 Printf.sprintf
631585 "move %s before any tags" (Token.describe token)
632586 in
633633- Raise.not_allowed
634634- l ~what:(describe token) ~in_what:"the tags section" ~suggestion
587587+ Parse_error.not_allowed
588588+ ~what:(describe token)
589589+ ~in_what:"the tags section"
590590+ ~suggestion
591591+ location
592592+ |> Error.raise_exception
635593 in
636594637637- let raise_because_not_at_top_level (l, token) =
595595+ let raise_because_not_at_top_level {Location.location; value = token} =
638596 let suggestion =
639597 Printf.sprintf
640598 "move %s outside of any other markup" (Token.print token)
641599 in
642642- Raise.not_allowed
643643- l
600600+ Parse_error.not_allowed
644601 ~what:(Token.describe token)
645602 ~in_what:(Token.describe parent_markup)
646603 ~suggestion
604604+ location
605605+ |> Error.raise_exception
647606 in
648607649608650609651610 match peek input with
652611 (* Terminators: the two tokens that terminate anything. *)
653653- | _, `End
654654- | _, `Right_brace as stream_head ->
612612+ | {value = `End; _}
613613+ | {value = `Right_brace; _} as next_token ->
655614 (* This little absurdity is needed to satisfy the type system. Without it,
656615 OCaml is unable to prove that [stream_head] has the right type for all
657616 possible values of [context]. *)
658617 begin match context with
659618 | Top_level ->
660660- List.rev acc, stream_head, where_in_line
619619+ List.rev acc, next_token, where_in_line
661620 | In_shorthand_list ->
662662- List.rev acc, stream_head, where_in_line
621621+ List.rev acc, next_token, where_in_line
663622 | In_explicit_list ->
664664- List.rev acc, stream_head, where_in_line
623623+ List.rev acc, next_token, where_in_line
665624 | In_tag ->
666666- List.rev acc, stream_head, where_in_line
625625+ List.rev acc, next_token, where_in_line
667626 end
668627669628···671630 (* Whitespace. This can terminate some kinds of block elements. It is also
672631 necessary to track it to interpret [`Minus] and [`Plus] correctly, as
673632 well as to ensure that all block elements begin on their own line. *)
674674- | _, `Space ->
633633+ | {value = `Space; _} ->
675634 junk input;
676635 consume_block_elements ~parsed_a_tag where_in_line acc
677636678678- | _, `Single_newline ->
637637+ | {value = `Single_newline; _} ->
679638 junk input;
680639 consume_block_elements ~parsed_a_tag `At_start_of_line acc
681640682682- | _, `Blank_line as stream_head ->
641641+ | {value = `Blank_line; _} as next_token ->
683642 begin match context with
684643 (* Blank lines terminate shorthand lists ([- foo]). They also terminate
685644 paragraphs, but the paragraph parser is aware of that internally. *)
686645 | In_shorthand_list ->
687687- List.rev acc, stream_head, where_in_line
646646+ List.rev acc, next_token, where_in_line
688647 (* Otherwise, blank lines are pretty much like single newlines. *)
689648 | _ ->
690649 junk input;
···696655 (* Explicit list items ([{li ...}] and [{- ...}]) can never appear directly
697656 in block content. They can only appear inside [{ul ...}] and [{ol ...}].
698657 So, catch those. *)
699699- | l, (`Begin_list_item _ as token) ->
658658+ | {value = `Begin_list_item _ as token; location} ->
700659 let suggestion =
701660 Printf.sprintf
702661 "move %s into %s, or use %s"
···704663 (Token.describe (`Begin_list `Unordered))
705664 (Token.describe (`Minus))
706665 in
707707- Raise.not_allowed
708708- l
666666+ Parse_error.not_allowed
709667 ~what:(Token.describe token)
710668 ~in_what:(Token.describe parent_markup)
711669 ~suggestion
670670+ location
671671+ |> Error.raise_exception
712672713673714674715675 (* Tags. These can appear at the top level only. Also, once one tag is seen,
716676 the only top-level elements allowed are more tags. *)
717717- | l, (`Tag tag as token) as stream_head ->
677677+ | {value = `Tag tag as token; location} as next_token ->
718678 begin match context with
719679 (* Tags cannot make sense in an explicit list ([{ul {li ...}}]). *)
720680 | In_explicit_list ->
721721- raise_because_not_at_top_level stream_head
681681+ raise_because_not_at_top_level next_token
722682 (* If a tag starts at the beginning of a line, it terminates the preceding
723683 tag and/or the current shorthand list. In this case, return to the
724684 caller, and let the caller decide how to interpret the tag token. *)
725685 | In_shorthand_list ->
726686 if where_in_line = `At_start_of_line then
727727- List.rev acc, stream_head, where_in_line
687687+ List.rev acc, next_token, where_in_line
728688 else
729729- raise_because_not_at_top_level stream_head
689689+ raise_because_not_at_top_level next_token
730690 | In_tag ->
731691 if where_in_line = `At_start_of_line then
732732- List.rev acc, stream_head, where_in_line
692692+ List.rev acc, next_token, where_in_line
733693 else
734734- raise_because_not_at_top_level stream_head
694694+ raise_because_not_at_top_level next_token
735695736696 (* If this is the top-level call to [block_element_list], parse the
737697 tag. *)
738698 | Top_level ->
739699 if where_in_line <> `At_start_of_line then
740740- Raise.must_begin_on_its_own_line l ~what:(Token.describe token);
700700+ Parse_error.must_begin_on_its_own_line
701701+ ~what:(Token.describe token) location
702702+ |> Error.raise_exception;
703703+741704 junk input;
742705743706 begin match tag with
744707 | `Author s | `Since s | `Version s | `Canonical s as tag ->
745708 let s = String.trim s in
746709 if s = "" then
747747- Raise.cannot_be_empty l ~what:(Token.describe token);
710710+ Parse_error.cannot_be_empty ~what:(Token.describe token) location
711711+ |> Error.raise_exception;
748712 let tag =
749713 match tag with
750714 | `Author _ -> `Author s
···755719 let module_ = Helpers.read_mod_longident s in
756720 `Canonical (path, module_)
757721 in
758758- let tag = at_token input l (`Tag tag) in
722722+ let tag = Location.at location (`Tag tag) in
759723 consume_block_elements ~parsed_a_tag:true `After_text (tag::acc)
760724761725 | `Deprecated | `Return as tag ->
···766730 | `Deprecated -> `Deprecated content
767731 | `Return -> `Return content
768732 in
769769- let tag = child_span input l content (`Tag tag) in
733733+ let location =
734734+ location::(List.map Location.location content)
735735+ |> Location.span
736736+ in
737737+ let tag = Location.at location (`Tag tag) in
770738 consume_block_elements ~parsed_a_tag:true where_in_line (tag::acc)
771739772740 | `Param _ | `Raise _ | `Before _ as tag ->
···778746 | `Raise s -> `Raise (s, content)
779747 | `Before s -> `Before (s, content)
780748 in
781781- let tag = child_span input l content (`Tag tag) in
749749+ let location =
750750+ location::(List.map Location.location content)
751751+ |> Location.span
752752+ in
753753+ let tag = Location.at location (`Tag tag) in
782754 consume_block_elements ~parsed_a_tag:true where_in_line (tag::acc)
783755784756 | `See (kind, target) ->
785785- let content, _stream_head, where_in_line =
757757+ let content, _next_token, where_in_line =
786758 block_element_list In_tag ~parent_markup:token input in
759759+ let location =
760760+ location::(List.map Location.location content)
761761+ |> Location.span
762762+ in
787763 let tag = `Tag (`See (kind, target, content)) in
788788- let tag = child_span input l content tag in
764764+ let tag = Location.at location tag in
789765 consume_block_elements ~parsed_a_tag:true where_in_line (tag::acc)
790766 end
791767 end
792768793769794770795795- | l, #token_that_begins_a_paragraph_line as stream_head ->
796796- raise_if_after_tags stream_head;
797797- raise_if_after_text stream_head;
798798- let block = paragraph input l in
771771+ | {value = #token_that_begins_a_paragraph_line; _} as next_token ->
772772+ raise_if_after_tags next_token;
773773+ raise_if_after_text next_token;
774774+775775+ let block = paragraph input in
799776 let block =
800777 Model.Location_.map (accepted_in_all_contexts context) block in
801778 let acc = block::acc in
802779 consume_block_elements ~parsed_a_tag `After_text acc
803780804804- | l, ((`Code_block s | `Verbatim s) as token) as stream_head ->
805805- raise_if_after_tags stream_head;
806806- raise_if_after_text stream_head;
781781+ | {value = `Code_block s | `Verbatim s as token; location} as next_token ->
782782+ raise_if_after_tags next_token;
783783+ raise_if_after_text next_token;
807784 if s = "" then
808808- Raise.cannot_be_empty l ~what:(Token.describe token);
785785+ Parse_error.cannot_be_empty ~what:(Token.describe token) location
786786+ |> Error.raise_exception;
787787+809788 junk input;
810789 let block =
811790 match token with
···813792 | `Verbatim _ -> `Verbatim s
814793 in
815794 let block = accepted_in_all_contexts context block in
816816- let block = at_token input l block in
795795+ let block = Location.at location block in
817796 let acc = block::acc in
818797 consume_block_elements ~parsed_a_tag `After_text acc
819798820820- | l, (`Modules s as token) as stream_head ->
821821- raise_if_after_tags stream_head;
822822- raise_if_after_text stream_head;
799799+ | {value = `Modules s as token; location} as next_token ->
800800+ raise_if_after_tags next_token;
801801+ raise_if_after_text next_token;
823802824803 junk input;
825804···857836 in
858837859838 if modules = [] then
860860- Raise.cannot_be_empty l ~what:(Token.describe token);
839839+ Parse_error.cannot_be_empty ~what:(Token.describe token) location
840840+ |> Error.raise_exception;
861841862842 let block = accepted_in_all_contexts context (`Modules modules) in
863863- let block = at_token input l block in
843843+ let block = Location.at location block in
864844 let acc = block::acc in
865845 consume_block_elements ~parsed_a_tag `After_text acc
866846867847868848869869- | l, (`Begin_list kind as token) as stream_head ->
870870- raise_if_after_tags stream_head;
871871- raise_if_after_text stream_head;
849849+ | {value = `Begin_list kind as token; location} as next_token ->
850850+ raise_if_after_tags next_token;
851851+ raise_if_after_text next_token;
852852+872853 junk input;
873873- let items, right_brace_offsets =
854854+855855+ let items, brace_location =
874856 explicit_list_items ~parent_markup:token input in
875857 if items = [] then
876876- Raise.cannot_be_empty l ~what:(Token.describe token);
858858+ Parse_error.cannot_be_empty ~what:(Token.describe token) location
859859+ |> Error.raise_exception;
860860+861861+ let location = Location.span [location; brace_location] in
877862 let block = `List (kind, items) in
878863 let block = accepted_in_all_contexts context block in
879879- let block = token_span input l right_brace_offsets block in
864864+ let block = Location.at location block in
880865 let acc = block::acc in
881866 consume_block_elements ~parsed_a_tag `After_text acc
882867883868884869885885- | l, (`Minus | `Plus as token) as stream_head ->
886886- raise_if_after_tags stream_head;
870870+ | {value = `Minus | `Plus as token; location} as next_token ->
871871+ raise_if_after_tags next_token;
887872 begin match where_in_line with
888873 | `After_text | `After_shorthand_bullet ->
889889- Raise.must_begin_on_its_own_line l ~what:(Token.describe token);
874874+ Parse_error.must_begin_on_its_own_line
875875+ ~what:(Token.describe token) location
876876+ |> Error.raise_exception
890877 | _ ->
891878 ()
892879 end;
880880+893881 begin match context with
894882 | In_shorthand_list ->
895895- List.rev acc, stream_head, where_in_line
883883+ List.rev acc, next_token, where_in_line
896884 | _ ->
897885 let items, where_in_line =
898898- shorthand_list_items stream_head where_in_line input in
886886+ shorthand_list_items next_token where_in_line input in
899887 let kind =
900888 match token with
901889 | `Minus -> `Unordered
902890 | `Plus -> `Ordered
903891 in
892892+ let location =
893893+ location::(List.map Location.location (List.flatten items))
894894+ |> Location.span
895895+ in
904896 let block = `List (kind, items) in
905897 let block = accepted_in_all_contexts context block in
906906- let block = child_span input l (List.flatten items) block in
898898+ let block = Location.at location block in
907899 let acc = block::acc in
908900 consume_block_elements ~parsed_a_tag where_in_line acc
909901 end
910902911903912904913913- | l, (`Begin_section_heading (level, label) as token) as stream_head ->
914914- raise_if_after_tags stream_head;
905905+ | {value = `Begin_section_heading (level, label) as token; location}
906906+ as next_token ->
907907+908908+ raise_if_after_tags next_token;
915909916910 begin match context with
917911 | In_shorthand_list ->
918912 if where_in_line = `At_start_of_line then
919919- List.rev acc, stream_head, where_in_line
913913+ List.rev acc, next_token, where_in_line
920914 else
921921- raise_because_not_at_top_level stream_head
915915+ raise_because_not_at_top_level next_token
922916 | In_explicit_list ->
923923- raise_because_not_at_top_level stream_head
917917+ raise_because_not_at_top_level next_token
924918 | In_tag ->
925925- raise_because_not_at_top_level stream_head
919919+ raise_because_not_at_top_level next_token
926920927921 | Top_level ->
928922 if where_in_line <> `At_start_of_line then
929929- Raise.must_begin_on_its_own_line l ~what:(Token.describe token);
923923+ Parse_error.must_begin_on_its_own_line
924924+ ~what:(Token.describe token) location
925925+ |> Error.raise_exception;
926926+930927 junk input;
931928932932- let content, right_brace_offsets =
929929+ let content, brace_location =
933930 delimited_non_link_inline_element_list
934931 ~parent_markup:token
935935- ~parent_markup_location:l
932932+ ~parent_markup_location:location
936933 ~requires_leading_whitespace:true
937934 input
938935 in
939936 if content = [] then
940940- Raise.cannot_be_empty l ~what:(Token.describe token);
937937+ Parse_error.cannot_be_empty ~what:(Token.describe token) location
938938+ |> Error.raise_exception;
941939940940+ let location = Location.span [location; brace_location] in
942941 let heading = `Heading (level, label, content) in
943943- let heading = token_span input l right_brace_offsets heading in
942942+ let heading = Location.at location heading in
944943 let acc = heading::acc in
945944 consume_block_elements ~parsed_a_tag `After_text acc
946945 end
···969968 above). That parser returns to [implicit_list_items] only on [`Blank_line],
970969 [`End], [`Minus] or [`Plus] at the start of a line, or [`Right_brace]. *)
971970and shorthand_list_items
972972- : [ `Minus | `Plus ] stream_head ->
971971+ : [ `Minus | `Plus ] with_location ->
973972 where_in_line ->
974973 input ->
975974 ((Comment.nestable_block_element with_location) list) list *
976975 where_in_line =
977977- fun ((_, bullet_token) as stream_head) where_in_line input ->
976976+ fun first_token where_in_line input ->
977977+978978+ let bullet_token = first_token.value in
978979979980 let rec consume_list_items
980980- : [> ] stream_head ->
981981+ : [> ] with_location ->
981982 where_in_line ->
982983 ((Comment.nestable_block_element with_location) list) list ->
983984 ((Comment.nestable_block_element with_location) list) list *
984985 where_in_line =
985985- fun stream_head where_in_line acc ->
986986+ fun next_token where_in_line acc ->
986987987987- match stream_head with
988988- | _, `End
989989- | _, `Right_brace
990990- | _, `Blank_line
991991- | _, `Tag _
992992- | _, `Begin_section_heading _ ->
988988+ match next_token.value with
989989+ | `End
990990+ | `Right_brace
991991+ | `Blank_line
992992+ | `Tag _
993993+ | `Begin_section_heading _ ->
993994 List.rev acc, where_in_line
994995995995- | l, (`Minus | `Plus as bullet) ->
996996+ | `Minus
997997+ | `Plus as bullet ->
996998 if bullet = bullet_token then begin
997999 junk input;
99810009991001 let content, stream_head, where_in_line =
10001002 block_element_list In_shorthand_list ~parent_markup:bullet input in
10011003 if content = [] then
10021002- Raise.cannot_be_empty l ~what:(Token.describe bullet);
10041004+ Parse_error.cannot_be_empty
10051005+ ~what:(Token.describe bullet) next_token.location
10061006+ |> Error.raise_exception;
1003100710041008 let acc = content::acc in
10051009 consume_list_items stream_head where_in_line acc
···10091013 in
1010101410111015 consume_list_items
10121012- (stream_head :> stopped_implicitly stream_head) where_in_line []
10161016+ (first_token :> stopped_implicitly with_location) where_in_line []
1013101710141018(* Consumes a sequence of explicit list items (starting with '{li ...}' and
10151019 '{-...}', which are represented by [`Begin_list_item _] tokens).
···10251029 : parent_markup:[< Token.t ] ->
10261030 input ->
10271031 ((Comment.nestable_block_element with_location) list) list *
10281028- (int * int) =
10321032+ Location.span =
10291033 fun ~parent_markup input ->
1030103410311035 let rec consume_list_items
10321036 : ((Comment.nestable_block_element with_location) list) list ->
10331037 ((Comment.nestable_block_element with_location) list) list *
10341034- (int * int) =
10381038+ Location.span =
10351039 fun acc ->
1036104010371037- match peek input with
10381038- | l, `End ->
10391039- Raise.not_allowed
10401040- l ~what:(Token.describe `End) ~in_what:(Token.describe parent_markup)
10411041+ let next_token = peek input in
10421042+ match next_token.value with
10431043+ | `End ->
10441044+ Parse_error.not_allowed
10451045+ next_token.location
10461046+ ~what:(Token.describe `End)
10471047+ ~in_what:(Token.describe parent_markup)
10481048+ |> Error.raise_exception
1041104910421042- | l, `Right_brace ->
10501050+ | `Right_brace ->
10431051 junk input;
10441044- List.rev acc, l
10521052+ List.rev acc, next_token.location
1045105310461046- | _, `Space
10471047- | _, `Single_newline
10481048- | _, `Blank_line ->
10541054+ | `Space
10551055+ | `Single_newline
10561056+ | `Blank_line ->
10491057 junk input;
10501058 consume_list_items acc
1051105910521052- | l, (`Begin_list_item kind as token) ->
10601060+ | `Begin_list_item kind as token ->
10531061 junk input;
1054106210551063 (* '{li', represented by [`Begin_list_item `Li], must be followed by
10561064 whitespace. *)
10571065 if kind = `Li then begin
10581058- match peek input with
10591059- | _, (`Space | `Single_newline | `Blank_line | `Right_brace) ->
10661066+ match (peek input).value with
10671067+ | `Space | `Single_newline | `Blank_line | `Right_brace ->
10601068 ()
10611069 (* The presence of [`Right_brace] above requires some explanation:
10621070···10711079 it is not represented as [`Space], [`Single_newline], or
10721080 [`Blank_line]. *)
10731081 | _ ->
10741074- Raise.must_be_followed_by_whitespace l ~what:(Token.print token)
10821082+ Parse_error.must_be_followed_by_whitespace
10831083+ next_token.location ~what:(Token.print token)
10841084+ |> Error.raise_exception
10751085 end;
1076108610771077- let content, stream_head, _where_in_line =
10871087+ let content, token_after_list_item, _where_in_line =
10781088 block_element_list In_explicit_list ~parent_markup:token input in
1079108910801090 if content = [] then
10811081- Raise.cannot_be_empty l ~what:(Token.describe token);
10911091+ Parse_error.cannot_be_empty
10921092+ next_token.location ~what:(Token.describe token)
10931093+ |> Error.raise_exception;
1082109410831083- begin match stream_head with
10841084- | _, `Right_brace ->
10951095+ begin match token_after_list_item.value with
10961096+ | `Right_brace ->
10851097 junk input
10861086- | l', `End ->
10871087- Raise.not_allowed
10881088- l' ~what:(Token.describe `End) ~in_what:(Token.describe token)
10981098+ | `End ->
10991099+ Parse_error.not_allowed
11001100+ token_after_list_item.location
11011101+ ~what:(Token.describe `End)
11021102+ ~in_what:(Token.describe token)
11031103+ |> Error.raise_exception
10891104 end;
1090110510911106 let acc = content::acc in
10921107 consume_list_items acc
1093110810941094- | l, token ->
11091109+ | token ->
10951110 let suggestion =
10961111 match token with
10971112 | `Begin_section_heading _ | `Tag _ ->
···11031118 (Token.print (`Begin_list_item `Li))
11041119 (Token.print (`Begin_list_item `Dash))
11051120 in
11061106- Raise.not_allowed
11071107- l
11211121+ Parse_error.not_allowed
11221122+ next_token.location
11081123 ~what:(Token.describe token)
11091124 ~in_what:(Token.describe parent_markup)
11101125 ~suggestion
11261126+ |> Error.raise_exception
11111127 in
1112112811131129 consume_list_items []
···1116113211171133(* {2 Entry point} *)
1118113411191119-let parse ~file ~offset_to_location ~token_stream =
11201120- let input = {file; offset_to_location; token_stream} in
11211121-11221122- let elements, stream_head, _where_in_line =
11231123- block_element_list Top_level ~parent_markup:`Comment input in
11241124-11251125- match stream_head with
11261126- | _, `End ->
11271127- elements
11351135+let parse token_stream =
11361136+ Error.catch begin fun () ->
11371137+ let elements, last_token, _where_in_line =
11381138+ block_element_list Top_level ~parent_markup:`Comment token_stream in
1128113911291129- | l, `Right_brace ->
11301130- raise_notrace (Helpers.Parse_error {
11311131- start_offset = fst l;
11321132- end_offset = snd l;
11331133- text = "unpaired '}' (end of markup)"
11341134- })
11401140+ match last_token.value with
11411141+ | `End ->
11421142+ elements
11431143+ | `Right_brace ->
11441144+ Parse_error.unpaired_right_brace last_token.location
11451145+ |> Error.raise_exception
11461146+ end