| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432 |
- #include "yaml_private.h"
- /*
- * API functions.
- */
- YAML_DECLARE(int)
- yaml_parser_load(yaml_parser_t *parser, yaml_document_t *document);
- /*
- * Error handling.
- */
- static int
- yaml_parser_set_composer_error(yaml_parser_t *parser,
- const char *problem, yaml_mark_t problem_mark);
- static int
- yaml_parser_set_composer_error_context(yaml_parser_t *parser,
- const char *context, yaml_mark_t context_mark,
- const char *problem, yaml_mark_t problem_mark);
- /*
- * Alias handling.
- */
- static int
- yaml_parser_register_anchor(yaml_parser_t *parser,
- int index, yaml_char_t *anchor);
- /*
- * Clean up functions.
- */
- static void
- yaml_parser_delete_aliases(yaml_parser_t *parser);
- /*
- * Composer functions.
- */
- static int
- yaml_parser_load_document(yaml_parser_t *parser, yaml_event_t *first_event);
- static int
- yaml_parser_load_node(yaml_parser_t *parser, yaml_event_t *first_event);
- static int
- yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *first_event);
- static int
- yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *first_event);
- static int
- yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *first_event);
- static int
- yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *first_event);
- /*
- * Load the next document of the stream.
- */
- YAML_DECLARE(int)
- yaml_parser_load(yaml_parser_t *parser, yaml_document_t *document)
- {
- yaml_event_t event;
- assert(parser); /* Non-NULL parser object is expected. */
- assert(document); /* Non-NULL document object is expected. */
- memset(document, 0, sizeof(yaml_document_t));
- if (!STACK_INIT(parser, document->nodes, INITIAL_STACK_SIZE))
- goto error;
- if (!parser->stream_start_produced) {
- if (!yaml_parser_parse(parser, &event)) goto error;
- assert(event.type == YAML_STREAM_START_EVENT);
- /* STREAM-START is expected. */
- }
- if (parser->stream_end_produced) {
- return 1;
- }
- if (!yaml_parser_parse(parser, &event)) goto error;
- if (event.type == YAML_STREAM_END_EVENT) {
- return 1;
- }
- if (!STACK_INIT(parser, parser->aliases, INITIAL_STACK_SIZE))
- goto error;
- parser->document = document;
- if (!yaml_parser_load_document(parser, &event)) goto error;
- yaml_parser_delete_aliases(parser);
- parser->document = NULL;
- return 1;
- error:
- yaml_parser_delete_aliases(parser);
- yaml_document_delete(document);
- parser->document = NULL;
- return 0;
- }
- /*
- * Set composer error.
- */
- static int
- yaml_parser_set_composer_error(yaml_parser_t *parser,
- const char *problem, yaml_mark_t problem_mark)
- {
- parser->error = YAML_COMPOSER_ERROR;
- parser->problem = problem;
- parser->problem_mark = problem_mark;
- return 0;
- }
- /*
- * Set composer error with context.
- */
- static int
- yaml_parser_set_composer_error_context(yaml_parser_t *parser,
- const char *context, yaml_mark_t context_mark,
- const char *problem, yaml_mark_t problem_mark)
- {
- parser->error = YAML_COMPOSER_ERROR;
- parser->context = context;
- parser->context_mark = context_mark;
- parser->problem = problem;
- parser->problem_mark = problem_mark;
- return 0;
- }
- /*
- * Delete the stack of aliases.
- */
- static void
- yaml_parser_delete_aliases(yaml_parser_t *parser)
- {
- while (!STACK_EMPTY(parser, parser->aliases)) {
- yaml_free(POP(parser, parser->aliases).anchor);
- }
- STACK_DEL(parser, parser->aliases);
- }
- /*
- * Compose a document object.
- */
- static int
- yaml_parser_load_document(yaml_parser_t *parser, yaml_event_t *first_event)
- {
- yaml_event_t event;
- assert(first_event->type == YAML_DOCUMENT_START_EVENT);
- /* DOCUMENT-START is expected. */
- parser->document->version_directive
- = first_event->data.document_start.version_directive;
- parser->document->tag_directives.start
- = first_event->data.document_start.tag_directives.start;
- parser->document->tag_directives.end
- = first_event->data.document_start.tag_directives.end;
- parser->document->start_implicit
- = first_event->data.document_start.implicit;
- parser->document->start_mark = first_event->start_mark;
- if (!yaml_parser_parse(parser, &event)) return 0;
- if (!yaml_parser_load_node(parser, &event)) return 0;
- if (!yaml_parser_parse(parser, &event)) return 0;
- assert(event.type == YAML_DOCUMENT_END_EVENT);
- /* DOCUMENT-END is expected. */
- parser->document->end_implicit = event.data.document_end.implicit;
- parser->document->end_mark = event.end_mark;
- return 1;
- }
- /*
- * Compose a node.
- */
- static int
- yaml_parser_load_node(yaml_parser_t *parser, yaml_event_t *first_event)
- {
- switch (first_event->type) {
- case YAML_ALIAS_EVENT:
- return yaml_parser_load_alias(parser, first_event);
- case YAML_SCALAR_EVENT:
- return yaml_parser_load_scalar(parser, first_event);
- case YAML_SEQUENCE_START_EVENT:
- return yaml_parser_load_sequence(parser, first_event);
- case YAML_MAPPING_START_EVENT:
- return yaml_parser_load_mapping(parser, first_event);
- default:
- assert(0); /* Could not happen. */
- return 0;
- }
- return 0;
- }
- /*
- * Add an anchor.
- */
- static int
- yaml_parser_register_anchor(yaml_parser_t *parser,
- int index, yaml_char_t *anchor)
- {
- yaml_alias_data_t data;
- yaml_alias_data_t *alias_data;
- if (!anchor) return 1;
- data.anchor = anchor;
- data.index = index;
- data.mark = parser->document->nodes.start[index-1].start_mark;
- for (alias_data = parser->aliases.start;
- alias_data != parser->aliases.top; alias_data ++) {
- if (strcmp((char *)alias_data->anchor, (char *)anchor) == 0) {
- yaml_free(anchor);
- return yaml_parser_set_composer_error_context(parser,
- "found duplicate anchor; first occurence",
- alias_data->mark, "second occurence", data.mark);
- }
- }
- if (!PUSH(parser, parser->aliases, data)) {
- yaml_free(anchor);
- return 0;
- }
- return 1;
- }
- /*
- * Compose a node corresponding to an alias.
- */
- static int
- yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *first_event)
- {
- yaml_char_t *anchor = first_event->data.alias.anchor;
- yaml_alias_data_t *alias_data;
- for (alias_data = parser->aliases.start;
- alias_data != parser->aliases.top; alias_data ++) {
- if (strcmp((char *)alias_data->anchor, (char *)anchor) == 0) {
- yaml_free(anchor);
- return alias_data->index;
- }
- }
- yaml_free(anchor);
- return yaml_parser_set_composer_error(parser, "found undefined alias",
- first_event->start_mark);
- }
- /*
- * Compose a scalar node.
- */
- static int
- yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *first_event)
- {
- yaml_node_t node;
- int index;
- yaml_char_t *tag = first_event->data.scalar.tag;
- if (!tag || strcmp((char *)tag, "!") == 0) {
- yaml_free(tag);
- tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_SCALAR_TAG);
- if (!tag) goto error;
- }
- SCALAR_NODE_INIT(node, tag, first_event->data.scalar.value,
- first_event->data.scalar.length, first_event->data.scalar.style,
- first_event->start_mark, first_event->end_mark);
- if (!PUSH(parser, parser->document->nodes, node)) goto error;
- index = parser->document->nodes.top - parser->document->nodes.start;
- if (!yaml_parser_register_anchor(parser, index,
- first_event->data.scalar.anchor)) return 0;
- return index;
- error:
- yaml_free(tag);
- yaml_free(first_event->data.scalar.anchor);
- yaml_free(first_event->data.scalar.value);
- return 0;
- }
- /*
- * Compose a sequence node.
- */
- static int
- yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *first_event)
- {
- yaml_event_t event;
- yaml_node_t node;
- struct {
- yaml_node_item_t *start;
- yaml_node_item_t *end;
- yaml_node_item_t *top;
- } items = { NULL, NULL, NULL };
- int index, item_index;
- yaml_char_t *tag = first_event->data.sequence_start.tag;
- if (!tag || strcmp((char *)tag, "!") == 0) {
- yaml_free(tag);
- tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG);
- if (!tag) goto error;
- }
- if (!STACK_INIT(parser, items, INITIAL_STACK_SIZE)) goto error;
- SEQUENCE_NODE_INIT(node, tag, items.start, items.end,
- first_event->data.sequence_start.style,
- first_event->start_mark, first_event->end_mark);
- if (!PUSH(parser, parser->document->nodes, node)) goto error;
- index = parser->document->nodes.top - parser->document->nodes.start;
- if (!yaml_parser_register_anchor(parser, index,
- first_event->data.sequence_start.anchor)) return 0;
- if (!yaml_parser_parse(parser, &event)) return 0;
- while (event.type != YAML_SEQUENCE_END_EVENT) {
- item_index = yaml_parser_load_node(parser, &event);
- if (!item_index) return 0;
- if (!PUSH(parser,
- parser->document->nodes.start[index-1].data.sequence.items,
- item_index)) return 0;
- if (!yaml_parser_parse(parser, &event)) return 0;
- }
- parser->document->nodes.start[index-1].end_mark = event.end_mark;
- return index;
- error:
- yaml_free(tag);
- yaml_free(first_event->data.sequence_start.anchor);
- return 0;
- }
- /*
- * Compose a mapping node.
- */
- static int
- yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *first_event)
- {
- yaml_event_t event;
- yaml_node_t node;
- struct {
- yaml_node_pair_t *start;
- yaml_node_pair_t *end;
- yaml_node_pair_t *top;
- } pairs = { NULL, NULL, NULL };
- int index;
- yaml_node_pair_t pair;
- yaml_char_t *tag = first_event->data.mapping_start.tag;
- if (!tag || strcmp((char *)tag, "!") == 0) {
- yaml_free(tag);
- tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_MAPPING_TAG);
- if (!tag) goto error;
- }
- if (!STACK_INIT(parser, pairs, INITIAL_STACK_SIZE)) goto error;
- MAPPING_NODE_INIT(node, tag, pairs.start, pairs.end,
- first_event->data.mapping_start.style,
- first_event->start_mark, first_event->end_mark);
- if (!PUSH(parser, parser->document->nodes, node)) goto error;
- index = parser->document->nodes.top - parser->document->nodes.start;
- if (!yaml_parser_register_anchor(parser, index,
- first_event->data.mapping_start.anchor)) return 0;
- if (!yaml_parser_parse(parser, &event)) return 0;
- while (event.type != YAML_MAPPING_END_EVENT) {
- pair.key = yaml_parser_load_node(parser, &event);
- if (!pair.key) return 0;
- if (!yaml_parser_parse(parser, &event)) return 0;
- pair.value = yaml_parser_load_node(parser, &event);
- if (!pair.value) return 0;
- if (!PUSH(parser,
- parser->document->nodes.start[index-1].data.mapping.pairs,
- pair)) return 0;
- if (!yaml_parser_parse(parser, &event)) return 0;
- }
- parser->document->nodes.start[index-1].end_mark = event.end_mark;
- return index;
- error:
- yaml_free(tag);
- yaml_free(first_event->data.mapping_start.anchor);
- return 0;
- }
|