package yamlx

All checked builds pass
  1. Overview
  2. Docs
Pure-OCaml YAML 1.2/1.1 parser with a lossless, comment-preserving AST

Install

dune-project
 Dependency

Authors

Maintainers

Sources

yamlx-0.5.0.tbz
sha256=7a3a45658e06ea6e3f10f02937a183c047c50bda92f1acd678942ca4e0918640
sha512=2d8317506966f09f75229d03325cdb12be4ecbd19684ade3ac6206ee6d5358d570a18112aef0e109f7449c65a2d4e0273fce73ed52a7ab44871b1bb659b8c199

Description

YAMLx is a pure-OCaml YAML 1.2 library. It passes all 371 tests from the yaml-test-suite and has no C bindings or external runtime dependencies. The parsed node tree preserves scalar styles, flow vs. block collection style, tags, anchors, source positions, and comments. A pretty-printer can round-trip the AST back to YAML. A typed-value resolver applies the YAML 1.2 JSON schema and returns Null / Bool / Int / Float / String / Seq / Map values. Structured errors carry line, column, and byte-offset information.

YAMLx is currently released under the AGPL. A commercial license and a path to a fully permissive ISC license are available β€” see FUNDING.md.

Tags

yaml parser serialization

Added to opam-repository:

README

YAMLx

A pure-OCaml YAML 1.2 and 1.1 library with a lossless, comment-preserving AST.

This is AI-assisted software, fully owned and maintained by Martin Jambon.

πŸ‘‰ API Documentation

Features

  • Full YAML 1.2 compliance β€” passes all 371 tests from the yaml-test-suite.
  • Pure OCaml β€” no C bindings, no external runtime dependencies.
  • Lossless AST β€” the parsed node tree preserves scalar styles (plain, 'single-quoted', "double-quoted", | literal, > folded), flow vs. block collection style, tags, anchors, and source positions.
  • Best-effort comment preservation β€” standalone (head) comments before a node, inline (line) comments after a value, and trailing (foot) comments after the last item of a block collection are attached to the nearest node and re-emitted by the printer.
  • Pretty-printer β€” Nodes.to_yaml serializes a node list back to a YAML string, preserving all of the above.
  • Plain-YAML printer β€” Nodes.to_plain_yaml_exn produces a restricted subset with no anchors, no aliases (expanded inline), no tags, no flow collections, and no complex mapping keys β€” the fragment of YAML that most people recognize on sight.
  • Typed-value resolver β€” Values.of_yaml applies the YAML 1.2 JSON schema and returns value list with Null | Bool | Int | Float | String | Seq | Map constructors.
  • Programmatic value construction β€” Value.Build provides convenience constructors (null, bool, int, float, string, seq, map) that fill in zero_loc automatically, for building value trees without a source file.
  • Duplicate-key detection on export β€” Values.to_yaml and friends raise Duplicate_key_error by default when a map contains repeated keys, catching bugs in programmatically-constructed values before they reach the output. Pass ~strict_keys:false to allow duplicates through.
  • Multi-document streams β€” both the node and value APIs handle streams containing more than one ----separated document.
  • Correct anchor scoping β€” anchors are document-local; an alias in document N cannot refer to an anchor defined in document Nβˆ’1.
  • Structured errors β€” Scan_error and Parse_error carry a pos record with line, column, and byte offset. catch_errors wraps any of these into a (_, string) result with a human-readable message, optionally prefixed with a file name.
  • Command-line tool β€” the yamlx binary reads YAML from a file or stdin and prints it in one of several formats (see below).

Quick start

(* Single-document config file β€” most common pattern *)
match YAMLx.Value.of_yaml_file "config.yaml" with
| Ok value  -> ...
| Error msg -> prerr_endline msg  (* "file config.yaml, line 3, col 5: ..." *)

(* Parse a YAML string into a single typed value *)
match YAMLx.Value.of_yaml "answer: 42\nflag: true" with
| Ok (Map (_, [(_, String (_, "answer"), Int (_, 42L));
               (_, String (_, "flag"),   Bool (_, true))])) -> ...
| _ -> ...

(* Multi-document stream *)
match YAMLx.Values.of_yaml input with
| Ok values -> ...
| Error msg -> ...

(* Build a value tree programmatically and serialize it *)
let v =
  YAMLx.Value.Build.(
    map [ "name", string "Alice"; "scores", seq [ int 95; int 87 ] ])
in
print_string (YAMLx.Value.to_yaml v)

(* Round-trip through the lossless AST *)
match YAMLx.Nodes.of_yaml input with
| Ok nodes -> print_string (YAMLx.Nodes.to_yaml nodes)
| Error msg -> ...

(* Strip YAML-specific features *)
match YAMLx.Nodes.of_yaml input with
| Ok nodes ->
    (match YAMLx.catch_errors (fun () ->
         YAMLx.Nodes.to_plain_yaml_exn nodes) with
    | Ok plain -> print_string plain
    | Error msg -> ...)
| Error msg -> ...

Command-line tool

yamlx [-f FORMAT] [--schema VERSION] [FILE]

Output formats (-f FORMAT):
  yaml         Pretty-printed YAML β€” scalar styles and block/flow mode
               preserved (default)
  plain        Simplified YAML β€” aliases expanded, tags stripped, flow
               collections converted to block; merge keys expanded in
               YAML 1.1 mode
  reformat     Normalized YAML β€” reads input as typed values, then
               re-serializes. Drops comments, anchors, and tags. Converts
               flow collections to block. Long strings use literal (|) or
               folded (>) block style as appropriate.
  value        Typed-value tree: Null / Bool / Int / Float / String / Seq /
               Map. Useful for checking how scalars are resolved.
  value-loc    Same as value but with source locations
  node         Full AST without source locations or heights
  node-loc     Same as node but with source locations and heights
  events       yaml-test-suite event-tree notation (mainly for parser testing)

YAML schema (--schema VERSION):
  1.2  YAML 1.2 JSON schema β€” default. Booleans: true/false only.
  1.1  YAML 1.1 schema β€” extended booleans (yes/no/on/off), 0755-style
       octal, sexagesimal, merge keys (<<).

Options:
  --strict          With -f plain: error on tags instead of stripping them
  --strict-schema   Error if the document's %YAML directive disagrees with
                    --schema
  --reject-ambiguous
                    With --schema 1.2: error on plain scalars that would
                    resolve differently under YAML 1.1 (e.g. yes, 0755, <<)
  --plain           With -f value or value-loc: error on anchors, aliases,
                    explicit tags, or (with --schema 1.1) merge keys
  --strict-keys     With -f value or value-loc: error on duplicate mapping
                    keys instead of silently keeping the last occurrence

Comment preservation

Comments are captured on a best-effort basis during scanning and attached to the AST after parsing:

# head comment (attached to the node that follows)
key: value  # line comment (attached to the scalar)
list:
  - a
  - b
  # foot comment (attached to the sequence, after the last item)

Comments inside flow collections ([...], {...}) and on block scalar header lines (key: | # this) are not captured.

Pipeline

Reader β†’ Scanner β†’ Parser β†’ Composer β†’ Resolver
  • Reader β€” UTF-8 / UTF-16 / UTF-32 input normalization.
  • Scanner β€” tokenization, indentation, flow-level tracking, comment capture.
  • Parser β€” token stream β†’ event stream (YAML grammar).
  • Composer β€” events β†’ node graph (anchor/alias resolution).
  • Resolver β€” nodes β†’ typed value tree (YAML 1.2 JSON schema).

License

YAMLx is currently released under the AGPL. There is an ongoing fundraiser: once a funding goal is reached, the license will switch to the permissive ISC license for everyone. Donors above a certain threshold receive an immediate commercial license. See FUNDING.md for details.

References

Dependencies (3)

  1. ppx_deriving
  2. ocaml >= "4.14.0"
  3. dune >= "3.20"

Dev Dependencies (5)

  1. yaml with-dev-setup
  2. ocamlformat = "0.29.0" & with-dev-setup
  3. afl-persistent with-dev-setup
  4. odoc >= "3.2.1" & with-doc
  5. testo with-test

Optional Dependencies

None

Conflicts

None

Build status

Results of building yamlx with each compiler on check.ci.ocaml.org, run of against opam-repository 8a77e58. All results for this package.

Each result links to its build log. To keep crawlers from overloading the site, build logs require a GitHub sign-in (see ocurrent/opam-health-check). On your first log, GitHub asks you to β€œAuthorize opam-health-check”, the OCurrent app that runs these checks; it sees only your public profile, not your repositories. The sign-in lasts 30 days.

Version OCaml 4.11 OCaml 4.14 OCaml 5.2 OCaml 5.4 OCaml 5.5
0.5.0 (this version) n/a good good good good
  • good Package successfully built
  • partial One of the dependencies failed to build
  • bad Package failed to build
  • n/a Package is not available in this environment
  • internal Internal failure