1 2#include "yaml_private.h" 3 4/* 5 * API functions. 6 */ 7 8YAML_DECLARE(int) 9yaml_parser_load(yaml_parser_t *parser, yaml_document_t *document); 10 11/* 12 * Error handling. 13 */ 14 15static int 16yaml_parser_set_composer_error(yaml_parser_t *parser, 17 const char *problem, yaml_mark_t problem_mark); 18 19static int 20yaml_parser_set_composer_error_context(yaml_parser_t *parser, 21 const char *context, yaml_mark_t context_mark, 22 const char *problem, yaml_mark_t problem_mark); 23 24 25/* 26 * Alias handling. 27 */ 28 29static int 30yaml_parser_register_anchor(yaml_parser_t *parser, 31 int index, yaml_char_t *anchor); 32 33/* 34 * Clean up functions. 35 */ 36 37static void 38yaml_parser_delete_aliases(yaml_parser_t *parser); 39 40/* 41 * Composer functions. 42 */ 43 44static int 45yaml_parser_load_document(yaml_parser_t *parser, yaml_event_t *first_event); 46 47static int 48yaml_parser_load_node(yaml_parser_t *parser, yaml_event_t *first_event); 49 50static int 51yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *first_event); 52 53static int 54yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *first_event); 55 56static int 57yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *first_event); 58 59static int 60yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *first_event); 61 62/* 63 * Load the next document of the stream. 64 */ 65 66YAML_DECLARE(int) 67yaml_parser_load(yaml_parser_t *parser, yaml_document_t *document) 68{ 69 yaml_event_t event; 70 71 assert(parser); /* Non-NULL parser object is expected. */ 72 assert(document); /* Non-NULL document object is expected. */ 73 74 memset(document, 0, sizeof(yaml_document_t)); 75 if (!STACK_INIT(parser, document->nodes, INITIAL_STACK_SIZE)) 76 goto error; 77 78 if (!parser->stream_start_produced) { 79 if (!yaml_parser_parse(parser, &event)) goto error; 80 assert(event.type == YAML_STREAM_START_EVENT); 81 /* STREAM-START is expected. */ 82 } 83 84 if (parser->stream_end_produced) { 85 return 1; 86 } 87 88 if (!yaml_parser_parse(parser, &event)) goto error; 89 if (event.type == YAML_STREAM_END_EVENT) { 90 return 1; 91 } 92 93 if (!STACK_INIT(parser, parser->aliases, INITIAL_STACK_SIZE)) 94 goto error; 95 96 parser->document = document; 97 98 if (!yaml_parser_load_document(parser, &event)) goto error; 99 100 yaml_parser_delete_aliases(parser); 101 parser->document = NULL; 102 103 return 1; 104 105error: 106 107 yaml_parser_delete_aliases(parser); 108 yaml_document_delete(document); 109 parser->document = NULL; 110 111 return 0; 112} 113 114/* 115 * Set composer error. 116 */ 117 118static int 119yaml_parser_set_composer_error(yaml_parser_t *parser, 120 const char *problem, yaml_mark_t problem_mark) 121{ 122 parser->error = YAML_COMPOSER_ERROR; 123 parser->problem = problem; 124 parser->problem_mark = problem_mark; 125 126 return 0; 127} 128 129/* 130 * Set composer error with context. 131 */ 132 133static int 134yaml_parser_set_composer_error_context(yaml_parser_t *parser, 135 const char *context, yaml_mark_t context_mark, 136 const char *problem, yaml_mark_t problem_mark) 137{ 138 parser->error = YAML_COMPOSER_ERROR; 139 parser->context = context; 140 parser->context_mark = context_mark; 141 parser->problem = problem; 142 parser->problem_mark = problem_mark; 143 144 return 0; 145} 146 147/* 148 * Delete the stack of aliases. 149 */ 150 151static void 152yaml_parser_delete_aliases(yaml_parser_t *parser) 153{ 154 while (!STACK_EMPTY(parser, parser->aliases)) { 155 yaml_free(POP(parser, parser->aliases).anchor); 156 } 157 STACK_DEL(parser, parser->aliases); 158} 159 160/* 161 * Compose a document object. 162 */ 163 164static int 165yaml_parser_load_document(yaml_parser_t *parser, yaml_event_t *first_event) 166{ 167 yaml_event_t event; 168 169 assert(first_event->type == YAML_DOCUMENT_START_EVENT); 170 /* DOCUMENT-START is expected. */ 171 172 parser->document->version_directive 173 = first_event->data.document_start.version_directive; 174 parser->document->tag_directives.start 175 = first_event->data.document_start.tag_directives.start; 176 parser->document->tag_directives.end 177 = first_event->data.document_start.tag_directives.end; 178 parser->document->start_implicit 179 = first_event->data.document_start.implicit; 180 parser->document->start_mark = first_event->start_mark; 181 182 if (!yaml_parser_parse(parser, &event)) return 0; 183 184 if (!yaml_parser_load_node(parser, &event)) return 0; 185 186 if (!yaml_parser_parse(parser, &event)) return 0; 187 assert(event.type == YAML_DOCUMENT_END_EVENT); 188 /* DOCUMENT-END is expected. */ 189 190 parser->document->end_implicit = event.data.document_end.implicit; 191 parser->document->end_mark = event.end_mark; 192 193 return 1; 194} 195 196/* 197 * Compose a node. 198 */ 199 200static int 201yaml_parser_load_node(yaml_parser_t *parser, yaml_event_t *first_event) 202{ 203 switch (first_event->type) { 204 case YAML_ALIAS_EVENT: 205 return yaml_parser_load_alias(parser, first_event); 206 case YAML_SCALAR_EVENT: 207 return yaml_parser_load_scalar(parser, first_event); 208 case YAML_SEQUENCE_START_EVENT: 209 return yaml_parser_load_sequence(parser, first_event); 210 case YAML_MAPPING_START_EVENT: 211 return yaml_parser_load_mapping(parser, first_event); 212 default: 213 assert(0); /* Could not happen. */ 214 return 0; 215 } 216 217 return 0; 218} 219 220/* 221 * Add an anchor. 222 */ 223 224static int 225yaml_parser_register_anchor(yaml_parser_t *parser, 226 int index, yaml_char_t *anchor) 227{ 228 yaml_alias_data_t data; 229 yaml_alias_data_t *alias_data; 230 231 if (!anchor) return 1; 232 233 data.anchor = anchor; 234 data.index = index; 235 data.mark = parser->document->nodes.start[index-1].start_mark; 236 237 for (alias_data = parser->aliases.start; 238 alias_data != parser->aliases.top; alias_data ++) { 239 if (strcmp((char *)alias_data->anchor, (char *)anchor) == 0) { 240 yaml_free(anchor); 241 return yaml_parser_set_composer_error_context(parser, 242 "found duplicate anchor; first occurence", 243 alias_data->mark, "second occurence", data.mark); 244 } 245 } 246 247 if (!PUSH(parser, parser->aliases, data)) { 248 yaml_free(anchor); 249 return 0; 250 } 251 252 return 1; 253} 254 255/* 256 * Compose a node corresponding to an alias. 257 */ 258 259static int 260yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *first_event) 261{ 262 yaml_char_t *anchor = first_event->data.alias.anchor; 263 yaml_alias_data_t *alias_data; 264 265 for (alias_data = parser->aliases.start; 266 alias_data != parser->aliases.top; alias_data ++) { 267 if (strcmp((char *)alias_data->anchor, (char *)anchor) == 0) { 268 yaml_free(anchor); 269 return alias_data->index; 270 } 271 } 272 273 yaml_free(anchor); 274 return yaml_parser_set_composer_error(parser, "found undefined alias", 275 first_event->start_mark); 276} 277 278/* 279 * Compose a scalar node. 280 */ 281 282static int 283yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *first_event) 284{ 285 yaml_node_t node; 286 int index; 287 yaml_char_t *tag = first_event->data.scalar.tag; 288 289 if (!tag || strcmp((char *)tag, "!") == 0) { 290 yaml_free(tag); 291 tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_SCALAR_TAG); 292 if (!tag) goto error; 293 } 294 295 SCALAR_NODE_INIT(node, tag, first_event->data.scalar.value, 296 first_event->data.scalar.length, first_event->data.scalar.style, 297 first_event->start_mark, first_event->end_mark); 298 299 if (!PUSH(parser, parser->document->nodes, node)) goto error; 300 301 index = parser->document->nodes.top - parser->document->nodes.start; 302 303 if (!yaml_parser_register_anchor(parser, index, 304 first_event->data.scalar.anchor)) return 0; 305 306 return index; 307 308error: 309 yaml_free(tag); 310 yaml_free(first_event->data.scalar.anchor); 311 yaml_free(first_event->data.scalar.value); 312 return 0; 313} 314 315/* 316 * Compose a sequence node. 317 */ 318 319static int 320yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *first_event) 321{ 322 yaml_event_t event; 323 yaml_node_t node; 324 struct { 325 yaml_node_item_t *start; 326 yaml_node_item_t *end; 327 yaml_node_item_t *top; 328 } items = { NULL, NULL, NULL }; 329 int index, item_index; 330 yaml_char_t *tag = first_event->data.sequence_start.tag; 331 332 if (!tag || strcmp((char *)tag, "!") == 0) { 333 yaml_free(tag); 334 tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG); 335 if (!tag) goto error; 336 } 337 338 if (!STACK_INIT(parser, items, INITIAL_STACK_SIZE)) goto error; 339 340 SEQUENCE_NODE_INIT(node, tag, items.start, items.end, 341 first_event->data.sequence_start.style, 342 first_event->start_mark, first_event->end_mark); 343 344 if (!PUSH(parser, parser->document->nodes, node)) goto error; 345 346 index = parser->document->nodes.top - parser->document->nodes.start; 347 348 if (!yaml_parser_register_anchor(parser, index, 349 first_event->data.sequence_start.anchor)) return 0; 350 351 if (!yaml_parser_parse(parser, &event)) return 0; 352 353 while (event.type != YAML_SEQUENCE_END_EVENT) { 354 item_index = yaml_parser_load_node(parser, &event); 355 if (!item_index) return 0; 356 if (!PUSH(parser, 357 parser->document->nodes.start[index-1].data.sequence.items, 358 item_index)) return 0; 359 if (!yaml_parser_parse(parser, &event)) return 0; 360 } 361 362 parser->document->nodes.start[index-1].end_mark = event.end_mark; 363 364 return index; 365 366error: 367 yaml_free(tag); 368 yaml_free(first_event->data.sequence_start.anchor); 369 return 0; 370} 371 372/* 373 * Compose a mapping node. 374 */ 375 376static int 377yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *first_event) 378{ 379 yaml_event_t event; 380 yaml_node_t node; 381 struct { 382 yaml_node_pair_t *start; 383 yaml_node_pair_t *end; 384 yaml_node_pair_t *top; 385 } pairs = { NULL, NULL, NULL }; 386 int index; 387 yaml_node_pair_t pair; 388 yaml_char_t *tag = first_event->data.mapping_start.tag; 389 390 if (!tag || strcmp((char *)tag, "!") == 0) { 391 yaml_free(tag); 392 tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_MAPPING_TAG); 393 if (!tag) goto error; 394 } 395 396 if (!STACK_INIT(parser, pairs, INITIAL_STACK_SIZE)) goto error; 397 398 MAPPING_NODE_INIT(node, tag, pairs.start, pairs.end, 399 first_event->data.mapping_start.style, 400 first_event->start_mark, first_event->end_mark); 401 402 if (!PUSH(parser, parser->document->nodes, node)) goto error; 403 404 index = parser->document->nodes.top - parser->document->nodes.start; 405 406 if (!yaml_parser_register_anchor(parser, index, 407 first_event->data.mapping_start.anchor)) return 0; 408 409 if (!yaml_parser_parse(parser, &event)) return 0; 410 411 while (event.type != YAML_MAPPING_END_EVENT) { 412 pair.key = yaml_parser_load_node(parser, &event); 413 if (!pair.key) return 0; 414 if (!yaml_parser_parse(parser, &event)) return 0; 415 pair.value = yaml_parser_load_node(parser, &event); 416 if (!pair.value) return 0; 417 if (!PUSH(parser, 418 parser->document->nodes.start[index-1].data.mapping.pairs, 419 pair)) return 0; 420 if (!yaml_parser_parse(parser, &event)) return 0; 421 } 422 423 parser->document->nodes.start[index-1].end_mark = event.end_mark; 424 425 return index; 426 427error: 428 yaml_free(tag); 429 yaml_free(first_event->data.mapping_start.anchor); 430 return 0; 431} 432 433