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

Revision 250, 44.1 KB checked in by xi, 8 years ago (diff)

Fixed a problem when the DOCUMENT-END event is not emitted until the beginning of the next document is available. Fixed #51. Thanks edward(at)sweetbytes.net for the bug report.

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->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
67YAML_DECLARE(int)
68yaml_parser_parse(yaml_parser_t *parser, yaml_event_t *event);
69
70/*
71 * Error handling.
72 */
73
74static int
75yaml_parser_set_parser_error(yaml_parser_t *parser,
76        const char *problem, yaml_mark_t problem_mark);
77
78static int
79yaml_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
87static int
88yaml_parser_state_machine(yaml_parser_t *parser, yaml_event_t *event);
89
90static int
91yaml_parser_parse_stream_start(yaml_parser_t *parser, yaml_event_t *event);
92
93static int
94yaml_parser_parse_document_start(yaml_parser_t *parser, yaml_event_t *event,
95        int implicit);
96
97static int
98yaml_parser_parse_document_content(yaml_parser_t *parser, yaml_event_t *event);
99
100static int
101yaml_parser_parse_document_end(yaml_parser_t *parser, yaml_event_t *event);
102
103static int
104yaml_parser_parse_node(yaml_parser_t *parser, yaml_event_t *event,
105        int block, int indentless_sequence);
106
107static int
108yaml_parser_parse_block_sequence_entry(yaml_parser_t *parser,
109        yaml_event_t *event, int first);
110
111static int
112yaml_parser_parse_indentless_sequence_entry(yaml_parser_t *parser,
113        yaml_event_t *event);
114
115static int
116yaml_parser_parse_block_mapping_key(yaml_parser_t *parser,
117        yaml_event_t *event, int first);
118
119static int
120yaml_parser_parse_block_mapping_value(yaml_parser_t *parser,
121        yaml_event_t *event);
122
123static int
124yaml_parser_parse_flow_sequence_entry(yaml_parser_t *parser,
125        yaml_event_t *event, int first);
126
127static int
128yaml_parser_parse_flow_sequence_entry_mapping_key(yaml_parser_t *parser,
129        yaml_event_t *event);
130
131static int
132yaml_parser_parse_flow_sequence_entry_mapping_value(yaml_parser_t *parser,
133        yaml_event_t *event);
134
135static int
136yaml_parser_parse_flow_sequence_entry_mapping_end(yaml_parser_t *parser,
137        yaml_event_t *event);
138
139static int
140yaml_parser_parse_flow_mapping_key(yaml_parser_t *parser,
141        yaml_event_t *event, int first);
142
143static int
144yaml_parser_parse_flow_mapping_value(yaml_parser_t *parser,
145        yaml_event_t *event, int empty);
146
147/*
148 * Utility functions.
149 */
150
151static int
152yaml_parser_process_empty_scalar(yaml_parser_t *parser,
153        yaml_event_t *event, yaml_mark_t mark);
154
155static int
156yaml_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
161static int
162yaml_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
169YAML_DECLARE(int)
170yaml_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
195static int
196yaml_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
206static int
207yaml_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
225static int
226yaml_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
312static int
313yaml_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 found 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
341static int
342yaml_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 found 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
422error:
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
439static int
440yaml_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
469static int
470yaml_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
528static int
529yaml_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 found expected node content", token->start_mark);
705                goto error;
706            }
707        }
708    }
709
710error:
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
725static int
726yaml_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 found expected '-' indicator", token->start_mark);
775    }
776}
777
778/*
779 * Parse the productions:
780 * indentless_sequence  ::= (BLOCK-ENTRY block_node?)+
781 *                           *********** *
782 */
783
784static int
785yaml_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
834static int
835yaml_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 found 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
900static int
901yaml_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
950static int
951yaml_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 found 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
1012static int
1013yaml_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
1042static int
1043yaml_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
1073static int
1074yaml_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
1102static int
1103yaml_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 found 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
1173static int
1174yaml_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
1209static int
1210yaml_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
1232static int
1233yaml_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                token->data.tag_directive.handle,
1285                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
1325error:
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
1340static int
1341yaml_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
1369error:
1370    yaml_free(copy.handle);
1371    yaml_free(copy.prefix);
1372    return 0;
1373}
1374
Note: See TracBrowser for help on using the repository browser.