Search code examples
cparsinglibyaml

C libyaml document-based parsing


I'm trying to code a yaml-formatted configuration file parser using C and libyaml. My Internet searches did not bring me any luck with finding a decent and complete documentation of the API with an operation manual. A tutorial by Andrew Poelstra here does not describe the document-based [with the use of yaml_parser_load ()] parsing method, which looks to me by far more logical and justified than the token-based and the event-based methods.

So currently I'm sticking to the doxygen-generated docs from yaml.h, and it really leaves me confused about how do I actually parse something after I load a document into a parser. Specifically I do not get which stack do we talk in the definitions of the yaml_document_s and yaml_node_s structs.

An example from yaml_node_s.data.mapping:

struct {
    /** The stack of mapping pairs (key, value). */
    struct {
        /** The beginning of the stack. */
        yaml_node_pair_t *start;
        /** The end of the stack. */
        yaml_node_pair_t *end;
        /** The top of the stack. */
        yaml_node_pair_t *top;
    } pairs;
    /** The mapping style. */
    yaml_mapping_style_t style;
} mapping;

I've figured out that *start (in my case) points to an array of yaml_node_pair_t's, each of which contains a pair of key and value integers, which are the indices by which the corresponding nodes can be acqured using the yaml_document_get_node () function. The meaning of the *end and *top pointers and how do I determine boundaries of and iterate a mapping using them remains a mystery to me, since *end does not contain the final node pair indices.

I would positively be happy if someone clarified to me at least the stack meaning here, or even better provided me with a good documentation and examples. Thanks in advance.


Solution

  • start is the bottom of the stack, top is above the top of the stack, and end points to the last yaml_node_pair_t piece of memory allocated for this stack. I figured this out with some experimentation and looking at the libyaml source. looking at yaml_document_get_node, yaml_document_get_root_node, and yaml_document_add_scalar provide some nice hints. for example:

    YAML_DECLARE(yaml_node_t *)
    yaml_document_get_node(yaml_document_t *document, int index)                                                    
    {
    
        assert(document);   /* Non-NULL document object is expected. */
    
        if (index > 0 && document->nodes.start + index <= document->nodes.top) {
            return document->nodes.start + index - 1;
        }
        return NULL;
    }
    

    but really I guess it should have been obvious to both of us with just the knowledge of what a stack is. Anyway, you want to iterate starting at start stopping before reaching top like I've done here in a basic implementation:

    http://codepad.org/W7StVSkV

    (Not guaranteed to be perfect, but it worked for my test case)