Coccinelle release 1.0.0-rc12
[bpt/coccinelle.git] / bundles / sexplib / sexplib-7.0.5 / lib / sexp_intf.ml
1 (******************************************************************************
2 * Sexplib *
3 * *
4 * Copyright (C) 2005- Jane Street Holding, LLC *
5 * Contact: opensource@janestreet.com *
6 * WWW: http://www.janestreet.com/ocaml *
7 * Author: Markus Mottl *
8 * *
9 * This library is free software; you can redistribute it and/or *
10 * modify it under the terms of the GNU Lesser General Public *
11 * License as published by the Free Software Foundation; either *
12 * version 2 of the License, or (at your option) any later version. *
13 * *
14 * This library is distributed in the hope that it will be useful, *
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
17 * Lesser General Public License for more details. *
18 * *
19 * You should have received a copy of the GNU Lesser General Public *
20 * License along with this library; if not, write to the Free Software *
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
22 * *
23 ******************************************************************************)
24
25 (** Sexp_intf: interface specification for handling S-expressions (I/O, etc.) *)
26
27 open Format
28 open Bigarray
29
30 module type S = sig
31
32 (** Type of S-expressions *)
33 type t = Type.t = Atom of string | List of t list
34
35 (** Type of bigstrings *)
36 type bigstring = (char, int8_unsigned_elt, c_layout) Array1.t
37
38
39 (** {6 Defaults} *)
40
41 val default_indent : int ref
42 (** [default_indent] reference to default indentation level for
43 human-readable conversions. Initialisation value: 2. *)
44
45
46 (** {6 S-expression size} *)
47
48 val size : t -> int * int
49 (** [size sexp] @return [(n_atoms, n_chars)], where [n_atoms] is
50 the number of atoms in S-expression [sexp], and [n_chars] is the
51 number of characters in the atoms of the S-expression. *)
52
53
54 (** {6 Scan functions} *)
55
56 val scan_sexp : ?buf : Buffer.t -> Lexing.lexbuf -> t
57 (** [scan_sexp ?buf lexbuf] scans an S-expression from lex buffer
58 [lexbuf] using the optional string buffer [buf] for storing
59 intermediate strings. *)
60
61 val scan_sexps : ?buf : Buffer.t -> Lexing.lexbuf -> t list
62 (** [scan_sexps ?buf lexbuf] reads a list of whitespace separated
63 S-expressions from lex buffer [lexbuf] using the optional string
64 buffer [buf] for storing intermediate strings. *)
65
66 val scan_iter_sexps :
67 ?buf : Buffer.t -> f : (t -> unit) -> Lexing.lexbuf -> unit
68 (** [scan_iter_sexps ?buf ~f lexbuf] iterates over all whitespace
69 separated S-expressions scanned from lex buffer [lexbuf] using
70 function [f], and the optional string buffer [buf] for storing
71 intermediate strings. *)
72
73 val scan_fold_sexps :
74 ?buf : Buffer.t -> f : ('a -> t -> 'a) -> init : 'a -> Lexing.lexbuf -> 'a
75 (** [scan_fold_sexps ?buf ~f ~init lexbuf] folds over all whitespace
76 separated S-expressions scanned from lex buffer [lexbuf] using
77 function [f], initial state [init], and the optional string buffer
78 [buf] for storing intermediate strings. *)
79
80 val scan_sexps_conv :
81 ?buf : Buffer.t -> f : (t -> 'a) -> Lexing.lexbuf -> 'a list
82 (** [scan_sexps_conv ?buf ~f lexbuf] maps all whitespace separated
83 S-expressions scanned from lex buffer [lexbuf] to some list using
84 function [f], and the optional string buffer [buf] for storing
85 intermediate strings. *)
86
87
88 (** {6 Type and exception definitions for (partial) parsing} *)
89
90 module Parse_pos : sig
91 (** Position information after complete parse *)
92 type t = Pre_sexp.Parse_pos.t =
93 private
94 {
95 mutable text_line : int; (** Line position in parsed text *)
96 mutable text_char : int; (** Character position in parsed text *)
97 mutable global_offset : int; (** Global/logical offset *)
98 mutable buf_pos : int; (** Read position in string buffer *)
99 }
100
101 val create :
102 ?text_line : int -> ?text_char : int ->
103 ?buf_pos : int -> ?global_offset : int -> unit -> t
104 (** [create ?text_line ?text_char ?buf_pos ?global_offset ()] @return
105 a parse position with the given parameters.
106
107 @param text_line default = [1]
108 @param text_char default = [0]
109 @param global_offset default = [0]
110 @param buf_pos default = [0]
111 *)
112
113 val with_buf_pos : t -> int -> t
114 (** [with_buf_pos t pos] @return a copy of the parse position [t] where
115 [buf_pos] is set to [pos]. *)
116 end
117
118 (** Type of result from calling {!Sexp.parse}. *)
119 type ('a, 't) parse_result = ('a, 't) Pre_sexp.parse_result =
120 | Done of 't * Parse_pos.t (** [Done (t, parse_pos)] finished parsing
121 an S-expression. Current parse position
122 is [parse_pos]. *)
123 | Cont of bool * ('a, 't) parse_fun
124 (** [Cont (ws_only, parse_fun)] met the end of input before completely
125 parsing an S-expression. The user has to call [parse_fun] to
126 continue parsing the S-expression in another buffer. If [ws_only]
127 is true, only whitespace has been parsed so far (or comments!).
128 NOTE: the continuation may only be called once and will raise
129 [Failure] otherwise! *)
130
131 (** Type of parsing functions with given offsets and lengths. *)
132 and ('a, 't) parse_fun = pos : int -> len : int -> 'a -> ('a, 't) parse_result
133
134 (** Module for parsing S-expressions annotated with location information *)
135 module Annotated : sig
136 (** Position information for annotated S-expressions *)
137 type pos = Pre_sexp.Annotated.pos = {
138 line : int;
139 col : int;
140 offset : int;
141 }
142
143 (** Range information for annotated S-expressions *)
144 type range = Pre_sexp.Annotated.range = { start_pos : pos; end_pos : pos }
145
146 (** S-expression annotated with location information *)
147 type t = Pre_sexp.Annotated.t =
148 | Atom of range * Type.t
149 | List of range * t list * Type.t
150
151 (** Type of conversion results of annotated S-expressions. *)
152 type 'a conv = [ `Result of 'a | `Error of exn * t ]
153
154 (** Exception associated with conversion errors. First argument describes
155 the location, the second the reason. *)
156 exception Conv_exn of string * exn
157
158 (** Stack used by annotation parsers *)
159 type stack = Pre_sexp.Annotated.stack = {
160 mutable positions : pos list;
161 mutable stack : t list list;
162 }
163
164 val get_sexp : t -> Type.t
165 (** [get_sexp annot_sexp] @return S-expression associated with annotated
166 S-expression [annot_sexp]. *)
167
168 val get_range : t -> range
169 (** [get_range annot_sexp] @return the range associated with annotated
170 S-expression [annot_sexp]. *)
171
172 val find_sexp : t -> Type.t -> t option
173 (** [find_sexp annot_sexp sexp] @return [Some res] where [res] is the
174 annotated S-expression that is physically equivalent to [sexp] in
175 [annot_sexp], or [None] if there is no such S-expression. *)
176
177
178 (** {6 Annotated (partial) parsing} *)
179
180 val parse :
181 ?parse_pos : Parse_pos.t -> ?len : int -> string
182 -> (string, t) parse_result
183 (** [parse ?parse_pos ?len str] same as {!parse}, but returns an
184 S-expression annotated with location information. *)
185
186 val parse_bigstring :
187 ?parse_pos : Parse_pos.t -> ?len : int -> bigstring
188 -> (bigstring, t) parse_result
189 (** [parse_bigstring ?parse_pos ?len str] same as {!parse_bigstring},
190 but returns an S-expression annotated with location information. *)
191
192 val input_sexp : ?parse_pos : Parse_pos.t -> in_channel -> t
193 (** [input_sexp ?parse_pos ic] like {!input_sexp}, but returns an
194 annotated S-expression instead. *)
195
196 val input_sexps :
197 ?parse_pos : Parse_pos.t -> ?buf : string -> in_channel -> t list
198 (** [input_sexps ?parse_pos ?buf ic] like {!input_sexps}, but returns
199 a list of annotated S-expressions. *)
200
201 val input_rev_sexps :
202 ?parse_pos : Parse_pos.t -> ?buf : string -> in_channel -> t list
203 (** [input_sexps ?parse_pos ?buf ic] like {!input_rev_sexps}, but
204 returns a list of annotated S-expressions. *)
205
206
207 (** {6 Loading of annotated S-expressions} *)
208
209 (** NOTE: these functions should only be used if an annotated S-expression
210 is required. *)
211
212 val load_sexp : ?strict : bool -> ?buf : string -> string -> t
213 (** [load_sexp ?strict ?buf file] like {!load_sexp}, but returns an
214 annotated S-expression. *)
215
216 val load_sexps : ?buf : string -> string -> t list
217 (** [load_sexps ?buf file] like {!load_sexps}, but returns a list of
218 annotated S-expressions. *)
219
220 val load_rev_sexps : ?buf : string -> string -> t list
221 (** [load_rev_sexps ?buf file] like {!load_rev_sexps}, but returns a
222 list of annotated S-expressions. *)
223
224
225 (** {6 String and bigstring conversions} *)
226
227 val of_string : string -> t
228 (** [of_string str] same as {!of_string}, but returns an annotated
229 S-expression. *)
230
231 val of_bigstring : bigstring -> t
232 (** [of_bigstring bstr] same as {!of_string}, but operates on bigstrings. *)
233
234
235 (** Converters using annotations for determining error locations *)
236
237 val conv : (Type.t -> 'a) -> t -> 'a conv
238 (** [conv f annot_sexp] converts the S-expression associated with
239 annotated S-expression [annot_sexp] using [f]. @return [`Result
240 res] on success, or [`Error (exn, sub_annot_sexp)] otherwise, where
241 [exn] is the exception associated with the conversion error, and
242 [sub_annot_sexp] is the annotated S-expression on which conversion
243 failed. *)
244
245 val get_conv_exn : file : string -> exc : exn -> t -> exn
246 (** [get_conv_exn ~file ~exc annot_sexp] @return the exception that
247 would be raised for a given [file] and exception [exc]
248 if conversion had failed on annotated S-expression [annot_sexp].
249 The format of the exception message is "file:line:col" *)
250 end
251
252 (** Type of state maintained during parsing *)
253 type 't parse_state = 't Pre_sexp.parse_state =
254 private
255 {
256 parse_pos : Parse_pos.t; (** Current parse position *)
257 mutable pstack : 't; (** Stack of found S-expression lists *)
258 pbuf : Buffer.t; (** Current atom buffer *)
259 }
260
261 (** Type of parse errors *)
262 type parse_error = Pre_sexp.parse_error =
263 {
264 location : string; (** Function in which the parse failed *)
265 err_msg : string; (** Reason why parsing failed *)
266 parse_state :
267 [
268 | `Sexp of t list list parse_state
269 | `Annot of Annotated.stack parse_state
270 ]
271 (** State of parser *)
272 }
273
274 (** Exception raised during partial parsing *)
275 exception Parse_error of parse_error
276
277
278 (** {6 Unannotated (partial) parsing} *)
279
280 val parse :
281 ?parse_pos : Parse_pos.t -> ?len : int -> string -> (string, t) parse_result
282 (** [parse ?parse_pos ?len str] (partially) parses an S-expression in
283 string buffer [str] starting out with position information provided in
284 [parse_pos] and reading at most [len] characters. To parse a single
285 atom that is not delimited by whitespace it is necessary to call this
286 function a second time with the returned continuation, and a dummy
287 buffer that contains whitespace.
288
289 @param parse_pos default = [Parse_pos.create ()]
290 @param len default = [String.length str - parse_pos.Parse_pos.buf_pos]
291 *)
292
293 val parse_bigstring :
294 ?parse_pos : Parse_pos.t -> ?len : int -> bigstring
295 -> (bigstring, t) parse_result
296 (** [parse_bigstring ?parse_pos ?len str] same as {!parse}, but operates on
297 bigstrings. *)
298
299 val input_sexp : ?parse_pos : Parse_pos.t -> in_channel -> t
300 (** [input_sexp ?parse_pos ic] parses an S-expression from input channel
301 [ic] using initial position information in [parse_pos]. NOTE: this
302 function is not as fast on files as {!Sexp.load_sexp}, and is also
303 slightly slower than the scan-functions. But it is guaranteed that
304 [input_sexp] is only going to read data parseable as an S-expression.
305 Thus, subsequent input functions will see the data immediately
306 following it.
307
308 @param parse_pos default = [Parse_pos.create ()]
309 *)
310
311 val input_sexps :
312 ?parse_pos : Parse_pos.t -> ?buf : string -> in_channel -> t list
313 (** [input_sexps ?parse_pos ?buf ic] parses whitespace separated
314 S-expressions from input channel [ic] until EOF is reached. Faster than
315 the scan-functions.
316
317 @param parse_pos default = [Parse_pos.create ()]
318 *)
319
320 val input_rev_sexps :
321 ?parse_pos : Parse_pos.t -> ?buf : string -> in_channel -> t list
322 (** [input_rev_sexps ?parse_pos ?buf ic] same as {!Sexp.input_sexps},
323 but returns a reversed list of S-expressions, which is slightly more
324 efficient. *)
325
326
327 (** {6 Loading of (converted) S-expressions} *)
328
329 val load_sexp : ?strict : bool -> ?buf : string -> string -> t
330 (** [load_sexp ?strict ?buf file] reads one S-expression from [file] using
331 buffer [buf] for storing intermediate data. Faster than the
332 scan-functions.
333
334 @raise Parse_error if the S-expression is unparseable.
335
336 @raise Failure if parsing reached the end of file before one S-expression
337 could be read.
338
339 @raise Failure if [strict] is true and there is more than one
340 S-expression in the file.
341
342 @param strict default = [true]
343 *)
344
345 val load_sexps : ?buf : string -> string -> t list
346 (** [load_sexps ?buf file] reads a list of whitespace separated S-expressions
347 from [file] using buffer [buf] for storing intermediate data.
348 Faster than the scan-functions.
349
350 @raise Parse_error if there is unparseable data in the file.
351
352 @raise Failure if parsing reached the end of file before the last
353 S-expression could be fully read.
354 *)
355
356 val load_rev_sexps : ?buf : string -> string -> t list
357 (** [load_rev_sexps ?buf file] same as {!Sexp.load_sexps}, but returns a
358 reversed list of S-expressions, which is slightly more efficient. *)
359
360 val load_sexp_conv :
361 ?strict : bool -> ?buf : string -> string -> (t -> 'a) -> 'a Annotated.conv
362 (** [load_sexp_conv ?strict ?buf file f] like {!Sexp.load_sexp}, but
363 performs a conversion on the fly using [f]. Performance is equivalent
364 to executing {!Sexp.load_sexp} and performing conversion when there
365 are no errors. In contrast to the plain S-expression loader, this
366 function not only performs the conversion, it will give exact error
367 ranges for conversion errors.
368
369 @raise Parse_error if there is unparseable data in the file.
370
371 @raise Failure if parsing reached the end of file before the last
372 S-expression could be fully read.
373 *)
374
375 val load_sexp_conv_exn :
376 ?strict : bool -> ?buf : string -> string -> (t -> 'a) -> 'a
377 (** [load_sexp_conv_exn ?strict ?buf file f] like {!load_sexp_conv},
378 but returns the converted value or raises [Of_sexp_error] with exact
379 location information in the case of a conversion error. *)
380
381 val load_sexps_conv :
382 ?buf : string -> string -> (t -> 'a) -> 'a Annotated.conv list
383 (** [load_sexps_conv ?buf file f] like {!Sexp.load_sexps}, but performs
384 a conversion on the fly using [f]. Performance is equivalent to
385 executing {!Sexp.load_sexps} and performing conversion when there
386 are no errors. In contrast to the plain S-expression loader, this
387 function not only performs the conversion, it will give exact error
388 ranges for conversion errors.
389
390 @raise Parse_error if there is unparseable data in the file.
391
392 @raise Failure if parsing reached the end of file before the last
393 S-expression could be fully read.
394 *)
395
396 val load_sexps_conv_exn : ?buf : string -> string -> (t -> 'a) -> 'a list
397 (** [load_sexps_conv_exn ?buf file f] like {!load_sexps_conv}, but returns
398 the converted value or raises [Of_sexp_error] with exact location
399 information in the case of a conversion error. *)
400
401
402 (** {6 Output of S-expressions to I/O-channels} *)
403
404 (** NOTE: for performance reasons these output functions may need to
405 allocate large strings to write out huge S-expressions. This may
406 cause problems on 32-bit platforms. If you think that you may need to
407 write huge S-expressions on such platforms, you might want to use the
408 pretty-printers that write to formatters instead (see further below). *)
409
410 val output_hum : out_channel -> t -> unit
411 (** [output_hum oc sexp] outputs S-expression [sexp] to output channel
412 [oc] in human readable form. *)
413
414 val output_hum_indent : int -> out_channel -> t -> unit
415 (** [output_hum_indent indent oc sexp] outputs S-expression [sexp]
416 to output channel [oc] in human readable form using indentation level
417 [indent].
418 *)
419
420 val output_mach : out_channel -> t -> unit
421 (** [output_mach oc sexp] outputs S-expression [sexp] to output channel
422 [oc] in machine readable (i.e. most compact) form. *)
423
424 val output : out_channel -> t -> unit
425 (** [output oc sexp] same as [output_mach]. *)
426
427
428 (** {6 Output of S-expressions to file} *)
429
430 (** All save-functions write to a temporary file before moving it into
431 place to avoid intermittent garbling of existing files, which may
432 cause problems for other processes that try to read. *)
433
434 val save_hum : ?perm : int -> string -> t -> unit
435 (** [save_hum ?perm file sexp] outputs S-expression [sexp] to [file] in human
436 readable form.
437
438 @param perm default = umask
439 *)
440
441 val save_mach : ?perm : int -> string -> t -> unit
442 (** [save_mach ?perm file sexp] outputs S-expression [sexp] to [file]
443 in machine readable (i.e. most compact) form.
444
445 @param perm default = umask
446 *)
447
448 val save : ?perm : int -> string -> t -> unit
449 (** [save ?perm file sexp] same as {!save_mach}. *)
450
451 val save_sexps_hum : ?perm : int -> string -> t list -> unit
452 (** [save_sexps_hum ?perm file sexps] outputs S-expression list [sexps] to
453 [file] in human readable form, each sexp being followed by a newline.
454
455 @param perm default = umask
456 *)
457
458 val save_sexps_mach : ?perm : int -> string -> t list -> unit
459 (** [save_sexps_mach ?perm file sexps] outputs S-expression list [sexps] to
460 [file] in machine readable form, each sexp being followed by a
461 newline.
462
463 @param perm default = umask
464 *)
465
466 val save_sexps : ?perm : int -> string -> t list -> unit
467 (** [save_sexps ?perm file sexp] same as {!save_sexps_mach}. *)
468
469
470 (** {6 Output of S-expressions to formatters} *)
471
472 val pp_hum : formatter -> t -> unit
473 (** [pp_hum ppf sexp] outputs S-expression [sexp] to formatter [ppf]
474 in human readable form. *)
475
476 val pp_hum_indent : int -> formatter -> t -> unit
477 (** [pp_hum_indent n ppf sexp] outputs S-expression [sexp] to formatter
478 [ppf] in human readable form and indentation level [n]. *)
479
480 val pp_mach : formatter -> t -> unit
481 (** [pp_mach ppf sexp] outputs S-expression [sexp] to formatter [ppf]
482 in machine readable (i.e. most compact) form. *)
483
484 val pp : formatter -> t -> unit
485 (** [pp ppf sexp] same as [pp_mach]. *)
486
487
488 (** {6 String and bigstring conversions} *)
489
490 (** Module encapsulating the exception raised by string converters when
491 type conversions fail. *)
492 module Of_string_conv_exn : sig
493 type t = { exc : exn; sexp : Type.t; sub_sexp : Type.t }
494
495 exception E of t
496 end
497
498 val of_string : string -> t
499 (** [of_string str] converts string [str] to an S-expression. NOTE:
500 trailing whitespace is considered an error, which may be overly
501 strict for some applications. Either strip the string of trailing
502 whitespace first, or, even cheaper, use {!parse} instead. *)
503
504 val of_string_conv : string -> (t -> 'a) -> 'a Annotated.conv
505 (** [of_string_conv str conv] like {!of_string}, but performs type conversion
506 with [conv]. @return conversion result. *)
507
508 val of_string_conv_exn : string -> (t -> 'a) -> 'a
509 (** [of_string_conv_exn str conv] like {!of_string_conv}, but raises
510 {!Of_string_conv_exn.E} if type conversion fails. @return converted
511 value. *)
512
513 val of_bigstring : bigstring -> t
514 (** [of_bigstring bstr] same as {!of_string}, but operates on bigstrings. *)
515
516 val of_bigstring_conv : bigstring -> (t -> 'a) -> 'a Annotated.conv
517 (** [of_bigstring_conv bstr conv] like {!of_bigstring}, but performs
518 type conversion with [conv]. @return conversion result. *)
519
520 val of_bigstring_conv_exn : bigstring -> (t -> 'a) -> 'a
521 (** [of_bigstring_conv_exn bstr conv] like {!of_bigstring_conv}, but raises
522 {!Of_string_conv_exn.E} if type conversion fails. @return converted
523 value. *)
524
525 val to_string_hum : ?indent : int -> t -> string
526 (** [to_string_hum ?indent sexp] converts S-expression [sexp] to a
527 string in human readable form with indentation level [indent].
528
529 @param indent default = [!default_indent]
530 *)
531
532 val to_string_mach : t -> string
533 (** [to_string_mach sexp] converts S-expression [sexp] to a string in
534 machine readable (i.e. most compact) form. *)
535
536 val to_string : t -> string
537 (** [to_string sexp] same as [to_string_mach]. *)
538
539
540 (** {6 Buffer conversions} *)
541
542 val to_buffer_hum : buf : Buffer.t -> ?indent : int -> t -> unit
543 (** [to_buffer_hum ~buf ?indent sexp] outputs the S-expression [sexp]
544 converted to a string in human readable form to buffer [buf].
545
546 @param indent default = [!default_indent]
547 *)
548
549 val to_buffer_mach : buf : Buffer.t -> t -> unit
550 (** [to_buffer_mach ~buf sexp] outputs the S-expression [sexp] converted
551 to a string in machine readable (i.e. most compact) form to buffer [buf].
552 *)
553
554 val to_buffer : buf : Buffer.t -> t -> unit
555 (** [to_buffer ~buf sexp] same as {!to_buffer_mach}. *)
556
557
558 (** {6 Utilities for automated type conversions} *)
559
560 val unit : t
561 (** [unit] the unit-value as expressed by an S-expression. *)
562
563 external sexp_of_t : t -> t = "%identity"
564 (** [sexp_of_t sexp] maps S-expressions which are part of a type with
565 automated S-expression conversion to themselves. *)
566
567 external t_of_sexp : t -> t = "%identity"
568 (** [t_of_sexp sexp] maps S-expressions which are part of a type with
569 automated S-expression conversion to themselves. *)
570
571
572 (** {6 Utilities for conversion error handling} *)
573
574 type found = [ `Found | `Pos of int * found ]
575 (** Type of successful search results. [`Found] means that an
576 S-expression was found at the immediate position, and [`Pos (pos,
577 found)] indicates that it was found at position [pos] within a
578 structure (= S-expression list) where [found] describes recursively
579 where it was found in that structure. *)
580
581 type search_result = [ `Not_found | found ]
582 (** Type of search results. [`Not_found] means that an
583 S-expression was not found within another S-expression. *)
584
585 val search_physical : t -> contained : t -> search_result
586 (** [search_physical sexp ~contained] @return the search result
587 indicating whether, and if, where the S-expression [contained]
588 was found within S-expression [sexp]. *)
589
590 val subst_found : t -> subst : t -> found -> t
591 (** [subst_found sexp ~subst found] @return the S-expression that
592 results from substituting [subst] within S-expression [sexp]
593 at the location described by [found]. *)
594 end