Combinator library for extracting data for s-exps?

I’ve done that in the past with ppx_sexp_conv. You describe the shape for the data and directly use the generated functions. The main trick is that you don’t have to map precisely everything: if you declare a field as sexp, it will parse as the sexp itself. And you can use a any type to put a unit hole instead of the sexp if you don’t need it.

type any = unit [@@deriving sexp_of]

let any_of_sexp _ = ()

type executables_stanza = {
  names : string list;
  requires : string list;
  modules : any;
  include_dirs : any;
}
[@@deriving sexp]

type library_stanza = {
  name : string;
  uid : string;
  local : bool;
  requires : string list;
  source_dir : any;
  modules : any;
  include_dirs : any;
}
[@@deriving sexp]

type stanza = Executables of executables_stanza | Library of library_stanza
[@@deriving sexp_of]

let stanza_of_sexp = function
  | Sexp.List [ Atom "executables"; s ] ->
      Executables (executables_stanza_of_sexp s)
  | Sexp.List [ Atom "library"; s ] -> Library (library_stanza_of_sexp s)
  | Sexp.List [ Atom atom; _ ] -> raise_s [%message "stanza_of_sexp" atom]
  | sexp -> raise_s [%message "stanza_of_sexp" (sexp : Sexp.t)]

type t = stanza list [@@deriving sexp]