source: trunk/packages/libyaml/src/parser.c @ 898

Last change on this file since 898 was 898, checked in by hartmans, 16 years ago

Add pyyaml and libyaml packages
backported from lenny.
There is discussion about how these should go in the repository; these are added in this form
in order to make forward progress.

File size: 44.1 KB
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.