Source

ocaml-core / base / sexplib / lib / sexp_intf.ml

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
(** Sexp_intf: interface specification for handling S-expressions (I/O, etc.) *)

open Format
open Bigarray

module type S = sig

  (** Type of S-expressions *)
  type t = Type.t = Atom of string | List of t list

  (** Type of bigstrings *)
  type bigstring = (char, int8_unsigned_elt, c_layout) Array1.t


  (** {6 Defaults} *)

  val default_indent : int ref
  (** [default_indent] reference to default indentation level for
      human-readable conversions.  Initialisation value: 2. *)


  (** {6 S-expression size} *)

  val size : t -> int * int
  (** [size sexp] @return [(n_atoms, n_chars)], where [n_atoms] is
      the number of atoms in S-expression [sexp], and [n_chars] is the
      number of characters in the atoms of the S-expression. *)


  (** {6 Scan functions} *)

  val scan_sexp : ?buf : Buffer.t -> Lexing.lexbuf -> t
  (** [scan_sexp ?buf lexbuf] scans an S-expression from lex buffer
      [lexbuf] using the optional string buffer [buf] for storing
      intermediate strings. *)

  val scan_sexps : ?buf : Buffer.t -> Lexing.lexbuf -> t list
  (** [scan_sexps ?buf lexbuf] reads a list of whitespace separated
      S-expressions from lex buffer [lexbuf] using the optional string
      buffer [buf] for storing intermediate strings. *)

  val scan_iter_sexps :
    ?buf : Buffer.t -> f : (t -> unit) -> Lexing.lexbuf -> unit
  (** [scan_iter_sexps ?buf ~f lexbuf] iterates over all whitespace
      separated S-expressions scanned from lex buffer [lexbuf] using
      function [f], and the optional string buffer [buf] for storing
      intermediate strings. *)

  val scan_fold_sexps :
    ?buf : Buffer.t -> f : ('a -> t -> 'a) -> init : 'a -> Lexing.lexbuf -> 'a
  (** [scan_fold_sexps ?buf ~f ~init lexbuf] folds over all whitespace
      separated S-expressions scanned from lex buffer [lexbuf] using
      function [f], initial state [init], and the optional string buffer
      [buf] for storing intermediate strings. *)

  val scan_sexps_conv :
    ?buf : Buffer.t -> f : (t -> 'a) -> Lexing.lexbuf -> 'a list
  (** [scan_sexps_conv ?buf ~f lexbuf] maps all whitespace separated
      S-expressions scanned from lex buffer [lexbuf] to some list using
      function [f], and the optional string buffer [buf] for storing
      intermediate strings. *)


  (** {6 Type and exception definitions for (partial) parsing} *)

  module Parse_pos : sig
    (** Position information after complete parse *)
    type t = Pre_sexp.Parse_pos.t =
      private
        {
          mutable text_line : int;  (** Line position in parsed text *)
          mutable text_char : int;  (** Character position in parsed text *)
          mutable global_offset : int;  (** Global/logical offset *)
          mutable buf_pos : int;  (** Read position in string buffer *)
        }

    val create :
      ?text_line : int -> ?text_char : int ->
      ?buf_pos : int -> ?global_offset : int -> unit -> t
    (** [create ?text_line ?text_char ?buf_pos ?global_offset ()] @return
        a parse position with the given parameters.

        @param text_line default = [1]
        @param text_char default = [0]
        @param global_offset default = [0]
        @param buf_pos default = [0]
    *)

    val with_buf_pos : t -> int -> t
    (** [with_buf_pos t pos] @return a copy of the parse position [t] where
        [buf_pos] is set to [pos]. *)
  end

  module Cont_state : sig
    (** State of parser continuations *)
    type t = Pre_sexp.Cont_state.t =
      | Parsing_whitespace
      | Parsing_atom
      | Parsing_list
      | Parsing_sexp_comment
      | Parsing_block_comment

    val to_string : t -> string
    (** [to_string cont_state] converts state of parser continuation
        [cont_state] to a string. *)
  end

  (** Type of result from calling {!Sexp.parse}. *)
  type ('a, 't) parse_result = ('a, 't) Pre_sexp.parse_result =
    | Done of 't * Parse_pos.t  (** [Done (t, parse_pos)] finished parsing
                                    an S-expression.  Current parse position
                                    is [parse_pos]. *)
    | Cont of Cont_state.t * ('a, 't) parse_fun
      (** [Cont (cont_state, parse_fun)] met the end of input before completely
          parsing an S-expression.  The user has to call [parse_fun] to
          continue parsing the S-expression in another buffer.  [cont_state]
          is the current parsing state of the continuation.
          NOTE: the continuation may only be called once and will raise
          [Failure] otherwise! *)

  (** Type of parsing functions with given offsets and lengths. *)
  and ('a, 't) parse_fun = pos : int -> len : int -> 'a -> ('a, 't) parse_result

  (** Module for parsing S-expressions annotated with location information *)
  module Annotated : sig
    (** Position information for annotated S-expressions *)
    type pos = Pre_sexp.Annotated.pos = {
      line : int;
      col : int;
      offset : int;
    }

    (** Range information for annotated S-expressions *)
    type range = Pre_sexp.Annotated.range = { start_pos : pos; end_pos : pos }

    (** S-expression annotated with location information *)
    type t = Pre_sexp.Annotated.t =
      | Atom of range * Type.t
      | List of range * t list * Type.t

    (** Type of conversion results of annotated S-expressions. *)
    type 'a conv = [ `Result of 'a | `Error of exn * t ]

    (** Exception associated with conversion errors.  First argument describes
        the location, the second the reason. *)
    exception Conv_exn of string * exn

    (** Stack used by annotation parsers *)
    type stack = Pre_sexp.Annotated.stack = {
      mutable positions : pos list;
      mutable stack : t list list;
    }

    val get_sexp : t -> Type.t
    (** [get_sexp annot_sexp] @return S-expression associated with annotated
        S-expression [annot_sexp]. *)

    val get_range : t -> range
    (** [get_range annot_sexp] @return the range associated with annotated
        S-expression [annot_sexp]. *)

    val find_sexp : t -> Type.t -> t option
    (** [find_sexp annot_sexp sexp] @return [Some res] where [res] is the
        annotated S-expression that is physically equivalent to [sexp] in
        [annot_sexp], or [None] if there is no such S-expression. *)


    (** {6 Annotated (partial) parsing} *)

    val parse :
      ?parse_pos : Parse_pos.t -> ?len : int -> string
      -> (string, t) parse_result
    (** [parse ?parse_pos ?len str] same as {!parse}, but returns an
        S-expression annotated with location information. *)

    val parse_bigstring :
      ?parse_pos : Parse_pos.t -> ?len : int -> bigstring
      -> (bigstring, t) parse_result
    (** [parse_bigstring ?parse_pos ?len str] same as {!parse_bigstring},
        but returns an S-expression annotated with location information. *)

    val input_sexp : ?parse_pos : Parse_pos.t -> in_channel -> t
    (** [input_sexp ?parse_pos ic] like {!input_sexp}, but returns an
        annotated S-expression instead. *)

    val input_sexps :
      ?parse_pos : Parse_pos.t -> ?buf : string -> in_channel -> t list
    (** [input_sexps ?parse_pos ?buf ic] like {!input_sexps}, but returns
        a list of annotated S-expressions. *)

    val input_rev_sexps :
      ?parse_pos : Parse_pos.t -> ?buf : string -> in_channel -> t list
    (** [input_sexps ?parse_pos ?buf ic] like {!input_rev_sexps}, but
        returns a list of annotated S-expressions. *)


    (** {6 Loading of annotated S-expressions} *)

    (** NOTE: these functions should only be used if an annotated S-expression
        is required. *)

    val load_sexp : ?strict : bool -> ?buf : string -> string -> t
    (** [load_sexp ?strict ?buf file] like {!load_sexp}, but returns an
        annotated S-expression. *)

    val load_sexps : ?buf : string -> string -> t list
    (** [load_sexps ?buf file] like {!load_sexps}, but returns a list of
        annotated S-expressions. *)

    val load_rev_sexps : ?buf : string -> string -> t list
    (** [load_rev_sexps ?buf file] like {!load_rev_sexps}, but returns a
        list of annotated S-expressions. *)


    (** {6 String and bigstring conversions} *)

    val of_string : string -> t
    (** [of_string str] same as {!of_string}, but returns an annotated
        S-expression. *)

    val of_bigstring : bigstring -> t
    (** [of_bigstring bstr] same as {!of_string}, but operates on bigstrings. *)


    (** Converters using annotations for determining error locations *)

    val conv : (Type.t -> 'a) -> t -> 'a conv
    (** [conv f annot_sexp] converts the S-expression associated with
        annotated S-expression [annot_sexp] using [f].  @return [`Result
        res] on success, or [`Error (exn, sub_annot_sexp)] otherwise, where
        [exn] is the exception associated with the conversion error, and
        [sub_annot_sexp] is the annotated S-expression on which conversion
        failed. *)

    val get_conv_exn : file : string -> exc : exn -> t -> exn
    (** [get_conv_exn ~file ~exc annot_sexp] @return the exception that
        would be raised for a given [file] and exception [exc]
        if conversion had failed on annotated S-expression [annot_sexp].
        The format of the exception message is "file:line:col" *)
  end

  (** Type of state maintained during parsing *)
  type 't parse_state = 't Pre_sexp.parse_state =
    private
      {
        parse_pos : Parse_pos.t;  (** Current parse position *)
        mutable pstack : 't;  (** Stack of found S-expression lists *)
        pbuf : Buffer.t;  (** Current atom buffer *)
      }

  (** Type of parse errors *)
  type parse_error = Pre_sexp.parse_error =
    {
      location : string;  (** Function in which the parse failed *)
      err_msg : string;  (** Reason why parsing failed *)
      parse_state :
        [
        | `Sexp of t list list parse_state
        | `Annot of Annotated.stack parse_state
        ]
        (** State of parser *)
    }

  (** Exception raised during partial parsing *)
  exception Parse_error of parse_error


  (** {6 Unannotated (partial) parsing} *)

  val parse :
    ?parse_pos : Parse_pos.t -> ?len : int -> string -> (string, t) parse_result
  (** [parse ?parse_pos ?len str] (partially) parses an S-expression in
      string buffer [str] starting out with position information provided in
      [parse_pos] and reading at most [len] characters.  To parse a single
      atom that is not delimited by whitespace it is necessary to call this
      function a second time with the returned continuation, and a dummy
      buffer that contains whitespace.

      @param parse_pos default = [Parse_pos.create ()]
      @param len default = [String.length str - parse_pos.Parse_pos.buf_pos]
  *)

  val parse_bigstring :
    ?parse_pos : Parse_pos.t -> ?len : int -> bigstring
    -> (bigstring, t) parse_result
  (** [parse_bigstring ?parse_pos ?len str] same as {!parse}, but operates on
      bigstrings. *)

  val input_sexp : ?parse_pos : Parse_pos.t -> in_channel -> t
  (** [input_sexp ?parse_pos ic] parses an S-expression from input channel
      [ic] using initial position information in [parse_pos].  NOTE: this
      function is not as fast on files as {!Sexp.load_sexp}, and is also
      slightly slower than the scan-functions.  But it is guaranteed that
      [input_sexp] is only going to read data parseable as an S-expression.
      Thus, subsequent input functions will see the data immediately
      following it.

      @param parse_pos default = [Parse_pos.create ()]
  *)

  val input_sexps :
    ?parse_pos : Parse_pos.t -> ?buf : string -> in_channel -> t list
  (** [input_sexps ?parse_pos ?buf ic] parses whitespace separated
      S-expressions from input channel [ic] until EOF is reached.  Faster than
      the scan-functions.

      @param parse_pos default = [Parse_pos.create ()]
  *)

  val input_rev_sexps :
    ?parse_pos : Parse_pos.t -> ?buf : string -> in_channel -> t list
  (** [input_rev_sexps ?parse_pos ?buf ic] same as {!Sexp.input_sexps},
      but returns a reversed list of S-expressions, which is slightly more
      efficient. *)


  (** {6 Loading of (converted) S-expressions} *)

  val load_sexp : ?strict : bool -> ?buf : string -> string -> t
  (** [load_sexp ?strict ?buf file] reads one S-expression from [file] using
      buffer [buf] for storing intermediate data.  Faster than the
      scan-functions.

      @raise Parse_error if the S-expression is unparseable.

      @raise Failure if parsing reached the end of file before one S-expression
      could be read.

      @raise Failure if [strict] is true and there is more than one
      S-expression in the file.

      @param strict default = [true]
  *)

  val load_sexps : ?buf : string -> string -> t list
  (** [load_sexps ?buf file] reads a list of whitespace separated S-expressions
      from [file] using buffer [buf] for storing intermediate data.
      Faster than the scan-functions.

      @raise Parse_error if there is unparseable data in the file.

      @raise Failure if parsing reached the end of file before the last
      S-expression could be fully read.
  *)

  val load_rev_sexps : ?buf : string -> string -> t list
  (** [load_rev_sexps ?buf file] same as {!Sexp.load_sexps}, but returns a
      reversed list of S-expressions, which is slightly more efficient. *)

  val load_sexp_conv :
    ?strict : bool -> ?buf : string -> string -> (t -> 'a) -> 'a Annotated.conv
  (** [load_sexp_conv ?strict ?buf file f] like {!Sexp.load_sexp}, but
      performs a conversion on the fly using [f].  Performance is equivalent
      to executing {!Sexp.load_sexp} and performing conversion when there
      are no errors.  In contrast to the plain S-expression loader, this
      function not only performs the conversion, it will give exact error
      ranges for conversion errors.

      @raise Parse_error if there is unparseable data in the file.

      @raise Failure if parsing reached the end of file before the last
      S-expression could be fully read.
  *)

  val load_sexp_conv_exn :
    ?strict : bool -> ?buf : string -> string -> (t -> 'a) -> 'a
  (** [load_sexp_conv_exn ?strict ?buf file f] like {!load_sexp_conv},
      but returns the converted value or raises [Of_sexp_error] with exact
      location information in the case of a conversion error. *)

  val load_sexps_conv :
    ?buf : string -> string -> (t -> 'a) -> 'a Annotated.conv list
  (** [load_sexps_conv ?buf file f] like {!Sexp.load_sexps}, but performs
      a conversion on the fly using [f].  Performance is equivalent to
      executing {!Sexp.load_sexps} and performing conversion when there
      are no errors.  In contrast to the plain S-expression loader, this
      function not only performs the conversion, it will give exact error
      ranges for conversion errors.

      @raise Parse_error if there is unparseable data in the file.

      @raise Failure if parsing reached the end of file before the last
      S-expression could be fully read.
  *)

  val load_sexps_conv_exn : ?buf : string -> string -> (t -> 'a) -> 'a list
  (** [load_sexps_conv_exn ?buf file f] like {!load_sexps_conv}, but returns
      the converted value or raises [Of_sexp_error] with exact location
      information in the case of a conversion error. *)


  (** {6 Output of S-expressions to I/O-channels} *)

  (** NOTE: for performance reasons these output functions may need to
      allocate large strings to write out huge S-expressions.  This may
      cause problems on 32-bit platforms.  If you think that you may need to
      write huge S-expressions on such platforms, you might want to use the
      pretty-printers that write to formatters instead (see further below). *)

  val output_hum : out_channel -> t -> unit
  (** [output_hum oc sexp] outputs S-expression [sexp] to output channel
      [oc] in human readable form. *)

  val output_hum_indent : int -> out_channel -> t -> unit
  (** [output_hum_indent indent oc sexp] outputs S-expression [sexp]
      to output channel [oc] in human readable form using indentation level
      [indent].
  *)

  val output_mach : out_channel -> t -> unit
  (** [output_mach oc sexp] outputs S-expression [sexp] to output channel
      [oc] in machine readable (i.e. most compact) form. *)

  val output : out_channel -> t -> unit
  (** [output oc sexp] same as [output_mach]. *)


  (** {6 Output of S-expressions to file} *)

  (** All save-functions write to a temporary file before moving it into
      place to avoid intermittent garbling of existing files, which may
      cause problems for other processes that try to read. *)

  val save_hum : ?perm : int -> string -> t -> unit
  (** [save_hum ?perm file sexp] outputs S-expression [sexp] to [file] in human
      readable form.

      @param perm default = umask
  *)

  val save_mach : ?perm : int -> string -> t -> unit
  (** [save_mach ?perm file sexp] outputs S-expression [sexp] to [file]
      in machine readable (i.e. most compact) form.

      @param perm default = umask
  *)

  val save : ?perm : int -> string -> t -> unit
  (** [save ?perm file sexp] same as {!save_mach}. *)

  val save_sexps_hum : ?perm : int -> string -> t list -> unit
  (** [save_sexps_hum ?perm file sexps] outputs S-expression list [sexps] to
      [file] in human readable form, each sexp being followed by a newline.

      @param perm default = umask
  *)

  val save_sexps_mach : ?perm : int -> string -> t list -> unit
  (** [save_sexps_mach ?perm file sexps] outputs S-expression list [sexps] to
      [file] in machine readable form, each sexp being followed by a
      newline.

      @param perm default = umask
  *)

  val save_sexps : ?perm : int -> string -> t list -> unit
  (** [save_sexps ?perm file sexp] same as {!save_sexps_mach}. *)


  (** {6 Output of S-expressions to formatters} *)

  val pp_hum : formatter -> t -> unit
  (** [pp_hum ppf sexp] outputs S-expression [sexp] to formatter [ppf]
      in human readable form. *)

  val pp_hum_indent : int -> formatter -> t -> unit
  (** [pp_hum_indent n ppf sexp] outputs S-expression [sexp] to formatter
      [ppf] in human readable form and indentation level [n]. *)

  val pp_mach : formatter -> t -> unit
  (** [pp_mach ppf sexp] outputs S-expression [sexp] to formatter [ppf]
      in machine readable (i.e. most compact) form. *)

  val pp : formatter -> t -> unit
  (** [pp ppf sexp] same as [pp_mach]. *)


  (** {6 String and bigstring conversions} *)

  (** Module encapsulating the exception raised by string converters when
      type conversions fail. *)
  module Of_string_conv_exn : sig
    type t = { exc : exn; sexp : Type.t; sub_sexp : Type.t }

    exception E of t
  end

  val of_string : string -> t
  (** [of_string str] converts string [str] to an S-expression.  NOTE:
      trailing whitespace is considered an error, which may be overly
      strict for some applications.  Either strip the string of trailing
      whitespace first, or, even cheaper, use {!parse} instead. *)

  val of_string_conv : string -> (t -> 'a) -> 'a Annotated.conv
  (** [of_string_conv str conv] like {!of_string}, but performs type conversion
      with [conv].  @return conversion result. *)

  val of_string_conv_exn : string -> (t -> 'a) -> 'a
  (** [of_string_conv_exn str conv] like {!of_string_conv}, but raises
      {!Of_string_conv_exn.E} if type conversion fails.  @return converted
      value. *)

  val of_bigstring : bigstring -> t
  (** [of_bigstring bstr] same as {!of_string}, but operates on bigstrings. *)

  val of_bigstring_conv : bigstring -> (t -> 'a) -> 'a Annotated.conv
  (** [of_bigstring_conv bstr conv] like {!of_bigstring}, but performs
      type conversion with [conv].  @return conversion result. *)

  val of_bigstring_conv_exn : bigstring -> (t -> 'a) -> 'a
  (** [of_bigstring_conv_exn bstr conv] like {!of_bigstring_conv}, but raises
      {!Of_string_conv_exn.E} if type conversion fails.  @return converted
      value. *)

  val to_string_hum : ?indent : int -> t -> string
  (** [to_string_hum ?indent sexp] converts S-expression [sexp] to a
      string in human readable form with indentation level [indent].

      @param indent default = [!default_indent]
  *)

  val to_string_mach : t -> string
  (** [to_string_mach sexp] converts S-expression [sexp] to a string in
      machine readable (i.e. most compact) form. *)

  val to_string : t -> string
  (** [to_string sexp] same as [to_string_mach]. *)


  (** {6 Buffer conversions} *)

  val to_buffer_hum : buf : Buffer.t -> ?indent : int -> t -> unit
  (** [to_buffer_hum ~buf ?indent sexp] outputs the S-expression [sexp]
      converted to a string in human readable form to buffer [buf].

      @param indent default = [!default_indent]
  *)

  val to_buffer_mach : buf : Buffer.t -> t -> unit
  (** [to_buffer_mach ~buf sexp] outputs the S-expression [sexp] converted
      to a string in machine readable (i.e. most compact) form to buffer [buf].
  *)

  val to_buffer : buf : Buffer.t -> t -> unit
  (** [to_buffer ~buf sexp] same as {!to_buffer_mach}. *)

  val to_buffer_gen :
       buf : 'buffer
    -> add_char : ('buffer -> char -> unit)
    -> add_string : ('buffer -> string -> unit)
    -> t
    -> unit
  (** [to_buffer_gen ~buf ~add_char ~add_string sexp] outputs the S-expression
      [sexp] converted to a string to buffer [buf] using the output functions
      [add_char] and [add_string]. *)


  (** {6 Utilities for automated type conversions} *)

  val unit : t
  (** [unit] the unit-value as expressed by an S-expression. *)

  external sexp_of_t : t -> t = "%identity"
  (** [sexp_of_t sexp] maps S-expressions which are part of a type with
      automated S-expression conversion to themselves. *)

  external t_of_sexp : t -> t = "%identity"
  (** [t_of_sexp sexp] maps S-expressions which are part of a type with
      automated S-expression conversion to themselves. *)


  (** {6 Utilities for conversion error handling} *)

  type found = [ `Found | `Pos of int * found ]
  (** Type of successful search results.  [`Found] means that an
      S-expression was found at the immediate position, and [`Pos (pos,
      found)] indicates that it was found at position [pos] within a
      structure (= S-expression list) where [found] describes recursively
      where it was found in that structure. *)

  type search_result = [ `Not_found | found ]
  (** Type of search results.  [`Not_found] means that an
      S-expression was not found within another S-expression. *)

  val search_physical : t -> contained : t -> search_result
  (** [search_physical sexp ~contained] @return the search result
      indicating whether, and if, where the S-expression [contained]
      was found within S-expression [sexp]. *)

  val subst_found : t -> subst : t -> found -> t
  (** [subst_found sexp ~subst found] @return the S-expression that
      results from substituting [subst] within S-expression [sexp]
      at the location described by [found]. *)
end
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.