Chapter 66. Parsing YAML documents

Index

Parsing scalars
Parsing sequences
Parsing mappings
Parsing aliases (not)
Example of parsing a YAML document
#include <x/yaml/parser.H>
#include <x/yaml/document.H>
#include <x/yaml/node.H>

std::ifstream i("file.yml");

x::yaml::parser p=
    x::yaml::parser::create(std::istreambuf_iterator<char>(i),
                            std::istreambuf_iterator<char>());

if (p->documents.size() != 1)
    throw EXCEPTION("file.yml did not contain a single YAML document");

x::yaml::document doc=p->documents.front();

x::yaml::node n=p->root();

x::yaml::parser and x::yaml::document are references to reference-counted objects that represent one or more parsed YAML documents.

x::yaml::parser's constructor takes a pair of iterators that define an input sequence of characters that comprise one or more YAML documents. The constructor iterates over the input sequence, and parses it into a std::list<x::yaml::document>, the documents member of the constructed object.

The above example uses input stream iterators to parse YAML document(s) from a file, but any char input iterator works. An exception gets thrown if there was a parsing error and a YAML document was ill-formed, or if the iterators themselves threw an exception. Note that if the iterators report failures by means other than throwing an exception, this will have to checked out of band, unless the resulting YAML document ended up being ill-formed, and x::yaml::parser itself threw an exception for that reason.

Note

create() loads all the documents into memory, although they are stored in LibYAML's internal structures, which are quite modest in size (and the reference-counted objects and templates described below get constructed on demand). To enforce an upper limit on the size of loaded YAML documents, use an iterator that throws an exception after the number of read characters exceeds the limit, something along the lines of x::http::form::limited_iter.

The contents of a YAML documents are presented as a hierarchical tree of nodes. The document object's root() returns the root node of the document.

x::yaml::node is a reference to an instance of x::yaml::nodeObj, which a superclass of several possible kinds of YAML, with two members: tag, the node's YAML tag, and nodetype that specifies what kind of a node it is:

YAML_SCALAR_NODE

This x::yaml::node is convertible to a x::yaml::scalarnode.

YAML_SEQUENCE_NODE

This x::yaml::node is convertible to a x::yaml::sequencenode.

YAML_MAPPING_NODE

This x::yaml::node is convertible to a x::yaml::mappingnode.

YAML_NO_NODE

An unknown node. This is a stub that gets returned for the root node of an empty YAML document.

When the root node type's is known, coerce the expected reference type:

x::yaml::mappingnode n=p->root();

If the document's root node turns out to be something else, the conversion cannot be made, and an exception gets thrown. It's presumed that this is within the scope that catches YAML parsing exceptions, and can be treated the same way.

Parsing scalars

#include <x/yaml/scalarnode.H>

switch (n->nodetype) {

// ...
case YAML_SCALAR_NODE:
    handle_scalar(x::yaml::scalarnode(n));
    break;

// ...
};

// ...

void handle_scalar(const x::yaml::scalarnode &scalar)
{
    std::cout <<scalar->value << std::endl;
}

The value member of a scalar node object gives the value of the scalar.