···112.1.3 [???]
22* Fix module link order (broken by #37) [#41 @dra27]
33-* opam-version: "2.1" must appear at most once and as the first non-comment item [#43 @dra27]
33+* opam-version: "2.1" must appear at most once and as the first non-comment
44+ item. If opam-version is at the start and is greater than the library version,
55+ `OpamLexer.Error` and `Parsing.Parse_error` are no longer raised; instead the
66+ items parsed so far are returned. [#43 @dra27]
47582.1.2 [07 Jan 2021]
69* Some hash-consing for strings [#27 @AltGr]
···26262727let get_pos n = get_pos_full ~s:n n
28282929+let parsed_so_far = ref []
3030+3131+let record_token t =
3232+ parsed_so_far := t :: !parsed_so_far; t
3333+3434+(* This must match up with the package's version; checked by the build system *)
3535+let version = (2, 1)
3636+2937%}
30383139%token <string> STRING IDENT
···6169%%
62706371main:
6464-| items EOF { fun file_name ->
7272+| items EOF { parsed_so_far := []; fun file_name ->
6573 { file_contents = $1; file_name } }
6674;
6775···72807381item:
7482| IDENT COLON value {
8383+ record_token
7584 { pos = get_pos_full 3;
7685 pelem =
7786 Variable ({ pos = get_pos 1; pelem = $1 }, $3);
7887 }
7988}
8089| IDENT LBRACE items RBRACE {
9090+ record_token
8191 { pos = get_pos_full 4;
8292 pelem =
8393 Section ({section_kind = { pos = get_pos 1; pelem = $1 };
···8898 }
8999}
90100| IDENT STRING LBRACE items RBRACE {
101101+ record_token
91102 { pos = get_pos_full 4;
92103 pelem =
93104 Section ({section_kind = { pos = get_pos 1; pelem = $1 };
···145156 try Scanf.sscanf s "%u.%u" (fun maj min -> (maj, min))
146157 with Scanf.Scan_failure _ -> (0, 0)
147158148148-let main t l f =
149149- let r =
150150- try
151151- let r = main t l f in
152152- Parsing.clear_parser ();
153153- r
159159+let with_clear_parser f x =
160160+ try
161161+ let r = f x in
162162+ Parsing.clear_parser ();
163163+ r
164164+ with e ->
165165+ Parsing.clear_parser ();
166166+ raise e
167167+168168+exception Nothing
169169+170170+let main t l file_name =
171171+ (* Always return a result from parsing/lexing, but note if an exception
172172+ occurred. *)
173173+ let parsing_exception = ref Nothing in
174174+ let t l =
175175+ try t l
154176 with
155155- | e ->
156156- Parsing.clear_parser ();
157157- raise e in
158158- match r with
159159- | {file_contents = {pelem = Variable({pelem = "opam-version"; _}, {pelem = String ver; _}); _}::items; _}
160160- when nopatch ver >= (2, 1) ->
161161- let opam_version_variable = function
162162- | {pelem = Variable({pelem = "opam-version"; _}, _); _} -> true
163163- | _ -> false
164164- in
165165- (* For opam-version: 2.1 and later, there must be no other opam-version
166166- fields. *)
167167- if List.exists opam_version_variable items then
168168- raise Parsing.Parse_error;
169169- r
170170- | {file_contents = items; _} ->
171171- let opam_version_greater_2_0 = function
172172- | {pelem = Variable({pelem = "opam-version"; _}, {pelem = String ver; _}); _} ->
173173- nopatch ver > (2, 0)
174174- | _ -> false
175175- in
176176- (* opam-version: 2.1 or later must be the first item. *)
177177- if List.exists opam_version_greater_2_0 items then
178178- raise Parsing.Parse_error;
177177+ | Sys.Break
178178+ | Assert_failure _
179179+ | Match_failure _ as e -> raise e
180180+ | e -> parsing_exception := e; EOF
181181+ in
182182+ let r =
183183+ try with_clear_parser (main t l) file_name
184184+ with Parsing.Parse_error as e ->
185185+ parsing_exception := e;
186186+ (* Record the tokens captured so far *)
187187+ let r = {file_contents = List.rev !parsed_so_far; file_name} in
188188+ parsed_so_far := [];
179189 r
190190+ in
191191+ match r with
192192+ | {file_contents = {pelem = Variable({pelem = "opam-version"; _}, {pelem = String ver; _}); _}::items; _}
193193+ when nopatch ver >= (2, 1) ->
194194+ let opam_version_variable = function
195195+ | {pelem = Variable({pelem = "opam-version"; _}, _); _} -> true
196196+ | _ -> false
197197+ in
198198+ (* For opam-version: 2.1 and later, there must be no other opam-version
199199+ fields. *)
200200+ if List.exists opam_version_variable items then
201201+ raise Parsing.Parse_error;
202202+ (* Parsing and lexing errors from future versions of opam are ignored:
203203+ the intent is that the tool will abort/ignore because of the
204204+ opam-version field rather than through lexer/parser errors. *)
205205+ if !parsing_exception != Nothing && nopatch ver <= version then
206206+ raise !parsing_exception;
207207+ r
208208+ | {file_contents = items; _} ->
209209+ let opam_version_greater_2_0 = function
210210+ | {pelem = Variable({pelem = "opam-version"; _}, {pelem = String ver; _}); _} ->
211211+ nopatch ver > (2, 0)
212212+ | _ -> false
213213+ in
214214+ (* opam-version: 2.1 or later must be the first item. *)
215215+ if List.exists opam_version_greater_2_0 items then
216216+ raise Parsing.Parse_error;
217217+ (* If no opam-version field was given, all exceptions must be
218218+ raised. *)
219219+ if !parsing_exception != Nothing then
220220+ raise !parsing_exception;
221221+ r
180222181223let value t l =
182224 try