Mercurial > embed
comparison yaml/src/parser.c @ 1:4d89bd8a3f7f
yaml: import 0.1.5
author | David Demelier <markand@malikania.fr> |
---|---|
date | Wed, 24 Feb 2016 20:50:29 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
0:0047655db1aa | 1:4d89bd8a3f7f |
---|---|
1 | |
2 /* | |
3 * The parser implements the following grammar: | |
4 * | |
5 * stream ::= STREAM-START implicit_document? explicit_document* STREAM-END | |
6 * implicit_document ::= block_node DOCUMENT-END* | |
7 * explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* | |
8 * block_node_or_indentless_sequence ::= | |
9 * ALIAS | |
10 * | properties (block_content | indentless_block_sequence)? | |
11 * | block_content | |
12 * | indentless_block_sequence | |
13 * block_node ::= ALIAS | |
14 * | properties block_content? | |
15 * | block_content | |
16 * flow_node ::= ALIAS | |
17 * | properties flow_content? | |
18 * | flow_content | |
19 * properties ::= TAG ANCHOR? | ANCHOR TAG? | |
20 * block_content ::= block_collection | flow_collection | SCALAR | |
21 * flow_content ::= flow_collection | SCALAR | |
22 * block_collection ::= block_sequence | block_mapping | |
23 * flow_collection ::= flow_sequence | flow_mapping | |
24 * block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END | |
25 * indentless_sequence ::= (BLOCK-ENTRY block_node?)+ | |
26 * block_mapping ::= BLOCK-MAPPING_START | |
27 * ((KEY block_node_or_indentless_sequence?)? | |
28 * (VALUE block_node_or_indentless_sequence?)?)* | |
29 * BLOCK-END | |
30 * flow_sequence ::= FLOW-SEQUENCE-START | |
31 * (flow_sequence_entry FLOW-ENTRY)* | |
32 * flow_sequence_entry? | |
33 * FLOW-SEQUENCE-END | |
34 * flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? | |
35 * flow_mapping ::= FLOW-MAPPING-START | |
36 * (flow_mapping_entry FLOW-ENTRY)* | |
37 * flow_mapping_entry? | |
38 * FLOW-MAPPING-END | |
39 * flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? | |
40 */ | |
41 | |
42 #include "yaml_private.h" | |
43 | |
44 /* | |
45 * Peek the next token in the token queue. | |
46 */ | |
47 | |
48 #define PEEK_TOKEN(parser) \ | |
49 ((parser->token_available || yaml_parser_fetch_more_tokens(parser)) ? \ | |
50 parser->tokens.head : NULL) | |
51 | |
52 /* | |
53 * Remove the next token from the queue (must be called after PEEK_TOKEN). | |
54 */ | |
55 | |
56 #define SKIP_TOKEN(parser) \ | |
57 (parser->token_available = 0, \ | |
58 parser->tokens_parsed ++, \ | |
59 parser->stream_end_produced = \ | |
60 (parser->tokens.head->type == YAML_STREAM_END_TOKEN), \ | |
61 parser->tokens.head ++) | |
62 | |
63 /* | |
64 * Public API declarations. | |
65 */ | |
66 | |
67 YAML_DECLARE(int) | |
68 yaml_parser_parse(yaml_parser_t *parser, yaml_event_t *event); | |
69 | |
70 /* | |
71 * Error handling. | |
72 */ | |
73 | |
74 static int | |
75 yaml_parser_set_parser_error(yaml_parser_t *parser, | |
76 const char *problem, yaml_mark_t problem_mark); | |
77 | |
78 static int | |
79 yaml_parser_set_parser_error_context(yaml_parser_t *parser, | |
80 const char *context, yaml_mark_t context_mark, | |
81 const char *problem, yaml_mark_t problem_mark); | |
82 | |
83 /* | |
84 * State functions. | |
85 */ | |
86 | |
87 static int | |
88 yaml_parser_state_machine(yaml_parser_t *parser, yaml_event_t *event); | |
89 | |
90 static int | |
91 yaml_parser_parse_stream_start(yaml_parser_t *parser, yaml_event_t *event); | |
92 | |
93 static int | |
94 yaml_parser_parse_document_start(yaml_parser_t *parser, yaml_event_t *event, | |
95 int implicit); | |
96 | |
97 static int | |
98 yaml_parser_parse_document_content(yaml_parser_t *parser, yaml_event_t *event); | |
99 | |
100 static int | |
101 yaml_parser_parse_document_end(yaml_parser_t *parser, yaml_event_t *event); | |
102 | |
103 static int | |
104 yaml_parser_parse_node(yaml_parser_t *parser, yaml_event_t *event, | |
105 int block, int indentless_sequence); | |
106 | |
107 static int | |
108 yaml_parser_parse_block_sequence_entry(yaml_parser_t *parser, | |
109 yaml_event_t *event, int first); | |
110 | |
111 static int | |
112 yaml_parser_parse_indentless_sequence_entry(yaml_parser_t *parser, | |
113 yaml_event_t *event); | |
114 | |
115 static int | |
116 yaml_parser_parse_block_mapping_key(yaml_parser_t *parser, | |
117 yaml_event_t *event, int first); | |
118 | |
119 static int | |
120 yaml_parser_parse_block_mapping_value(yaml_parser_t *parser, | |
121 yaml_event_t *event); | |
122 | |
123 static int | |
124 yaml_parser_parse_flow_sequence_entry(yaml_parser_t *parser, | |
125 yaml_event_t *event, int first); | |
126 | |
127 static int | |
128 yaml_parser_parse_flow_sequence_entry_mapping_key(yaml_parser_t *parser, | |
129 yaml_event_t *event); | |
130 | |
131 static int | |
132 yaml_parser_parse_flow_sequence_entry_mapping_value(yaml_parser_t *parser, | |
133 yaml_event_t *event); | |
134 | |
135 static int | |
136 yaml_parser_parse_flow_sequence_entry_mapping_end(yaml_parser_t *parser, | |
137 yaml_event_t *event); | |
138 | |
139 static int | |
140 yaml_parser_parse_flow_mapping_key(yaml_parser_t *parser, | |
141 yaml_event_t *event, int first); | |
142 | |
143 static int | |
144 yaml_parser_parse_flow_mapping_value(yaml_parser_t *parser, | |
145 yaml_event_t *event, int empty); | |
146 | |
147 /* | |
148 * Utility functions. | |
149 */ | |
150 | |
151 static int | |
152 yaml_parser_process_empty_scalar(yaml_parser_t *parser, | |
153 yaml_event_t *event, yaml_mark_t mark); | |
154 | |
155 static int | |
156 yaml_parser_process_directives(yaml_parser_t *parser, | |
157 yaml_version_directive_t **version_directive_ref, | |
158 yaml_tag_directive_t **tag_directives_start_ref, | |
159 yaml_tag_directive_t **tag_directives_end_ref); | |
160 | |
161 static int | |
162 yaml_parser_append_tag_directive(yaml_parser_t *parser, | |
163 yaml_tag_directive_t value, int allow_duplicates, yaml_mark_t mark); | |
164 | |
165 /* | |
166 * Get the next event. | |
167 */ | |
168 | |
169 YAML_DECLARE(int) | |
170 yaml_parser_parse(yaml_parser_t *parser, yaml_event_t *event) | |
171 { | |
172 assert(parser); /* Non-NULL parser object is expected. */ | |
173 assert(event); /* Non-NULL event object is expected. */ | |
174 | |
175 /* Erase the event object. */ | |
176 | |
177 memset(event, 0, sizeof(yaml_event_t)); | |
178 | |
179 /* No events after the end of the stream or error. */ | |
180 | |
181 if (parser->stream_end_produced || parser->error || | |
182 parser->state == YAML_PARSE_END_STATE) { | |
183 return 1; | |
184 } | |
185 | |
186 /* Generate the next event. */ | |
187 | |
188 return yaml_parser_state_machine(parser, event); | |
189 } | |
190 | |
191 /* | |
192 * Set parser error. | |
193 */ | |
194 | |
195 static int | |
196 yaml_parser_set_parser_error(yaml_parser_t *parser, | |
197 const char *problem, yaml_mark_t problem_mark) | |
198 { | |
199 parser->error = YAML_PARSER_ERROR; | |
200 parser->problem = problem; | |
201 parser->problem_mark = problem_mark; | |
202 | |
203 return 0; | |
204 } | |
205 | |
206 static int | |
207 yaml_parser_set_parser_error_context(yaml_parser_t *parser, | |
208 const char *context, yaml_mark_t context_mark, | |
209 const char *problem, yaml_mark_t problem_mark) | |
210 { | |
211 parser->error = YAML_PARSER_ERROR; | |
212 parser->context = context; | |
213 parser->context_mark = context_mark; | |
214 parser->problem = problem; | |
215 parser->problem_mark = problem_mark; | |
216 | |
217 return 0; | |
218 } | |
219 | |
220 | |
221 /* | |
222 * State dispatcher. | |
223 */ | |
224 | |
225 static int | |
226 yaml_parser_state_machine(yaml_parser_t *parser, yaml_event_t *event) | |
227 { | |
228 switch (parser->state) | |
229 { | |
230 case YAML_PARSE_STREAM_START_STATE: | |
231 return yaml_parser_parse_stream_start(parser, event); | |
232 | |
233 case YAML_PARSE_IMPLICIT_DOCUMENT_START_STATE: | |
234 return yaml_parser_parse_document_start(parser, event, 1); | |
235 | |
236 case YAML_PARSE_DOCUMENT_START_STATE: | |
237 return yaml_parser_parse_document_start(parser, event, 0); | |
238 | |
239 case YAML_PARSE_DOCUMENT_CONTENT_STATE: | |
240 return yaml_parser_parse_document_content(parser, event); | |
241 | |
242 case YAML_PARSE_DOCUMENT_END_STATE: | |
243 return yaml_parser_parse_document_end(parser, event); | |
244 | |
245 case YAML_PARSE_BLOCK_NODE_STATE: | |
246 return yaml_parser_parse_node(parser, event, 1, 0); | |
247 | |
248 case YAML_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE: | |
249 return yaml_parser_parse_node(parser, event, 1, 1); | |
250 | |
251 case YAML_PARSE_FLOW_NODE_STATE: | |
252 return yaml_parser_parse_node(parser, event, 0, 0); | |
253 | |
254 case YAML_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE: | |
255 return yaml_parser_parse_block_sequence_entry(parser, event, 1); | |
256 | |
257 case YAML_PARSE_BLOCK_SEQUENCE_ENTRY_STATE: | |
258 return yaml_parser_parse_block_sequence_entry(parser, event, 0); | |
259 | |
260 case YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE: | |
261 return yaml_parser_parse_indentless_sequence_entry(parser, event); | |
262 | |
263 case YAML_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE: | |
264 return yaml_parser_parse_block_mapping_key(parser, event, 1); | |
265 | |
266 case YAML_PARSE_BLOCK_MAPPING_KEY_STATE: | |
267 return yaml_parser_parse_block_mapping_key(parser, event, 0); | |
268 | |
269 case YAML_PARSE_BLOCK_MAPPING_VALUE_STATE: | |
270 return yaml_parser_parse_block_mapping_value(parser, event); | |
271 | |
272 case YAML_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE: | |
273 return yaml_parser_parse_flow_sequence_entry(parser, event, 1); | |
274 | |
275 case YAML_PARSE_FLOW_SEQUENCE_ENTRY_STATE: | |
276 return yaml_parser_parse_flow_sequence_entry(parser, event, 0); | |
277 | |
278 case YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE: | |
279 return yaml_parser_parse_flow_sequence_entry_mapping_key(parser, event); | |
280 | |
281 case YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE: | |
282 return yaml_parser_parse_flow_sequence_entry_mapping_value(parser, event); | |
283 | |
284 case YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE: | |
285 return yaml_parser_parse_flow_sequence_entry_mapping_end(parser, event); | |
286 | |
287 case YAML_PARSE_FLOW_MAPPING_FIRST_KEY_STATE: | |
288 return yaml_parser_parse_flow_mapping_key(parser, event, 1); | |
289 | |
290 case YAML_PARSE_FLOW_MAPPING_KEY_STATE: | |
291 return yaml_parser_parse_flow_mapping_key(parser, event, 0); | |
292 | |
293 case YAML_PARSE_FLOW_MAPPING_VALUE_STATE: | |
294 return yaml_parser_parse_flow_mapping_value(parser, event, 0); | |
295 | |
296 case YAML_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE: | |
297 return yaml_parser_parse_flow_mapping_value(parser, event, 1); | |
298 | |
299 default: | |
300 assert(1); /* Invalid state. */ | |
301 } | |
302 | |
303 return 0; | |
304 } | |
305 | |
306 /* | |
307 * Parse the production: | |
308 * stream ::= STREAM-START implicit_document? explicit_document* STREAM-END | |
309 * ************ | |
310 */ | |
311 | |
312 static int | |
313 yaml_parser_parse_stream_start(yaml_parser_t *parser, yaml_event_t *event) | |
314 { | |
315 yaml_token_t *token; | |
316 | |
317 token = PEEK_TOKEN(parser); | |
318 if (!token) return 0; | |
319 | |
320 if (token->type != YAML_STREAM_START_TOKEN) { | |
321 return yaml_parser_set_parser_error(parser, | |
322 "did not find expected <stream-start>", token->start_mark); | |
323 } | |
324 | |
325 parser->state = YAML_PARSE_IMPLICIT_DOCUMENT_START_STATE; | |
326 STREAM_START_EVENT_INIT(*event, token->data.stream_start.encoding, | |
327 token->start_mark, token->start_mark); | |
328 SKIP_TOKEN(parser); | |
329 | |
330 return 1; | |
331 } | |
332 | |
333 /* | |
334 * Parse the productions: | |
335 * implicit_document ::= block_node DOCUMENT-END* | |
336 * * | |
337 * explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* | |
338 * ************************* | |
339 */ | |
340 | |
341 static int | |
342 yaml_parser_parse_document_start(yaml_parser_t *parser, yaml_event_t *event, | |
343 int implicit) | |
344 { | |
345 yaml_token_t *token; | |
346 yaml_version_directive_t *version_directive = NULL; | |
347 struct { | |
348 yaml_tag_directive_t *start; | |
349 yaml_tag_directive_t *end; | |
350 } tag_directives = { NULL, NULL }; | |
351 | |
352 token = PEEK_TOKEN(parser); | |
353 if (!token) return 0; | |
354 | |
355 /* Parse extra document end indicators. */ | |
356 | |
357 if (!implicit) | |
358 { | |
359 while (token->type == YAML_DOCUMENT_END_TOKEN) { | |
360 SKIP_TOKEN(parser); | |
361 token = PEEK_TOKEN(parser); | |
362 if (!token) return 0; | |
363 } | |
364 } | |
365 | |
366 /* Parse an implicit document. */ | |
367 | |
368 if (implicit && token->type != YAML_VERSION_DIRECTIVE_TOKEN && | |
369 token->type != YAML_TAG_DIRECTIVE_TOKEN && | |
370 token->type != YAML_DOCUMENT_START_TOKEN && | |
371 token->type != YAML_STREAM_END_TOKEN) | |
372 { | |
373 if (!yaml_parser_process_directives(parser, NULL, NULL, NULL)) | |
374 return 0; | |
375 if (!PUSH(parser, parser->states, YAML_PARSE_DOCUMENT_END_STATE)) | |
376 return 0; | |
377 parser->state = YAML_PARSE_BLOCK_NODE_STATE; | |
378 DOCUMENT_START_EVENT_INIT(*event, NULL, NULL, NULL, 1, | |
379 token->start_mark, token->start_mark); | |
380 return 1; | |
381 } | |
382 | |
383 /* Parse an explicit document. */ | |
384 | |
385 else if (token->type != YAML_STREAM_END_TOKEN) | |
386 { | |
387 yaml_mark_t start_mark, end_mark; | |
388 start_mark = token->start_mark; | |
389 if (!yaml_parser_process_directives(parser, &version_directive, | |
390 &tag_directives.start, &tag_directives.end)) | |
391 return 0; | |
392 token = PEEK_TOKEN(parser); | |
393 if (!token) goto error; | |
394 if (token->type != YAML_DOCUMENT_START_TOKEN) { | |
395 yaml_parser_set_parser_error(parser, | |
396 "did not find expected <document start>", token->start_mark); | |
397 goto error; | |
398 } | |
399 if (!PUSH(parser, parser->states, YAML_PARSE_DOCUMENT_END_STATE)) | |
400 goto error; | |
401 parser->state = YAML_PARSE_DOCUMENT_CONTENT_STATE; | |
402 end_mark = token->end_mark; | |
403 DOCUMENT_START_EVENT_INIT(*event, version_directive, | |
404 tag_directives.start, tag_directives.end, 0, | |
405 start_mark, end_mark); | |
406 SKIP_TOKEN(parser); | |
407 version_directive = NULL; | |
408 tag_directives.start = tag_directives.end = NULL; | |
409 return 1; | |
410 } | |
411 | |
412 /* Parse the stream end. */ | |
413 | |
414 else | |
415 { | |
416 parser->state = YAML_PARSE_END_STATE; | |
417 STREAM_END_EVENT_INIT(*event, token->start_mark, token->end_mark); | |
418 SKIP_TOKEN(parser); | |
419 return 1; | |
420 } | |
421 | |
422 error: | |
423 yaml_free(version_directive); | |
424 while (tag_directives.start != tag_directives.end) { | |
425 yaml_free(tag_directives.end[-1].handle); | |
426 yaml_free(tag_directives.end[-1].prefix); | |
427 tag_directives.end --; | |
428 } | |
429 yaml_free(tag_directives.start); | |
430 return 0; | |
431 } | |
432 | |
433 /* | |
434 * Parse the productions: | |
435 * explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* | |
436 * *********** | |
437 */ | |
438 | |
439 static int | |
440 yaml_parser_parse_document_content(yaml_parser_t *parser, yaml_event_t *event) | |
441 { | |
442 yaml_token_t *token; | |
443 | |
444 token = PEEK_TOKEN(parser); | |
445 if (!token) return 0; | |
446 | |
447 if (token->type == YAML_VERSION_DIRECTIVE_TOKEN || | |
448 token->type == YAML_TAG_DIRECTIVE_TOKEN || | |
449 token->type == YAML_DOCUMENT_START_TOKEN || | |
450 token->type == YAML_DOCUMENT_END_TOKEN || | |
451 token->type == YAML_STREAM_END_TOKEN) { | |
452 parser->state = POP(parser, parser->states); | |
453 return yaml_parser_process_empty_scalar(parser, event, | |
454 token->start_mark); | |
455 } | |
456 else { | |
457 return yaml_parser_parse_node(parser, event, 1, 0); | |
458 } | |
459 } | |
460 | |
461 /* | |
462 * Parse the productions: | |
463 * implicit_document ::= block_node DOCUMENT-END* | |
464 * ************* | |
465 * explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* | |
466 * ************* | |
467 */ | |
468 | |
469 static int | |
470 yaml_parser_parse_document_end(yaml_parser_t *parser, yaml_event_t *event) | |
471 { | |
472 yaml_token_t *token; | |
473 yaml_mark_t start_mark, end_mark; | |
474 int implicit = 1; | |
475 | |
476 token = PEEK_TOKEN(parser); | |
477 if (!token) return 0; | |
478 | |
479 start_mark = end_mark = token->start_mark; | |
480 | |
481 if (token->type == YAML_DOCUMENT_END_TOKEN) { | |
482 end_mark = token->end_mark; | |
483 SKIP_TOKEN(parser); | |
484 implicit = 0; | |
485 } | |
486 | |
487 while (!STACK_EMPTY(parser, parser->tag_directives)) { | |
488 yaml_tag_directive_t tag_directive = POP(parser, parser->tag_directives); | |
489 yaml_free(tag_directive.handle); | |
490 yaml_free(tag_directive.prefix); | |
491 } | |
492 | |
493 parser->state = YAML_PARSE_DOCUMENT_START_STATE; | |
494 DOCUMENT_END_EVENT_INIT(*event, implicit, start_mark, end_mark); | |
495 | |
496 return 1; | |
497 } | |
498 | |
499 /* | |
500 * Parse the productions: | |
501 * block_node_or_indentless_sequence ::= | |
502 * ALIAS | |
503 * ***** | |
504 * | properties (block_content | indentless_block_sequence)? | |
505 * ********** * | |
506 * | block_content | indentless_block_sequence | |
507 * * | |
508 * block_node ::= ALIAS | |
509 * ***** | |
510 * | properties block_content? | |
511 * ********** * | |
512 * | block_content | |
513 * * | |
514 * flow_node ::= ALIAS | |
515 * ***** | |
516 * | properties flow_content? | |
517 * ********** * | |
518 * | flow_content | |
519 * * | |
520 * properties ::= TAG ANCHOR? | ANCHOR TAG? | |
521 * ************************* | |
522 * block_content ::= block_collection | flow_collection | SCALAR | |
523 * ****** | |
524 * flow_content ::= flow_collection | SCALAR | |
525 * ****** | |
526 */ | |
527 | |
528 static int | |
529 yaml_parser_parse_node(yaml_parser_t *parser, yaml_event_t *event, | |
530 int block, int indentless_sequence) | |
531 { | |
532 yaml_token_t *token; | |
533 yaml_char_t *anchor = NULL; | |
534 yaml_char_t *tag_handle = NULL; | |
535 yaml_char_t *tag_suffix = NULL; | |
536 yaml_char_t *tag = NULL; | |
537 yaml_mark_t start_mark, end_mark, tag_mark; | |
538 int implicit; | |
539 | |
540 token = PEEK_TOKEN(parser); | |
541 if (!token) return 0; | |
542 | |
543 if (token->type == YAML_ALIAS_TOKEN) | |
544 { | |
545 parser->state = POP(parser, parser->states); | |
546 ALIAS_EVENT_INIT(*event, token->data.alias.value, | |
547 token->start_mark, token->end_mark); | |
548 SKIP_TOKEN(parser); | |
549 return 1; | |
550 } | |
551 | |
552 else | |
553 { | |
554 start_mark = end_mark = token->start_mark; | |
555 | |
556 if (token->type == YAML_ANCHOR_TOKEN) | |
557 { | |
558 anchor = token->data.anchor.value; | |
559 start_mark = token->start_mark; | |
560 end_mark = token->end_mark; | |
561 SKIP_TOKEN(parser); | |
562 token = PEEK_TOKEN(parser); | |
563 if (!token) goto error; | |
564 if (token->type == YAML_TAG_TOKEN) | |
565 { | |
566 tag_handle = token->data.tag.handle; | |
567 tag_suffix = token->data.tag.suffix; | |
568 tag_mark = token->start_mark; | |
569 end_mark = token->end_mark; | |
570 SKIP_TOKEN(parser); | |
571 token = PEEK_TOKEN(parser); | |
572 if (!token) goto error; | |
573 } | |
574 } | |
575 else if (token->type == YAML_TAG_TOKEN) | |
576 { | |
577 tag_handle = token->data.tag.handle; | |
578 tag_suffix = token->data.tag.suffix; | |
579 start_mark = tag_mark = token->start_mark; | |
580 end_mark = token->end_mark; | |
581 SKIP_TOKEN(parser); | |
582 token = PEEK_TOKEN(parser); | |
583 if (!token) goto error; | |
584 if (token->type == YAML_ANCHOR_TOKEN) | |
585 { | |
586 anchor = token->data.anchor.value; | |
587 end_mark = token->end_mark; | |
588 SKIP_TOKEN(parser); | |
589 token = PEEK_TOKEN(parser); | |
590 if (!token) goto error; | |
591 } | |
592 } | |
593 | |
594 if (tag_handle) { | |
595 if (!*tag_handle) { | |
596 tag = tag_suffix; | |
597 yaml_free(tag_handle); | |
598 tag_handle = tag_suffix = NULL; | |
599 } | |
600 else { | |
601 yaml_tag_directive_t *tag_directive; | |
602 for (tag_directive = parser->tag_directives.start; | |
603 tag_directive != parser->tag_directives.top; | |
604 tag_directive ++) { | |
605 if (strcmp((char *)tag_directive->handle, (char *)tag_handle) == 0) { | |
606 size_t prefix_len = strlen((char *)tag_directive->prefix); | |
607 size_t suffix_len = strlen((char *)tag_suffix); | |
608 tag = yaml_malloc(prefix_len+suffix_len+1); | |
609 if (!tag) { | |
610 parser->error = YAML_MEMORY_ERROR; | |
611 goto error; | |
612 } | |
613 memcpy(tag, tag_directive->prefix, prefix_len); | |
614 memcpy(tag+prefix_len, tag_suffix, suffix_len); | |
615 tag[prefix_len+suffix_len] = '\0'; | |
616 yaml_free(tag_handle); | |
617 yaml_free(tag_suffix); | |
618 tag_handle = tag_suffix = NULL; | |
619 break; | |
620 } | |
621 } | |
622 if (!tag) { | |
623 yaml_parser_set_parser_error_context(parser, | |
624 "while parsing a node", start_mark, | |
625 "found undefined tag handle", tag_mark); | |
626 goto error; | |
627 } | |
628 } | |
629 } | |
630 | |
631 implicit = (!tag || !*tag); | |
632 if (indentless_sequence && token->type == YAML_BLOCK_ENTRY_TOKEN) { | |
633 end_mark = token->end_mark; | |
634 parser->state = YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE; | |
635 SEQUENCE_START_EVENT_INIT(*event, anchor, tag, implicit, | |
636 YAML_BLOCK_SEQUENCE_STYLE, start_mark, end_mark); | |
637 return 1; | |
638 } | |
639 else { | |
640 if (token->type == YAML_SCALAR_TOKEN) { | |
641 int plain_implicit = 0; | |
642 int quoted_implicit = 0; | |
643 end_mark = token->end_mark; | |
644 if ((token->data.scalar.style == YAML_PLAIN_SCALAR_STYLE && !tag) | |
645 || (tag && strcmp((char *)tag, "!") == 0)) { | |
646 plain_implicit = 1; | |
647 } | |
648 else if (!tag) { | |
649 quoted_implicit = 1; | |
650 } | |
651 parser->state = POP(parser, parser->states); | |
652 SCALAR_EVENT_INIT(*event, anchor, tag, | |
653 token->data.scalar.value, token->data.scalar.length, | |
654 plain_implicit, quoted_implicit, | |
655 token->data.scalar.style, start_mark, end_mark); | |
656 SKIP_TOKEN(parser); | |
657 return 1; | |
658 } | |
659 else if (token->type == YAML_FLOW_SEQUENCE_START_TOKEN) { | |
660 end_mark = token->end_mark; | |
661 parser->state = YAML_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE; | |
662 SEQUENCE_START_EVENT_INIT(*event, anchor, tag, implicit, | |
663 YAML_FLOW_SEQUENCE_STYLE, start_mark, end_mark); | |
664 return 1; | |
665 } | |
666 else if (token->type == YAML_FLOW_MAPPING_START_TOKEN) { | |
667 end_mark = token->end_mark; | |
668 parser->state = YAML_PARSE_FLOW_MAPPING_FIRST_KEY_STATE; | |
669 MAPPING_START_EVENT_INIT(*event, anchor, tag, implicit, | |
670 YAML_FLOW_MAPPING_STYLE, start_mark, end_mark); | |
671 return 1; | |
672 } | |
673 else if (block && token->type == YAML_BLOCK_SEQUENCE_START_TOKEN) { | |
674 end_mark = token->end_mark; | |
675 parser->state = YAML_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE; | |
676 SEQUENCE_START_EVENT_INIT(*event, anchor, tag, implicit, | |
677 YAML_BLOCK_SEQUENCE_STYLE, start_mark, end_mark); | |
678 return 1; | |
679 } | |
680 else if (block && token->type == YAML_BLOCK_MAPPING_START_TOKEN) { | |
681 end_mark = token->end_mark; | |
682 parser->state = YAML_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE; | |
683 MAPPING_START_EVENT_INIT(*event, anchor, tag, implicit, | |
684 YAML_BLOCK_MAPPING_STYLE, start_mark, end_mark); | |
685 return 1; | |
686 } | |
687 else if (anchor || tag) { | |
688 yaml_char_t *value = yaml_malloc(1); | |
689 if (!value) { | |
690 parser->error = YAML_MEMORY_ERROR; | |
691 goto error; | |
692 } | |
693 value[0] = '\0'; | |
694 parser->state = POP(parser, parser->states); | |
695 SCALAR_EVENT_INIT(*event, anchor, tag, value, 0, | |
696 implicit, 0, YAML_PLAIN_SCALAR_STYLE, | |
697 start_mark, end_mark); | |
698 return 1; | |
699 } | |
700 else { | |
701 yaml_parser_set_parser_error_context(parser, | |
702 (block ? "while parsing a block node" | |
703 : "while parsing a flow node"), start_mark, | |
704 "did not find expected node content", token->start_mark); | |
705 goto error; | |
706 } | |
707 } | |
708 } | |
709 | |
710 error: | |
711 yaml_free(anchor); | |
712 yaml_free(tag_handle); | |
713 yaml_free(tag_suffix); | |
714 yaml_free(tag); | |
715 | |
716 return 0; | |
717 } | |
718 | |
719 /* | |
720 * Parse the productions: | |
721 * block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END | |
722 * ******************** *********** * ********* | |
723 */ | |
724 | |
725 static int | |
726 yaml_parser_parse_block_sequence_entry(yaml_parser_t *parser, | |
727 yaml_event_t *event, int first) | |
728 { | |
729 yaml_token_t *token; | |
730 | |
731 if (first) { | |
732 token = PEEK_TOKEN(parser); | |
733 if (!PUSH(parser, parser->marks, token->start_mark)) | |
734 return 0; | |
735 SKIP_TOKEN(parser); | |
736 } | |
737 | |
738 token = PEEK_TOKEN(parser); | |
739 if (!token) return 0; | |
740 | |
741 if (token->type == YAML_BLOCK_ENTRY_TOKEN) | |
742 { | |
743 yaml_mark_t mark = token->end_mark; | |
744 SKIP_TOKEN(parser); | |
745 token = PEEK_TOKEN(parser); | |
746 if (!token) return 0; | |
747 if (token->type != YAML_BLOCK_ENTRY_TOKEN && | |
748 token->type != YAML_BLOCK_END_TOKEN) { | |
749 if (!PUSH(parser, parser->states, | |
750 YAML_PARSE_BLOCK_SEQUENCE_ENTRY_STATE)) | |
751 return 0; | |
752 return yaml_parser_parse_node(parser, event, 1, 0); | |
753 } | |
754 else { | |
755 parser->state = YAML_PARSE_BLOCK_SEQUENCE_ENTRY_STATE; | |
756 return yaml_parser_process_empty_scalar(parser, event, mark); | |
757 } | |
758 } | |
759 | |
760 else if (token->type == YAML_BLOCK_END_TOKEN) | |
761 { | |
762 yaml_mark_t dummy_mark; /* Used to eliminate a compiler warning. */ | |
763 parser->state = POP(parser, parser->states); | |
764 dummy_mark = POP(parser, parser->marks); | |
765 SEQUENCE_END_EVENT_INIT(*event, token->start_mark, token->end_mark); | |
766 SKIP_TOKEN(parser); | |
767 return 1; | |
768 } | |
769 | |
770 else | |
771 { | |
772 return yaml_parser_set_parser_error_context(parser, | |
773 "while parsing a block collection", POP(parser, parser->marks), | |
774 "did not find expected '-' indicator", token->start_mark); | |
775 } | |
776 } | |
777 | |
778 /* | |
779 * Parse the productions: | |
780 * indentless_sequence ::= (BLOCK-ENTRY block_node?)+ | |
781 * *********** * | |
782 */ | |
783 | |
784 static int | |
785 yaml_parser_parse_indentless_sequence_entry(yaml_parser_t *parser, | |
786 yaml_event_t *event) | |
787 { | |
788 yaml_token_t *token; | |
789 | |
790 token = PEEK_TOKEN(parser); | |
791 if (!token) return 0; | |
792 | |
793 if (token->type == YAML_BLOCK_ENTRY_TOKEN) | |
794 { | |
795 yaml_mark_t mark = token->end_mark; | |
796 SKIP_TOKEN(parser); | |
797 token = PEEK_TOKEN(parser); | |
798 if (!token) return 0; | |
799 if (token->type != YAML_BLOCK_ENTRY_TOKEN && | |
800 token->type != YAML_KEY_TOKEN && | |
801 token->type != YAML_VALUE_TOKEN && | |
802 token->type != YAML_BLOCK_END_TOKEN) { | |
803 if (!PUSH(parser, parser->states, | |
804 YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE)) | |
805 return 0; | |
806 return yaml_parser_parse_node(parser, event, 1, 0); | |
807 } | |
808 else { | |
809 parser->state = YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE; | |
810 return yaml_parser_process_empty_scalar(parser, event, mark); | |
811 } | |
812 } | |
813 | |
814 else | |
815 { | |
816 parser->state = POP(parser, parser->states); | |
817 SEQUENCE_END_EVENT_INIT(*event, token->start_mark, token->start_mark); | |
818 return 1; | |
819 } | |
820 } | |
821 | |
822 /* | |
823 * Parse the productions: | |
824 * block_mapping ::= BLOCK-MAPPING_START | |
825 * ******************* | |
826 * ((KEY block_node_or_indentless_sequence?)? | |
827 * *** * | |
828 * (VALUE block_node_or_indentless_sequence?)?)* | |
829 * | |
830 * BLOCK-END | |
831 * ********* | |
832 */ | |
833 | |
834 static int | |
835 yaml_parser_parse_block_mapping_key(yaml_parser_t *parser, | |
836 yaml_event_t *event, int first) | |
837 { | |
838 yaml_token_t *token; | |
839 | |
840 if (first) { | |
841 token = PEEK_TOKEN(parser); | |
842 if (!PUSH(parser, parser->marks, token->start_mark)) | |
843 return 0; | |
844 SKIP_TOKEN(parser); | |
845 } | |
846 | |
847 token = PEEK_TOKEN(parser); | |
848 if (!token) return 0; | |
849 | |
850 if (token->type == YAML_KEY_TOKEN) | |
851 { | |
852 yaml_mark_t mark = token->end_mark; | |
853 SKIP_TOKEN(parser); | |
854 token = PEEK_TOKEN(parser); | |
855 if (!token) return 0; | |
856 if (token->type != YAML_KEY_TOKEN && | |
857 token->type != YAML_VALUE_TOKEN && | |
858 token->type != YAML_BLOCK_END_TOKEN) { | |
859 if (!PUSH(parser, parser->states, | |
860 YAML_PARSE_BLOCK_MAPPING_VALUE_STATE)) | |
861 return 0; | |
862 return yaml_parser_parse_node(parser, event, 1, 1); | |
863 } | |
864 else { | |
865 parser->state = YAML_PARSE_BLOCK_MAPPING_VALUE_STATE; | |
866 return yaml_parser_process_empty_scalar(parser, event, mark); | |
867 } | |
868 } | |
869 | |
870 else if (token->type == YAML_BLOCK_END_TOKEN) | |
871 { | |
872 yaml_mark_t dummy_mark; /* Used to eliminate a compiler warning. */ | |
873 parser->state = POP(parser, parser->states); | |
874 dummy_mark = POP(parser, parser->marks); | |
875 MAPPING_END_EVENT_INIT(*event, token->start_mark, token->end_mark); | |
876 SKIP_TOKEN(parser); | |
877 return 1; | |
878 } | |
879 | |
880 else | |
881 { | |
882 return yaml_parser_set_parser_error_context(parser, | |
883 "while parsing a block mapping", POP(parser, parser->marks), | |
884 "did not find expected key", token->start_mark); | |
885 } | |
886 } | |
887 | |
888 /* | |
889 * Parse the productions: | |
890 * block_mapping ::= BLOCK-MAPPING_START | |
891 * | |
892 * ((KEY block_node_or_indentless_sequence?)? | |
893 * | |
894 * (VALUE block_node_or_indentless_sequence?)?)* | |
895 * ***** * | |
896 * BLOCK-END | |
897 * | |
898 */ | |
899 | |
900 static int | |
901 yaml_parser_parse_block_mapping_value(yaml_parser_t *parser, | |
902 yaml_event_t *event) | |
903 { | |
904 yaml_token_t *token; | |
905 | |
906 token = PEEK_TOKEN(parser); | |
907 if (!token) return 0; | |
908 | |
909 if (token->type == YAML_VALUE_TOKEN) | |
910 { | |
911 yaml_mark_t mark = token->end_mark; | |
912 SKIP_TOKEN(parser); | |
913 token = PEEK_TOKEN(parser); | |
914 if (!token) return 0; | |
915 if (token->type != YAML_KEY_TOKEN && | |
916 token->type != YAML_VALUE_TOKEN && | |
917 token->type != YAML_BLOCK_END_TOKEN) { | |
918 if (!PUSH(parser, parser->states, | |
919 YAML_PARSE_BLOCK_MAPPING_KEY_STATE)) | |
920 return 0; | |
921 return yaml_parser_parse_node(parser, event, 1, 1); | |
922 } | |
923 else { | |
924 parser->state = YAML_PARSE_BLOCK_MAPPING_KEY_STATE; | |
925 return yaml_parser_process_empty_scalar(parser, event, mark); | |
926 } | |
927 } | |
928 | |
929 else | |
930 { | |
931 parser->state = YAML_PARSE_BLOCK_MAPPING_KEY_STATE; | |
932 return yaml_parser_process_empty_scalar(parser, event, token->start_mark); | |
933 } | |
934 } | |
935 | |
936 /* | |
937 * Parse the productions: | |
938 * flow_sequence ::= FLOW-SEQUENCE-START | |
939 * ******************* | |
940 * (flow_sequence_entry FLOW-ENTRY)* | |
941 * * ********** | |
942 * flow_sequence_entry? | |
943 * * | |
944 * FLOW-SEQUENCE-END | |
945 * ***************** | |
946 * flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? | |
947 * * | |
948 */ | |
949 | |
950 static int | |
951 yaml_parser_parse_flow_sequence_entry(yaml_parser_t *parser, | |
952 yaml_event_t *event, int first) | |
953 { | |
954 yaml_token_t *token; | |
955 yaml_mark_t dummy_mark; /* Used to eliminate a compiler warning. */ | |
956 | |
957 if (first) { | |
958 token = PEEK_TOKEN(parser); | |
959 if (!PUSH(parser, parser->marks, token->start_mark)) | |
960 return 0; | |
961 SKIP_TOKEN(parser); | |
962 } | |
963 | |
964 token = PEEK_TOKEN(parser); | |
965 if (!token) return 0; | |
966 | |
967 if (token->type != YAML_FLOW_SEQUENCE_END_TOKEN) | |
968 { | |
969 if (!first) { | |
970 if (token->type == YAML_FLOW_ENTRY_TOKEN) { | |
971 SKIP_TOKEN(parser); | |
972 token = PEEK_TOKEN(parser); | |
973 if (!token) return 0; | |
974 } | |
975 else { | |
976 return yaml_parser_set_parser_error_context(parser, | |
977 "while parsing a flow sequence", POP(parser, parser->marks), | |
978 "did not find expected ',' or ']'", token->start_mark); | |
979 } | |
980 } | |
981 | |
982 if (token->type == YAML_KEY_TOKEN) { | |
983 parser->state = YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE; | |
984 MAPPING_START_EVENT_INIT(*event, NULL, NULL, | |
985 1, YAML_FLOW_MAPPING_STYLE, | |
986 token->start_mark, token->end_mark); | |
987 SKIP_TOKEN(parser); | |
988 return 1; | |
989 } | |
990 | |
991 else if (token->type != YAML_FLOW_SEQUENCE_END_TOKEN) { | |
992 if (!PUSH(parser, parser->states, | |
993 YAML_PARSE_FLOW_SEQUENCE_ENTRY_STATE)) | |
994 return 0; | |
995 return yaml_parser_parse_node(parser, event, 0, 0); | |
996 } | |
997 } | |
998 | |
999 parser->state = POP(parser, parser->states); | |
1000 dummy_mark = POP(parser, parser->marks); | |
1001 SEQUENCE_END_EVENT_INIT(*event, token->start_mark, token->end_mark); | |
1002 SKIP_TOKEN(parser); | |
1003 return 1; | |
1004 } | |
1005 | |
1006 /* | |
1007 * Parse the productions: | |
1008 * flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? | |
1009 * *** * | |
1010 */ | |
1011 | |
1012 static int | |
1013 yaml_parser_parse_flow_sequence_entry_mapping_key(yaml_parser_t *parser, | |
1014 yaml_event_t *event) | |
1015 { | |
1016 yaml_token_t *token; | |
1017 | |
1018 token = PEEK_TOKEN(parser); | |
1019 if (!token) return 0; | |
1020 | |
1021 if (token->type != YAML_VALUE_TOKEN && token->type != YAML_FLOW_ENTRY_TOKEN | |
1022 && token->type != YAML_FLOW_SEQUENCE_END_TOKEN) { | |
1023 if (!PUSH(parser, parser->states, | |
1024 YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE)) | |
1025 return 0; | |
1026 return yaml_parser_parse_node(parser, event, 0, 0); | |
1027 } | |
1028 else { | |
1029 yaml_mark_t mark = token->end_mark; | |
1030 SKIP_TOKEN(parser); | |
1031 parser->state = YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE; | |
1032 return yaml_parser_process_empty_scalar(parser, event, mark); | |
1033 } | |
1034 } | |
1035 | |
1036 /* | |
1037 * Parse the productions: | |
1038 * flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? | |
1039 * ***** * | |
1040 */ | |
1041 | |
1042 static int | |
1043 yaml_parser_parse_flow_sequence_entry_mapping_value(yaml_parser_t *parser, | |
1044 yaml_event_t *event) | |
1045 { | |
1046 yaml_token_t *token; | |
1047 | |
1048 token = PEEK_TOKEN(parser); | |
1049 if (!token) return 0; | |
1050 | |
1051 if (token->type == YAML_VALUE_TOKEN) { | |
1052 SKIP_TOKEN(parser); | |
1053 token = PEEK_TOKEN(parser); | |
1054 if (!token) return 0; | |
1055 if (token->type != YAML_FLOW_ENTRY_TOKEN | |
1056 && token->type != YAML_FLOW_SEQUENCE_END_TOKEN) { | |
1057 if (!PUSH(parser, parser->states, | |
1058 YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE)) | |
1059 return 0; | |
1060 return yaml_parser_parse_node(parser, event, 0, 0); | |
1061 } | |
1062 } | |
1063 parser->state = YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE; | |
1064 return yaml_parser_process_empty_scalar(parser, event, token->start_mark); | |
1065 } | |
1066 | |
1067 /* | |
1068 * Parse the productions: | |
1069 * flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? | |
1070 * * | |
1071 */ | |
1072 | |
1073 static int | |
1074 yaml_parser_parse_flow_sequence_entry_mapping_end(yaml_parser_t *parser, | |
1075 yaml_event_t *event) | |
1076 { | |
1077 yaml_token_t *token; | |
1078 | |
1079 token = PEEK_TOKEN(parser); | |
1080 if (!token) return 0; | |
1081 | |
1082 parser->state = YAML_PARSE_FLOW_SEQUENCE_ENTRY_STATE; | |
1083 | |
1084 MAPPING_END_EVENT_INIT(*event, token->start_mark, token->start_mark); | |
1085 return 1; | |
1086 } | |
1087 | |
1088 /* | |
1089 * Parse the productions: | |
1090 * flow_mapping ::= FLOW-MAPPING-START | |
1091 * ****************** | |
1092 * (flow_mapping_entry FLOW-ENTRY)* | |
1093 * * ********** | |
1094 * flow_mapping_entry? | |
1095 * ****************** | |
1096 * FLOW-MAPPING-END | |
1097 * **************** | |
1098 * flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? | |
1099 * * *** * | |
1100 */ | |
1101 | |
1102 static int | |
1103 yaml_parser_parse_flow_mapping_key(yaml_parser_t *parser, | |
1104 yaml_event_t *event, int first) | |
1105 { | |
1106 yaml_token_t *token; | |
1107 yaml_mark_t dummy_mark; /* Used to eliminate a compiler warning. */ | |
1108 | |
1109 if (first) { | |
1110 token = PEEK_TOKEN(parser); | |
1111 if (!PUSH(parser, parser->marks, token->start_mark)) | |
1112 return 0; | |
1113 SKIP_TOKEN(parser); | |
1114 } | |
1115 | |
1116 token = PEEK_TOKEN(parser); | |
1117 if (!token) return 0; | |
1118 | |
1119 if (token->type != YAML_FLOW_MAPPING_END_TOKEN) | |
1120 { | |
1121 if (!first) { | |
1122 if (token->type == YAML_FLOW_ENTRY_TOKEN) { | |
1123 SKIP_TOKEN(parser); | |
1124 token = PEEK_TOKEN(parser); | |
1125 if (!token) return 0; | |
1126 } | |
1127 else { | |
1128 return yaml_parser_set_parser_error_context(parser, | |
1129 "while parsing a flow mapping", POP(parser, parser->marks), | |
1130 "did not find expected ',' or '}'", token->start_mark); | |
1131 } | |
1132 } | |
1133 | |
1134 if (token->type == YAML_KEY_TOKEN) { | |
1135 SKIP_TOKEN(parser); | |
1136 token = PEEK_TOKEN(parser); | |
1137 if (!token) return 0; | |
1138 if (token->type != YAML_VALUE_TOKEN | |
1139 && token->type != YAML_FLOW_ENTRY_TOKEN | |
1140 && token->type != YAML_FLOW_MAPPING_END_TOKEN) { | |
1141 if (!PUSH(parser, parser->states, | |
1142 YAML_PARSE_FLOW_MAPPING_VALUE_STATE)) | |
1143 return 0; | |
1144 return yaml_parser_parse_node(parser, event, 0, 0); | |
1145 } | |
1146 else { | |
1147 parser->state = YAML_PARSE_FLOW_MAPPING_VALUE_STATE; | |
1148 return yaml_parser_process_empty_scalar(parser, event, | |
1149 token->start_mark); | |
1150 } | |
1151 } | |
1152 else if (token->type != YAML_FLOW_MAPPING_END_TOKEN) { | |
1153 if (!PUSH(parser, parser->states, | |
1154 YAML_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE)) | |
1155 return 0; | |
1156 return yaml_parser_parse_node(parser, event, 0, 0); | |
1157 } | |
1158 } | |
1159 | |
1160 parser->state = POP(parser, parser->states); | |
1161 dummy_mark = POP(parser, parser->marks); | |
1162 MAPPING_END_EVENT_INIT(*event, token->start_mark, token->end_mark); | |
1163 SKIP_TOKEN(parser); | |
1164 return 1; | |
1165 } | |
1166 | |
1167 /* | |
1168 * Parse the productions: | |
1169 * flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? | |
1170 * * ***** * | |
1171 */ | |
1172 | |
1173 static int | |
1174 yaml_parser_parse_flow_mapping_value(yaml_parser_t *parser, | |
1175 yaml_event_t *event, int empty) | |
1176 { | |
1177 yaml_token_t *token; | |
1178 | |
1179 token = PEEK_TOKEN(parser); | |
1180 if (!token) return 0; | |
1181 | |
1182 if (empty) { | |
1183 parser->state = YAML_PARSE_FLOW_MAPPING_KEY_STATE; | |
1184 return yaml_parser_process_empty_scalar(parser, event, | |
1185 token->start_mark); | |
1186 } | |
1187 | |
1188 if (token->type == YAML_VALUE_TOKEN) { | |
1189 SKIP_TOKEN(parser); | |
1190 token = PEEK_TOKEN(parser); | |
1191 if (!token) return 0; | |
1192 if (token->type != YAML_FLOW_ENTRY_TOKEN | |
1193 && token->type != YAML_FLOW_MAPPING_END_TOKEN) { | |
1194 if (!PUSH(parser, parser->states, | |
1195 YAML_PARSE_FLOW_MAPPING_KEY_STATE)) | |
1196 return 0; | |
1197 return yaml_parser_parse_node(parser, event, 0, 0); | |
1198 } | |
1199 } | |
1200 | |
1201 parser->state = YAML_PARSE_FLOW_MAPPING_KEY_STATE; | |
1202 return yaml_parser_process_empty_scalar(parser, event, token->start_mark); | |
1203 } | |
1204 | |
1205 /* | |
1206 * Generate an empty scalar event. | |
1207 */ | |
1208 | |
1209 static int | |
1210 yaml_parser_process_empty_scalar(yaml_parser_t *parser, yaml_event_t *event, | |
1211 yaml_mark_t mark) | |
1212 { | |
1213 yaml_char_t *value; | |
1214 | |
1215 value = yaml_malloc(1); | |
1216 if (!value) { | |
1217 parser->error = YAML_MEMORY_ERROR; | |
1218 return 0; | |
1219 } | |
1220 value[0] = '\0'; | |
1221 | |
1222 SCALAR_EVENT_INIT(*event, NULL, NULL, value, 0, | |
1223 1, 0, YAML_PLAIN_SCALAR_STYLE, mark, mark); | |
1224 | |
1225 return 1; | |
1226 } | |
1227 | |
1228 /* | |
1229 * Parse directives. | |
1230 */ | |
1231 | |
1232 static int | |
1233 yaml_parser_process_directives(yaml_parser_t *parser, | |
1234 yaml_version_directive_t **version_directive_ref, | |
1235 yaml_tag_directive_t **tag_directives_start_ref, | |
1236 yaml_tag_directive_t **tag_directives_end_ref) | |
1237 { | |
1238 yaml_tag_directive_t default_tag_directives[] = { | |
1239 {(yaml_char_t *)"!", (yaml_char_t *)"!"}, | |
1240 {(yaml_char_t *)"!!", (yaml_char_t *)"tag:yaml.org,2002:"}, | |
1241 {NULL, NULL} | |
1242 }; | |
1243 yaml_tag_directive_t *default_tag_directive; | |
1244 yaml_version_directive_t *version_directive = NULL; | |
1245 struct { | |
1246 yaml_tag_directive_t *start; | |
1247 yaml_tag_directive_t *end; | |
1248 yaml_tag_directive_t *top; | |
1249 } tag_directives = { NULL, NULL, NULL }; | |
1250 yaml_token_t *token; | |
1251 | |
1252 if (!STACK_INIT(parser, tag_directives, INITIAL_STACK_SIZE)) | |
1253 goto error; | |
1254 | |
1255 token = PEEK_TOKEN(parser); | |
1256 if (!token) goto error; | |
1257 | |
1258 while (token->type == YAML_VERSION_DIRECTIVE_TOKEN || | |
1259 token->type == YAML_TAG_DIRECTIVE_TOKEN) | |
1260 { | |
1261 if (token->type == YAML_VERSION_DIRECTIVE_TOKEN) { | |
1262 if (version_directive) { | |
1263 yaml_parser_set_parser_error(parser, | |
1264 "found duplicate %YAML directive", token->start_mark); | |
1265 goto error; | |
1266 } | |
1267 if (token->data.version_directive.major != 1 | |
1268 || token->data.version_directive.minor != 1) { | |
1269 yaml_parser_set_parser_error(parser, | |
1270 "found incompatible YAML document", token->start_mark); | |
1271 goto error; | |
1272 } | |
1273 version_directive = yaml_malloc(sizeof(yaml_version_directive_t)); | |
1274 if (!version_directive) { | |
1275 parser->error = YAML_MEMORY_ERROR; | |
1276 goto error; | |
1277 } | |
1278 version_directive->major = token->data.version_directive.major; | |
1279 version_directive->minor = token->data.version_directive.minor; | |
1280 } | |
1281 | |
1282 else if (token->type == YAML_TAG_DIRECTIVE_TOKEN) { | |
1283 yaml_tag_directive_t value; | |
1284 value.handle = token->data.tag_directive.handle; | |
1285 value.prefix = token->data.tag_directive.prefix; | |
1286 | |
1287 if (!yaml_parser_append_tag_directive(parser, value, 0, | |
1288 token->start_mark)) | |
1289 goto error; | |
1290 if (!PUSH(parser, tag_directives, value)) | |
1291 goto error; | |
1292 } | |
1293 | |
1294 SKIP_TOKEN(parser); | |
1295 token = PEEK_TOKEN(parser); | |
1296 if (!token) goto error; | |
1297 } | |
1298 | |
1299 for (default_tag_directive = default_tag_directives; | |
1300 default_tag_directive->handle; default_tag_directive++) { | |
1301 if (!yaml_parser_append_tag_directive(parser, *default_tag_directive, 1, | |
1302 token->start_mark)) | |
1303 goto error; | |
1304 } | |
1305 | |
1306 if (version_directive_ref) { | |
1307 *version_directive_ref = version_directive; | |
1308 } | |
1309 if (tag_directives_start_ref) { | |
1310 if (STACK_EMPTY(parser, tag_directives)) { | |
1311 *tag_directives_start_ref = *tag_directives_end_ref = NULL; | |
1312 STACK_DEL(parser, tag_directives); | |
1313 } | |
1314 else { | |
1315 *tag_directives_start_ref = tag_directives.start; | |
1316 *tag_directives_end_ref = tag_directives.top; | |
1317 } | |
1318 } | |
1319 else { | |
1320 STACK_DEL(parser, tag_directives); | |
1321 } | |
1322 | |
1323 return 1; | |
1324 | |
1325 error: | |
1326 yaml_free(version_directive); | |
1327 while (!STACK_EMPTY(parser, tag_directives)) { | |
1328 yaml_tag_directive_t tag_directive = POP(parser, tag_directives); | |
1329 yaml_free(tag_directive.handle); | |
1330 yaml_free(tag_directive.prefix); | |
1331 } | |
1332 STACK_DEL(parser, tag_directives); | |
1333 return 0; | |
1334 } | |
1335 | |
1336 /* | |
1337 * Append a tag directive to the directives stack. | |
1338 */ | |
1339 | |
1340 static int | |
1341 yaml_parser_append_tag_directive(yaml_parser_t *parser, | |
1342 yaml_tag_directive_t value, int allow_duplicates, yaml_mark_t mark) | |
1343 { | |
1344 yaml_tag_directive_t *tag_directive; | |
1345 yaml_tag_directive_t copy = { NULL, NULL }; | |
1346 | |
1347 for (tag_directive = parser->tag_directives.start; | |
1348 tag_directive != parser->tag_directives.top; tag_directive ++) { | |
1349 if (strcmp((char *)value.handle, (char *)tag_directive->handle) == 0) { | |
1350 if (allow_duplicates) | |
1351 return 1; | |
1352 return yaml_parser_set_parser_error(parser, | |
1353 "found duplicate %TAG directive", mark); | |
1354 } | |
1355 } | |
1356 | |
1357 copy.handle = yaml_strdup(value.handle); | |
1358 copy.prefix = yaml_strdup(value.prefix); | |
1359 if (!copy.handle || !copy.prefix) { | |
1360 parser->error = YAML_MEMORY_ERROR; | |
1361 goto error; | |
1362 } | |
1363 | |
1364 if (!PUSH(parser, parser->tag_directives, copy)) | |
1365 goto error; | |
1366 | |
1367 return 1; | |
1368 | |
1369 error: | |
1370 yaml_free(copy.handle); | |
1371 yaml_free(copy.prefix); | |
1372 return 0; | |
1373 } | |
1374 |