package sexplib

  1. Overview
  2. Docs
Library for serializing OCaml values to and from S-expressions

Install

Dune Dependency

Authors

Maintainers

Sources

v0.15.1.tar.gz
sha256=75da7d290d92d758c01f441f9589ccce031e11301563efde1c19149d39edbcbc

Description

Part of Jane Street's Core library The Core suite of libraries is an industrial strength alternative to OCaml's standard library that was developed by Jane Street, the largest industrial user of OCaml.

Published: 25 Jul 2022

README

README.org

* Sexplib - S-Expressions for OCaml

=sexplib= contains functionality for parsing and pretty-printing
s-expressions.  S-expressions are defined by the following type:

#+begin_src ocaml
type sexp = Atom of string | List of sexp list
#+end_src

** Usage example

In this example we build an s-expression that corresponds to =(This
(is an) (s expression))=, serialize that into a string, and then parse
the string back into an s-expression.

#+begin_src ocaml
open Sexplib

let () =
  (* Build an Sexp from: (This (is an) (s expression)) *)
  let exp1 = Sexp.(List [
    Atom "This";
    List [Atom "is"; Atom "an"];
    List [Atom "s"; Atom "expression"]
  ]) in
  (* Serialize an Sexp object into a string *)
  print_endline (Sexp.to_string exp1);
  (* Parse a string and produce a Sexp object  *)
  let exp2 = Sexp.of_string "(This (is an) (s expression))" in
  (* Ensure we parsed what we expected. *)
  assert (Sexp.compare exp1 exp2 = 0)
#+end_src


** About

This library is often used in conjunction with =ppx_sexp_conv=, a
syntax extension which generates code from type definitions for
efficiently converting OCaml-values to s-expressions and vice versa.

Together, these two libraries make it easy to convert your OCaml
values to and from a human-readable serializable form, without the
tedium of having to write your own converters.

The library also offers functionality for extracting and replacing
sub-expressions in s-expressions.  Here, we'll only document =sexplib=
proper.  If you want to know more about the way in which OCaml types
are mapped on to s-expressions, you should look at the documentation
for [[https://github.com/janestreet/ppx_sexp_conv][=ppx_sexp_conv=]].

** Lexical conventions of s-expression

Whitespace, which consists of the space, newline, horizontal tab, and
form feed characters, is ignored unless within an OCaml-string, where
it is treated according to OCaml-conventions.  The left parenthesis
opens a new list, the right one closes it again.  Lists can be empty.

The double quote denotes the beginning and end of a string following
the lexical conventions of OCaml (see the [[http://caml.inria.fr/pub/docs/manual-ocaml/][OCaml-manual]] for
details). All characters other than double quotes, left and right
parentheses, whitespace, carriage return, and comment-introducing
characters or sequences (see next paragraph) are considered part of a
contiguous string.

** Comments

There are three kinds of comments:

- /line comments/ are introduced with =;=, and end at the newline.
- /sexp comments/ are introduced with =#;=, and end at the end of the
  following s-expression.
- /block comments/ are introduced with =#|= and end with =|#=.  These
  can be nested, and double-quotes within them must be balanced and be
  lexically correct OCaml strings.

** Grammar of s-expressions

S-expressions are either strings (= atoms) or lists.  The lists can
recursively contain further s-expressions or be empty, and must be
balanced, i.e., parentheses must match.

** Examples

#+begin_src scheme
  this_is_an_atom_123'&^%!  ; this is a comment
  "another atom in an OCaml-string \"string in a string\" \123"
  
  ; empty list follows below
  ()
  
  ; a more complex example
  (
    (
      list in a list  ; comment within a list
      (list in a list in a list)
      42 is the answer to all questions
      #; (this S-expression
           (has been commented out)
         )
      #| Block comments #| can be "nested" |# |#
    )
  )
#+end_src

** I/O and Type Conversions

There are multiple ways to perform I/O with s-expressions.  If exact
error locations are required when type conversions fail, s-expressions
need to be parsed with location annotations.  The associated parser is
slower, however, and needs more memory.

In most cases users may therefore want to use functions like
=load_sexp_conv= or =load_sexp_conv_exn=, which load s-expressions
from files and convert them.  They initially read the file without
location annotations for performance reasons.  Only if conversions
fail will the file be reparsed with location annotations.  Type errors
can then be reported accurately with file name, line number, column,
and file position.

** Custom converters

In addition to the converters provided automatically by
=ppx_sexp_conv=, it's possible to write one's own sexp-converter.  For
such converters to be available by other automatically generated
converters, it should follow the convention of being defined in the
same scope as the type, and should be named =sexp_of_[type]= and
=[type]_of_sexp=.

You must report failures by raising the =Of_sexp_error=-exception so
that then =sexplib='s tools for pinpointing the location of type
errors within an s-expression file will work properly.

** Pretty-printers for OCaml toplevel

To get s-expressions pretty-printed in an OCaml toplevel (e.g. utop),
you need to install a pretty printer.

If you use [[https://github.com/janestreet/base][=base=]], then you should look at =Base.Pretty_printer.all= and get those pretty-printers registered.

If not, then =#install_printer Sexplib.Sexp.pp_hum= should work.

Dependencies (5)

  1. num
  2. dune >= "2.0.0"
  3. sexplib0 >= "v0.15" & < "v0.16"
  4. parsexp >= "v0.15" & < "v0.16"
  5. ocaml >= "4.08.0"

Dev Dependencies

None

  1. amf < "0.1.2"
  2. arakoon = "1.9.0"
  3. async-zmq >= "0.3.0"
  4. async_core < "108.00.02"
  5. awa < "0.2.0"
  6. biocaml >= "0.11.0"
  7. bistro >= "0.2.0" & < "0.4.0" | >= "0.6.0"
  8. bookaml >= "3.1"
  9. caldav
  10. cconv-ppx
  11. charrua
  12. charrua-core >= "0.3"
  13. charrua-server
  14. cohttp >= "0.20.0" & < "1.2.0"
  15. cohttp-mirage < "2.0.0"
  16. conduit >= "0.12.0" & != "3.0.0" & < "7.0.0"
  17. conduit-async >= "1.2.0" & != "3.0.0" & < "7.0.0"
  18. conduit-lwt >= "1.3.0" & != "3.0.0" & < "7.0.0"
  19. conduit-mirage != "3.0.0" & < "7.0.0"
  20. conformist >= "0.2.1"
  21. coq-lsp >= "0.2.0+8.17"
  22. coq-serapi < "8.7.2+0.4.13" | >= "8.10.0+0.7.1"
  23. core >= "v0.15.0" & < "v0.16.0"
  24. core_unix >= "v0.15.0" & < "v0.16.0"
  25. cppffigen
  26. cstruct >= "1.8.0" & != "3.6.0" & < "4.0.0"
  27. cstruct-sexp
  28. csvfields >= "v0.15.0" & < "v0.16.0"
  29. current_web >= "0.4"
  30. datakit-server >= "0.10.0" & < "0.11.0"
  31. datakit-server-9p
  32. decoders-sexplib
  33. diet < "0.4"
  34. dns-forward
  35. dockerfile >= "1.3.0"
  36. dockerfile-cmd >= "8.1.0"
  37. dockerfile-opam = "4.0.0" | >= "7.1.0"
  38. dune-compiledb
  39. dune-deps
  40. earlybird >= "1.0.1"
  41. ego
  42. erlang
  43. ezjsonm >= "0.4.0" & < "1.2.0"
  44. ezjsonm-lwt
  45. frenetic >= "5.0.0" & < "5.0.5"
  46. git < "1.1.0"
  47. git-http >= "1.11.4" & < "2.1.0"
  48. graphql < "0.4.0"
  49. graphql_parser < "0.9.0"
  50. guile
  51. hack_parallel
  52. ipaddr >= "2.8.0" & < "3.0.0"
  53. jekyll-format >= "0.3.0"
  54. ketrew = "3.0.0"
  55. lazy-trie >= "1.2.0"
  56. lintcstubs
  57. lua_parser
  58. mecab
  59. message-switch >= "1.4.0"
  60. mirage-conduit = "1.3.0" | >= "3.1.0"
  61. mirage-crypto-pk < "0.10.4"
  62. mirage-http >= "2.5.0" & < "2.5.3"
  63. mirage-net-macosx
  64. mirage-net-xen >= "1.6.0" & < "1.7.1"
  65. mirage-tc >= "0.2.0" & < "0.3.0"
  66. msgpck < "1.1"
  67. nbd >= "2.1.0" & < "2.1.3" | >= "3.0.0"
  68. netchannel
  69. nocrypto >= "0.5.4-1"
  70. not-ocamlfind < "0.07.02"
  71. obuilder
  72. obuilder-spec
  73. ocaml-basics
  74. ocaml-indent
  75. ocaml-topexpect >= "0.3"
  76. ocaml_plugin >= "v0.15.0"
  77. odep
  78. odoc >= "1.4.0" & < "2.0.0"
  79. opam-dune-lint
  80. opass >= "1.0.6"
  81. open_packaging
  82. opine
  83. opium >= "0.14.0" & < "0.16.0"
  84. opium_kernel
  85. otr >= "0.3.1" & < "0.3.6"
  86. pa_ppx = "0.03" | >= "0.10"
  87. pgocaml >= "4.2"
  88. pgocaml_ppx >= "4.2" & < "4.3.0"
  89. planck >= "2.2.0"
  90. ppx_cstruct >= "4.0.0"
  91. ppx_log = "v0.15.0"
  92. ppx_meta_conv = "2.0.2" | = "2.5.0"
  93. ppx_protocol_conv >= "5.1.2"
  94. ppx_protocol_conv_json >= "3.1.0" & != "4.0.0"
  95. ppx_protocol_conv_jsonm != "4.0.0"
  96. ppx_protocol_conv_msgpack >= "3.1.0" & != "4.0.0"
  97. ppx_protocol_conv_xml_light >= "3.1.0" & != "4.0.0"
  98. ppx_protocol_conv_xmlm
  99. ppx_protocol_conv_yaml >= "3.1.0" & != "4.0.0"
  100. ppx_typed_fields < "v0.16.0"
  101. protocol-9p >= "0.6.0" & < "2.0.2"
  102. protocol-9p-unix != "2.0.0"
  103. pyre-ast
  104. qcow
  105. qcow-format >= "0.3"
  106. qcow-tool
  107. rpc_parallel = "v0.15.0"
  108. sentry >= "v0.11.0"
  109. sexp = "v0.15.0"
  110. sexp_macro = "v0.15.0"
  111. sexp_pretty >= "v0.15.0" & < "v0.16.0"
  112. shared-block-ring >= "2.3.0"
  113. sihl < "0.2.0" | >= "0.3.0~rc2"
  114. sihl-core
  115. spin
  116. ssh-agent < "0.4.0"
  117. sslconf
  118. timedesc = "0.8.0"
  119. timedesc-sexp
  120. timmy
  121. tls >= "0.7.1" & < "0.17.0"
  122. tlstunnel >= "0.1.2"
  123. torch < "v0.16.0"
  124. um-abt >= "0.1.7"
  125. uri >= "1.9.2" & < "2.0.0"
  126. vchan >= "2.1.0" & < "6.0.2"
  127. vchan-unix < "6.0.2"
  128. vchan-xen < "6.0.2"
  129. vendredi
  130. vmnet >= "1.1.0"
  131. vscoq-language-server
  132. wamp = "1.0"
  133. websocket-lwt-unix >= "2.17"
  134. x509 >= "0.5.1" & < "0.7.0"
  135. xapi-backtrace < "0.7"
  136. yaml >= "0.2.0" & < "3.0.0"
  137. yaml-sexp
  138. yices2_bindings
  139. zanuda

Conflicts

None

OCaml

Innovation. Community. Security.