···12.1.3 [???]
2* Fix module link order (broken by #37) [#41 @dra27]
3-* opam-version: "2.1" must appear at most once and as the first non-comment item [#43 @dra27]
000452.1.2 [07 Jan 2021]
6* Some hash-consing for strings [#27 @AltGr]
···12.1.3 [???]
2* Fix module link order (broken by #37) [#41 @dra27]
3+* opam-version: "2.1" must appear at most once and as the first non-comment
4+ item. If opam-version is at the start and is greater than the library version,
5+ `OpamLexer.Error` and `Parsing.Parse_error` are no longer raised; instead the
6+ items parsed so far are returned. [#43 @dra27]
782.1.2 [07 Jan 2021]
9* Some hash-consing for strings [#27 @AltGr]
···2627let get_pos n = get_pos_full ~s:n n
280000000029%}
3031%token <string> STRING IDENT
···61%%
6263main:
64-| items EOF { fun file_name ->
65 { file_contents = $1; file_name } }
66;
67···7273item:
74| IDENT COLON value {
075 { pos = get_pos_full 3;
76 pelem =
77 Variable ({ pos = get_pos 1; pelem = $1 }, $3);
78 }
79}
80| IDENT LBRACE items RBRACE {
081 { pos = get_pos_full 4;
82 pelem =
83 Section ({section_kind = { pos = get_pos 1; pelem = $1 };
···88 }
89}
90| IDENT STRING LBRACE items RBRACE {
091 { pos = get_pos_full 4;
92 pelem =
93 Section ({section_kind = { pos = get_pos 1; pelem = $1 };
···145 try Scanf.sscanf s "%u.%u" (fun maj min -> (maj, min))
146 with Scanf.Scan_failure _ -> (0, 0)
147148-let main t l f =
149- let r =
150- try
151- let r = main t l f in
152- Parsing.clear_parser ();
153- r
00000000000154 with
155- | e ->
156- Parsing.clear_parser ();
157- raise e in
158- match r with
159- | {file_contents = {pelem = Variable({pelem = "opam-version"; _}, {pelem = String ver; _}); _}::items; _}
160- when nopatch ver >= (2, 1) ->
161- let opam_version_variable = function
162- | {pelem = Variable({pelem = "opam-version"; _}, _); _} -> true
163- | _ -> false
164- in
165- (* For opam-version: 2.1 and later, there must be no other opam-version
166- fields. *)
167- if List.exists opam_version_variable items then
168- raise Parsing.Parse_error;
169- r
170- | {file_contents = items; _} ->
171- let opam_version_greater_2_0 = function
172- | {pelem = Variable({pelem = "opam-version"; _}, {pelem = String ver; _}); _} ->
173- nopatch ver > (2, 0)
174- | _ -> false
175- in
176- (* opam-version: 2.1 or later must be the first item. *)
177- if List.exists opam_version_greater_2_0 items then
178- raise Parsing.Parse_error;
179 r
00000000000000000000000000000000180181let value t l =
182 try
···2627let get_pos n = get_pos_full ~s:n n
2829+let parsed_so_far = ref []
30+31+let record_token t =
32+ parsed_so_far := t :: !parsed_so_far; t
33+34+(* This must match up with the package's version; checked by the build system *)
35+let version = (2, 1)
36+37%}
3839%token <string> STRING IDENT
···69%%
7071main:
72+| items EOF { parsed_so_far := []; fun file_name ->
73 { file_contents = $1; file_name } }
74;
75···8081item:
82| IDENT COLON value {
83+ record_token
84 { pos = get_pos_full 3;
85 pelem =
86 Variable ({ pos = get_pos 1; pelem = $1 }, $3);
87 }
88}
89| IDENT LBRACE items RBRACE {
90+ record_token
91 { pos = get_pos_full 4;
92 pelem =
93 Section ({section_kind = { pos = get_pos 1; pelem = $1 };
···98 }
99}
100| IDENT STRING LBRACE items RBRACE {
101+ record_token
102 { pos = get_pos_full 4;
103 pelem =
104 Section ({section_kind = { pos = get_pos 1; pelem = $1 };
···156 try Scanf.sscanf s "%u.%u" (fun maj min -> (maj, min))
157 with Scanf.Scan_failure _ -> (0, 0)
158159+let with_clear_parser f x =
160+ try
161+ let r = f x in
162+ Parsing.clear_parser ();
163+ r
164+ with e ->
165+ Parsing.clear_parser ();
166+ raise e
167+168+exception Nothing
169+170+let main t l file_name =
171+ (* Always return a result from parsing/lexing, but note if an exception
172+ occurred. *)
173+ let parsing_exception = ref Nothing in
174+ let t l =
175+ try t l
176 with
177+ | Sys.Break
178+ | Assert_failure _
179+ | Match_failure _ as e -> raise e
180+ | e -> parsing_exception := e; EOF
181+ in
182+ let r =
183+ try with_clear_parser (main t l) file_name
184+ with Parsing.Parse_error as e ->
185+ parsing_exception := e;
186+ (* Record the tokens captured so far *)
187+ let r = {file_contents = List.rev !parsed_so_far; file_name} in
188+ parsed_so_far := [];
000000000000189 r
190+ in
191+ match r with
192+ | {file_contents = {pelem = Variable({pelem = "opam-version"; _}, {pelem = String ver; _}); _}::items; _}
193+ when nopatch ver >= (2, 1) ->
194+ let opam_version_variable = function
195+ | {pelem = Variable({pelem = "opam-version"; _}, _); _} -> true
196+ | _ -> false
197+ in
198+ (* For opam-version: 2.1 and later, there must be no other opam-version
199+ fields. *)
200+ if List.exists opam_version_variable items then
201+ raise Parsing.Parse_error;
202+ (* Parsing and lexing errors from future versions of opam are ignored:
203+ the intent is that the tool will abort/ignore because of the
204+ opam-version field rather than through lexer/parser errors. *)
205+ if !parsing_exception != Nothing && nopatch ver <= version then
206+ raise !parsing_exception;
207+ r
208+ | {file_contents = items; _} ->
209+ let opam_version_greater_2_0 = function
210+ | {pelem = Variable({pelem = "opam-version"; _}, {pelem = String ver; _}); _} ->
211+ nopatch ver > (2, 0)
212+ | _ -> false
213+ in
214+ (* opam-version: 2.1 or later must be the first item. *)
215+ if List.exists opam_version_greater_2_0 items then
216+ raise Parsing.Parse_error;
217+ (* If no opam-version field was given, all exceptions must be
218+ raised. *)
219+ if !parsing_exception != Nothing then
220+ raise !parsing_exception;
221+ r
222223let value t l =
224 try