source: libyaml/trunk/src/parser.c @ 263

Revision 263, 43.4 KB checked in by xi, 7 years ago (diff)

Completed the first phase of API refactoring.

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