libyaml / src / parser.c

/*
 * The parser implements the following grammar:
 *
 * stream               ::= STREAM-START implicit_document? explicit_document* STREAM-END
 * implicit_document    ::= block_node DOCUMENT-END*
 * explicit_document    ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
 * block_node_or_indentless_sequence    ::=
 *                          ALIAS
 *                          | properties (block_content | indentless_block_sequence)?
 *                          | block_content
 *                          | indentless_block_sequence
 * block_node           ::= ALIAS
 *                          | properties block_content?
 *                          | block_content
 * flow_node            ::= ALIAS
 *                          | properties flow_content?
 *                          | flow_content
 * properties           ::= TAG ANCHOR? | ANCHOR TAG?
 * block_content        ::= block_collection | flow_collection | SCALAR
 * flow_content         ::= flow_collection | SCALAR
 * block_collection     ::= block_sequence | block_mapping
 * flow_collection      ::= flow_sequence | flow_mapping
 * block_sequence       ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
 * indentless_sequence  ::= (BLOCK-ENTRY block_node?)+
 * block_mapping        ::= BLOCK-MAPPING_START
 *                          ((KEY block_node_or_indentless_sequence?)?
 *                          (VALUE block_node_or_indentless_sequence?)?)*
 *                          BLOCK-END
 * flow_sequence        ::= FLOW-SEQUENCE-START
 *                          (flow_sequence_entry FLOW-ENTRY)*
 *                          flow_sequence_entry?
 *                          FLOW-SEQUENCE-END
 * flow_sequence_entry  ::= flow_node | KEY flow_node? (VALUE flow_node?)?
 * flow_mapping         ::= FLOW-MAPPING-START
 *                          (flow_mapping_entry FLOW-ENTRY)*
 *                          flow_mapping_entry?
 *                          FLOW-MAPPING-END
 * flow_mapping_entry   ::= flow_node | KEY flow_node? (VALUE flow_node?)?
 */

#if HAVE_CONFIG_H
#include <config.h>
#endif

#include <yaml.h>

#include <assert.h>

/*
 * Public API declarations.
 */

YAML_DECLARE(yaml_event_t *)
yaml_parser_get_event(yaml_parser_t *parser);

YAML_DECLARE(yaml_event_t *)
yaml_parser_peek_event(yaml_parser_t *parser);

/*
 * State functions.
 */

static yaml_event_t *
yaml_parser_state_machine(yaml_parser_t *parser);

static yaml_event_t *
yaml_parser_parse_stream_start(yaml_parser_t *parser);

static yaml_event_t *
yaml_parser_parse_document_start(yaml_parser_t *parser, int implicit);

static yaml_event_t *
yaml_parser_parse_document_content(yaml_parser_t *parser);

static yaml_event_t *
yaml_parser_parse_document_end(yaml_parser_t *parser);

static yaml_event_t *
yaml_parser_parse_node(yaml_parser_t *parser,
        int block, int indentless_sequence);

static yaml_event_t *
yaml_parser_parse_block_sequence_entry(yaml_parser_t *parser, int first);

static yaml_event_t *
yaml_parser_parse_indentless_sequence_entry(yaml_parser_t *parser);

static yaml_event_t *
yaml_parser_parse_block_mapping_key(yaml_parser_t *parser, int first);

static yaml_event_t *
yaml_parser_parse_block_mapping_value(yaml_parser_t *parser);

static yaml_event_t *
yaml_parser_parse_flow_sequence_entry(yaml_parser_t *parser, int first);

static yaml_event_t *
yaml_parser_parse_flow_sequence_entry_mapping_key(yaml_parser_t *parser);

static yaml_event_t *
yaml_parser_parse_flow_sequence_entry_mapping_value(yaml_parser_t *parser);

static yaml_event_t *
yaml_parser_parse_flow_sequence_entry_mapping_end(yaml_parser_t *parser);

static yaml_event_t *
yaml_parser_parse_flow_mapping_key(yaml_parser_t *parser, int first);

static yaml_event_t *
yaml_parser_parse_flow_mapping_value(yaml_parser_t *parser, int empty);

/*
 * Get the next event and advance the parser.
 */

YAML_DECLARE(yaml_event_t *)
yaml_parser_get_event(yaml_parser_t *parser)
{
    yaml_event_t *value;

    /* Update the current event if needed. */
    
    if (!parser->current_event) {
        parser->current_event = yaml_parser_state_machine(parser);
    }

    /* Return and clear the current event. */

    value = parser->current_event;
    parser->current_event = NULL;
    return value;
}

/*
 * Peek the next event.
 */

YAML_DECLARE(yaml_event_t *)
yaml_parser_peek_event(yaml_parser_t *parser)
{
    yaml_event_t *value;

    /* Update the current event if needed. */
    
    if (!parser->current_event) {
        parser->current_event = yaml_parser_state_machine(parser);
    }

    /* Return the current event. */

    return parser->current_event;
}

/*
 * State dispatcher.
 */

static yaml_event_t *
yaml_parser_state_machine(yaml_parser_t *parser)
{
    assert (parser->state != YAML_PARSE_END_STATE);

    switch (parser->state)
    {
        case YAML_PARSE_STREAM_START_STATE:
            return yaml_parser_parse_stream_start(parser);

        case YAML_PARSE_IMPLICIT_DOCUMENT_START_STATE:
            return yaml_parser_parse_document_start(parser, 1);

        case YAML_PARSE_DOCUMENT_START_STATE:
            return yaml_parser_parse_document_start(parser, 0);

        case YAML_PARSE_DOCUMENT_CONTENT_STATE:
            return yaml_parser_parse_document_content(parser);

        case YAML_PARSE_DOCUMENT_END_STATE:
            return yaml_parser_parse_document_end(parser);

        case YAML_PARSE_BLOCK_NODE_STATE:
            return yaml_parser_parse_node(parser, 1, 0);

        case YAML_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE:
            return yaml_parser_parse_node(parser, 1, 1);

        case YAML_PARSE_FLOW_NODE_STATE:
            return yaml_parser_parse_node(parser, 0, 0);

        case YAML_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE:
            return yaml_parser_parse_block_sequence_entry(parser, 1);

        case YAML_PARSE_BLOCK_SEQUENCE_ENTRY_STATE:
            return yaml_parser_parse_block_sequence_entry(parser, 0);

        case YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE:
            return yaml_parser_parse_indentless_sequence_entry(parser);

        case YAML_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE:
            return yaml_parser_parse_block_mapping_key(parser, 1);

        case YAML_PARSE_BLOCK_MAPPING_KEY_STATE:
            return yaml_parser_parse_block_mapping_key(parser, 0);

        case YAML_PARSE_BLOCK_MAPPING_VALUE_STATE:
            return yaml_parser_parse_block_mapping_value(parser);

        case YAML_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE:
            return yaml_parser_parse_flow_sequence_entry(parser, 1);

        case YAML_PARSE_FLOW_SEQUENCE_ENTRY_STATE:
            return yaml_parser_parse_flow_sequence_entry(parser, 0);

        case YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE:
            return yaml_parser_parse_flow_sequence_entry_mapping_key(parser);

        case YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE:
            return yaml_parser_parse_flow_sequence_entry_mapping_value(parser);

        case YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE:
            return yaml_parser_parse_flow_sequence_entry_mapping_end(parser);

        case YAML_PARSE_FLOW_MAPPING_FIRST_KEY_STATE:
            return yaml_parser_parse_flow_mapping_key(parser, 1);

        case YAML_PARSE_FLOW_MAPPING_KEY_STATE:
            return yaml_parser_parse_flow_mapping_key(parser, 0);

        case YAML_PARSE_FLOW_MAPPING_VALUE_STATE:
            return yaml_parser_parse_flow_mapping_value(parser, 0);

        case YAML_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE:
            return yaml_parser_parse_flow_mapping_value(parser, 1);
    }
    assert(1);
}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.