mirror of
https://github.com/valitydev/yamerl.git
synced 2024-11-06 02:45:23 +00:00
parent
1f39cf3455
commit
c19aab0228
6
.gitignore
vendored
6
.gitignore
vendored
@ -7,8 +7,4 @@
|
||||
/doc/
|
||||
/ebin
|
||||
/rebar.lock
|
||||
|
||||
# Elixir Support
|
||||
/mix.lock
|
||||
/yamerl-*-contents.tar.gz
|
||||
*.ez
|
||||
/rebar3.crashdump
|
||||
|
@ -1,7 +0,0 @@
|
||||
# yamerl Documentation
|
||||
|
||||
* [Features](features.md#yamerl-features)
|
||||
* [Installation instructions](installation.md#yamerl-installation)
|
||||
* [Reference Manual](reference-manual#yamerl-reference-manual)
|
||||
* [User Guide](user-guide#yamerl-user-guide)
|
||||
* [Alternatives to yamerl](alternatives.md#alternatives-to-yamerl)
|
@ -1,15 +0,0 @@
|
||||
# Alternatives to yamerl
|
||||
|
||||
## YAML parsers
|
||||
|
||||
* [yamler](https://github.com/goertzenator/yamler):
|
||||
* Based on libyaml, wrapped in a NIF
|
||||
* Support YAML 1.1
|
||||
* Faster than yamerl
|
||||
* Support Erlang atoms, however, single-quoted scalar are treated as atom, which breaks the YAML specifications
|
||||
* Don't support Erlang fun()
|
||||
|
||||
## JSON parsers
|
||||
|
||||
* `mochijson2`, provided by [Mochiweb](https://github.com/mochi/mochiweb):
|
||||
* A lot faster than yamerl
|
@ -1,77 +0,0 @@
|
||||
# Features
|
||||
|
||||
## When to use or not yamerl
|
||||
|
||||
### Advantages
|
||||
|
||||
* Pure Erlang implementation:
|
||||
* should scale more easily than a port-driver based implementation;
|
||||
* won't take the whole VM down in case of a crash.
|
||||
* YAML 1.2 support, which is not widely supported in many other languages.
|
||||
|
||||
### Caveats
|
||||
|
||||
* Current implementation is slow, compared to yamler (NIF-based) or any JSON-only parsers.
|
||||
* Adding schemas is not easy.
|
||||
* No support for YAML serialization.
|
||||
|
||||
## Features + examples
|
||||
|
||||
* Support [YAML 1.2](http://www.yaml.org/spec/1.2/spec.html) parsing:
|
||||
|
||||
```erlang
|
||||
yamerl_constr:string("YAML snippet").
|
||||
```
|
||||
|
||||
* Support [YAML 1.1](http://yaml.org/spec/1.1/) parsing:
|
||||
|
||||
```erlang
|
||||
yamerl_constr:string("YAML snippet", [{schema, yaml11}]).
|
||||
```
|
||||
|
||||
* Support [JSON](http://json.org/) parsing:
|
||||
|
||||
```erlang
|
||||
yamerl_constr:string(<<"JSON snippet">>, [{schema, json}]).
|
||||
```
|
||||
|
||||
* Support **Erlang atom** node type, either when tagged as atom, or if autodetected in plain scalars, and, if asked, only if the atom already exists:
|
||||
|
||||
```erlang
|
||||
% Enable support for Erlang atoms.
|
||||
yamerl_app:set_param(node_mods, [yamerl_node_erlang_atom]),
|
||||
yamerl_constr:string("!<tag:yamerl,2012:atom> atom").
|
||||
|
||||
% Autodetect Erlang atoms in plain scalars.
|
||||
yamerl_app:set_param(node_mods, [yamerl_node_erlang_atom]),
|
||||
yamerl_constr:string("atom", [{erlang_atom_autodetection, true}]).
|
||||
|
||||
% Atoms must already exist.
|
||||
yamerl_app:set_param(node_mods, [yamerl_node_erlang_atom]),
|
||||
yamerl_constr:string("atom", [
|
||||
{erlang_atom_autodetection, true},
|
||||
{erlang_atom_only_if_exist, true}
|
||||
]).
|
||||
```
|
||||
|
||||
* Support **Erlang fun()** node type:
|
||||
|
||||
```erlang
|
||||
% Enable support for Erlang fun().
|
||||
yamerl_app:set_param(node_mods, [yamerl_node_erlang_fun]),
|
||||
[Plus_One_Fun] = yamerl_constr:string(<<"!<tag:yamerl,2012:fun> fun(X) -> X + 1 end.">>),
|
||||
|
||||
Plus_One_Fun(2). % Return 3.
|
||||
```
|
||||
|
||||
* Provide a **yamler compatibility layer**:
|
||||
|
||||
```erlang
|
||||
% Both calls return the same value.
|
||||
yaml:load_file("input.yaml", [{schema, yaml_schema_failsafe}]),
|
||||
yamerl_yamler_compat:load_file("input.yaml", [{schema, yaml_schema_failsafe}])
|
||||
```
|
||||
|
||||
## Alternatives to yamerl
|
||||
|
||||
If yamerl doesn't fit your needs, you can read a [list of alternatives](alternatives.md#alternatives-to-yamerl).
|
@ -1,176 +0,0 @@
|
||||
# Installation
|
||||
|
||||
## tl;dr
|
||||
|
||||
### Using Rebar
|
||||
|
||||
1. Take the sources from GitHub and run rebar(1):
|
||||
|
||||
```bash
|
||||
git clone 'https://github.com/yakaz/yamerl.git'
|
||||
cd yamerl/
|
||||
rebar compile
|
||||
```
|
||||
|
||||
### Using the Autotools
|
||||
|
||||
1. Take the sources from GitHub and generate Autotools files:
|
||||
|
||||
```bash
|
||||
git clone 'https://github.com/yakaz/yamerl.git'
|
||||
cd yamerl/
|
||||
autoreconf -vif
|
||||
```
|
||||
|
||||
2. Enter the sources directory and run the usual configure/make/make
|
||||
install:
|
||||
|
||||
```bash
|
||||
./configure
|
||||
make
|
||||
make install
|
||||
```
|
||||
|
||||
The default installation path is your Erlang's distribution libraries
|
||||
directory.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Build dependencies
|
||||
|
||||
If you're using Rebar:
|
||||
* rebar
|
||||
* awk (tested with FreeBSD's awk, mawk and gawk, should work with any
|
||||
flavor of Awk)
|
||||
* Erlang/OTP R14B02 or later
|
||||
|
||||
If you're using the Autotools:
|
||||
* autoconf 2.64 or later
|
||||
* automake 1.11 or later
|
||||
* awk (tested with FreeBSD's awk, mawk and gawk, should work with any
|
||||
flavor of Awk)
|
||||
* make (tested with FreeBSD's make and GNU make, should work with any
|
||||
flavor of make)
|
||||
* Erlang/OTP R14B02 or later
|
||||
|
||||
### Testsuite dependencies
|
||||
|
||||
* Erlang/OTP R14B02 or later
|
||||
* Perl
|
||||
* [yamler](https://github.com/goertzenator/yamler) (optional)
|
||||
|
||||
### Runtime dependencies
|
||||
|
||||
* Erlang/OTP R14B02 or later
|
||||
|
||||
## Building using Rebar
|
||||
|
||||
A single step is required here:
|
||||
```bash
|
||||
rebar compile
|
||||
```
|
||||
|
||||
If you want to run the testsuite:
|
||||
```bash
|
||||
rebar eunit
|
||||
```
|
||||
|
||||
## Building using the Autotools
|
||||
|
||||
### Generating the Autotools files
|
||||
|
||||
> If you use a release tarball, you can skip this step.
|
||||
|
||||
You need to generate the Autotools files:
|
||||
* after a fresh clone of the Git repository;
|
||||
* each time you modify `configure.ac` or any `Makefile.am`
|
||||
|
||||
```bash
|
||||
autoreconf -vif
|
||||
```
|
||||
|
||||
### Configuring the build
|
||||
|
||||
#### Inside sources vs. outside sources
|
||||
|
||||
* The simplest method is to run the `configure` script from the sources
|
||||
directory:
|
||||
|
||||
```bash
|
||||
./configure
|
||||
```
|
||||
|
||||
* The **recommended method** is to run the `configure` script from a
|
||||
separate directory, in order to keep the sources directory clean:
|
||||
|
||||
```bash
|
||||
# Create and enter a separate directory.
|
||||
mkdir build-yamerl
|
||||
cd build-yamerl
|
||||
|
||||
# Execute the configure script from this directory; all files are
|
||||
# created in this directory, not in the sources directory.
|
||||
/path/to/yamerl-sources/configure
|
||||
```
|
||||
|
||||
#### Changing the install path
|
||||
|
||||
The default installation path is your Erlang's distribution libraries
|
||||
directory, as reported by `code:lib_dir()`. To install in a different
|
||||
directory (eg. because you do not have sufficient privileges), you can
|
||||
use the `--prefix` option:
|
||||
```bash
|
||||
.../configure --prefix=$HOME/my-erlang-apps
|
||||
```
|
||||
|
||||
#### Using a non-default Erlang distribution
|
||||
|
||||
By default, the system Erlang distribution is used by querying `erl(1)`
|
||||
taken from the `$PATH`. You can specify another Erlang distribution:
|
||||
|
||||
* using the `--with-erlang` option to point to the Erlang root directory:
|
||||
|
||||
```bash
|
||||
.../configure --with-erlang=/erlang/root/directory
|
||||
```
|
||||
|
||||
* using the `$ERL` variable to point to the alternate `erl(1)` binary:
|
||||
|
||||
```bash
|
||||
.../configure ERL=/path/to/erl
|
||||
```
|
||||
|
||||
### Compiling
|
||||
|
||||
Easy peasy Japanesey!
|
||||
```bash
|
||||
make
|
||||
```
|
||||
|
||||
You can use multiple make jobs (ie. using the `-j` option). However
|
||||
Erlang modules are built using Erlang's `make` application. And, as of
|
||||
this writing (Erlang R15B03), this application doesn't build modules in
|
||||
parallel.
|
||||
|
||||
If you want to run the testsuite:
|
||||
```bash
|
||||
make check
|
||||
```
|
||||
|
||||
## Installing
|
||||
|
||||
> Installation is only supported when using the Autotools.
|
||||
|
||||
* Simply run:
|
||||
|
||||
```bash
|
||||
make install
|
||||
```
|
||||
|
||||
Note that you may need increased privileges.
|
||||
|
||||
* To help mostly packagers, the `$DESTDIR` variable is honored:
|
||||
|
||||
```bash
|
||||
make install DESTDIR=/path/to/fake/root
|
||||
```
|
@ -1,5 +0,0 @@
|
||||
# yamerl Reference Manual
|
||||
|
||||
## Modules
|
||||
|
||||
* [`yamerl_constr`](module-yamerl_constr.md)
|
@ -1,274 +0,0 @@
|
||||
# Module: yamerl\_constr
|
||||
|
||||
## Functions list
|
||||
|
||||
* In-memory string parsing:
|
||||
* [`string/1`](#function-stringstring)
|
||||
* [`string/2`](#function-stringstring-options)
|
||||
* File parsing:
|
||||
* [`file/1`](#function-filefilename)
|
||||
* [`file/2`](#function-filefilename-options)
|
||||
* Stream parsing:
|
||||
* [`new/1`](#function-newsource)
|
||||
* [`new/2`](#function-newsource-options)
|
||||
* [`next_chunk/2`](#function-next_chunkconstr_state-chunk)
|
||||
* [`next_chunk/3`](#function-next_chunkconstr_state-chunk-last_chunk)
|
||||
* [`last_chunk/2`](#function-last_chunkconstr_state-chunk)
|
||||
|
||||
## Functions reference
|
||||
|
||||
### Function: new(Source)
|
||||
|
||||
Same as:
|
||||
```erlang
|
||||
yamerl_constr:new(Source, []).
|
||||
```
|
||||
|
||||
> See [`new/2`](#function-newsource-options).
|
||||
|
||||
### Function: new(Source, Options)
|
||||
|
||||
#### Arguments
|
||||
|
||||
* `Source`: An arbitrary term describing the source of the data.
|
||||
* `Options`: A proplist of options:
|
||||
* `{detailed_constr, boolean()}`: Flag to enable/disable the detailed construction mode (default: `false`).
|
||||
* `{schema, failsafe | json | core | yaml11}`: Name of the official schema to use (default: `core`).
|
||||
* `{node_mods, Mods_List}`: List of Erlang modules to extend supported node types (default: `[]`).
|
||||
|
||||
#### Description
|
||||
|
||||
Create a new construction state.
|
||||
|
||||
The returned state is then used in the [next\_chunk/2](#function-next_chunkconstr_state-chunk), [next\_chunk/3](#function-next_chunkconstr_state-chunk-last_chunk) and [last\_chunk/2](#function-last_chunkconstr_state-chunk) functions.
|
||||
|
||||
#### Return values & exceptions
|
||||
|
||||
If specified options are valid, return a new construction state.
|
||||
|
||||
If specified options are invalid, throw an exception.
|
||||
|
||||
### Function: next\_chunk(Constr\_State, Chunk)
|
||||
|
||||
Same as:
|
||||
```erlang
|
||||
yamerl_constr:next_chunk(Constr_State, Chunk, false).
|
||||
```
|
||||
|
||||
> See [`next_chunk/3`](#function-next_chunkconstr_state-chunk-last_chunk).
|
||||
|
||||
### Function: next\_chunk(Constr\_State, Chunk, Last\_Chunk)
|
||||
|
||||
#### Arguments
|
||||
|
||||
* `Constr_State`: A construction state as returned by [new/1](#function-newsource), [new/2](#function-newsource-options), [next\_chunk/2](#function-next_chunkconstr_state-chunk) or [next\_chunk/3](#function-next_chunkconstr_state-chunk-last_chunk).
|
||||
* `Chunk`: A UTF-8/16/32-encoded binary chunk of a stream containing one or more YAML documents.
|
||||
* `Last_Chunk`: Flag indicating if the given chunk is the last one or not.
|
||||
|
||||
#### Description
|
||||
|
||||
Parse the given chunk and return a new construction state or, if last chunk, a list of constructed YAML documents.
|
||||
|
||||
The chunk must be an Erlang binary, using the UTF-8, UTF-16 or UTF-32 Unicode encoding. A leading _BOM_ character in the first chunk is used to determine the encoding and endianness. If no BOM is present, UTF-8 is assumed.
|
||||
|
||||
#### Return values & exceptions
|
||||
|
||||
If parsing succeeds and `Last_Chunk` is `false`, return `{continue, New_Constr_State}`. The `New_Constr_State` must be used for subsequent calls to [next\_chunk/2](#function-next_chunkconstr_state-chunk), [next\_chunk/3](#function-next_chunkconstr_state-chunk-last_chunk) or [last\_chunk/2](#function-last_chunkconstr_state-chunk).
|
||||
|
||||
If parsing and construction succeed and `Last_Chunk` is `true`, return a list of documents:
|
||||
* Basic-terms-based documents are returned if option `{detailed_constr, false}` is set (default);
|
||||
* Detailed records-based documents are returned if option `{detailed_constr, true}` is set.
|
||||
|
||||
If parsing or construction fails, throw an exception.
|
||||
|
||||
#### Examples
|
||||
|
||||
##### Parse a valid stream
|
||||
|
||||
```erlang
|
||||
Stream_St1 = yamerl_constr:new({file, "<stdin>"}),
|
||||
{continue, Stream_St2} = yamerl_constr:next_chunk(Stream_St1, <<"He">>),
|
||||
{continue, Stream_St3} = yamerl_constr:next_chunk(Stream_St2, <<"ll">>),
|
||||
yamerl_constr:last_chunk(Stream_St3, <<"o!">>).
|
||||
```
|
||||
|
||||
Returns:
|
||||
```erlang
|
||||
% List of documents; here, only one.
|
||||
[
|
||||
% Document root node: a string.
|
||||
"Hello!"
|
||||
].
|
||||
```
|
||||
|
||||
##### Parse an invalid stream
|
||||
|
||||
```erlang
|
||||
Stream_St1 = yamerl_constr:new({file, "<stdin>"}),
|
||||
{continue, Stream_St2} = yamerl_constr:next_chunk(Stream_St1, <<"'He">>),
|
||||
{continue, Stream_St3} = yamerl_constr:next_chunk(Stream_St2, <<"ll">>),
|
||||
yamerl_constr:last_chunk(Stream_St3, <<"o!">>) % Unfinished single-quoted scalar.
|
||||
```
|
||||
|
||||
Throws:
|
||||
```erlang
|
||||
{yamerl_exception,
|
||||
% List of warnings and errors; here, one fatal error.
|
||||
[
|
||||
% Error #1.
|
||||
{yamerl_parsing_error, error,
|
||||
"Unexpected end-of-stream while parsing flow scalar", % Human-readable message.
|
||||
1, 8, % Error location.
|
||||
unexpected_eos,
|
||||
{yamerl_scalar, 1, 1, {yamerl_tag, 1, 1, {non_specific, "!"}}, % Token being parsed.
|
||||
flow, single_quoted,
|
||||
"Hello!"},
|
||||
[]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Function: last\_chunk(Constr\_State, Chunk)
|
||||
|
||||
Same as:
|
||||
```erlang
|
||||
yamerl_constr:next_chunk(Constr_State, Chunk, true).
|
||||
```
|
||||
|
||||
> See [`next_chunk/3`](#function-next_chunkconstr_state-chunk-last_chunk).
|
||||
|
||||
### Function: string(String)
|
||||
|
||||
#### Description
|
||||
|
||||
Same as:
|
||||
```erlang
|
||||
yamerl_constr:string(String, []).
|
||||
```
|
||||
|
||||
> See [`string/2`](#function-stringstring-options).
|
||||
|
||||
### Function: string(String, Options)
|
||||
|
||||
#### Arguments
|
||||
|
||||
* `String`: A string or UTF-8/16/32-encoded binary containing one or more YAML documents.
|
||||
* `Options`: A proplist of options; see [`new/2`](#function-newsource-options).
|
||||
|
||||
#### Description
|
||||
|
||||
Parse the given string and return a list of constructed YAML documents.
|
||||
|
||||
The `String` argument can be:
|
||||
|
||||
* an Erlang string (ie. list):
|
||||
|
||||
```erlang
|
||||
yamerl_constr:string("This is a string").
|
||||
```
|
||||
|
||||
* a binary using the UTF-8, UTF-16 or UTF-32 Unicode encoding. A leading _BOM_ character is used to determine the encoding and endianness. If no BOM is present, UTF-8 is assumed.
|
||||
|
||||
```erlang
|
||||
yamerl_constr:string(<<50,32,226,130,172>>). % The string "2 €" encoded in UTF-8.
|
||||
```
|
||||
|
||||
#### Return values & exceptions
|
||||
|
||||
If parsing and construction succeed, return a list of documents:
|
||||
* Basic-terms-based documents are returned if option `{detailed_constr, false}` is set (default);
|
||||
* Detailed records-based documents are returned if option `{detailed_constr, true}` is set.
|
||||
|
||||
If parsing or construction fails, throw an exception.
|
||||
|
||||
#### Examples
|
||||
|
||||
##### Get simple documents
|
||||
|
||||
```erlang
|
||||
yamerl_constr:string("Hello!").
|
||||
```
|
||||
|
||||
Returns:
|
||||
```erlang
|
||||
% List of documents; here, only one.
|
||||
[
|
||||
% Document root node: a string.
|
||||
"Hello!"
|
||||
].
|
||||
```
|
||||
|
||||
##### Get detailed documents
|
||||
|
||||
```erlang
|
||||
yamerl_constr:string("Hello!", [detailed_constr]).
|
||||
```
|
||||
|
||||
Returns:
|
||||
```erlang
|
||||
% List of documents; here, only one.
|
||||
[
|
||||
% Document #1.
|
||||
{yamerl_doc,
|
||||
% Document root node: a string.
|
||||
{yamerl_str, yamerl_node_str, "tag:yaml.org,2002:str",
|
||||
[{line, 1}, {column, 1}], % Node location in the original string.
|
||||
"Hello!" % String value.
|
||||
}
|
||||
}
|
||||
].
|
||||
```
|
||||
|
||||
##### Parse an invalid document
|
||||
|
||||
```erlang
|
||||
yamerl_constr:string(<<"'Oh-oh...">>). % Unfinished single-quoted scalar.
|
||||
```
|
||||
|
||||
Throws an exception:
|
||||
```erlang
|
||||
{yamerl_exception,
|
||||
% List of warnings and errors; here, one fatal error.
|
||||
[
|
||||
% Error #1.
|
||||
{yamerl_parsing_error, error,
|
||||
"Unexpected end-of-stream while parsing flow scalar", % Human-readable message.
|
||||
1, 10, % Error location.
|
||||
unexpected_eos,
|
||||
{yamerl_scalar, 1, 1, {yamerl_tag, 1, 1, {non_specific, "!"}}, % Token being parsed.
|
||||
flow, single_quoted,
|
||||
"Oh-oh..."},
|
||||
[]
|
||||
}
|
||||
]
|
||||
}.
|
||||
```
|
||||
|
||||
### Function: file(Filename)
|
||||
|
||||
#### Description
|
||||
|
||||
Same as:
|
||||
```erlang
|
||||
yamerl_constr:file(Filename, []).
|
||||
```
|
||||
|
||||
> See [`file/2`](#function-filefilename-options).
|
||||
|
||||
### Function: file(Filename, Options)
|
||||
|
||||
#### Arguments
|
||||
|
||||
* `Filename`: A string containing the filename to parse.
|
||||
* `Options`: A proplist of options; see [`new/2`](#function-newsource-options).
|
||||
|
||||
#### Description
|
||||
|
||||
Parse the file indicated by the given filename and return a list of constructed YAML documents.
|
||||
|
||||
The file is read by chunk of 4096 bytes (not configurable at this time).
|
||||
|
||||
Otherwise, the behavior is the same as [`string/2`](#function-stringstring-options).
|
||||
|
||||
> See [`string/2`](#function-stringstring-options) for return values, exceptions and examples.
|
@ -1,6 +0,0 @@
|
||||
# yamerl User Guide
|
||||
|
||||
## Recipes
|
||||
|
||||
* [Basic parsing](recipe-basic-parsing.md)
|
||||
* [Error handling](recipe-error-handling.md)
|
@ -1,48 +0,0 @@
|
||||
# Recipe: Basic parsing
|
||||
|
||||
1. Start the yamerl application. This is a mandatory step.
|
||||
|
||||
```erlang
|
||||
application:start(yamerl).
|
||||
```
|
||||
|
||||
2. You're now ready to parse a serialized document:
|
||||
|
||||
* To parse an in-memory string or binary:
|
||||
|
||||
```erlang
|
||||
Documents = yamerl_constr:string("Hello!").
|
||||
% Documents is a list of constructed documents.
|
||||
```
|
||||
|
||||
* To parse a file:
|
||||
|
||||
```erlang
|
||||
Documents = yamerl_constr:file("input.yaml").
|
||||
% Documents is a list of constructed documents.
|
||||
```
|
||||
|
||||
* To parse a stream:
|
||||
|
||||
```erlang
|
||||
% Create a new construction state. The only required argument is an
|
||||
% arbitrary term describing the source of the data. Here, we use the
|
||||
% same term structure as yamerl_constr:file/{1, 2}.
|
||||
Constr_State = yamerl_constr:new({file, "<stdin>"}),
|
||||
|
||||
% Feed the parser with binary chunks. The developer is responsible for
|
||||
% reading the chunk from the underlying source.
|
||||
%
|
||||
% The function returns an updated construction state, which replace the
|
||||
% previous one.
|
||||
%
|
||||
% yamerl_constr:next_chunk/2 can be called as many times as possible.
|
||||
{continue, Constr_State2} = yamerl_constr:next_chunk(Constr_State, Chunk),
|
||||
|
||||
% When the last chunk is reached, call yamerl_constr:last_chunk/2.
|
||||
Documents = yamerl_constr:last_chunk(Constr_State2, Last_Chunk).
|
||||
% Documents is a list of constructed documents.
|
||||
```
|
||||
|
||||
> For further informations, see:
|
||||
> * [yamerl\_constr module reference](../reference-manual/module-yamerl_constr.md);
|
@ -1,48 +0,0 @@
|
||||
# Recipe: Error handling
|
||||
|
||||
yamerl **throws an exception when an error occurs**.
|
||||
|
||||
1. Start the yamerl application. This is a mandatory step.
|
||||
|
||||
```erlang
|
||||
application:start(yamerl).
|
||||
```
|
||||
|
||||
2. You're now ready to parse a serialized document:
|
||||
|
||||
* To parse an in-memory string or binary:
|
||||
|
||||
```erlang
|
||||
-include_lib("yamerl/include/yamerl_errors.hrl").
|
||||
|
||||
% ...
|
||||
|
||||
try
|
||||
Documents = yamerl_constr:string("Hello!"),
|
||||
% Documents is a list of constructed documents.
|
||||
Documents
|
||||
catch
|
||||
throw:#yamerl_exception{errors = Errors} ->
|
||||
% Do something with the exception.
|
||||
Errors
|
||||
end.
|
||||
```
|
||||
|
||||
As you can see, the `#yamerl_exception{}` record embeds all encountered errors:
|
||||
```erlang
|
||||
#yamerl_exception{
|
||||
errors = [] % List of errors.
|
||||
}.
|
||||
```
|
||||
|
||||
Errors are records where the two first members are always:
|
||||
|
||||
1. `type`, either `error` or `warning`;
|
||||
2. `text`, a human-readable error message.
|
||||
|
||||
Following members depend on the error record. Two records are currently defined:
|
||||
* `#yamerl_invalid_option{}`;
|
||||
* `#yamerl_parsing_error{}`.
|
||||
|
||||
> For further informations, see:
|
||||
> * [yamerl\_constr module reference](../reference-manual/module-yamerl_constr.md);
|
237
doc/overview.edoc
Normal file
237
doc/overview.edoc
Normal file
@ -0,0 +1,237 @@
|
||||
@author Jean-Sébastien Pédron <jean-sebastien.pedron@dumbbell.fr>
|
||||
@copyright
|
||||
2012-2014 Yakaz,
|
||||
2016 Jean-Sébastien Pédron <jean-sebastien.pedron@dumbbell.fr>
|
||||
|
||||
@doc
|
||||
|
||||
== Introduction ==
|
||||
|
||||
YAML is a human-friendly data serialization format. The specification
|
||||
for this language and many examples are available from the <a
|
||||
href="http://www.yaml.org/">Official YAML web site</a>. You may also
|
||||
want to check the <a href="http://en.wikipedia.org/wiki/YAML">YAML
|
||||
Wikipedia article</a>.
|
||||
|
||||
<strong>`yamerl'</strong> is a pure <a
|
||||
href="http://www.erlang.org/">Erlang application</a> which is able
|
||||
to parse <a href="http://yaml.org/spec/1.1/">YAML 1.1</a> and <a
|
||||
href="http://www.yaml.org/spec/1.2/spec.html">YAML 1.2</a> documents, as
|
||||
well as <a href="http://json.org/">JSON</a> documents. It only depends
|
||||
on standard Erlang/OTP applications; no external dependency is required.
|
||||
It doesn't use native code either (neither port drivers nor NIFs). At
|
||||
this time, it has no support to serialize a YAML document.
|
||||
|
||||
`yamerl' is distributed under the terms of the <strong>2-clause BSD
|
||||
license</strong>; see `COPYING'.
|
||||
|
||||
== When to use yamerl or not ==
|
||||
|
||||
=== Advantages ===
|
||||
|
||||
<ul>
|
||||
<li>Pure Erlang implementation:
|
||||
<ul>
|
||||
<li>should scale more easily than a port-driver based implementation;</li>
|
||||
<li>won't take the whole VM down in case of a crash.</li>
|
||||
</ul></li>
|
||||
<li>YAML 1.2 support, which is not widely supported in many other languages.</li>
|
||||
</ul>
|
||||
|
||||
=== Caveats ===
|
||||
|
||||
<ul>
|
||||
<li>Current implementation is slow, compared to yamler (NIF-based) or any JSON-only parsers.</li>
|
||||
<li>Adding schemas is not easy.</li>
|
||||
<li>No support for YAML serialization.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
== Features ==
|
||||
|
||||
<ul>
|
||||
<li>Supports <a href="http://www.yaml.org/spec/1.2/spec.html">YAML 1.2</a> parsing:
|
||||
```
|
||||
yamerl_constr:string("YAML snippet").
|
||||
'''</li>
|
||||
<li>Supports <a href="http://yaml.org/spec/1.1/">[YAML 1.1</a> parsing:
|
||||
```
|
||||
yamerl_constr:string("YAML snippet", [{schema, yaml11}]).
|
||||
'''</li>
|
||||
<li>Supports <a href="http://json.org/">JSON</a> parsing:
|
||||
```
|
||||
yamerl_constr:string(<<"JSON snippet">>, [{schema, json}]).
|
||||
'''</li>
|
||||
<li>Supports <strong>Erlang atom</strong> node type, either when tagged
|
||||
as atom, or if autodetected in plain scalars, and, if asked, only if the
|
||||
atom already exists:
|
||||
```
|
||||
% Enable support for Erlang atoms.
|
||||
yamerl_app:set_param(node_mods, [yamerl_node_erlang_atom]),
|
||||
yamerl_constr:string("!<tag:yamerl,2012:atom> atom").
|
||||
|
||||
% Autodetect Erlang atoms in plain scalars.
|
||||
yamerl_app:set_param(node_mods, [yamerl_node_erlang_atom]),
|
||||
yamerl_constr:string("atom", [{erlang_atom_autodetection, true}]).
|
||||
|
||||
% Atoms must already exist.
|
||||
yamerl_app:set_param(node_mods, [yamerl_node_erlang_atom]),
|
||||
yamerl_constr:string("atom", [
|
||||
{erlang_atom_autodetection, true},
|
||||
{erlang_atom_only_if_exist, true}
|
||||
]).
|
||||
'''</li>
|
||||
<li>Supports <strong>Erlang fun()</strong> node type:
|
||||
```
|
||||
% Enable support for Erlang fun().
|
||||
yamerl_app:set_param(node_mods, [yamerl_node_erlang_fun]),
|
||||
[Plus_One_Fun] = yamerl_constr:string(<<"!<tag:yamerl,2012:fun> fun(X) -> X + 1 end.">>),
|
||||
|
||||
Plus_One_Fun(2). % Return 3.
|
||||
'''</li>
|
||||
<li>Provides a <strong>yamler compatibility layer</strong>:
|
||||
```erlang
|
||||
% Both calls return the same value.
|
||||
yaml:load_file("input.yaml", [{schema, yaml_schema_failsafe}]),
|
||||
yamerl_yamler_compat:load_file("input.yaml", [{schema, yaml_schema_failsafe}])
|
||||
'''</li>
|
||||
</ul>
|
||||
|
||||
== Prerequisites ==
|
||||
|
||||
Before using yamerl, the application must be started:
|
||||
```
|
||||
application:start(yamerl).
|
||||
'''
|
||||
|
||||
This is required so that application environment variables are available.
|
||||
|
||||
Now, you can use the {@link yamerl_constr} module to parse and construct a
|
||||
list of documents from:
|
||||
<ul>
|
||||
<li>an in-memory document (string or binary);</li>
|
||||
<li>a regular file;</li>
|
||||
<li>a stream.</li>
|
||||
</ul>
|
||||
|
||||
Because a YAML input stream may contain multiple documents, {@link
|
||||
yamerl_constr} always returns a list of documents, even if the input
|
||||
stream only contains one.
|
||||
|
||||
== Examples ==
|
||||
|
||||
=== Basic parsing ===
|
||||
|
||||
<ol>
|
||||
<li>Start the yamerl application. This is a mandatory step.
|
||||
```
|
||||
application:start(yamerl).
|
||||
'''</li>
|
||||
<li>You're now ready to parse a serialized document:
|
||||
<ul>
|
||||
<li>To parse an in-memory string or binary:
|
||||
```
|
||||
Documents = yamerl_constr:string("Hello!").
|
||||
% Documents is a list of constructed documents.
|
||||
'''</li>
|
||||
<li>To parse a file:
|
||||
```
|
||||
Documents = yamerl_constr:file("input.yaml").
|
||||
% Documents is a list of constructed documents.
|
||||
'''</li>
|
||||
<li>To parse a stream:
|
||||
```
|
||||
% Create a new construction state. The only required argument is an
|
||||
% arbitrary term describing the source of the data. Here, we use the
|
||||
% same term structure as yamerl_constr:file/{1, 2}.
|
||||
Constr_State = yamerl_constr:new({file, "<stdin>"}),
|
||||
|
||||
% Feed the parser with binary chunks. The developer is responsible for
|
||||
% reading the chunk from the backing source.
|
||||
%
|
||||
% The function returns an updated construction state, which replaces the
|
||||
% previous one.
|
||||
%
|
||||
% yamerl_constr:next_chunk/2 can be called as many times as necessary.
|
||||
{continue, Constr_State2} = yamerl_constr:next_chunk(Constr_State, Chunk),
|
||||
|
||||
% When the last chunk is reached, call yamerl_constr:last_chunk/2.
|
||||
Documents = yamerl_constr:last_chunk(Constr_State2, Last_Chunk).
|
||||
% Documents is a list of constructed documents.
|
||||
'''</li>
|
||||
</ul></li>
|
||||
</ol>
|
||||
|
||||
See {@link yamerl_constr} for more informations.
|
||||
|
||||
=== Error handling ===
|
||||
|
||||
yamerl <strong>throws an exception when an error occurs</strong>.
|
||||
|
||||
<ol>
|
||||
<li>Start the yamerl application. This is a mandatory step.
|
||||
```
|
||||
application:start(yamerl).
|
||||
'''</li>
|
||||
<li>You're now ready to parse a serialized document. To parse an
|
||||
in-memory string or binary:
|
||||
```
|
||||
-include_lib("yamerl/include/yamerl_errors.hrl").
|
||||
|
||||
% ...
|
||||
|
||||
try
|
||||
Documents = yamerl_constr:string("Hello!"),
|
||||
% Documents is a list of constructed documents.
|
||||
Documents
|
||||
catch
|
||||
throw:#yamerl_exception{errors = Errors} ->
|
||||
% Do something with the exception.
|
||||
Errors
|
||||
end.
|
||||
'''</li>
|
||||
</ol>
|
||||
|
||||
As you can see, the `#yamerl_exception{}' record embeds all encountered
|
||||
errors:
|
||||
```
|
||||
#yamerl_exception{
|
||||
errors = [] % List of errors.
|
||||
}.
|
||||
'''
|
||||
|
||||
Errors are records where the two first members are always:
|
||||
<ol>
|
||||
<li>`type', either `error' or `warning';</li>
|
||||
<li>`text', a human-readable error message.</li>
|
||||
</ol>
|
||||
|
||||
Following members depend on the error record. Two records are currently
|
||||
defined:
|
||||
<ul>
|
||||
<li>`#yamerl_invalid_option{}';</li>
|
||||
<li>`#yamerl_parsing_error{}'.</li>
|
||||
</ul>
|
||||
|
||||
See {@link yamerl_constr} for more informations.
|
||||
|
||||
== Alternatives to yamerl ==
|
||||
|
||||
=== YAML parsers ===
|
||||
|
||||
<ul>
|
||||
<li><a href="https://github.com/goertzenator/yamler">yamler</a>:
|
||||
<ul>
|
||||
<li>Based on libyaml, wrapped in a NIF</li>
|
||||
<li>Supports YAML 1.1</li>
|
||||
<li>Faster than yamerl</li>
|
||||
<li>Supports Erlang atoms, however, single-quoted scalar are treated as
|
||||
atom, which breaks the YAML specifications</li>
|
||||
<li>Doesn't support Erlang fun()</li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
|
||||
=== JSON parsers ===
|
||||
|
||||
There are too many to choose from now to list them here. Use your
|
||||
preferred search engine :-)
|
@ -24,6 +24,13 @@
|
||||
% OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
% SUCH DAMAGE.
|
||||
|
||||
%% @author Jean-Sébastien Pédron <jean-sebastien.pedron@dumbbell.fr>
|
||||
%% @copyright
|
||||
%% 2012-2014 Yakaz,
|
||||
%% 2016 Jean-Sébastien Pédron <jean-sebastien.pedron@dumbbell.fr>
|
||||
%%
|
||||
%% @doc Wrappers for common uses of {@link yamerl_constr}.
|
||||
|
||||
-module(yamerl).
|
||||
|
||||
-include("yamerl_nodes.hrl").
|
||||
@ -44,6 +51,8 @@
|
||||
%% All those functions are only wrapper above yamerl_constr common
|
||||
%% functions. The purpose is just to avoid some typing.
|
||||
|
||||
%% @equiv yamerl_constr:string(String)
|
||||
|
||||
-spec decode(String) ->
|
||||
Result | no_return() when
|
||||
String :: unicode_data(),
|
||||
@ -54,6 +63,8 @@
|
||||
decode(String) ->
|
||||
yamerl_constr:string(String).
|
||||
|
||||
%% @equiv yamerl_constr:string(String, Options)
|
||||
|
||||
-spec decode(String, Options) ->
|
||||
Result | no_return() when
|
||||
String :: unicode_data(),
|
||||
@ -67,6 +78,8 @@ decode(String) ->
|
||||
decode(String, Options) ->
|
||||
yamerl_constr:string(String, Options).
|
||||
|
||||
%% @equiv yamerl_constr:file(Filename)
|
||||
|
||||
-spec decode_file(Filename) ->
|
||||
Result | no_return() when
|
||||
Filename :: string(),
|
||||
@ -77,6 +90,8 @@ decode(String, Options) ->
|
||||
decode_file(Filename) ->
|
||||
yamerl_constr:file(Filename).
|
||||
|
||||
%% @equiv yamerl_constr:file(Filename, Options)
|
||||
|
||||
-spec decode_file(Filename, Options) ->
|
||||
Result | no_return() when
|
||||
Filename :: string(),
|
||||
|
@ -24,6 +24,8 @@
|
||||
% OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
% SUCH DAMAGE.
|
||||
|
||||
%% @private
|
||||
|
||||
-module(yamerl_app).
|
||||
|
||||
-behaviour(application).
|
||||
|
@ -24,6 +24,64 @@
|
||||
% OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
% SUCH DAMAGE.
|
||||
|
||||
%% @author Jean-Sébastien Pédron <jean-sebastien.pedron@dumbbell.fr>
|
||||
%% @copyright
|
||||
%% 2012-2014 Yakaz,
|
||||
%% 2016 Jean-Sébastien Pédron <jean-sebastien.pedron@dumbbell.fr>
|
||||
%%
|
||||
%% @doc {@module} implements a YAML constructor. It uses {@link
|
||||
%% yamerl_parser} as the underlying parser. The parser emits YAML nodes
|
||||
%% which are assembled as structured YAML documents by the constructor.
|
||||
%%
|
||||
%% It is able to construct YAML documents from in-memory strings (see
|
||||
%% {@link string/1} and {@link string/2}), regular files (see {@link
|
||||
%% file/1} and {@link file/2}) or streams (see {@link new/1}, {@link
|
||||
%% new/2} and {@link next_chunk/3}).
|
||||
%%
|
||||
%% YAML documents can be constructed in simple or detailed modes. In
|
||||
%% simple mode, they are made of simple builting Erlang types. In
|
||||
%% detailed mode, they are made of records, holding more informations
|
||||
%% about YAML nodes and their presentation.
|
||||
%%
|
||||
%% The `yamerl' application must be started to use the constructor.
|
||||
%%
|
||||
%% <strong>Example: parse a string in simple mode</strong>
|
||||
%% ```
|
||||
%% yamerl_constr:string("Hello!").
|
||||
%% '''
|
||||
%%
|
||||
%% It returns:
|
||||
%% ```
|
||||
%% % List of documents; here, only one.
|
||||
%% [
|
||||
%% % Document root node: a string.
|
||||
%% "Hello!"
|
||||
%% ].
|
||||
%% '''
|
||||
%%
|
||||
%% <strong>Example: parse a stream in detailed mode</strong>
|
||||
%% ```
|
||||
%% Stream_St1 = yamerl_constr:new({file, "<stdin>"}, [{detailed_constr, true}]),
|
||||
%% {continue, Stream_St2} = yamerl_constr:next_chunk(Stream_St1, <<"He">>),
|
||||
%% {continue, Stream_St3} = yamerl_constr:next_chunk(Stream_St2, <<"ll">>),
|
||||
%% yamerl_constr:last_chunk(Stream_St3, <<"o!">>).
|
||||
%% '''
|
||||
%%
|
||||
%% It returns:
|
||||
%% ```
|
||||
%% % List of documents; here, only one.
|
||||
%% [
|
||||
%% % Document #1.
|
||||
%% {yamerl_doc,
|
||||
%% % Document root node: a string.
|
||||
%% {yamerl_str, yamerl_node_str, "tag:yaml.org,2002:str",
|
||||
%% [{line, 1}, {column, 1}], % Node location in the original string.
|
||||
%% "Hello!" % String value.
|
||||
%% }
|
||||
%% }
|
||||
%% ].
|
||||
%% '''
|
||||
|
||||
-module(yamerl_constr).
|
||||
|
||||
-include("yamerl_errors.hrl").
|
||||
@ -96,6 +154,8 @@
|
||||
%% Public API: chunked stream scanning.
|
||||
%% -------------------------------------------------------------------
|
||||
|
||||
%% @equiv new(Source, [])
|
||||
|
||||
-spec new(Source) ->
|
||||
Constr | no_return() when
|
||||
Source :: term(),
|
||||
@ -104,6 +164,89 @@
|
||||
new(Source) ->
|
||||
new(Source, []).
|
||||
|
||||
%% @doc Creates and returns a new YAML construction state.
|
||||
%%
|
||||
%% When you want to parse a stream (as opposed to in-memory strings or
|
||||
%% regular files), this is the first function you call before feeding
|
||||
%% the constructor with stream "chunks".
|
||||
%%
|
||||
%% `Source' can be any term describing the stream. {@link string/1} and
|
||||
%% {@link string/2} sets it to the atom `string'. {@link file/1} and
|
||||
%% {@link file/2} sets it to `{file, Filename}'. The constructor doesn't
|
||||
%% use that value.
|
||||
%%
|
||||
%% `Options' is a list of options for the parser and the constructor.
|
||||
%% Valid options are:
|
||||
%%
|
||||
%% <dl>
|
||||
%% <dt>`{detailed_constr, boolean()}'</dt>
|
||||
%% <dd>Flag to enable/disable the detailed construction mode. In simple
|
||||
%% construction mode, YAML nodes are returned as Erlang integers,
|
||||
%% strings, lists, proplists, etc. In other words, only simple builtin
|
||||
%% types. In detailed construction mode, YAML nodes are returned using
|
||||
%% records. Those records gives additional informations such as the YAML
|
||||
%% node type, the location in the stream (line and column number) and so
|
||||
%% on.</dd>
|
||||
%% <dd>Default: `false'</dd>
|
||||
%% <dt>`{schema, failsafe | json | core | yaml11}'</dt>
|
||||
%% <dd>Name of the official schema to use.</dd>
|
||||
%% <dd>Default: `core'.</dd>
|
||||
%% <dt>`{node_mods, Mods_List}'</dt>
|
||||
%% <dd>List of Erlang modules to extend support node types.</dd>
|
||||
%% <dd>Default: `[]'.</dd>
|
||||
%% </dl>
|
||||
%%
|
||||
%% The returned state is opaque value. You then pass it to {@link
|
||||
%% next_chunk/2}, {@link next_chunk/3} and {@link last_chunk/2}.
|
||||
%%
|
||||
%% If an option is invalid, an exception is thrown.
|
||||
%%
|
||||
%% <strong>Example: parse a valid stream</strong>
|
||||
%% ```
|
||||
%% Stream_St1 = yamerl_constr:new({file, "<stdin>"}),
|
||||
%% {continue, Stream_St2} = yamerl_constr:next_chunk(Stream_St1, <<"He">>),
|
||||
%% {continue, Stream_St3} = yamerl_constr:next_chunk(Stream_St2, <<"ll">>),
|
||||
%% yamerl_constr:last_chunk(Stream_St3, <<"o!">>).
|
||||
%% '''
|
||||
%% It returns:
|
||||
%%
|
||||
%% ```
|
||||
%% % List of documents; here, only one.
|
||||
%% [
|
||||
%% % Document root node: a string.
|
||||
%% "Hello!"
|
||||
%% ].
|
||||
%% '''
|
||||
%%
|
||||
%% <strong>Example: parse an invalid stream</strong>
|
||||
%% ```
|
||||
%% Stream_St1 = yamerl_constr:new({file, "<stdin>"}),
|
||||
%% {continue, Stream_St2} = yamerl_constr:next_chunk(Stream_St1, <<"'He">>),
|
||||
%% {continue, Stream_St3} = yamerl_constr:next_chunk(Stream_St2, <<"ll">>),
|
||||
%% yamerl_constr:last_chunk(Stream_St3, <<"o!">>) % Unfinished single-quoted scalar.
|
||||
%% '''
|
||||
%%
|
||||
%% It throws:
|
||||
%% ```
|
||||
%% {yamerl_exception,
|
||||
%% % List of warnings and errors; here, one fatal error.
|
||||
%% [
|
||||
%% % Error #1.
|
||||
%% {yamerl_parsing_error, error,
|
||||
%% "Unexpected end-of-stream while parsing flow scalar", % Human-readable message.
|
||||
%% 1, 8, % Error location.
|
||||
%% unexpected_eos,
|
||||
%% {yamerl_scalar, 1, 1, {yamerl_tag, 1, 1, {non_specific, "!"}}, % Token being parsed.
|
||||
%% flow, single_quoted,
|
||||
%% "Hello!"},
|
||||
%% []
|
||||
%% }
|
||||
%% ]
|
||||
%% }
|
||||
%% '''
|
||||
%%
|
||||
%% @see new/1.
|
||||
|
||||
-spec new(Source, Options) ->
|
||||
Constr | no_return() when
|
||||
Source :: term(),
|
||||
@ -118,6 +261,8 @@ new(Source, Options) ->
|
||||
Parser_Options = initialize(Options),
|
||||
yamerl_parser:new(Source, Parser_Options).
|
||||
|
||||
%% @equiv next_chunk(Constr, Chunk, false)
|
||||
|
||||
-spec next_chunk(Constr, Chunk) ->
|
||||
Ret | no_return() when
|
||||
Constr :: yamerl_parser:yamerl_parser(),
|
||||
@ -128,6 +273,33 @@ new(Source, Options) ->
|
||||
next_chunk(Constr, Chunk) ->
|
||||
next_chunk(Constr, Chunk, false).
|
||||
|
||||
%% @doc Feeds the constructor with the next chunk from the YAML stream.
|
||||
%%
|
||||
%% `Constr' is the constructor state returned by a previous call
|
||||
%% to {@link new/1}, {@link new/2}, {@link next_chunk/2} or {@link
|
||||
%% next_chunk/3}.
|
||||
%%
|
||||
%% `Chunk' must be an Erlang binary using the UTF-8, UTF-16 or UTF-32
|
||||
%% Unicode encoding. A leading BOM character in the first chunk is used
|
||||
%% to determine the encoding and endianness. If no BOM is present, UTF-8
|
||||
%% is assumed.
|
||||
%%
|
||||
%% `EOS' indicates the constructor if this is the last chunk from the
|
||||
%% stream.
|
||||
%%
|
||||
%% If this is not the last chunk (`EOS = false'), it returns `{continue,
|
||||
%% New_Constr}' where `New_Constr' is an updated state which replaces
|
||||
%% `Constr'. The new state is to be passed to future calls to {@link
|
||||
%% next_chunk/2}, {@link next_chunk/3} or {@link last_chunk/2}.
|
||||
%%
|
||||
%% If this is the last chunk (`EOS = true'), it returns a list of YAML
|
||||
%% documents. Documents are made of simple builtin Erlang types if the
|
||||
%% detailed construction mode is disabled, or records if the detailed
|
||||
%% construction mode is enabled (`{detailed_constr, boolean()}' passed
|
||||
%% as an option; default is `false').
|
||||
%%
|
||||
%% It throws an exception if there is a parsing or construction error.
|
||||
|
||||
-spec next_chunk(Constr, Chunk, false) ->
|
||||
Ret | no_return() when
|
||||
Constr :: yamerl_parser:yamerl_parser(),
|
||||
@ -148,6 +320,8 @@ next_chunk(Constr, Chunk, EOS) ->
|
||||
true -> Ret
|
||||
end.
|
||||
|
||||
%% @equiv next_chunk(Constr, Chunk, true)
|
||||
|
||||
-spec last_chunk(Constr, Chunk) ->
|
||||
Result | no_return() when
|
||||
Constr :: yamerl_parser:yamerl_parser(),
|
||||
@ -179,6 +353,8 @@ get_docs(Constr) ->
|
||||
%% Public API: common stream sources.
|
||||
%% -------------------------------------------------------------------
|
||||
|
||||
%% @equiv string(String, [])
|
||||
|
||||
-spec string(String) ->
|
||||
Result | no_return() when
|
||||
String :: unicode_data(),
|
||||
@ -189,6 +365,89 @@ get_docs(Constr) ->
|
||||
string(String) ->
|
||||
string(String, []).
|
||||
|
||||
%% @doc Constructs a YAML document from an in-memory YAML string.
|
||||
%%
|
||||
%% `String' must be an Erlang list or binary containing one or more YAML
|
||||
%% documents. If it is a binary, it must be encoded using UTF-8, UTF-16
|
||||
%% or UTF-32. A leading BOM character is used to determine the encoding
|
||||
%% and endianness. If no BOM is present, UTF-8 is assumed.
|
||||
%%
|
||||
%% `Options' is a list of options for the parser and the constructor.
|
||||
%% See {@link new/2} for valid options.
|
||||
%%
|
||||
%% It returns a list of YAML documents. See {@link next_chunk/3} for
|
||||
%% more details about the returned documents.
|
||||
%%
|
||||
%% It throws an exception if there is a parsing or construction error.
|
||||
%%
|
||||
%% <strong>Example: parse an Erlang list</strong>
|
||||
%% ```
|
||||
%% yamerl_constr:string("This is a string").
|
||||
%% '''
|
||||
%%
|
||||
%% <strong>Example: parse an UTF-8-encoded Erlang binary</strong>
|
||||
%% ```
|
||||
%% yamerl_constr:string(<<50,32,226,130,172>>). % The string "2 €" encoded in UTF-8.
|
||||
%% '''
|
||||
%%
|
||||
%% <strong>Example: parse a string in simple mode</strong>
|
||||
%% ```
|
||||
%% yamerl_constr:string("Hello!").
|
||||
%% '''
|
||||
%%
|
||||
%% It returns:
|
||||
%% ```
|
||||
%% % List of documents; here, only one.
|
||||
%% [
|
||||
%% % Document root node: a string.
|
||||
%% "Hello!"
|
||||
%% ].
|
||||
%% '''
|
||||
%%
|
||||
%% <strong>Example: parse a string in detailed mode</strong>
|
||||
%% ```
|
||||
%% yamerl_constr:string("Hello!", [{detailed_constr, true}]).
|
||||
%% '''
|
||||
%%
|
||||
%% It returns:
|
||||
%% ```
|
||||
%% % List of documents; here, only one.
|
||||
%% [
|
||||
%% % Document #1.
|
||||
%% {yamerl_doc,
|
||||
%% % Document root node: a string.
|
||||
%% {yamerl_str, yamerl_node_str, "tag:yaml.org,2002:str",
|
||||
%% [{line, 1}, {column, 1}], % Node location in the original string.
|
||||
%% "Hello!" % String value.
|
||||
%% }
|
||||
%% }
|
||||
%% ].
|
||||
%% '''
|
||||
%%
|
||||
%% <strong>Example: parse an invalid document</strong>
|
||||
%% ```
|
||||
%% yamerl_constr:string(<<"'Oh-oh...">>). % Unfinished single-quoted scalar.
|
||||
%% '''
|
||||
%%
|
||||
%% It throws:
|
||||
%% ```
|
||||
%% {yamerl_exception,
|
||||
%% % List of warnings and errors; here, one fatal error.
|
||||
%% [
|
||||
%% % Error #1.
|
||||
%% {yamerl_parsing_error, error,
|
||||
%% "Unexpected end-of-stream while parsing flow scalar", % Human-readable message.
|
||||
%% 1, 10, % Error location.
|
||||
%% unexpected_eos,
|
||||
%% {yamerl_scalar, 1, 1, {yamerl_tag, 1, 1, {non_specific, "!"}}, % Token being parsed.
|
||||
%% flow, single_quoted,
|
||||
%% "Oh-oh..."},
|
||||
%% []
|
||||
%% }
|
||||
%% ]
|
||||
%% }.
|
||||
%% '''
|
||||
|
||||
-spec string(String, Options) ->
|
||||
Result | no_return() when
|
||||
String :: unicode_data(),
|
||||
@ -211,9 +470,28 @@ string(String, Options) ->
|
||||
| [yamerl_simple_doc()]
|
||||
| term().
|
||||
|
||||
%% @equiv file(Filename, [])
|
||||
|
||||
file(Filename) ->
|
||||
file(Filename, []).
|
||||
|
||||
%% @doc Constructs a YAML document from a regular file.
|
||||
%%
|
||||
%% `Filename' must be a string indicating the filename. The file must
|
||||
%% contain one or more YAML documents. The file must be encoded using
|
||||
%% UTF-8, UTF-16 or UTF-32. A leading BOM character is used to determine
|
||||
%% the encoding and endianness. If no BOM is present, UTF-8 is assumed.
|
||||
%%
|
||||
%% `Options' is a list of options for the parser and the constructor.
|
||||
%% See {@link new/2} for valid options.
|
||||
%%
|
||||
%% It returns a list of YAML documents. See {@link next_chunk/3} for
|
||||
%% more details about the returned documents.
|
||||
%%
|
||||
%% It throws an exception if there is a parsing or construction error.
|
||||
%%
|
||||
%% See {@link string/2} for some examples.
|
||||
|
||||
-spec file(Filename, Options) ->
|
||||
Result | no_return() when
|
||||
Filename :: string(),
|
||||
@ -233,6 +511,13 @@ file(Filename, Options) ->
|
||||
%% Presentation details.
|
||||
%% -------------------------------------------------------------------
|
||||
|
||||
%% @doc Returns presentation informations in the stream for the given
|
||||
%% node.
|
||||
%%
|
||||
%% This only makes sense when the detailed construction mode is enabled
|
||||
%% (ie. `{detailed_constr, true}' was passed as an option to {@link
|
||||
%% new/2}, {@link file/2} or {@link string/2}).
|
||||
|
||||
get_pres_details(Token) ->
|
||||
Line = ?TOKEN_LINE(Token),
|
||||
Column = ?TOKEN_COLUMN(Token),
|
||||
@ -242,12 +527,24 @@ get_pres_details(Token) ->
|
||||
%% Node informations.
|
||||
%% -------------------------------------------------------------------
|
||||
|
||||
%% @doc Returns the line number in the stream for the given node.
|
||||
%%
|
||||
%% This only makes sense when the detailed construction mode is enabled
|
||||
%% (ie. `{detailed_constr, true}' was passed as an option to {@link
|
||||
%% new/2}, {@link file/2} or {@link string/2}).
|
||||
|
||||
node_line(Node) ->
|
||||
case node_pres(Node) of
|
||||
undefined -> undefined;
|
||||
Pres -> proplists:get_value(line, Pres)
|
||||
end.
|
||||
|
||||
%% @doc Returns the column number in the stream for the given node.
|
||||
%%
|
||||
%% This only makes sense when the detailed construction mode is enabled
|
||||
%% (ie. `{detailed_constr, true}' was passed as an option to {@link
|
||||
%% new/2}, {@link file/2} or {@link string/2}).
|
||||
|
||||
node_column(Node) ->
|
||||
case node_pres(Node) of
|
||||
undefined -> undefined;
|
||||
@ -553,6 +850,8 @@ filter_options2([], _, _, Constr_Options, Parser_Options, Ext_Options) ->
|
||||
lists:reverse(Ext_Options)
|
||||
}.
|
||||
|
||||
%% @private
|
||||
|
||||
option_names() ->
|
||||
[
|
||||
node_mods,
|
||||
|
@ -24,6 +24,8 @@
|
||||
% OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
% SUCH DAMAGE.
|
||||
|
||||
%% @private
|
||||
|
||||
-module(yamerl_errors).
|
||||
|
||||
-include("yamerl_errors.hrl").
|
||||
|
@ -24,6 +24,8 @@
|
||||
% OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
% SUCH DAMAGE.
|
||||
|
||||
%% @private
|
||||
|
||||
-module(yamerl_node_bool).
|
||||
|
||||
-include("yamerl_tokens.hrl").
|
||||
|
@ -24,6 +24,8 @@
|
||||
% OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
% SUCH DAMAGE.
|
||||
|
||||
%% @private
|
||||
|
||||
-module(yamerl_node_bool_ext).
|
||||
|
||||
-include("yamerl_tokens.hrl").
|
||||
|
@ -24,6 +24,8 @@
|
||||
% OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
% SUCH DAMAGE.
|
||||
|
||||
%% @private
|
||||
|
||||
-module(yamerl_node_bool_json).
|
||||
|
||||
-include("yamerl_tokens.hrl").
|
||||
|
@ -24,6 +24,8 @@
|
||||
% OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
% SUCH DAMAGE.
|
||||
|
||||
%% @private
|
||||
|
||||
-module(yamerl_node_erlang_atom).
|
||||
|
||||
-include("yamerl_errors.hrl").
|
||||
|
@ -24,6 +24,8 @@
|
||||
% OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
% SUCH DAMAGE.
|
||||
|
||||
%% @private
|
||||
|
||||
-module(yamerl_node_erlang_fun).
|
||||
|
||||
-include("yamerl_errors.hrl").
|
||||
|
@ -24,6 +24,8 @@
|
||||
% OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
% SUCH DAMAGE.
|
||||
|
||||
%% @private
|
||||
|
||||
-module(yamerl_node_float).
|
||||
|
||||
-include("yamerl_errors.hrl").
|
||||
|
@ -24,6 +24,8 @@
|
||||
% OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
% SUCH DAMAGE.
|
||||
|
||||
%% @private
|
||||
|
||||
-module(yamerl_node_float_ext).
|
||||
|
||||
-include("yamerl_errors.hrl").
|
||||
|
@ -24,6 +24,8 @@
|
||||
% OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
% SUCH DAMAGE.
|
||||
|
||||
%% @private
|
||||
|
||||
-module(yamerl_node_float_json).
|
||||
|
||||
-include("yamerl_errors.hrl").
|
||||
|
@ -24,6 +24,8 @@
|
||||
% OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
% SUCH DAMAGE.
|
||||
|
||||
%% @private
|
||||
|
||||
-module(yamerl_node_int).
|
||||
|
||||
-include("yamerl_errors.hrl").
|
||||
|
@ -24,6 +24,8 @@
|
||||
% OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
% SUCH DAMAGE.
|
||||
|
||||
%% @private
|
||||
|
||||
-module(yamerl_node_int_ext).
|
||||
|
||||
-include("yamerl_errors.hrl").
|
||||
|
@ -24,6 +24,8 @@
|
||||
% OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
% SUCH DAMAGE.
|
||||
|
||||
%% @private
|
||||
|
||||
-module(yamerl_node_int_json).
|
||||
|
||||
-include("yamerl_errors.hrl").
|
||||
|
@ -24,6 +24,8 @@
|
||||
% OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
% SUCH DAMAGE.
|
||||
|
||||
%% @private
|
||||
|
||||
-module(yamerl_node_ipaddr).
|
||||
|
||||
-include("yamerl_errors.hrl").
|
||||
|
@ -24,6 +24,8 @@
|
||||
% OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
% SUCH DAMAGE.
|
||||
|
||||
%% @private
|
||||
|
||||
-module(yamerl_node_map).
|
||||
|
||||
-include("yamerl_errors.hrl").
|
||||
|
@ -24,6 +24,8 @@
|
||||
% OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
% SUCH DAMAGE.
|
||||
|
||||
%% @private
|
||||
|
||||
-module(yamerl_node_null).
|
||||
|
||||
-include("yamerl_tokens.hrl").
|
||||
|
@ -24,6 +24,8 @@
|
||||
% OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
% SUCH DAMAGE.
|
||||
|
||||
%% @private
|
||||
|
||||
-module(yamerl_node_null_json).
|
||||
|
||||
-include("yamerl_tokens.hrl").
|
||||
|
@ -24,6 +24,8 @@
|
||||
% OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
% SUCH DAMAGE.
|
||||
|
||||
%% @private
|
||||
|
||||
-module(yamerl_node_seq).
|
||||
|
||||
-include("yamerl_errors.hrl").
|
||||
|
@ -24,6 +24,8 @@
|
||||
% OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
% SUCH DAMAGE.
|
||||
|
||||
%% @private
|
||||
|
||||
-module(yamerl_node_size).
|
||||
|
||||
-include("yamerl_errors.hrl").
|
||||
|
@ -24,6 +24,8 @@
|
||||
% OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
% SUCH DAMAGE.
|
||||
|
||||
%% @private
|
||||
|
||||
-module(yamerl_node_str).
|
||||
|
||||
-include("yamerl_errors.hrl").
|
||||
|
@ -24,6 +24,8 @@
|
||||
% OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
% SUCH DAMAGE.
|
||||
|
||||
%% @private
|
||||
|
||||
-module(yamerl_node_str_json).
|
||||
|
||||
-include("yamerl_errors.hrl").
|
||||
|
@ -24,6 +24,8 @@
|
||||
% OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
% SUCH DAMAGE.
|
||||
|
||||
%% @private
|
||||
|
||||
-module(yamerl_node_timestamp).
|
||||
|
||||
-include("yamerl_errors.hrl").
|
||||
|
@ -24,6 +24,16 @@
|
||||
% OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
% SUCH DAMAGE.
|
||||
|
||||
%% @author Jean-Sébastien Pédron <jean-sebastien.pedron@dumbbell.fr>
|
||||
%% @copyright
|
||||
%% 2012-2014 Yakaz,
|
||||
%% 2016 Jean-Sébastien Pédron <jean-sebastien.pedron@dumbbell.fr>
|
||||
%%
|
||||
%% @doc {@module} implements a YAML parser. It is not meant to be used
|
||||
%% directly. Instead, you should use {@link yamerl_constr}.
|
||||
%%
|
||||
%% The `yamerl' application must be started to use the parser.
|
||||
|
||||
-module(yamerl_parser).
|
||||
|
||||
-include("yamerl_errors.hrl").
|
||||
@ -276,6 +286,8 @@
|
||||
%% Public API: chunked stream scanning.
|
||||
%% -------------------------------------------------------------------
|
||||
|
||||
%% @equiv new(Source, [])
|
||||
|
||||
-spec new(Source) ->
|
||||
Parser | no_return() when
|
||||
Source :: term(),
|
||||
@ -284,6 +296,8 @@
|
||||
new(Source) ->
|
||||
new(Source, []).
|
||||
|
||||
%% @doc Creates and returns a new YAML parser state.
|
||||
|
||||
-spec new(Source, Options) ->
|
||||
Parser | no_return() when
|
||||
Source :: term(),
|
||||
@ -300,6 +314,8 @@ new(Source, Options) ->
|
||||
token_fun = proplists:get_value(token_fun, Options0, acc)
|
||||
}.
|
||||
|
||||
%% @equiv next_chunk(Parser, Chunk, false)
|
||||
|
||||
-spec next_chunk(Parser, Chunk) ->
|
||||
Ret | no_return() when
|
||||
Parser :: yamerl_parser(),
|
||||
@ -310,6 +326,8 @@ new(Source, Options) ->
|
||||
next_chunk(Parser, Chunk) ->
|
||||
next_chunk(Parser, Chunk, false).
|
||||
|
||||
%% @doc Feeds the parser with the next chunk from the YAML stream.
|
||||
|
||||
-spec next_chunk(Parser, Chunk, Last_Chunk) ->
|
||||
Ret | no_return() when
|
||||
Parser :: yamerl_parser(),
|
||||
@ -331,6 +349,8 @@ next_chunk(#yamerl_parser{raw_data = Data} = Parser, Chunk, EOS) ->
|
||||
},
|
||||
decode_unicode(Parser1).
|
||||
|
||||
%% @equiv next_chunk(Parser, Chunk, true)
|
||||
|
||||
-spec last_chunk(Parser, Chunk) ->
|
||||
Ret | no_return() when
|
||||
Parser :: yamerl_parser(),
|
||||
@ -345,6 +365,8 @@ last_chunk(Parser, Chunk) ->
|
||||
%% Public API: common stream sources.
|
||||
%% -------------------------------------------------------------------
|
||||
|
||||
%% @equiv string(String, [])
|
||||
|
||||
-spec string(String) ->
|
||||
Parser | no_return() when
|
||||
String :: unicode_data(),
|
||||
@ -353,6 +375,8 @@ last_chunk(Parser, Chunk) ->
|
||||
string(String) ->
|
||||
string(String, []).
|
||||
|
||||
%% @doc Parses a YAML document from an in-memory YAML string.
|
||||
|
||||
-spec string(String, Options) ->
|
||||
Parser | no_return() when
|
||||
String :: unicode_data(),
|
||||
@ -365,6 +389,8 @@ string(String, Options) when is_binary(String) ->
|
||||
string(String, Options) when is_list(String) ->
|
||||
string(unicode:characters_to_binary(String), Options).
|
||||
|
||||
%% @equiv file(Filename, [])
|
||||
|
||||
-spec file(Filename) ->
|
||||
Parser | no_return() when
|
||||
Filename :: string(),
|
||||
@ -373,6 +399,8 @@ string(String, Options) when is_list(String) ->
|
||||
file(Filename) ->
|
||||
file(Filename, []).
|
||||
|
||||
%% @doc Parses a YAML document from a regular file.
|
||||
|
||||
-spec file(Filename, Options) ->
|
||||
Parser | no_return() when
|
||||
Filename :: string(),
|
||||
@ -440,9 +468,13 @@ file2(#yamerl_parser{source = {file, Filename}} = Parser, FD, Blocksize) ->
|
||||
%% Public API: get/set the token function.
|
||||
%% -------------------------------------------------------------------
|
||||
|
||||
%% @doc Returns the constructor callback function
|
||||
|
||||
get_token_fun(#yamerl_parser{token_fun = Fun}) ->
|
||||
Fun.
|
||||
|
||||
%% @doc Sets the constructor callback function
|
||||
|
||||
set_token_fun(Parser, Fun) when is_function(Fun, 1) ->
|
||||
Parser#yamerl_parser{token_fun = Fun}.
|
||||
|
||||
@ -4203,6 +4235,8 @@ setup_default_tags(#yamerl_parser{options = Options} = Parser) ->
|
||||
%% Internal functions.
|
||||
%% -------------------------------------------------------------------
|
||||
|
||||
%% @private
|
||||
|
||||
option_names() ->
|
||||
[
|
||||
default_tags,
|
||||
|
@ -24,6 +24,8 @@
|
||||
% OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
% SUCH DAMAGE.
|
||||
|
||||
%% @private
|
||||
|
||||
-module(yamerl_sup).
|
||||
|
||||
-behaviour(supervisor).
|
||||
|
@ -24,6 +24,16 @@
|
||||
% OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
% SUCH DAMAGE.
|
||||
|
||||
%% @author Jean-Sébastien Pédron <jean-sebastien.pedron@dumbbell.fr>
|
||||
%% @copyright
|
||||
%% 2012-2014 Yakaz,
|
||||
%% 2016 Jean-Sébastien Pédron <jean-sebastien.pedron@dumbbell.fr>
|
||||
%%
|
||||
%% @doc {@module} implements the <em>yamerl</em> API above {@link
|
||||
%% yamerl_constr}.
|
||||
%%
|
||||
%% See <em>yamler</em> documentation: [https://github.com/goertzenator/yamler].
|
||||
|
||||
-module(yamerl_yamler_compat).
|
||||
|
||||
-include("yamerl_errors.hrl").
|
||||
@ -50,6 +60,8 @@
|
||||
%% Public API.
|
||||
%% -------------------------------------------------------------------
|
||||
|
||||
%% @equiv load(String, [])
|
||||
|
||||
-spec load(String) ->
|
||||
Result | Error when
|
||||
String :: binary(),
|
||||
@ -60,6 +72,10 @@
|
||||
load(String) ->
|
||||
load(String, []).
|
||||
|
||||
%% @doc Constructs a YAML document from an in-memory string.
|
||||
%%
|
||||
%% The `yamerl' application must be started to use this wrapper.
|
||||
|
||||
-spec load(String, Options) ->
|
||||
Result | Error when
|
||||
String :: binary(),
|
||||
@ -78,6 +94,8 @@ load(String, Options) ->
|
||||
format_error(Error)
|
||||
end.
|
||||
|
||||
%% @equiv load_file(Filename, [])
|
||||
|
||||
-spec load_file(Filename) ->
|
||||
Result | Error when
|
||||
Filename :: string(),
|
||||
@ -88,6 +106,8 @@ load(String, Options) ->
|
||||
load_file(Filename) ->
|
||||
load_file(Filename, []).
|
||||
|
||||
%% @doc Constructs a YAML document from a regular file.
|
||||
|
||||
-spec load_file(Filename, Options) ->
|
||||
Result | Error when
|
||||
Filename :: string(),
|
||||
@ -106,6 +126,8 @@ load_file(Filename, Options) ->
|
||||
format_error(Error)
|
||||
end.
|
||||
|
||||
%% @private
|
||||
|
||||
-spec convert_options(Options) ->
|
||||
Converted when
|
||||
Options :: [yamler_option()],
|
||||
@ -118,6 +140,8 @@ load_file(Filename, Options) ->
|
||||
convert_options(Options) ->
|
||||
convert_options(Options, []).
|
||||
|
||||
%% @private
|
||||
|
||||
convert_options([{schema, yaml_schema_failsafe} | Rest], Converted) ->
|
||||
Converted1 = [
|
||||
{schema, failsafe}
|
||||
|
Loading…
Reference in New Issue
Block a user