yamerl

repository·master·Indexed 42 days ago

https://github.com/yakaz/yamerl

A pure Erlang application for parsing YAML 1.1, YAML 1.2, and JSON documents. It is lightweight, has no external dependencies, and does not use native code (NIFs or port drivers). It provides a primary interface via the yamerl_constr module with support for simple and detailed parsing modes, and is compatible with Erlang and Elixir build systems.

Tokens
1.1K
Snippets
7
Records
7
Agent score
3%

What's inside yamerl

  1. Parse YAML and JSON with yamerl_constr

    master

    The yamerl_constr module is the primary interface for parsing YAML 1.1, YAML 1.2, and JSON documents.

    Important: Before using yamerl_constr, you must start the application:

    application:start(yamerl).

    Because YAML input streams can contain multiple documents, yamerl_constr always returns a list of documents, even if the input contains only one.

  2. Compare simple vs detailed document structures

    master

    yamerl provides two modes for document output:

    Simple Mode (Default)

    Outputs documents using standard Erlang types. Mappings are represented as proplists (e.g., [{"key", "value"}]). This is ideal for most application logic where you only care about the data.

    Detailed Mode

    Triggered by passing [{detailed_constr, true}] as the second argument to yamerl_constr:file/2.

    It outputs complex records (e.g., yamerl_doc, yamerl_seq, yamerl_map, yamerl_str) that include:

    • Line and Column numbers
    • Tag URIs (e.g., tag:yaml.org,2002:map)
    • YAML node types
    • Module information

    This mode is useful for building tools like linters, formatters, or debuggers that need to know exactly where in the source file a piece of data originated.

    % Simple mode
    yamerl_constr:file("system.yaml").
    
    % Detailed mode
    yamerl_constr:file("system.yaml", [{detailed_constr, true}]).
  3. Integrate yamerl into your project

    master

    yamerl can be integrated into various Erlang and Elixir build systems. It is available as a Hex.pm package.

    Rebar 3

    Add yamerl to your rebar.config dependencies:

    {deps, [yamerl]}.

    Erlang.mk

    Add yamerl to your Makefile dependencies:

    DEPS = yamerl

    Mix (Elixir)

    Add yamerl to your mix.exs dependencies:

    def project do
      [deps: [{:yamerl, "~> 0.8.0"}]
    end
  4. Use yamerl in an Elixir project

    master

    To use yamerl in Elixir, add it to your mix.exs dependencies and call the Erlang modules using the :module_name syntax.

    Note: You must call Application.start(:yamerl) before attempting to parse.

    defmodule Myapp do
      def simple(filename) do
        Application.start(:yamerl)
        :yamerl_constr.file(filename)
      end
    
      def detailed(filename) do
        Application.start(:yamerl)
        :yamerl_constr.file(filename, [:detailed_constr])
      end
    end
  5. Parse a file

    master

    Use yamerl_constr:file/1 (simple mode) or yamerl_constr:file/2 (detailed mode) to parse a file from disk.

    Simple Mode (Default): Returns documents as basic Erlang structures (strings, numbers, lists, proplists).

    yamerl_constr:file("applications.yaml").

    Detailed Mode: Returns documents using records that include metadata like line/column numbers, tag URIs, and node types. Use the detailed_constr option.

    yamerl_constr:file("applications.yaml", [{detailed_constr, true}]).
  6. Parse a stream

    master

    For large documents or streaming inputs, you can manually feed chunks to the parser. The developer is responsible for reading the stream and providing chunks.

    1. Initialize the state with yamerl_constr:new/1.
    2. Feed chunks using yamerl_constr:next_chunk/2.
    3. Finalize the stream with yamerl_constr:last_chunk/2.
    % 1. Initialize
    Parser0 = yamerl_constr:new({file, "<stdin>"}),
    
    % 2. Feed chunks
    {continue, Parser1} = yamerl_constr:next_chunk(Parser0, Chunk1),
    {continue, Parser2} = yamerl_constr:next_chunk(Parser1, Chunk2),
    
    % 3. Finalize
    Documents = yamerl_constr:last_chunk(Parser2, Chunk3).
    Parser0 = yamerl_constr:new({file, "<stdin>"}),
    {continue, Parser1} = yamerl_constr:next_chunk(Parser0, Chunk1),
    {continue, Parser2} = yamerl_constr:next_chunk(Parser1, Chunk2),
    Documents = yamerl_constr:last_chunk(Parser2, Chunk3).
  7. Parse an in-memory document

    master

    Use yamerl_constr:string/1 to parse a string or binary directly in memory.

    % Returns a list of documents
    yamerl_constr:string("Hello World!").
    // Result: ["Hello World!"]
    yamerl_constr:string("Hello World!").