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

Revision 213, 43.6 KB checked in by xi, 8 years ago (diff)

Implement Emitter state machine.

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 an implicit document. */
356
357    if (implicit && token->type != YAML_VERSION_DIRECTIVE_TOKEN &&
358            token->type != YAML_TAG_DIRECTIVE_TOKEN &&
359            token->type != YAML_DOCUMENT_START_TOKEN &&
360            token->type != YAML_STREAM_END_TOKEN)
361    {
362        if (!yaml_parser_process_directives(parser, NULL, NULL, NULL))
363            return 0;
364        if (!PUSH(parser, parser->states, YAML_PARSE_DOCUMENT_END_STATE))
365            return 0;
366        parser->state = YAML_PARSE_BLOCK_NODE_STATE;
367        DOCUMENT_START_EVENT_INIT(*event, NULL, NULL, NULL, 1,
368                token->start_mark, token->start_mark);
369        return 1;
370    }
371
372    /* Parse an explicit document. */
373
374    else if (token->type != YAML_STREAM_END_TOKEN)
375    {
376        yaml_mark_t start_mark, end_mark;
377        start_mark = token->start_mark;
378        if (!yaml_parser_process_directives(parser, &version_directive,
379                    &tag_directives.start, &tag_directives.end))
380            return 0;
381        token = PEEK_TOKEN(parser);
382        if (!token) goto error;
383        if (token->type != YAML_DOCUMENT_START_TOKEN) {
384            yaml_parser_set_parser_error(parser,
385                    "did not found expected <document start>", token->start_mark);
386            goto error;
387        }
388        if (!PUSH(parser, parser->states, YAML_PARSE_DOCUMENT_END_STATE))
389            goto error;
390        parser->state = YAML_PARSE_DOCUMENT_CONTENT_STATE;
391        end_mark = token->end_mark;
392        DOCUMENT_START_EVENT_INIT(*event, version_directive,
393                tag_directives.start, tag_directives.end, 0,
394                start_mark, end_mark);
395        SKIP_TOKEN(parser);
396        version_directive = NULL;
397        tag_directives.start = tag_directives.end = NULL;
398        return 1;
399    }
400
401    /* Parse the stream end. */
402
403    else
404    {
405        parser->state = YAML_PARSE_END_STATE;
406        STREAM_END_EVENT_INIT(*event, token->start_mark, token->end_mark);
407        SKIP_TOKEN(parser);
408        return 1;
409    }
410
411error:
412    yaml_free(version_directive);
413    while (tag_directives.start != tag_directives.end) {
414        yaml_free(tag_directives.end[-1].handle);
415        yaml_free(tag_directives.end[-1].prefix);
416        tag_directives.end --;
417    }
418    yaml_free(tag_directives.start);
419    return 0;
420}
421
422/*
423 * Parse the productions:
424 * explicit_document    ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
425 *                                                    ***********
426 */
427
428static int
429yaml_parser_parse_document_content(yaml_parser_t *parser, yaml_event_t *event)
430{
431    yaml_token_t *token;
432
433    token = PEEK_TOKEN(parser);
434    if (!token) return 0;
435
436    if (token->type == YAML_VERSION_DIRECTIVE_TOKEN ||
437            token->type == YAML_TAG_DIRECTIVE_TOKEN ||
438            token->type == YAML_DOCUMENT_START_TOKEN ||
439            token->type == YAML_DOCUMENT_END_TOKEN ||
440            token->type == YAML_STREAM_END_TOKEN) {
441        parser->state = POP(parser, parser->states);
442        return yaml_parser_process_empty_scalar(parser, event,
443                token->start_mark);
444    }
445    else {
446        return yaml_parser_parse_node(parser, event, 1, 0);
447    }
448}
449
450/*
451 * Parse the productions:
452 * implicit_document    ::= block_node DOCUMENT-END*
453 *                                     *************
454 * explicit_document    ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
455 *                                                                *************
456 */
457
458static int
459yaml_parser_parse_document_end(yaml_parser_t *parser, yaml_event_t *event)
460{
461    yaml_token_t *token;
462    yaml_mark_t start_mark, end_mark;
463    int implicit = 1;
464
465    token = PEEK_TOKEN(parser);
466    if (!token) return 0;
467
468    start_mark = end_mark = token->start_mark;
469
470    while (token->type == YAML_DOCUMENT_END_TOKEN) {
471        end_mark = token->end_mark;
472        SKIP_TOKEN(parser);
473        token = PEEK_TOKEN(parser);
474        if (!token) return 0;
475        implicit = 0;
476    }
477
478    while (!STACK_EMPTY(parser, parser->tag_directives)) {
479        yaml_tag_directive_t tag_directive = POP(parser, parser->tag_directives);
480        yaml_free(tag_directive.handle);
481        yaml_free(tag_directive.prefix);
482    }
483
484    parser->state = YAML_PARSE_DOCUMENT_START_STATE;
485    DOCUMENT_END_EVENT_INIT(*event, implicit, start_mark, end_mark);
486
487    return 1;
488}
489
490/*
491 * Parse the productions:
492 * block_node_or_indentless_sequence    ::=
493 *                          ALIAS
494 *                          *****
495 *                          | properties (block_content | indentless_block_sequence)?
496 *                            **********  *
497 *                          | block_content | indentless_block_sequence
498 *                            *
499 * block_node           ::= ALIAS
500 *                          *****
501 *                          | properties block_content?
502 *                            ********** *
503 *                          | block_content
504 *                            *
505 * flow_node            ::= ALIAS
506 *                          *****
507 *                          | properties flow_content?
508 *                            ********** *
509 *                          | flow_content
510 *                            *
511 * properties           ::= TAG ANCHOR? | ANCHOR TAG?
512 *                          *************************
513 * block_content        ::= block_collection | flow_collection | SCALAR
514 *                                                               ******
515 * flow_content         ::= flow_collection | SCALAR
516 *                                            ******
517 */
518
519static int
520yaml_parser_parse_node(yaml_parser_t *parser, yaml_event_t *event,
521        int block, int indentless_sequence)
522{
523    yaml_token_t *token;
524    yaml_char_t *anchor = NULL;
525    yaml_char_t *tag_handle = NULL;
526    yaml_char_t *tag_suffix = NULL;
527    yaml_char_t *tag = NULL;
528    yaml_mark_t start_mark, end_mark, tag_mark;
529    int implicit;
530
531    token = PEEK_TOKEN(parser);
532    if (!token) return 0;
533
534    if (token->type == YAML_ALIAS_TOKEN)
535    {
536        parser->state = POP(parser, parser->states);
537        ALIAS_EVENT_INIT(*event, token->data.alias.value,
538                token->start_mark, token->end_mark);
539        SKIP_TOKEN(parser);
540        return 1;
541    }
542
543    else
544    {
545        start_mark = end_mark = token->start_mark;
546
547        if (token->type == YAML_ANCHOR_TOKEN)
548        {
549            anchor = token->data.anchor.value;
550            start_mark = token->start_mark;
551            end_mark = token->end_mark;
552            SKIP_TOKEN(parser);
553            token = PEEK_TOKEN(parser);
554            if (!token) goto error;
555            if (token->type == YAML_TAG_TOKEN)
556            {
557                tag_handle = token->data.tag.handle;
558                tag_suffix = token->data.tag.suffix;
559                tag_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            }
565        }
566        else if (token->type == YAML_TAG_TOKEN)
567        {
568            tag_handle = token->data.tag.handle;
569            tag_suffix = token->data.tag.suffix;
570            start_mark = tag_mark = token->start_mark;
571            end_mark = token->end_mark;
572            SKIP_TOKEN(parser);
573            token = PEEK_TOKEN(parser);
574            if (!token) goto error;
575            if (token->type == YAML_ANCHOR_TOKEN)
576            {
577                anchor = token->data.anchor.value;
578                end_mark = token->end_mark;
579                SKIP_TOKEN(parser);
580                token = PEEK_TOKEN(parser);
581                if (!token) goto error;
582            }
583        }
584
585        if (tag_handle) {
586            if (!*tag_handle) {
587                tag = tag_suffix;
588                yaml_free(tag_handle);
589                tag_handle = tag_suffix = NULL;
590            }
591            else {
592                yaml_tag_directive_t *tag_directive;
593                for (tag_directive = parser->tag_directives.start;
594                        tag_directive != parser->tag_directives.top;
595                        tag_directive ++) {
596                    if (strcmp((char *)tag_directive->handle, (char *)tag_handle) == 0) {
597                        size_t prefix_len = strlen((char *)tag_directive->prefix);
598                        size_t suffix_len = strlen((char *)tag_suffix);
599                        tag = yaml_malloc(prefix_len+suffix_len+1);
600                        if (!tag) {
601                            parser->error = YAML_MEMORY_ERROR;
602                            goto error;
603                        }
604                        memcpy(tag, tag_directive->prefix, prefix_len);
605                        memcpy(tag+prefix_len, tag_suffix, suffix_len);
606                        tag[prefix_len+suffix_len] = '\0';
607                        yaml_free(tag_handle);
608                        yaml_free(tag_suffix);
609                        tag_handle = tag_suffix = NULL;
610                        break;
611                    }
612                }
613                if (!tag) {
614                    yaml_parser_set_parser_error_context(parser,
615                            "while parsing a node", start_mark,
616                            "found undefined tag handle", tag_mark);
617                    goto error;
618                }
619            }
620        }
621
622        implicit = (!tag || !*tag);
623        if (indentless_sequence && token->type == YAML_BLOCK_ENTRY_TOKEN) {
624            end_mark = token->end_mark;
625            parser->state = YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE;
626            SEQUENCE_START_EVENT_INIT(*event, anchor, tag, implicit,
627                    YAML_BLOCK_SEQUENCE_STYLE, start_mark, end_mark);
628            return 1;
629        }
630        else {
631            if (token->type == YAML_SCALAR_TOKEN) {
632                int plain_implicit = 0;
633                int quoted_implicit = 0;
634                end_mark = token->end_mark;
635                if ((token->data.scalar.style == YAML_PLAIN_SCALAR_STYLE && !tag)
636                        || (tag && strcmp((char *)tag, "!") == 0)) {
637                    plain_implicit = 1;
638                }
639                else if (!tag) {
640                    quoted_implicit = 1;
641                }
642                parser->state = POP(parser, parser->states);
643                SCALAR_EVENT_INIT(*event, anchor, tag,
644                        token->data.scalar.value, token->data.scalar.length,
645                        plain_implicit, quoted_implicit,
646                        token->data.scalar.style, start_mark, end_mark);
647                SKIP_TOKEN(parser);
648                return 1;
649            }
650            else if (token->type == YAML_FLOW_SEQUENCE_START_TOKEN) {
651                end_mark = token->end_mark;
652                parser->state = YAML_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE;
653                SEQUENCE_START_EVENT_INIT(*event, anchor, tag, implicit,
654                        YAML_FLOW_SEQUENCE_STYLE, start_mark, end_mark);
655                return 1;
656            }
657            else if (token->type == YAML_FLOW_MAPPING_START_TOKEN) {
658                end_mark = token->end_mark;
659                parser->state = YAML_PARSE_FLOW_MAPPING_FIRST_KEY_STATE;
660                MAPPING_START_EVENT_INIT(*event, anchor, tag, implicit,
661                        YAML_FLOW_MAPPING_STYLE, start_mark, end_mark);
662                return 1;
663            }
664            else if (block && token->type == YAML_BLOCK_SEQUENCE_START_TOKEN) {
665                end_mark = token->end_mark;
666                parser->state = YAML_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE;
667                SEQUENCE_START_EVENT_INIT(*event, anchor, tag, implicit,
668                        YAML_BLOCK_SEQUENCE_STYLE, start_mark, end_mark);
669                return 1;
670            }
671            else if (block && token->type == YAML_BLOCK_MAPPING_START_TOKEN) {
672                end_mark = token->end_mark;
673                parser->state = YAML_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE;
674                MAPPING_START_EVENT_INIT(*event, anchor, tag, implicit,
675                        YAML_BLOCK_MAPPING_STYLE, start_mark, end_mark);
676                return 1;
677            }
678            else if (anchor || tag) {
679                yaml_char_t *value = yaml_malloc(1);
680                if (!value) {
681                    parser->error = YAML_MEMORY_ERROR;
682                    goto error;
683                }
684                value[0] = '\0';
685                parser->state = POP(parser, parser->states);
686                SCALAR_EVENT_INIT(*event, anchor, tag, value, 0,
687                        implicit, 0, YAML_PLAIN_SCALAR_STYLE,
688                        start_mark, end_mark);
689                return 1;
690            }
691            else {
692                yaml_parser_set_parser_error_context(parser,
693                        (block ? "while parsing a block node"
694                         : "while parsing a flow node"), start_mark,
695                        "did not found expected node content", token->start_mark);
696                goto error;
697            }
698        }
699    }
700
701error:
702    yaml_free(anchor);
703    yaml_free(tag_handle);
704    yaml_free(tag_suffix);
705    yaml_free(tag);
706
707    return 0;
708}
709
710/*
711 * Parse the productions:
712 * block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
713 *                    ********************  *********** *             *********
714 */
715
716static int
717yaml_parser_parse_block_sequence_entry(yaml_parser_t *parser,
718        yaml_event_t *event, int first)
719{
720    yaml_token_t *token;
721
722    if (first) {
723        token = PEEK_TOKEN(parser);
724        if (!PUSH(parser, parser->marks, token->start_mark))
725            return 0;
726        SKIP_TOKEN(parser);
727    }
728
729    token = PEEK_TOKEN(parser);
730    if (!token) return 0;
731
732    if (token->type == YAML_BLOCK_ENTRY_TOKEN)
733    {
734        yaml_mark_t mark = token->end_mark;
735        SKIP_TOKEN(parser);
736        token = PEEK_TOKEN(parser);
737        if (!token) return 0;
738        if (token->type != YAML_BLOCK_ENTRY_TOKEN &&
739                token->type != YAML_BLOCK_END_TOKEN) {
740            if (!PUSH(parser, parser->states,
741                        YAML_PARSE_BLOCK_SEQUENCE_ENTRY_STATE))
742                return 0;
743            return yaml_parser_parse_node(parser, event, 1, 0);
744        }
745        else {
746            parser->state = YAML_PARSE_BLOCK_SEQUENCE_ENTRY_STATE;
747            return yaml_parser_process_empty_scalar(parser, event, mark);
748        }
749    }
750
751    else if (token->type == YAML_BLOCK_END_TOKEN)
752    {
753        parser->state = POP(parser, parser->states);
754        POP(parser, parser->marks);
755        SEQUENCE_END_EVENT_INIT(*event, token->start_mark, token->end_mark);
756        SKIP_TOKEN(parser);
757        return 1;
758    }
759
760    else
761    {
762        return yaml_parser_set_parser_error_context(parser,
763                "while parsing a block collection", POP(parser, parser->marks),
764                "did not found expected '-' indicator", token->start_mark);
765    }
766}
767
768/*
769 * Parse the productions:
770 * indentless_sequence  ::= (BLOCK-ENTRY block_node?)+
771 *                           *********** *
772 */
773
774static int
775yaml_parser_parse_indentless_sequence_entry(yaml_parser_t *parser,
776        yaml_event_t *event)
777{
778    yaml_token_t *token;
779
780    token = PEEK_TOKEN(parser);
781    if (!token) return 0;
782
783    if (token->type == YAML_BLOCK_ENTRY_TOKEN)
784    {
785        yaml_mark_t mark = token->end_mark;
786        SKIP_TOKEN(parser);
787        token = PEEK_TOKEN(parser);
788        if (!token) return 0;
789        if (token->type != YAML_BLOCK_ENTRY_TOKEN &&
790                token->type != YAML_KEY_TOKEN &&
791                token->type != YAML_VALUE_TOKEN &&
792                token->type != YAML_BLOCK_END_TOKEN) {
793            if (!PUSH(parser, parser->states,
794                        YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE))
795                return 0;
796            return yaml_parser_parse_node(parser, event, 1, 0);
797        }
798        else {
799            parser->state = YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE;
800            return yaml_parser_process_empty_scalar(parser, event, mark);
801        }
802    }
803
804    else
805    {
806        parser->state = POP(parser, parser->states);
807        SEQUENCE_END_EVENT_INIT(*event, token->start_mark, token->start_mark);
808        return 1;
809    }
810}
811
812/*
813 * Parse the productions:
814 * block_mapping        ::= BLOCK-MAPPING_START
815 *                          *******************
816 *                          ((KEY block_node_or_indentless_sequence?)?
817 *                            *** *
818 *                          (VALUE block_node_or_indentless_sequence?)?)*
819 *
820 *                          BLOCK-END
821 *                          *********
822 */
823
824static int
825yaml_parser_parse_block_mapping_key(yaml_parser_t *parser,
826        yaml_event_t *event, int first)
827{
828    yaml_token_t *token;
829
830    if (first) {
831        token = PEEK_TOKEN(parser);
832        if (!PUSH(parser, parser->marks, token->start_mark))
833            return 0;
834        SKIP_TOKEN(parser);
835    }
836
837    token = PEEK_TOKEN(parser);
838    if (!token) return 0;
839
840    if (token->type == YAML_KEY_TOKEN)
841    {
842        yaml_mark_t mark = token->end_mark;
843        SKIP_TOKEN(parser);
844        token = PEEK_TOKEN(parser);
845        if (!token) return 0;
846        if (token->type != YAML_KEY_TOKEN &&
847                token->type != YAML_VALUE_TOKEN &&
848                token->type != YAML_BLOCK_END_TOKEN) {
849            if (!PUSH(parser, parser->states,
850                        YAML_PARSE_BLOCK_MAPPING_VALUE_STATE))
851                return 0;
852            return yaml_parser_parse_node(parser, event, 1, 1);
853        }
854        else {
855            parser->state = YAML_PARSE_BLOCK_MAPPING_VALUE_STATE;
856            return yaml_parser_process_empty_scalar(parser, event, mark);
857        }
858    }
859
860    else if (token->type == YAML_BLOCK_END_TOKEN)
861    {
862        parser->state = POP(parser, parser->states);
863        POP(parser, parser->marks);
864        MAPPING_END_EVENT_INIT(*event, token->start_mark, token->end_mark);
865        SKIP_TOKEN(parser);
866        return 1;
867    }
868
869    else
870    {
871        return yaml_parser_set_parser_error_context(parser,
872                "while parsing a block mapping", POP(parser, parser->marks),
873                "did not found expected key", token->start_mark);
874    }
875}
876
877/*
878 * Parse the productions:
879 * block_mapping        ::= BLOCK-MAPPING_START
880 *
881 *                          ((KEY block_node_or_indentless_sequence?)?
882 *
883 *                          (VALUE block_node_or_indentless_sequence?)?)*
884 *                           ***** *
885 *                          BLOCK-END
886 *
887 */
888
889static int
890yaml_parser_parse_block_mapping_value(yaml_parser_t *parser,
891        yaml_event_t *event)
892{
893    yaml_token_t *token;
894
895    token = PEEK_TOKEN(parser);
896    if (!token) return 0;
897
898    if (token->type == YAML_VALUE_TOKEN)
899    {
900        yaml_mark_t mark = token->end_mark;
901        SKIP_TOKEN(parser);
902        token = PEEK_TOKEN(parser);
903        if (!token) return 0;
904        if (token->type != YAML_KEY_TOKEN &&
905                token->type != YAML_VALUE_TOKEN &&
906                token->type != YAML_BLOCK_END_TOKEN) {
907            if (!PUSH(parser, parser->states,
908                        YAML_PARSE_BLOCK_MAPPING_KEY_STATE))
909                return 0;
910            return yaml_parser_parse_node(parser, event, 1, 1);
911        }
912        else {
913            parser->state = YAML_PARSE_BLOCK_MAPPING_KEY_STATE;
914            return yaml_parser_process_empty_scalar(parser, event, mark);
915        }
916    }
917
918    else
919    {
920        parser->state = YAML_PARSE_BLOCK_MAPPING_KEY_STATE;
921        return yaml_parser_process_empty_scalar(parser, event, token->start_mark);
922    }
923}
924
925/*
926 * Parse the productions:
927 * flow_sequence        ::= FLOW-SEQUENCE-START
928 *                          *******************
929 *                          (flow_sequence_entry FLOW-ENTRY)*
930 *                           *                   **********
931 *                          flow_sequence_entry?
932 *                          *
933 *                          FLOW-SEQUENCE-END
934 *                          *****************
935 * flow_sequence_entry  ::= flow_node | KEY flow_node? (VALUE flow_node?)?
936 *                          *
937 */
938
939static int
940yaml_parser_parse_flow_sequence_entry(yaml_parser_t *parser,
941        yaml_event_t *event, int first)
942{
943    yaml_token_t *token;
944
945    if (first) {
946        token = PEEK_TOKEN(parser);
947        if (!PUSH(parser, parser->marks, token->start_mark))
948            return 0;
949        SKIP_TOKEN(parser);
950    }
951
952    token = PEEK_TOKEN(parser);
953    if (!token) return 0;
954
955    if (token->type != YAML_FLOW_SEQUENCE_END_TOKEN)
956    {
957        if (!first) {
958            if (token->type == YAML_FLOW_ENTRY_TOKEN) {
959                SKIP_TOKEN(parser);
960                token = PEEK_TOKEN(parser);
961                if (!token) return 0;
962            }
963            else {
964                return yaml_parser_set_parser_error_context(parser,
965                        "while parsing a flow sequence", POP(parser, parser->marks),
966                        "did not found expected ',' or ']'", token->start_mark);
967            }
968        }
969
970        if (token->type == YAML_KEY_TOKEN) {
971            parser->state = YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE;
972            MAPPING_START_EVENT_INIT(*event, NULL, NULL,
973                    1, YAML_FLOW_MAPPING_STYLE,
974                    token->start_mark, token->end_mark);
975            SKIP_TOKEN(parser);
976            return 1;
977        }
978
979        else if (token->type != YAML_FLOW_SEQUENCE_END_TOKEN) {
980            if (!PUSH(parser, parser->states,
981                        YAML_PARSE_FLOW_SEQUENCE_ENTRY_STATE))
982                return 0;
983            return yaml_parser_parse_node(parser, event, 0, 0);
984        }
985    }
986
987    parser->state = POP(parser, parser->states);
988    POP(parser, parser->marks);
989    SEQUENCE_END_EVENT_INIT(*event, token->start_mark, token->end_mark);
990    SKIP_TOKEN(parser);
991    return 1;
992}
993
994/*
995 * Parse the productions:
996 * flow_sequence_entry  ::= flow_node | KEY flow_node? (VALUE flow_node?)?
997 *                                      *** *
998 */
999
1000static int
1001yaml_parser_parse_flow_sequence_entry_mapping_key(yaml_parser_t *parser,
1002        yaml_event_t *event)
1003{
1004    yaml_token_t *token;
1005
1006    token = PEEK_TOKEN(parser);
1007    if (!token) return 0;
1008
1009    if (token->type != YAML_VALUE_TOKEN && token->type != YAML_FLOW_ENTRY_TOKEN
1010            && token->type != YAML_FLOW_SEQUENCE_END_TOKEN) {
1011        if (!PUSH(parser, parser->states,
1012                    YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE))
1013            return 0;
1014        return yaml_parser_parse_node(parser, event, 0, 0);
1015    }
1016    else {
1017        yaml_mark_t mark = token->end_mark;
1018        SKIP_TOKEN(parser);
1019        parser->state = YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE;
1020        return yaml_parser_process_empty_scalar(parser, event, mark);
1021    }
1022}
1023
1024/*
1025 * Parse the productions:
1026 * flow_sequence_entry  ::= flow_node | KEY flow_node? (VALUE flow_node?)?
1027 *                                                      ***** *
1028 */
1029
1030static int
1031yaml_parser_parse_flow_sequence_entry_mapping_value(yaml_parser_t *parser,
1032        yaml_event_t *event)
1033{
1034    yaml_token_t *token;
1035
1036    token = PEEK_TOKEN(parser);
1037    if (!token) return 0;
1038
1039    if (token->type == YAML_VALUE_TOKEN) {
1040        SKIP_TOKEN(parser);
1041        token = PEEK_TOKEN(parser);
1042        if (!token) return 0;
1043        if (token->type != YAML_FLOW_ENTRY_TOKEN
1044                && token->type != YAML_FLOW_SEQUENCE_END_TOKEN) {
1045            if (!PUSH(parser, parser->states,
1046                        YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE))
1047                return 0;
1048            return yaml_parser_parse_node(parser, event, 0, 0);
1049        }
1050    }
1051    parser->state = YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE;
1052    return yaml_parser_process_empty_scalar(parser, event, token->start_mark);
1053}
1054
1055/*
1056 * Parse the productions:
1057 * flow_sequence_entry  ::= flow_node | KEY flow_node? (VALUE flow_node?)?
1058 *                                                                      *
1059 */
1060
1061static int
1062yaml_parser_parse_flow_sequence_entry_mapping_end(yaml_parser_t *parser,
1063        yaml_event_t *event)
1064{
1065    yaml_token_t *token;
1066
1067    token = PEEK_TOKEN(parser);
1068    if (!token) return 0;
1069
1070    parser->state = YAML_PARSE_FLOW_SEQUENCE_ENTRY_STATE;
1071
1072    MAPPING_END_EVENT_INIT(*event, token->start_mark, token->start_mark);
1073    return 1;
1074}
1075
1076/*
1077 * Parse the productions:
1078 * flow_mapping         ::= FLOW-MAPPING-START
1079 *                          ******************
1080 *                          (flow_mapping_entry FLOW-ENTRY)*
1081 *                           *                  **********
1082 *                          flow_mapping_entry?
1083 *                          ******************
1084 *                          FLOW-MAPPING-END
1085 *                          ****************
1086 * flow_mapping_entry   ::= flow_node | KEY flow_node? (VALUE flow_node?)?
1087 *                          *           *** *
1088 */
1089
1090static int
1091yaml_parser_parse_flow_mapping_key(yaml_parser_t *parser,
1092        yaml_event_t *event, int first)
1093{
1094    yaml_token_t *token;
1095
1096    if (first) {
1097        token = PEEK_TOKEN(parser);
1098        if (!PUSH(parser, parser->marks, token->start_mark))
1099            return 0;
1100        SKIP_TOKEN(parser);
1101    }
1102
1103    token = PEEK_TOKEN(parser);
1104    if (!token) return 0;
1105
1106    if (token->type != YAML_FLOW_MAPPING_END_TOKEN)
1107    {
1108        if (!first) {
1109            if (token->type == YAML_FLOW_ENTRY_TOKEN) {
1110                SKIP_TOKEN(parser);
1111                token = PEEK_TOKEN(parser);
1112                if (!token) return 0;
1113            }
1114            else {
1115                return yaml_parser_set_parser_error_context(parser,
1116                        "while parsing a flow mapping", POP(parser, parser->marks),
1117                        "did not found expected ',' or '}'", token->start_mark);
1118            }
1119        }
1120
1121        if (token->type == YAML_KEY_TOKEN) {
1122            SKIP_TOKEN(parser);
1123            token = PEEK_TOKEN(parser);
1124            if (!token) return 0;
1125            if (token->type != YAML_VALUE_TOKEN
1126                    && token->type != YAML_FLOW_ENTRY_TOKEN
1127                    && token->type != YAML_FLOW_MAPPING_END_TOKEN) {
1128                if (!PUSH(parser, parser->states,
1129                            YAML_PARSE_FLOW_MAPPING_VALUE_STATE))
1130                    return 0;
1131                return yaml_parser_parse_node(parser, event, 0, 0);
1132            }
1133            else {
1134                parser->state = YAML_PARSE_FLOW_MAPPING_VALUE_STATE;
1135                return yaml_parser_process_empty_scalar(parser, event,
1136                        token->start_mark);
1137            }
1138        }
1139        else if (token->type != YAML_FLOW_MAPPING_END_TOKEN) {
1140            if (!PUSH(parser, parser->states,
1141                        YAML_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE))
1142                return 0;
1143            return yaml_parser_parse_node(parser, event, 0, 0);
1144        }
1145    }
1146
1147    parser->state = POP(parser, parser->states);
1148    POP(parser, parser->marks);
1149    MAPPING_END_EVENT_INIT(*event, token->start_mark, token->end_mark);
1150    SKIP_TOKEN(parser);
1151    return 1;
1152}
1153
1154/*
1155 * Parse the productions:
1156 * flow_mapping_entry   ::= flow_node | KEY flow_node? (VALUE flow_node?)?
1157 *                                   *                  ***** *
1158 */
1159
1160static int
1161yaml_parser_parse_flow_mapping_value(yaml_parser_t *parser,
1162        yaml_event_t *event, int empty)
1163{
1164    yaml_token_t *token;
1165
1166    token = PEEK_TOKEN(parser);
1167    if (!token) return 0;
1168
1169    if (empty) {
1170        parser->state = YAML_PARSE_FLOW_MAPPING_KEY_STATE;
1171        return yaml_parser_process_empty_scalar(parser, event,
1172                token->start_mark);
1173    }
1174
1175    if (token->type == YAML_VALUE_TOKEN) {
1176        SKIP_TOKEN(parser);
1177        token = PEEK_TOKEN(parser);
1178        if (!token) return 0;
1179        if (token->type != YAML_FLOW_ENTRY_TOKEN
1180                && token->type != YAML_FLOW_MAPPING_END_TOKEN) {
1181            if (!PUSH(parser, parser->states,
1182                        YAML_PARSE_FLOW_MAPPING_KEY_STATE))
1183                return 0;
1184            return yaml_parser_parse_node(parser, event, 0, 0);
1185        }
1186    }
1187
1188    parser->state = YAML_PARSE_FLOW_MAPPING_KEY_STATE;
1189    return yaml_parser_process_empty_scalar(parser, event, token->start_mark);
1190}
1191
1192/*
1193 * Generate an empty scalar event.
1194 */
1195
1196static int
1197yaml_parser_process_empty_scalar(yaml_parser_t *parser, yaml_event_t *event,
1198        yaml_mark_t mark)
1199{
1200    yaml_char_t *value;
1201
1202    value = yaml_malloc(1);
1203    if (!value) {
1204        parser->error = YAML_MEMORY_ERROR;
1205        return 0;
1206    }
1207    value[0] = '\0';
1208
1209    SCALAR_EVENT_INIT(*event, NULL, NULL, value, 0,
1210            1, 0, YAML_PLAIN_SCALAR_STYLE, mark, mark);
1211
1212    return 1;
1213}
1214
1215/*
1216 * Parse directives.
1217 */
1218
1219static int
1220yaml_parser_process_directives(yaml_parser_t *parser,
1221        yaml_version_directive_t **version_directive_ref,
1222        yaml_tag_directive_t **tag_directives_start_ref,
1223        yaml_tag_directive_t **tag_directives_end_ref)
1224{
1225    yaml_tag_directive_t default_tag_directives[] = {
1226        {(yaml_char_t *)"!", (yaml_char_t *)"!"},
1227        {(yaml_char_t *)"!!", (yaml_char_t *)"tag:yaml.org,2002:"},
1228        {NULL, NULL}
1229    };
1230    yaml_tag_directive_t *default_tag_directive;
1231    yaml_version_directive_t *version_directive = NULL;
1232    struct {
1233        yaml_tag_directive_t *start;
1234        yaml_tag_directive_t *end;
1235        yaml_tag_directive_t *top;
1236    } tag_directives = { NULL, NULL, NULL };
1237    yaml_token_t *token;
1238
1239    if (!STACK_INIT(parser, tag_directives, INITIAL_STACK_SIZE))
1240        goto error;
1241
1242    token = PEEK_TOKEN(parser);
1243    if (!token) goto error;
1244
1245    while (token->type == YAML_VERSION_DIRECTIVE_TOKEN ||
1246            token->type == YAML_TAG_DIRECTIVE_TOKEN)
1247    {
1248        if (token->type == YAML_VERSION_DIRECTIVE_TOKEN) {
1249            if (version_directive) {
1250                yaml_parser_set_parser_error(parser,
1251                        "found duplicate %YAML directive", token->start_mark);
1252                goto error;
1253            }
1254            if (token->data.version_directive.major != 1
1255                    && token->data.version_directive.minor != 1) {
1256                yaml_parser_set_parser_error(parser,
1257                        "found incompatible YAML document", token->start_mark);
1258                goto error;
1259            }
1260            version_directive = yaml_malloc(sizeof(yaml_version_directive_t));
1261            if (!version_directive) {
1262                parser->error = YAML_MEMORY_ERROR;
1263                goto error;
1264            }
1265            version_directive->major = token->data.version_directive.major;
1266            version_directive->minor = token->data.version_directive.minor;
1267        }
1268
1269        else if (token->type == YAML_TAG_DIRECTIVE_TOKEN) {
1270            yaml_tag_directive_t value = {
1271                token->data.tag_directive.handle,
1272                token->data.tag_directive.prefix
1273            };
1274            if (!yaml_parser_append_tag_directive(parser, value, 0,
1275                        token->start_mark))
1276                goto error;
1277            if (!PUSH(parser, tag_directives, value))
1278                goto error;
1279        }
1280
1281        SKIP_TOKEN(parser);
1282        token = PEEK_TOKEN(parser);
1283        if (!token) goto error;
1284    }
1285   
1286    for (default_tag_directive = default_tag_directives;
1287            default_tag_directive->handle; default_tag_directive++) {
1288        if (!yaml_parser_append_tag_directive(parser, *default_tag_directive, 1,
1289                    token->start_mark))
1290            goto error;
1291    }
1292
1293    if (version_directive_ref) {
1294        *version_directive_ref = version_directive;
1295    }
1296    if (tag_directives_start_ref) {
1297        if (STACK_EMPTY(parser, tag_directives)) {
1298            *tag_directives_start_ref = *tag_directives_end_ref = NULL;
1299            STACK_DEL(parser, tag_directives);
1300        }
1301        else {
1302            *tag_directives_start_ref = tag_directives.start;
1303            *tag_directives_end_ref = tag_directives.top;
1304        }
1305    }
1306    else {
1307        STACK_DEL(parser, tag_directives);
1308    }
1309
1310    return 1;
1311
1312error:
1313    yaml_free(version_directive);
1314    while (!STACK_EMPTY(parser, tag_directives)) {
1315        yaml_tag_directive_t tag_directive = POP(parser, tag_directives);
1316        yaml_free(tag_directive.handle);
1317        yaml_free(tag_directive.prefix);
1318    }
1319    STACK_DEL(parser, tag_directives);
1320    return 0;
1321}
1322
1323/*
1324 * Append a tag directive to the directives stack.
1325 */
1326
1327static int
1328yaml_parser_append_tag_directive(yaml_parser_t *parser,
1329        yaml_tag_directive_t value, int allow_duplicates, yaml_mark_t mark)
1330{
1331    yaml_tag_directive_t *tag_directive;
1332    yaml_tag_directive_t copy = { NULL, NULL };
1333
1334    for (tag_directive = parser->tag_directives.start;
1335            tag_directive != parser->tag_directives.top; tag_directive ++) {
1336        if (strcmp((char *)value.handle, (char *)tag_directive->handle) == 0) {
1337            if (allow_duplicates)
1338                return 1;
1339            return yaml_parser_set_parser_error(parser,
1340                    "found duplicate %TAG directive", mark);
1341        }
1342    }
1343
1344    copy.handle = yaml_strdup(value.handle);
1345    copy.prefix = yaml_strdup(value.prefix);
1346    if (!copy.handle || !copy.prefix) {
1347        parser->error = YAML_MEMORY_ERROR;
1348        goto error;
1349    }
1350
1351    if (!PUSH(parser, parser->tag_directives, copy))
1352        goto error;
1353
1354    return 1;
1355
1356error:
1357    yaml_free(copy.handle);
1358    yaml_free(copy.prefix);
1359    return 0;
1360}
1361
Note: See TracBrowser for help on using the repository browser.