6 * The following notes assume that you are familiar with the YAML specification
7 * (http://yaml.org/spec/cvs/current.html). We mostly follow it, although in
8 * some cases we are less restrictive that it requires.
10 * The process of transforming a YAML stream into a sequence of events is
11 * divided on two steps: Scanning and Parsing.
13 * The Scanner transforms the input stream into a sequence of tokens, while the
14 * parser transform the sequence of tokens produced by the Scanner into a
15 * sequence of parsing events.
17 * The Scanner is rather clever and complicated. The Parser, on the contrary,
18 * is a straightforward implementation of a recursive-descendant parser (or,
19 * LL(1) parser, as it is usually called).
21 * Actually there are two issues of Scanning that might be called "clever", the
22 * rest is quite straightforward. The issues are "block collection start" and
23 * "simple keys". Both issues are explained below in details.
25 * Here the Scanning step is explained and implemented. We start with the list
26 * of all the tokens produced by the Scanner together with short descriptions.
30 * STREAM-START(encoding) # The stream start.
31 * STREAM-END # The stream end.
32 * VERSION-DIRECTIVE(major,minor) # The '%YAML' directive.
33 * TAG-DIRECTIVE(handle,prefix) # The '%TAG' directive.
34 * DOCUMENT-START # '---'
35 * DOCUMENT-END # '...'
36 * BLOCK-SEQUENCE-START # Indentation increase denoting a block
37 * BLOCK-MAPPING-START # sequence or a block mapping.
38 * BLOCK-END # Indentation decrease.
39 * FLOW-SEQUENCE-START # '['
40 * FLOW-SEQUENCE-END # ']'
41 * BLOCK-SEQUENCE-START # '{'
42 * BLOCK-SEQUENCE-END # '}'
45 * KEY # '?' or nothing (simple keys).
47 * ALIAS(anchor) # '*anchor'
48 * ANCHOR(anchor) # '&anchor'
49 * TAG(handle,suffix) # '!handle!suffix'
50 * SCALAR(value,style) # A scalar.
52 * The following two tokens are "virtual" tokens denoting the beginning and the
55 * STREAM-START(encoding)
58 * We pass the information about the input stream encoding with the
61 * The next two tokens are responsible for tags:
63 * VERSION-DIRECTIVE(major,minor)
64 * TAG-DIRECTIVE(handle,prefix)
70 * %TAG !yaml! tag:yaml.org,2002:
73 * The correspoding sequence of tokens:
76 * VERSION-DIRECTIVE(1,1)
77 * TAG-DIRECTIVE("!","!foo")
78 * TAG-DIRECTIVE("!yaml","tag:yaml.org,2002:")
82 * Note that the VERSION-DIRECTIVE and TAG-DIRECTIVE tokens occupy a whole
85 * The document start and end indicators are represented by:
90 * Note that if a YAML stream contains an implicit document (without '---'
91 * and '...' indicators), no DOCUMENT-START and DOCUMENT-END tokens will be
94 * In the following examples, we present whole documents together with the
97 * 1. An implicit document:
103 * STREAM-START(utf-8)
104 * SCALAR("a scalar",single-quoted)
107 * 2. An explicit document:
115 * STREAM-START(utf-8)
117 * SCALAR("a scalar",single-quoted)
121 * 3. Several documents in a stream:
127 * 'yet another scalar'
131 * STREAM-START(utf-8)
132 * SCALAR("a scalar",single-quoted)
134 * SCALAR("another scalar",single-quoted)
136 * SCALAR("yet another scalar",single-quoted)
139 * We have already introduced the SCALAR token above. The following tokens are
140 * used to describe aliases, anchors, tag, and scalars:
145 * SCALAR(value,style)
147 * The following series of examples illustrate the usage of these tokens:
149 * 1. A recursive sequence:
155 * STREAM-START(utf-8)
157 * FLOW-SEQUENCE-START
162 * 2. A tagged scalar:
164 * !!float "3.14" # A good approximation.
168 * STREAM-START(utf-8)
170 * SCALAR("3.14",double-quoted)
173 * 3. Various scalar styles:
175 * --- # Implicit empty plain scalars do not produce tokens.
177 * --- 'a single-quoted scalar'
178 * --- "a double-quoted scalar"
187 * STREAM-START(utf-8)
190 * SCALAR("a plain scalar",plain)
192 * SCALAR("a single-quoted scalar",single-quoted)
194 * SCALAR("a double-quoted scalar",double-quoted)
196 * SCALAR("a literal scalar",literal)
198 * SCALAR("a folded scalar",folded)
201 * Now it's time to review collection-related tokens. We will start with
204 * FLOW-SEQUENCE-START
212 * The tokens FLOW-SEQUENCE-START, FLOW-SEQUENCE-END, FLOW-MAPPING-START, and
213 * FLOW-MAPPING-END represent the indicators '[', ']', '{', and '}'
214 * correspondingly. FLOW-ENTRY represent the ',' indicator. Finally the
215 * indicators '?' and ':', which are used for denoting mapping keys and values,
216 * are represented by the KEY and VALUE tokens.
218 * The following examples show flow collections:
220 * 1. A flow sequence:
222 * [item 1, item 2, item 3]
226 * STREAM-START(utf-8)
227 * FLOW-SEQUENCE-START
228 * SCALAR("item 1",plain)
230 * SCALAR("item 2",plain)
232 * SCALAR("item 3",plain)
239 * a simple key: a value, # Note that the KEY token is produced.
240 * ? a complex key: another value,
245 * STREAM-START(utf-8)
248 * SCALAR("a simple key",plain)
250 * SCALAR("a value",plain)
253 * SCALAR("a complex key",plain)
255 * SCALAR("another value",plain)
260 * A simple key is a key which is not denoted by the '?' indicator. Note that
261 * the Scanner still produce the KEY token whenever it encounters a simple key.
263 * For scanning block collections, the following tokens are used (note that we
264 * repeat KEY and VALUE here):
266 * BLOCK-SEQUENCE-START
267 * BLOCK-MAPPING-START
273 * The tokens BLOCK-SEQUENCE-START and BLOCK-MAPPING-START denote indentation
274 * increase that precedes a block collection (cf. the INDENT token in Python).
275 * The token BLOCK-END denote indentation decrease that ends a block collection
276 * (cf. the DEDENT token in Python). However YAML has some syntax pecularities
277 * that makes detections of these tokens more complex.
279 * The tokens BLOCK-ENTRY, KEY, and VALUE are used to represent the indicators
280 * '-', '?', and ':' correspondingly.
282 * The following examples show how the tokens BLOCK-SEQUENCE-START,
283 * BLOCK-MAPPING-START, and BLOCK-END are emitted by the Scanner:
285 * 1. Block sequences:
298 * STREAM-START(utf-8)
299 * BLOCK-SEQUENCE-START
301 * SCALAR("item 1",plain)
303 * SCALAR("item 2",plain)
305 * BLOCK-SEQUENCE-START
307 * SCALAR("item 3.1",plain)
309 * SCALAR("item 3.2",plain)
312 * BLOCK-MAPPING-START
314 * SCALAR("key 1",plain)
316 * SCALAR("value 1",plain)
318 * SCALAR("key 2",plain)
320 * SCALAR("value 2",plain)
327 * a simple key: a value # The KEY token is produced here.
339 * STREAM-START(utf-8)
340 * BLOCK-MAPPING-START
342 * SCALAR("a simple key",plain)
344 * SCALAR("a value",plain)
346 * SCALAR("a complex key",plain)
348 * SCALAR("another value",plain)
350 * SCALAR("a mapping",plain)
351 * BLOCK-MAPPING-START
353 * SCALAR("key 1",plain)
355 * SCALAR("value 1",plain)
357 * SCALAR("key 2",plain)
359 * SCALAR("value 2",plain)
362 * SCALAR("a sequence",plain)
364 * BLOCK-SEQUENCE-START
366 * SCALAR("item 1",plain)
368 * SCALAR("item 2",plain)
373 * YAML does not always require to start a new block collection from a new
374 * line. If the current line contains only '-', '?', and ':' indicators, a new
375 * block collection may start at the current line. The following examples
376 * illustrate this case:
378 * 1. Collections in a sequence:
389 * STREAM-START(utf-8)
390 * BLOCK-SEQUENCE-START
392 * BLOCK-SEQUENCE-START
394 * SCALAR("item 1",plain)
396 * SCALAR("item 2",plain)
399 * BLOCK-MAPPING-START
401 * SCALAR("key 1",plain)
403 * SCALAR("value 1",plain)
405 * SCALAR("key 2",plain)
407 * SCALAR("value 2",plain)
410 * BLOCK-MAPPING-START
412 * SCALAR("complex key")
414 * SCALAR("complex value")
419 * 2. Collections in a mapping:
430 * STREAM-START(utf-8)
431 * BLOCK-MAPPING-START
433 * SCALAR("a sequence",plain)
435 * BLOCK-SEQUENCE-START
437 * SCALAR("item 1",plain)
439 * SCALAR("item 2",plain)
442 * SCALAR("a mapping",plain)
444 * BLOCK-MAPPING-START
446 * SCALAR("key 1",plain)
448 * SCALAR("value 1",plain)
450 * SCALAR("key 2",plain)
452 * SCALAR("value 2",plain)
457 * YAML also permits non-indented sequences if they are included into a block
458 * mapping. In this case, the token BLOCK-SEQUENCE-START is not produced:
461 * - item 1 # BLOCK-SEQUENCE-START is NOT produced here.
466 * STREAM-START(utf-8)
467 * BLOCK-MAPPING-START
469 * SCALAR("key",plain)
472 * SCALAR("item 1",plain)
474 * SCALAR("item 2",plain)
482 #include <yaml/yaml.h>
487 * Ensure that the buffer contains the required number of characters.
488 * Return 1 on success, 0 on failure (reader error or memory error).
491 #define UPDATE(parser,length) \
492 (parser->unread >= (length) \
494 : yaml_parser_update_buffer(parser, (length)))
497 * Check the octet at the specified position.
500 #define CHECK_AT(parser,octet,offset) \
501 (parser->pointer[offset] == (yaml_char_t)(octet))
504 * Check the current octet in the buffer.
507 #define CHECK(parser,octet) CHECK_AT(parser,(octet),0)
510 * Check if the character at the specified position is an alphabetical
511 * character, a digit, '_', or '-'.
514 #define IS_ALPHA_AT(parser,offset) \
515 ((parser->pointer[offset] >= (yaml_char_t) '0' && \
516 parser->pointer[offset] <= (yaml_char_t) '9') || \
517 (parser->pointer[offset] >= (yaml_char_t) 'A' && \
518 parser->pointer[offset] <= (yaml_char_t) 'Z') || \
519 (parser->pointer[offset] >= (yaml_char_t) 'a' && \
520 parser->pointer[offset] <= (yaml_char_t) 'z') || \
521 parser->pointer[offset] == '_' || \
522 parser->pointer[offset] == '-')
524 #define IS_ALPHA(parser) IS_ALPHA_AT(parser,0)
527 * Check if the character at the specified position is a digit.
530 #define IS_DIGIT_AT(parser,offset) \
531 ((parser->pointer[offset] >= (yaml_char_t) '0' && \
532 parser->pointer[offset] <= (yaml_char_t) '9'))
534 #define IS_DIGIT(parser) IS_DIGIT_AT(parser,0)
537 * Get the value of a digit.
540 #define AS_DIGIT_AT(parser,offset) \
541 (parser->pointer[offset] - (yaml_char_t) '0')
543 #define AS_DIGIT(parser) AS_DIGIT_AT(parser,0)
546 * Check if the character at the specified position is a hex-digit.
549 #define IS_HEX_AT(parser,offset) \
550 ((parser->pointer[offset] >= (yaml_char_t) '0' && \
551 parser->pointer[offset] <= (yaml_char_t) '9') || \
552 (parser->pointer[offset] >= (yaml_char_t) 'A' && \
553 parser->pointer[offset] <= (yaml_char_t) 'F') || \
554 (parser->pointer[offset] >= (yaml_char_t) 'a' && \
555 parser->pointer[offset] <= (yaml_char_t) 'f'))
557 #define IS_HEX(parser) IS_HEX_AT(parser,0)
560 * Get the value of a hex-digit.
563 #define AS_HEX_AT(parser,offset) \
564 ((parser->pointer[offset] >= (yaml_char_t) 'A' && \
565 parser->pointer[offset] <= (yaml_char_t) 'F') ? \
566 (parser->pointer[offset] - (yaml_char_t) 'A' + 10) : \
567 (parser->pointer[offset] >= (yaml_char_t) 'a' && \
568 parser->pointer[offset] <= (yaml_char_t) 'f') ? \
569 (parser->pointer[offset] - (yaml_char_t) 'a' + 10) : \
570 (parser->pointer[offset] - (yaml_char_t) '0'))
572 #define AS_HEX(parser) AS_HEX_AT(parser,0)
575 * Check if the character at the specified position is NUL.
578 #define IS_Z_AT(parser,offset) CHECK_AT(parser,'\0',(offset))
580 #define IS_Z(parser) IS_Z_AT(parser,0)
583 * Check if the character at the specified position is BOM.
586 #define IS_BOM_AT(parser,offset) \
587 (CHECK_AT(parser,'\xEF',(offset)) \
588 && CHECK_AT(parser,'\xBB',(offset)+1) \
589 && CHECK_AT(parser,'\xBF',(offset)+1)) /* BOM (#xFEFF) */
591 #define IS_BOM(parser) IS_BOM_AT(parser,0)
594 * Check if the character at the specified position is space.
597 #define IS_SPACE_AT(parser,offset) CHECK_AT(parser,' ',(offset))
599 #define IS_SPACE(parser) IS_SPACE_AT(parser,0)
602 * Check if the character at the specified position is tab.
605 #define IS_TAB_AT(parser,offset) CHECK_AT(parser,'\t',(offset))
607 #define IS_TAB(parser) IS_TAB_AT(parser,0)
610 * Check if the character at the specified position is blank (space or tab).
613 #define IS_BLANK_AT(parser,offset) \
614 (IS_SPACE_AT(parser,(offset)) || IS_TAB_AT(parser,(offset)))
616 #define IS_BLANK(parser) IS_BLANK_AT(parser,0)
619 * Check if the character at the specified position is a line break.
622 #define IS_BREAK_AT(parser,offset) \
623 (CHECK_AT(parser,'\r',(offset)) /* CR (#xD)*/ \
624 || CHECK_AT(parser,'\n',(offset)) /* LF (#xA) */ \
625 || (CHECK_AT(parser,'\xC2',(offset)) \
626 && CHECK_AT(parser,'\x85',(offset)+1)) /* NEL (#x85) */ \
627 || (CHECK_AT(parser,'\xE2',(offset)) \
628 && CHECK_AT(parser,'\x80',(offset)+1) \
629 && CHECK_AT(parser,'\xA8',(offset)+2)) /* LS (#x2028) */ \
630 || (CHECK_AT(parser,'\xE2',(offset)) \
631 && CHECK_AT(parser,'\x80',(offset)+1) \
632 && CHECK_AT(parser,'\xA9',(offset)+2))) /* PS (#x2029) */
634 #define IS_BREAK(parser) IS_BREAK_AT(parser,0)
636 #define IS_CRLF_AT(parser,offset) \
637 (CHECK_AT(parser,'\r',(offset)) && CHECK_AT(parser,'\n',(offset)+1))
639 #define IS_CRLF(parser) IS_CRLF_AT(parser,0)
642 * Check if the character is a line break or NUL.
645 #define IS_BREAKZ_AT(parser,offset) \
646 (IS_BREAK_AT(parser,(offset)) || IS_Z_AT(parser,(offset)))
648 #define IS_BREAKZ(parser) IS_BREAKZ_AT(parser,0)
651 * Check if the character is a line break, space, or NUL.
654 #define IS_SPACEZ_AT(parser,offset) \
655 (IS_SPACE_AT(parser,(offset)) || IS_BREAKZ_AT(parser,(offset)))
657 #define IS_SPACEZ(parser) IS_SPACEZ_AT(parser,0)
660 * Check if the character is a line break, space, tab, or NUL.
663 #define IS_BLANKZ_AT(parser,offset) \
664 (IS_BLANK_AT(parser,(offset)) || IS_BREAKZ_AT(parser,(offset)))
666 #define IS_BLANKZ(parser) IS_BLANKZ_AT(parser,0)
669 * Determine the width of the character.
672 #define WIDTH_AT(parser,offset) \
673 ((parser->pointer[(offset)] & 0x80) == 0x00 ? 1 : \
674 (parser->pointer[(offset)] & 0xE0) == 0xC0 ? 2 : \
675 (parser->pointer[(offset)] & 0xF0) == 0xE0 ? 3 : \
676 (parser->pointer[(offset)] & 0xF8) == 0xF0 ? 4 : 0)
678 #define WIDTH(parser) WIDTH_AT(parser,0)
681 * Advance the buffer pointer.
684 #define FORWARD(parser) \
688 parser->pointer += WIDTH(parser))
690 #define FORWARD_LINE(parser) \
692 (parser->index += 2, \
693 parser->column = 0, \
695 parser->unread -= 2, \
696 parser->pointer += 2) : \
699 parser->column = 0, \
702 parser->pointer += WIDTH(parser)) : 0)
705 * Resize a string if needed.
708 #define RESIZE(parser,string) \
709 ((string).pointer-(string).buffer+5 < (string).size ? 1 : \
710 yaml_parser_resize_string(parser, &(string)))
713 * Copy a character to a string buffer and advance pointers.
716 #define COPY(parser,string) \
717 (((*parser->pointer & 0x80) == 0x00 ? \
718 (*((string).pointer++) = *(parser->pointer++)) : \
719 (*parser->pointer & 0xE0) == 0xC0 ? \
720 (*((string).pointer++) = *(parser->pointer++), \
721 *((string).pointer++) = *(parser->pointer++)) : \
722 (*parser->pointer & 0xF0) == 0xE0 ? \
723 (*((string).pointer++) = *(parser->pointer++), \
724 *((string).pointer++) = *(parser->pointer++), \
725 *((string).pointer++) = *(parser->pointer++)) : \
726 (*parser->pointer & 0xF8) == 0xF0 ? \
727 (*((string).pointer++) = *(parser->pointer++), \
728 *((string).pointer++) = *(parser->pointer++), \
729 *((string).pointer++) = *(parser->pointer++), \
730 *((string).pointer++) = *(parser->pointer++)) : 0), \
736 * Copy a line break character to a string buffer and advance pointers.
739 #define COPY_LINE(parser,string) \
740 ((CHECK_AT(parser,'\r',0) && CHECK_AT(parser,'\n',1)) ? /* CR LF -> LF */ \
741 (*((string).pointer++) = (yaml_char_t) '\n', \
742 parser->pointer += 2, \
743 parser->index += 2, \
744 parser->column = 0, \
746 parser->unread -= 2) : \
747 (CHECK_AT(parser,'\r',0) || CHECK_AT(parser,'\n',0)) ? /* CR|LF -> LF */ \
748 (*((string).pointer++) = (yaml_char_t) '\n', \
749 parser->pointer ++, \
751 parser->column = 0, \
753 parser->unread --) : \
754 (CHECK_AT(parser,'\xC2',0) && CHECK_AT(parser,'\x85',1)) ? /* NEL -> LF */ \
755 (*((string).pointer++) = (yaml_char_t) '\n', \
756 parser->pointer += 2, \
758 parser->column = 0, \
760 parser->unread --) : \
761 (CHECK_AT(parser,'\xE2',0) && \
762 CHECK_AT(parser,'\x80',1) && \
763 (CHECK_AT(parser,'\xA8',2) || \
764 CHECK_AT(parser,'\xA9',2))) ? /* LS|PS -> LS|PS */ \
765 (*((string).pointer++) = *(parser->pointer++), \
766 *((string).pointer++) = *(parser->pointer++), \
767 *((string).pointer++) = *(parser->pointer++), \
769 parser->column = 0, \
771 parser->unread --) : 0)
774 * Append a string to another string and clear the former string.
777 #define JOIN(parser,head_string,tail_string) \
778 (yaml_parser_join_string(parser, &(head_string), &(tail_string)) && \
779 yaml_parser_clear_string(parser, &(tail_string)))
782 * Public API declarations.
785 YAML_DECLARE(yaml_token_t *)
786 yaml_parser_get_token(yaml_parser_t *parser);
788 YAML_DECLARE(yaml_token_t *)
789 yaml_parser_peek_token(yaml_parser_t *parser);
796 yaml_parser_set_scanner_error(yaml_parser_t *parser, const char *context,
797 yaml_mark_t context_mark, const char *problem);
800 yaml_parser_get_mark(yaml_parser_t *parser);
808 yaml_char_t *pointer;
813 yaml_parser_new_string(yaml_parser_t *parser);
816 yaml_parser_resize_string(yaml_parser_t *parser, yaml_string_t *string);
819 yaml_parser_join_string(yaml_parser_t *parser,
820 yaml_string_t *string1, yaml_string_t *string2);
823 yaml_parser_clear_string(yaml_parser_t *parser, yaml_string_t *string);
826 yaml_parser_resize_list(yaml_parser_t *parser, void **buffer, size_t *size,
830 * High-level token API.
834 yaml_parser_fetch_more_tokens(yaml_parser_t *parser);
837 yaml_parser_fetch_next_token(yaml_parser_t *parser);
840 * Potential simple keys.
844 yaml_parser_stale_simple_keys(yaml_parser_t *parser);
847 yaml_parser_save_simple_key(yaml_parser_t *parser);
850 yaml_parser_remove_simple_key(yaml_parser_t *parser);
853 yaml_parser_increase_flow_level(yaml_parser_t *parser);
856 yaml_parser_decrease_flow_level(yaml_parser_t *parser);
859 * Token manipulation.
863 yaml_parser_append_token(yaml_parser_t *parser, yaml_token_t *token);
866 yaml_parser_insert_token(yaml_parser_t *parser,
867 int number, yaml_token_t *token);
870 * Indentation treatment.
874 yaml_parser_roll_indent(yaml_parser_t *parser, int column,
875 int number, yaml_token_type_t type, yaml_mark_t mark);
878 yaml_parser_unroll_indent(yaml_parser_t *parser, int column);
885 yaml_parser_fetch_stream_start(yaml_parser_t *parser);
888 yaml_parser_fetch_stream_end(yaml_parser_t *parser);
891 yaml_parser_fetch_directive(yaml_parser_t *parser);
894 yaml_parser_fetch_document_indicator(yaml_parser_t *parser,
895 yaml_token_type_t type);
898 yaml_parser_fetch_flow_collection_start(yaml_parser_t *parser,
899 yaml_token_type_t type);
902 yaml_parser_fetch_flow_collection_end(yaml_parser_t *parser,
903 yaml_token_type_t type);
906 yaml_parser_fetch_flow_entry(yaml_parser_t *parser);
909 yaml_parser_fetch_block_entry(yaml_parser_t *parser);
912 yaml_parser_fetch_key(yaml_parser_t *parser);
915 yaml_parser_fetch_value(yaml_parser_t *parser);
918 yaml_parser_fetch_anchor(yaml_parser_t *parser, yaml_token_type_t type);
921 yaml_parser_fetch_tag(yaml_parser_t *parser);
924 yaml_parser_fetch_block_scalar(yaml_parser_t *parser, int literal);
927 yaml_parser_fetch_flow_scalar(yaml_parser_t *parser, int single);
930 yaml_parser_fetch_plain_scalar(yaml_parser_t *parser);
937 yaml_parser_scan_to_next_token(yaml_parser_t *parser);
939 static yaml_token_t *
940 yaml_parser_scan_directive(yaml_parser_t *parser);
943 yaml_parser_scan_directive_name(yaml_parser_t *parser,
944 yaml_mark_t start_mark, yaml_char_t **name);
947 yaml_parser_scan_version_directive_value(yaml_parser_t *parser,
948 yaml_mark_t start_mark, int *major, int *minor);
951 yaml_parser_scan_version_directive_number(yaml_parser_t *parser,
952 yaml_mark_t start_mark, int *number);
955 yaml_parser_scan_tag_directive_value(yaml_parser_t *parser,
956 yaml_mark_t mark, yaml_char_t **handle, yaml_char_t **prefix);
958 static yaml_token_t *
959 yaml_parser_scan_anchor(yaml_parser_t *parser,
960 yaml_token_type_t type);
962 static yaml_token_t *
963 yaml_parser_scan_tag(yaml_parser_t *parser);
966 yaml_parser_scan_tag_handle(yaml_parser_t *parser, int directive,
967 yaml_mark_t start_mark, yaml_char_t **handle);
970 yaml_parser_scan_tag_uri(yaml_parser_t *parser, int directive,
971 yaml_char_t *head, yaml_mark_t start_mark, yaml_char_t **uri);
974 yaml_parser_scan_uri_escapes(yaml_parser_t *parser, int directive,
975 yaml_mark_t start_mark, yaml_string_t *string);
977 static yaml_token_t *
978 yaml_parser_scan_block_scalar(yaml_parser_t *parser, int literal);
981 yaml_parser_scan_block_scalar_breaks(yaml_parser_t *parser,
982 int *indent, yaml_string_t *breaks,
983 yaml_mark_t start_mark, yaml_mark_t *end_mark);
985 static yaml_token_t *
986 yaml_parser_scan_flow_scalar(yaml_parser_t *parser, int single);
988 static yaml_token_t *
989 yaml_parser_scan_plain_scalar(yaml_parser_t *parser);
992 * Get the next token and remove it from the tokens queue.
995 YAML_DECLARE(yaml_token_t *)
996 yaml_parser_get_token(yaml_parser_t *parser)
1000 assert(parser); /* Non-NULL parser object is expected. */
1001 assert(!parser->stream_end_produced); /* No tokens after STREAM-END. */
1003 /* Ensure that the tokens queue contains enough tokens. */
1005 if (!yaml_parser_fetch_more_tokens(parser)) return NULL;
1007 /* Fetch the next token from the queue. */
1009 token = parser->tokens[parser->tokens_head];
1011 /* Move the queue head. */
1013 parser->tokens[parser->tokens_head++] = NULL;
1015 parser->tokens_parsed++;
1017 if (token->type == YAML_STREAM_END_TOKEN) {
1018 parser->stream_end_produced = 1;
1025 * Get the next token, but don't remove it from the queue.
1028 YAML_DECLARE(yaml_token_t *)
1029 yaml_parser_peek_token(yaml_parser_t *parser)
1031 assert(parser); /* Non-NULL parser object is expected. */
1032 assert(!parser->stream_end_produced); /* No tokens after STREAM-END. */
1034 /* Ensure that the tokens queue contains enough tokens. */
1036 if (!yaml_parser_fetch_more_tokens(parser)) return NULL;
1038 /* Fetch the next token from the queue. */
1040 return parser->tokens[parser->tokens_head];
1044 * Create a new string.
1047 static yaml_string_t
1048 yaml_parser_new_string(yaml_parser_t *parser)
1050 yaml_string_t string = { NULL, NULL, 0 };
1052 string.buffer = yaml_malloc(YAML_DEFAULT_SIZE);
1053 if (!string.buffer) {
1054 parser->error = YAML_MEMORY_ERROR;
1058 memset(string.buffer, 0, YAML_DEFAULT_SIZE);
1059 string.pointer = string.buffer;
1060 string.size = YAML_DEFAULT_SIZE;
1066 * Double the size of a string.
1070 yaml_parser_resize_string(yaml_parser_t *parser, yaml_string_t *string)
1072 yaml_char_t *new_buffer = yaml_realloc(string->buffer, string->size*2);
1075 yaml_free(string->buffer);
1076 string->buffer = NULL;
1077 string->pointer = NULL;
1079 parser->error = YAML_MEMORY_ERROR;
1083 memset(new_buffer+string->size, 0, string->size);
1085 string->pointer = new_buffer + (string->pointer-string->buffer);
1086 string->buffer = new_buffer;
1093 * Append a string to another string.
1097 yaml_parser_join_string(yaml_parser_t *parser,
1098 yaml_string_t *string1, yaml_string_t *string2)
1100 if (string2->buffer == string2->pointer) return 1;
1102 while (string1->pointer - string1->buffer + string2->pointer - string2->buffer + 1
1104 if (!yaml_parser_resize_string(parser, string1)) return 0;
1107 memcpy(string1->pointer, string2->buffer, string2->pointer-string2->buffer);
1108 string1->pointer += string2->pointer-string2->buffer;
1114 * Fill the string with NULs and move the pointer to the beginning.
1118 yaml_parser_clear_string(yaml_parser_t *parser, yaml_string_t *string)
1120 if (string->buffer == string->pointer) return 1;
1122 memset(string->buffer, 0, string->pointer-string->buffer);
1124 string->pointer = string->buffer;
1134 yaml_parser_resize_list(yaml_parser_t *parser, void **buffer, size_t *size,
1137 void *new_buffer = yaml_realloc(*buffer, item_size*(*size)*2);
1140 parser->error = YAML_MEMORY_ERROR;
1144 memset(new_buffer+item_size*(*size), 0, item_size*(*size));
1146 *buffer = new_buffer;
1153 * Set the scanner error and return 0.
1157 yaml_parser_set_scanner_error(yaml_parser_t *parser, const char *context,
1158 yaml_mark_t context_mark, const char *problem)
1160 parser->error = YAML_SCANNER_ERROR;
1161 parser->context = context;
1162 parser->context_mark = context_mark;
1163 parser->problem = problem;
1164 parser->problem_mark = yaml_parser_get_mark(parser);
1170 * Get the mark for the current buffer position.
1174 yaml_parser_get_mark(yaml_parser_t *parser)
1176 yaml_mark_t mark = { parser->index, parser->line, parser->column };
1183 * Ensure that the tokens queue contains at least one token which can be
1184 * returned to the Parser.
1188 yaml_parser_fetch_more_tokens(yaml_parser_t *parser)
1190 int need_more_tokens;
1193 /* While we need more tokens to fetch, do it. */
1198 * Check if we really need to fetch more tokens.
1201 need_more_tokens = 0;
1203 if (parser->tokens_head == parser->tokens_tail)
1205 /* Queue is empty. */
1207 need_more_tokens = 1;
1211 /* Check if any potential simple key may occupy the head position. */
1213 if (!yaml_parser_stale_simple_keys(parser))
1216 for (k = 0; k <= parser->flow_level; k++) {
1217 yaml_simple_key_t *simple_key = parser->simple_keys[k];
1219 && (simple_key->token_number == parser->tokens_parsed)) {
1220 need_more_tokens = 1;
1226 /* We are finished. */
1228 if (!need_more_tokens)
1231 /* Fetch the next token. */
1233 if (!yaml_parser_fetch_next_token(parser))
1241 * The dispatcher for token fetchers.
1245 yaml_parser_fetch_next_token(yaml_parser_t *parser)
1247 /* Ensure that the buffer is initialized. */
1249 if (!UPDATE(parser, 1))
1252 /* Check if we just started scanning. Fetch STREAM-START then. */
1254 if (!parser->stream_start_produced)
1255 return yaml_parser_fetch_stream_start(parser);
1257 /* Eat whitespaces and comments until we reach the next token. */
1259 if (!yaml_parser_scan_to_next_token(parser))
1262 /* Remove obsolete potential simple keys. */
1264 if (!yaml_parser_stale_simple_keys(parser))
1267 /* Check the indentation level against the current column. */
1269 if (!yaml_parser_unroll_indent(parser, parser->column))
1273 * Ensure that the buffer contains at least 4 characters. 4 is the length
1274 * of the longest indicators ('--- ' and '... ').
1277 if (!UPDATE(parser, 4))
1280 /* Is it the end of the stream? */
1283 return yaml_parser_fetch_stream_end(parser);
1285 /* Is it a directive? */
1287 if (parser->column == 0 && CHECK(parser, '%'))
1288 return yaml_parser_fetch_directive(parser);
1290 /* Is it the document start indicator? */
1292 if (parser->column == 0
1293 && CHECK_AT(parser, '-', 0)
1294 && CHECK_AT(parser, '-', 1)
1295 && CHECK_AT(parser, '-', 2)
1296 && IS_BLANKZ_AT(parser, 3))
1297 return yaml_parser_fetch_document_indicator(parser,
1298 YAML_DOCUMENT_START_TOKEN);
1300 /* Is it the document end indicator? */
1302 if (parser->column == 0
1303 && CHECK_AT(parser, '.', 0)
1304 && CHECK_AT(parser, '.', 1)
1305 && CHECK_AT(parser, '.', 2)
1306 && IS_BLANKZ_AT(parser, 3))
1307 return yaml_parser_fetch_document_indicator(parser,
1308 YAML_DOCUMENT_END_TOKEN);
1310 /* Is it the flow sequence start indicator? */
1312 if (CHECK(parser, '['))
1313 return yaml_parser_fetch_flow_collection_start(parser,
1314 YAML_FLOW_SEQUENCE_START_TOKEN);
1316 /* Is it the flow mapping start indicator? */
1318 if (CHECK(parser, '{'))
1319 return yaml_parser_fetch_flow_collection_start(parser,
1320 YAML_FLOW_MAPPING_START_TOKEN);
1322 /* Is it the flow sequence end indicator? */
1324 if (CHECK(parser, ']'))
1325 return yaml_parser_fetch_flow_collection_end(parser,
1326 YAML_FLOW_SEQUENCE_END_TOKEN);
1328 /* Is it the flow mapping end indicator? */
1330 if (CHECK(parser, '}'))
1331 return yaml_parser_fetch_flow_collection_end(parser,
1332 YAML_FLOW_MAPPING_END_TOKEN);
1334 /* Is it the flow entry indicator? */
1336 if (CHECK(parser, ','))
1337 return yaml_parser_fetch_flow_entry(parser);
1339 /* Is it the block entry indicator? */
1341 if (CHECK(parser, '-') && IS_BLANKZ_AT(parser, 1))
1342 return yaml_parser_fetch_block_entry(parser);
1344 /* Is it the key indicator? */
1346 if (CHECK(parser, '?') && (parser->flow_level || IS_BLANKZ_AT(parser, 1)))
1347 return yaml_parser_fetch_key(parser);
1349 /* Is it the value indicator? */
1351 if (CHECK(parser, ':') && (parser->flow_level || IS_BLANKZ_AT(parser, 1)))
1352 return yaml_parser_fetch_value(parser);
1354 /* Is it an alias? */
1356 if (CHECK(parser, '*'))
1357 return yaml_parser_fetch_anchor(parser, YAML_ALIAS_TOKEN);
1359 /* Is it an anchor? */
1361 if (CHECK(parser, '&'))
1362 return yaml_parser_fetch_anchor(parser, YAML_ANCHOR_TOKEN);
1366 if (CHECK(parser, '!'))
1367 return yaml_parser_fetch_tag(parser);
1369 /* Is it a literal scalar? */
1371 if (CHECK(parser, '|') && !parser->flow_level)
1372 return yaml_parser_fetch_block_scalar(parser, 1);
1374 /* Is it a folded scalar? */
1376 if (CHECK(parser, '>') && !parser->flow_level)
1377 return yaml_parser_fetch_block_scalar(parser, 0);
1379 /* Is it a single-quoted scalar? */
1381 if (CHECK(parser, '\''))
1382 return yaml_parser_fetch_flow_scalar(parser, 1);
1384 /* Is it a double-quoted scalar? */
1386 if (CHECK(parser, '"'))
1387 return yaml_parser_fetch_flow_scalar(parser, 0);
1390 * Is it a plain scalar?
1392 * A plain scalar may start with any non-blank characters except
1394 * '-', '?', ':', ',', '[', ']', '{', '}',
1395 * '#', '&', '*', '!', '|', '>', '\'', '\"',
1398 * In the block context (and, for the '-' indicator, in the flow context
1399 * too), it may also start with the characters
1403 * if it is followed by a non-space character.
1405 * The last rule is more restrictive than the specification requires.
1408 if (!(IS_BLANKZ(parser) || CHECK(parser, '-') || CHECK(parser, '?')
1409 || CHECK(parser, ':') || CHECK(parser, ',') || CHECK(parser, '[')
1410 || CHECK(parser, ']') || CHECK(parser, '{') || CHECK(parser, '}')
1411 || CHECK(parser, '#') || CHECK(parser, '&') || CHECK(parser, '*')
1412 || CHECK(parser, '!') || CHECK(parser, '|') || CHECK(parser, '>')
1413 || CHECK(parser, '\'') || CHECK(parser, '"') || CHECK(parser, '%')
1414 || CHECK(parser, '@') || CHECK(parser, '`')) ||
1415 (CHECK(parser, '-') && !IS_BLANK_AT(parser, 1)) ||
1416 (!parser->flow_level &&
1417 (CHECK(parser, '?') || CHECK(parser, ':')) && !IS_BLANKZ_AT(parser, 1)))
1418 return yaml_parser_fetch_plain_scalar(parser);
1421 * If we don't determine the token type so far, it is an error.
1424 return yaml_parser_set_scanner_error(parser, "while scanning for the next token",
1425 yaml_parser_get_mark(parser), "found character that cannot start any token");
1429 * Check the list of potential simple keys and remove the positions that
1430 * cannot contain simple keys anymore.
1434 yaml_parser_stale_simple_keys(yaml_parser_t *parser)
1438 /* Check for a potential simple key for each flow level. */
1440 for (level = 0; level <= parser->flow_level; level++)
1442 yaml_simple_key_t *simple_key = parser->simple_keys[level];
1445 * The specification requires that a simple key
1447 * - is limited to a single line,
1448 * - is shorter than 1024 characters.
1451 if (simple_key && (simple_key->line < parser->line ||
1452 simple_key->index+1024 < parser->index)) {
1454 /* Check if the potential simple key to be removed is required. */
1456 if (simple_key->required) {
1457 return yaml_parser_set_scanner_error(parser,
1458 "while scanning a simple key", simple_key->mark,
1459 "could not found expected ':'");
1462 yaml_free(simple_key);
1463 parser->simple_keys[level] = NULL;
1471 * Check if a simple key may start at the current position and add it if
1476 yaml_parser_save_simple_key(yaml_parser_t *parser)
1479 * A simple key is required at the current position if the scanner is in
1480 * the block context and the current column coincides with the indentation
1484 int required = (!parser->flow_level && parser->indent == parser->column);
1487 * A simple key is required only when it is the first token in the current
1488 * line. Therefore it is always allowed. But we add a check anyway.
1491 assert(parser->simple_key_allowed || !required); /* Impossible. */
1494 * If the current position may start a simple key, save it.
1497 if (parser->simple_key_allowed)
1499 yaml_simple_key_t simple_key = { required,
1500 parser->tokens_parsed + parser->tokens_tail - parser->tokens_head,
1501 parser->index, parser->line, parser->column,
1502 yaml_parser_get_mark(parser) };
1504 if (!yaml_parser_remove_simple_key(parser)) return 0;
1506 parser->simple_keys[parser->flow_level] =
1507 yaml_malloc(sizeof(yaml_simple_key_t));
1508 if (!parser->simple_keys[parser->flow_level]) {
1509 parser->error = YAML_MEMORY_ERROR;
1513 *(parser->simple_keys[parser->flow_level]) = simple_key;
1520 * Remove a potential simple key at the current flow level.
1524 yaml_parser_remove_simple_key(yaml_parser_t *parser)
1526 yaml_simple_key_t *simple_key = parser->simple_keys[parser->flow_level];
1530 /* If the key is required, it is an error. */
1532 if (simple_key->required) {
1533 return yaml_parser_set_scanner_error(parser,
1534 "while scanning a simple key", simple_key->mark,
1535 "could not found expected ':'");
1538 /* Remove the key from the list. */
1540 yaml_free(simple_key);
1541 parser->simple_keys[parser->flow_level] = NULL;
1548 * Increase the flow level and resize the simple key list if needed.
1552 yaml_parser_increase_flow_level(yaml_parser_t *parser)
1554 /* Check if we need to resize the list. */
1556 if (parser->flow_level == parser->simple_keys_size-1) {
1557 if (!yaml_parser_resize_list(parser, (void **)&parser->simple_keys,
1558 &parser->simple_keys_size, sizeof(yaml_simple_key_t *)))
1562 /* Increase the flow level and reset the simple key. */
1564 parser->simple_keys[++parser->flow_level] = NULL;
1570 * Decrease the flow level.
1574 yaml_parser_decrease_flow_level(yaml_parser_t *parser)
1576 assert(parser->flow_level); /* Greater than 0. */
1577 assert(!parser->simple_keys[parser->flow_level]); /* Must be removed. */
1579 parser->flow_level --;
1585 * Add a token to the tail of the tokens queue.
1589 yaml_parser_append_token(yaml_parser_t *parser, yaml_token_t *token)
1591 return yaml_parser_insert_token(parser, -1, token);
1595 * Insert the token into the tokens queue. The number parameter is the
1596 * ordinal number of the token. If the number is equal to -1, add the token
1597 * to the tail of the queue.
1601 yaml_parser_insert_token(yaml_parser_t *parser,
1602 int number, yaml_token_t *token)
1604 /* The index of the token in the queue. */
1606 int index = (number == -1)
1607 ? parser->tokens_tail - parser->tokens_head
1608 : number - parser->tokens_parsed;
1610 assert(index >= 0 && index <= (parser->tokens_tail-parser->tokens_head));
1612 /* Check if we need to resize the queue. */
1614 if (parser->tokens_head == 0 && parser->tokens_tail == parser->tokens_size) {
1615 if (!yaml_parser_resize_list(parser, (void **)&parser->tokens,
1616 &parser->tokens_size, sizeof(yaml_token_t *)))
1620 /* Check if we need to move the queue to the beginning of the buffer. */
1622 if (parser->tokens_tail == parser->tokens_size)
1624 if (parser->tokens_head < parser->tokens_tail) {
1625 memmove(parser->tokens, parser->tokens+parser->tokens_head,
1626 sizeof(yaml_token_t *)*(parser->tokens_tail-parser->tokens_head));
1628 parser->tokens_tail -= parser->tokens_head;
1629 parser->tokens_head = 0;
1632 /* Check if we need to free space within the queue. */
1634 if (index < (parser->tokens_tail-parser->tokens_head)) {
1635 memmove(parser->tokens+parser->tokens_head+index+1,
1636 parser->tokens+parser->tokens_head+index,
1637 sizeof(yaml_token_t *)*(parser->tokens_tail-parser->tokens_head-index));
1640 /* Insert the token. */
1642 parser->tokens[parser->tokens_head+index] = token;
1643 parser->tokens_tail ++;
1649 * Push the current indentation level to the stack and set the new level
1650 * the current column is greater than the indentation level. In this case,
1651 * append or insert the specified token into the token queue.
1656 yaml_parser_roll_indent(yaml_parser_t *parser, int column,
1657 int number, yaml_token_type_t type, yaml_mark_t mark)
1659 yaml_token_t *token;
1661 /* In the flow context, do nothing. */
1663 if (parser->flow_level)
1666 if (parser->indent < column)
1668 /* Check if we need to expand the indents stack. */
1670 if (parser->indents_length == parser->indents_size) {
1671 if (!yaml_parser_resize_list(parser, (void **)&parser->indents,
1672 &parser->indents_size, sizeof(int)))
1677 * Push the current indentation level to the stack and set the new
1678 * indentation level.
1681 parser->indents[parser->indents_length++] = parser->indent;
1682 parser->indent = column;
1684 /* Create a token. */
1686 token = yaml_token_new(type, mark, mark);
1688 parser->error = YAML_MEMORY_ERROR;
1692 /* Insert the token into the queue. */
1694 if (!yaml_parser_insert_token(parser, number, token)) {
1695 yaml_token_delete(token);
1704 * Pop indentation levels from the indents stack until the current level
1705 * becomes less or equal to the column. For each intendation level, append
1706 * the BLOCK-END token.
1711 yaml_parser_unroll_indent(yaml_parser_t *parser, int column)
1713 yaml_token_t *token;
1715 /* In the flow context, do nothing. */
1717 if (parser->flow_level)
1720 /* Loop through the intendation levels in the stack. */
1722 while (parser->indent > column)
1724 yaml_mark_t mark = yaml_parser_get_mark(parser);
1726 /* Create a token. */
1728 token = yaml_token_new(YAML_BLOCK_END_TOKEN, mark, mark);
1730 parser->error = YAML_MEMORY_ERROR;
1734 /* Append the token to the queue. */
1736 if (!yaml_parser_append_token(parser, token)) {
1737 yaml_token_delete(token);
1741 /* Pop the indentation level. */
1743 assert(parser->indents_length); /* Non-empty stack expected. */
1745 parser->indent = parser->indents[--parser->indents_length];
1752 * Initialize the scanner and produce the STREAM-START token.
1756 yaml_parser_fetch_stream_start(yaml_parser_t *parser)
1758 yaml_mark_t mark = yaml_parser_get_mark(parser);
1759 yaml_token_t *token;
1761 /* Set the initial indentation. */
1763 parser->indent = -1;
1765 /* A simple key is allowed at the beginning of the stream. */
1767 parser->simple_key_allowed = 1;
1769 /* We have started. */
1771 parser->stream_start_produced = 1;
1773 /* Create the STREAM-START token. */
1775 token = yaml_stream_start_token_new(parser->encoding, mark, mark);
1777 parser->error = YAML_MEMORY_ERROR;
1781 /* Append the token to the queue. */
1783 if (!yaml_parser_append_token(parser, token)) {
1784 yaml_token_delete(token);
1792 * Produce the STREAM-END token and shut down the scanner.
1796 yaml_parser_fetch_stream_end(yaml_parser_t *parser)
1798 yaml_mark_t mark = yaml_parser_get_mark(parser);
1799 yaml_token_t *token;
1801 /* Reset the indentation level. */
1803 if (!yaml_parser_unroll_indent(parser, -1))
1806 /* Reset simple keys. */
1808 if (!yaml_parser_remove_simple_key(parser))
1811 parser->simple_key_allowed = 0;
1813 /* Create the STREAM-END token. */
1815 token = yaml_stream_end_token_new(mark, mark);
1817 parser->error = YAML_MEMORY_ERROR;
1821 /* Append the token to the queue. */
1823 if (!yaml_parser_append_token(parser, token)) {
1824 yaml_token_delete(token);
1832 * Produce the YAML-DIRECTIVE or TAG-DIRECTIVE token.
1836 yaml_parser_fetch_directive(yaml_parser_t *parser)
1838 yaml_token_t *token;
1840 /* Reset the indentation level. */
1842 if (!yaml_parser_unroll_indent(parser, -1))
1845 /* Reset simple keys. */
1847 if (!yaml_parser_remove_simple_key(parser))
1850 parser->simple_key_allowed = 0;
1852 /* Create the YAML-DIRECTIVE or TAG-DIRECTIVE token. */
1854 token = yaml_parser_scan_directive(parser);
1855 if (!token) return 0;
1857 /* Append the token to the queue. */
1859 if (!yaml_parser_append_token(parser, token)) {
1860 yaml_token_delete(token);
1868 * Produce the DOCUMENT-START or DOCUMENT-END token.
1872 yaml_parser_fetch_document_indicator(yaml_parser_t *parser,
1873 yaml_token_type_t type)
1875 yaml_mark_t start_mark, end_mark;
1876 yaml_token_t *token;
1878 /* Reset the indentation level. */
1880 if (!yaml_parser_unroll_indent(parser, -1))
1883 /* Reset simple keys. */
1885 if (!yaml_parser_remove_simple_key(parser))
1888 parser->simple_key_allowed = 0;
1890 /* Consume the token. */
1892 start_mark = yaml_parser_get_mark(parser);
1898 end_mark = yaml_parser_get_mark(parser);
1900 /* Create the DOCUMENT-START or DOCUMENT-END token. */
1902 token = yaml_token_new(type, start_mark, end_mark);
1904 parser->error = YAML_MEMORY_ERROR;
1908 /* Append the token to the queue. */
1910 if (!yaml_parser_append_token(parser, token)) {
1911 yaml_token_delete(token);
1919 * Produce the FLOW-SEQUENCE-START or FLOW-MAPPING-START token.
1923 yaml_parser_fetch_flow_collection_start(yaml_parser_t *parser,
1924 yaml_token_type_t type)
1926 yaml_mark_t start_mark, end_mark;
1927 yaml_token_t *token;
1929 /* The indicators '[' and '{' may start a simple key. */
1931 if (!yaml_parser_save_simple_key(parser))
1934 /* Increase the flow level. */
1936 if (!yaml_parser_increase_flow_level(parser))
1939 /* A simple key may follow the indicators '[' and '{'. */
1941 parser->simple_key_allowed = 1;
1943 /* Consume the token. */
1945 start_mark = yaml_parser_get_mark(parser);
1947 end_mark = yaml_parser_get_mark(parser);
1949 /* Create the FLOW-SEQUENCE-START of FLOW-MAPPING-START token. */
1951 token = yaml_token_new(type, start_mark, end_mark);
1953 parser->error = YAML_MEMORY_ERROR;
1957 /* Append the token to the queue. */
1959 if (!yaml_parser_append_token(parser, token)) {
1960 yaml_token_delete(token);
1968 * Produce the FLOW-SEQUENCE-END or FLOW-MAPPING-END token.
1972 yaml_parser_fetch_flow_collection_end(yaml_parser_t *parser,
1973 yaml_token_type_t type)
1975 yaml_mark_t start_mark, end_mark;
1976 yaml_token_t *token;
1978 /* Reset any potential simple key on the current flow level. */
1980 if (!yaml_parser_remove_simple_key(parser))
1983 /* Decrease the flow level. */
1985 if (!yaml_parser_decrease_flow_level(parser))
1988 /* No simple keys after the indicators ']' and '}'. */
1990 parser->simple_key_allowed = 0;
1992 /* Consume the token. */
1994 start_mark = yaml_parser_get_mark(parser);
1996 end_mark = yaml_parser_get_mark(parser);
1998 /* Create the FLOW-SEQUENCE-END of FLOW-MAPPING-END token. */
2000 token = yaml_token_new(type, start_mark, end_mark);
2002 parser->error = YAML_MEMORY_ERROR;
2006 /* Append the token to the queue. */
2008 if (!yaml_parser_append_token(parser, token)) {
2009 yaml_token_delete(token);
2017 * Produce the FLOW-ENTRY token.
2021 yaml_parser_fetch_flow_entry(yaml_parser_t *parser)
2023 yaml_mark_t start_mark, end_mark;
2024 yaml_token_t *token;
2026 /* Reset any potential simple keys on the current flow level. */
2028 if (!yaml_parser_remove_simple_key(parser))
2031 /* Simple keys are allowed after ','. */
2033 parser->simple_key_allowed = 1;
2035 /* Consume the token. */
2037 start_mark = yaml_parser_get_mark(parser);
2039 end_mark = yaml_parser_get_mark(parser);
2041 /* Create the FLOW-ENTRY token. */
2043 token = yaml_token_new(YAML_FLOW_ENTRY_TOKEN, start_mark, end_mark);
2045 parser->error = YAML_MEMORY_ERROR;
2049 /* Append the token to the queue. */
2051 if (!yaml_parser_append_token(parser, token)) {
2052 yaml_token_delete(token);
2060 * Produce the BLOCK-ENTRY token.
2064 yaml_parser_fetch_block_entry(yaml_parser_t *parser)
2066 yaml_mark_t start_mark, end_mark;
2067 yaml_token_t *token;
2069 /* Check if the scanner is in the block context. */
2071 if (!parser->flow_level)
2073 /* Check if we are allowed to start a new entry. */
2075 if (!parser->simple_key_allowed) {
2076 return yaml_parser_set_scanner_error(parser, NULL,
2077 yaml_parser_get_mark(parser),
2078 "block sequence entries are not allowed in this context");
2081 /* Add the BLOCK-SEQUENCE-START token if needed. */
2083 if (!yaml_parser_roll_indent(parser, parser->column, -1,
2084 YAML_BLOCK_SEQUENCE_START_TOKEN, yaml_parser_get_mark(parser)))
2090 * It is an error for the '-' indicator to occur in the flow context,
2091 * but we let the Parser detect and report about it because the Parser
2092 * is able to point to the context.
2096 /* Reset any potential simple keys on the current flow level. */
2098 if (!yaml_parser_remove_simple_key(parser))
2101 /* Simple keys are allowed after '-'. */
2103 parser->simple_key_allowed = 1;
2105 /* Consume the token. */
2107 start_mark = yaml_parser_get_mark(parser);
2109 end_mark = yaml_parser_get_mark(parser);
2111 /* Create the BLOCK-ENTRY token. */
2113 token = yaml_token_new(YAML_BLOCK_ENTRY_TOKEN, start_mark, end_mark);
2115 parser->error = YAML_MEMORY_ERROR;
2119 /* Append the token to the queue. */
2121 if (!yaml_parser_append_token(parser, token)) {
2122 yaml_token_delete(token);
2130 * Produce the KEY token.
2134 yaml_parser_fetch_key(yaml_parser_t *parser)
2136 yaml_mark_t start_mark, end_mark;
2137 yaml_token_t *token;
2139 /* In the block context, additional checks are required. */
2141 if (!parser->flow_level)
2143 /* Check if we are allowed to start a new key (not nessesary simple). */
2145 if (!parser->simple_key_allowed) {
2146 return yaml_parser_set_scanner_error(parser, NULL,
2147 yaml_parser_get_mark(parser),
2148 "mapping keys are not allowed in this context");
2151 /* Add the BLOCK-MAPPING-START token if needed. */
2153 if (!yaml_parser_roll_indent(parser, parser->column, -1,
2154 YAML_BLOCK_MAPPING_START_TOKEN, yaml_parser_get_mark(parser)))
2158 /* Reset any potential simple keys on the current flow level. */
2160 if (!yaml_parser_remove_simple_key(parser))
2163 /* Simple keys are allowed after '?' in the block context. */
2165 parser->simple_key_allowed = (!parser->flow_level);
2167 /* Consume the token. */
2169 start_mark = yaml_parser_get_mark(parser);
2171 end_mark = yaml_parser_get_mark(parser);
2173 /* Create the KEY token. */
2175 token = yaml_token_new(YAML_KEY_TOKEN, start_mark, end_mark);
2177 parser->error = YAML_MEMORY_ERROR;
2181 /* Append the token to the queue. */
2183 if (!yaml_parser_append_token(parser, token)) {
2184 yaml_token_delete(token);
2192 * Produce the VALUE token.
2196 yaml_parser_fetch_value(yaml_parser_t *parser)
2198 yaml_mark_t start_mark, end_mark;
2199 yaml_token_t *token;
2201 /* Have we found a simple key? */
2203 if (parser->simple_keys[parser->flow_level])
2205 yaml_simple_key_t *simple_key = parser->simple_keys[parser->flow_level];
2207 /* Create the KEY token. */
2209 token = yaml_token_new(YAML_KEY_TOKEN, simple_key->mark, simple_key->mark);
2211 parser->error = YAML_MEMORY_ERROR;
2215 /* Insert the token into the queue. */
2217 if (!yaml_parser_insert_token(parser, simple_key->token_number, token)) {
2218 yaml_token_delete(token);
2222 /* In the block context, we may need to add the BLOCK-MAPPING-START token. */
2224 if (!yaml_parser_roll_indent(parser, simple_key->column,
2225 simple_key->token_number,
2226 YAML_BLOCK_MAPPING_START_TOKEN, simple_key->mark))
2229 /* Remove the simple key from the list. */
2231 yaml_free(simple_key);
2232 parser->simple_keys[parser->flow_level] = NULL;
2234 /* A simple key cannot follow another simple key. */
2236 parser->simple_key_allowed = 0;
2240 /* The ':' indicator follows a complex key. */
2242 /* In the block context, extra checks are required. */
2244 if (!parser->flow_level)
2246 /* Check if we are allowed to start a complex value. */
2248 if (!parser->simple_key_allowed) {
2249 return yaml_parser_set_scanner_error(parser, NULL,
2250 yaml_parser_get_mark(parser),
2251 "mapping values are not allowed in this context");
2254 /* Add the BLOCK-MAPPING-START token if needed. */
2256 if (!yaml_parser_roll_indent(parser, parser->column, -1,
2257 YAML_BLOCK_MAPPING_START_TOKEN, yaml_parser_get_mark(parser)))
2261 /* Simple keys after ':' are allowed in the block context. */
2263 parser->simple_key_allowed = (!parser->flow_level);
2266 /* Consume the token. */
2268 start_mark = yaml_parser_get_mark(parser);
2270 end_mark = yaml_parser_get_mark(parser);
2272 /* Create the VALUE token. */
2274 token = yaml_token_new(YAML_VALUE_TOKEN, start_mark, end_mark);
2276 parser->error = YAML_MEMORY_ERROR;
2280 /* Append the token to the queue. */
2282 if (!yaml_parser_append_token(parser, token)) {
2283 yaml_token_delete(token);
2291 * Produce the ALIAS or ANCHOR token.
2295 yaml_parser_fetch_anchor(yaml_parser_t *parser, yaml_token_type_t type)
2297 yaml_token_t *token;
2299 /* An anchor or an alias could be a simple key. */
2301 if (!yaml_parser_save_simple_key(parser))
2304 /* A simple key cannot follow an anchor or an alias. */
2306 parser->simple_key_allowed = 0;
2308 /* Create the ALIAS or ANCHOR token. */
2310 token = yaml_parser_scan_anchor(parser, type);
2311 if (!token) return 0;
2313 /* Append the token to the queue. */
2315 if (!yaml_parser_append_token(parser, token)) {
2316 yaml_token_delete(token);
2324 * Produce the TAG token.
2328 yaml_parser_fetch_tag(yaml_parser_t *parser)
2330 yaml_token_t *token;
2332 /* A tag could be a simple key. */
2334 if (!yaml_parser_save_simple_key(parser))
2337 /* A simple key cannot follow a tag. */
2339 parser->simple_key_allowed = 0;
2341 /* Create the TAG token. */
2343 token = yaml_parser_scan_tag(parser);
2344 if (!token) return 0;
2346 /* Append the token to the queue. */
2348 if (!yaml_parser_append_token(parser, token)) {
2349 yaml_token_delete(token);
2357 * Produce the SCALAR(...,literal) or SCALAR(...,folded) tokens.
2361 yaml_parser_fetch_block_scalar(yaml_parser_t *parser, int literal)
2363 yaml_token_t *token;
2365 /* Remove any potential simple keys. */
2367 if (!yaml_parser_remove_simple_key(parser))
2370 /* A simple key may follow a block scalar. */
2372 parser->simple_key_allowed = 1;
2374 /* Create the SCALAR token. */
2376 token = yaml_parser_scan_block_scalar(parser, literal);
2377 if (!token) return 0;
2379 /* Append the token to the queue. */
2381 if (!yaml_parser_append_token(parser, token)) {
2382 yaml_token_delete(token);
2390 * Produce the SCALAR(...,single-quoted) or SCALAR(...,double-quoted) tokens.
2394 yaml_parser_fetch_flow_scalar(yaml_parser_t *parser, int single)
2396 yaml_token_t *token;
2398 /* A plain scalar could be a simple key. */
2400 if (!yaml_parser_save_simple_key(parser))
2403 /* A simple key cannot follow a flow scalar. */
2405 parser->simple_key_allowed = 0;
2407 /* Create the SCALAR token. */
2409 token = yaml_parser_scan_flow_scalar(parser, single);
2410 if (!token) return 0;
2412 /* Append the token to the queue. */
2414 if (!yaml_parser_append_token(parser, token)) {
2415 yaml_token_delete(token);
2423 * Produce the SCALAR(...,plain) token.
2427 yaml_parser_fetch_plain_scalar(yaml_parser_t *parser)
2429 yaml_token_t *token;
2431 /* A plain scalar could be a simple key. */
2433 if (!yaml_parser_save_simple_key(parser))
2436 /* A simple key cannot follow a flow scalar. */
2438 parser->simple_key_allowed = 0;
2440 /* Create the SCALAR token. */
2442 token = yaml_parser_scan_plain_scalar(parser);
2443 if (!token) return 0;
2445 /* Append the token to the queue. */
2447 if (!yaml_parser_append_token(parser, token)) {
2448 yaml_token_delete(token);
2456 * Eat whitespaces and comments until the next token is found.
2460 yaml_parser_scan_to_next_token(yaml_parser_t *parser)
2462 /* Until the next token is not found. */
2466 /* Allow the BOM mark to start a line. */
2468 if (!UPDATE(parser, 1)) return 0;
2470 if (parser->column == 0 && IS_BOM(parser))
2478 * - in the flow context;
2479 * - in the block context, but not at the beginning of the line or
2480 * after '-', '?', or ':' (complex value).
2483 if (!UPDATE(parser, 1)) return 0;
2485 while (CHECK(parser,' ') ||
2486 ((parser->flow_level || !parser->simple_key_allowed) &&
2487 CHECK(parser, '\t'))) {
2489 if (!UPDATE(parser, 1)) return 0;
2492 /* Eat a comment until a line break. */
2494 if (CHECK(parser, '#')) {
2495 while (!IS_BREAKZ(parser)) {
2497 if (!UPDATE(parser, 1)) return 0;
2501 /* If it is a line break, eat it. */
2503 if (IS_BREAK(parser))
2505 if (!UPDATE(parser, 2)) return 0;
2506 FORWARD_LINE(parser);
2508 /* In the block context, a new line may start a simple key. */
2510 if (!parser->flow_level) {
2511 parser->simple_key_allowed = 1;
2516 /* We have found a token. */
2526 * Scan a YAML-DIRECTIVE or TAG-DIRECTIVE token.
2529 * %YAML 1.1 # a comment \n
2530 * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2531 * %TAG !yaml! tag:yaml.org,2002: \n
2532 * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2535 static yaml_token_t *
2536 yaml_parser_scan_directive(yaml_parser_t *parser)
2538 yaml_mark_t start_mark, end_mark;
2539 yaml_char_t *name = NULL;
2541 yaml_char_t *handle = NULL, *prefix = NULL;
2542 yaml_token_t *token = NULL;
2546 start_mark = yaml_parser_get_mark(parser);
2550 /* Scan the directive name. */
2552 if (!yaml_parser_scan_directive_name(parser, start_mark, &name))
2555 /* Is it a YAML directive? */
2557 if (strcmp((char *)name, "YAML") == 0)
2559 /* Scan the VERSION directive value. */
2561 if (!yaml_parser_scan_version_directive_value(parser, start_mark,
2565 end_mark = yaml_parser_get_mark(parser);
2567 /* Create a VERSION-DIRECTIVE token. */
2569 token = yaml_version_directive_token_new(major, minor,
2570 start_mark, end_mark);
2572 parser->error = YAML_MEMORY_ERROR;
2577 /* Is it a TAG directive? */
2579 else if (strcmp((char *)name, "TAG") == 0)
2581 /* Scan the TAG directive value. */
2583 if (!yaml_parser_scan_tag_directive_value(parser, start_mark,
2587 end_mark = yaml_parser_get_mark(parser);
2589 /* Create a TAG-DIRECTIVE token. */
2591 token = yaml_tag_directive_token_new(handle, prefix,
2592 start_mark, end_mark);
2594 parser->error = YAML_MEMORY_ERROR;
2599 /* Unknown directive. */
2603 yaml_parser_set_scanner_error(parser, "while scanning a directive",
2604 start_mark, "found uknown directive name");
2608 /* Eat the rest of the line including any comments. */
2610 while (IS_BLANK(parser)) {
2612 if (!UPDATE(parser, 1)) goto error;
2615 if (CHECK(parser, '#')) {
2616 while (!IS_BREAKZ(parser)) {
2618 if (!UPDATE(parser, 1)) goto error;
2622 /* Check if we are at the end of the line. */
2624 if (!IS_BREAKZ(parser)) {
2625 yaml_parser_set_scanner_error(parser, "while scanning a directive",
2626 start_mark, "did not found expected comment or line break");
2630 /* Eat a line break. */
2632 if (IS_BREAK(parser)) {
2633 if (!UPDATE(parser, 2)) goto error;
2634 FORWARD_LINE(parser);
2650 * Scan the directive name.
2653 * %YAML 1.1 # a comment \n
2655 * %TAG !yaml! tag:yaml.org,2002: \n
2660 yaml_parser_scan_directive_name(yaml_parser_t *parser,
2661 yaml_mark_t start_mark, yaml_char_t **name)
2663 yaml_string_t string = yaml_parser_new_string(parser);
2665 if (!string.buffer) goto error;
2667 /* Consume the directive name. */
2669 if (!UPDATE(parser, 1)) goto error;
2671 while (IS_ALPHA(parser))
2673 if (!RESIZE(parser, string)) goto error;
2674 COPY(parser, string);
2675 if (!UPDATE(parser, 1)) goto error;
2678 /* Check if the name is empty. */
2680 if (string.buffer == string.pointer) {
2681 yaml_parser_set_scanner_error(parser, "while scanning a directive",
2682 start_mark, "cannot found expected directive name");
2686 /* Check for an blank character after the name. */
2688 if (!IS_BLANKZ(parser)) {
2689 yaml_parser_set_scanner_error(parser, "while scanning a directive",
2690 start_mark, "found unexpected non-alphabetical character");
2694 *name = string.buffer;
2699 yaml_free(string.buffer);
2704 * Scan the value of VERSION-DIRECTIVE.
2707 * %YAML 1.1 # a comment \n
2712 yaml_parser_scan_version_directive_value(yaml_parser_t *parser,
2713 yaml_mark_t start_mark, int *major, int *minor)
2715 /* Eat whitespaces. */
2717 if (!UPDATE(parser, 1)) return 0;
2719 while (IS_BLANK(parser)) {
2721 if (!UPDATE(parser, 1)) return 0;
2724 /* Consume the major version number. */
2726 if (!yaml_parser_scan_version_directive_number(parser, start_mark, major))
2731 if (!CHECK(parser, '.')) {
2732 return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
2733 start_mark, "did not find expected digit or '.' character");
2738 /* Consume the minor version number. */
2740 if (!yaml_parser_scan_version_directive_number(parser, start_mark, minor))
2744 #define MAX_NUMBER_LENGTH 9
2747 * Scan the version number of VERSION-DIRECTIVE.
2750 * %YAML 1.1 # a comment \n
2752 * %YAML 1.1 # a comment \n
2757 yaml_parser_scan_version_directive_number(yaml_parser_t *parser,
2758 yaml_mark_t start_mark, int *number)
2763 /* Repeat while the next character is digit. */
2765 if (!UPDATE(parser, 1)) return 0;
2767 while (IS_DIGIT(parser))
2769 /* Check if the number is too long. */
2771 if (++length > MAX_NUMBER_LENGTH) {
2772 return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
2773 start_mark, "found extremely long version number");
2776 value = value*10 + AS_DIGIT(parser);
2780 if (!UPDATE(parser, 1)) return 0;
2783 /* Check if the number was present. */
2786 return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
2787 start_mark, "did not find expected version number");
2796 * Scan the value of a TAG-DIRECTIVE token.
2799 * %TAG !yaml! tag:yaml.org,2002: \n
2800 * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2804 yaml_parser_scan_tag_directive_value(yaml_parser_t *parser,
2805 yaml_mark_t start_mark, yaml_char_t **handle, yaml_char_t **prefix)
2807 yaml_char_t *handle_value = NULL;
2808 yaml_char_t *prefix_value = NULL;
2810 /* Eat whitespaces. */
2812 if (!UPDATE(parser, 1)) goto error;
2814 while (IS_BLANK(parser)) {
2816 if (!UPDATE(parser, 1)) goto error;
2819 /* Scan a handle. */
2821 if (!yaml_parser_scan_tag_handle(parser, 1, start_mark, &handle_value))
2824 /* Expect a whitespace. */
2826 if (!UPDATE(parser, 1)) goto error;
2828 if (!IS_BLANK(parser)) {
2829 yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive",
2830 start_mark, "did not find expected whitespace");
2834 /* Eat whitespaces. */
2836 while (IS_BLANK(parser)) {
2838 if (!UPDATE(parser, 1)) goto error;
2841 /* Scan a prefix. */
2843 if (!yaml_parser_scan_tag_uri(parser, 1, NULL, start_mark, &prefix_value))
2846 /* Expect a whitespace or line break. */
2848 if (!UPDATE(parser, 1)) goto error;
2850 if (!IS_BLANKZ(parser)) {
2851 yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive",
2852 start_mark, "did not find expected whitespace or line break");
2856 *handle = handle_value;
2857 *prefix = prefix_value;
2862 yaml_free(handle_value);
2863 yaml_free(prefix_value);
2867 static yaml_token_t *
2868 yaml_parser_scan_anchor(yaml_parser_t *parser,
2869 yaml_token_type_t type)
2872 yaml_mark_t start_mark, end_mark;
2873 yaml_token_t *token = NULL;
2874 yaml_string_t string = yaml_parser_new_string(parser);
2876 if (!string.buffer) goto error;
2878 /* Eat the indicator character. */
2880 start_mark = yaml_parser_get_mark(parser);
2884 /* Consume the value. */
2886 if (!UPDATE(parser, 1)) goto error;
2888 while (IS_ALPHA(parser)) {
2889 if (!RESIZE(parser, string)) goto error;
2890 COPY(parser, string);
2891 if (!UPDATE(parser, 1)) goto error;
2895 end_mark = yaml_parser_get_mark(parser);
2898 * Check if length of the anchor is greater than 0 and it is followed by
2899 * a whitespace character or one of the indicators:
2901 * '?', ':', ',', ']', '}', '%', '@', '`'.
2904 if (!length || !(IS_BLANKZ(parser) || CHECK(parser, '?') || CHECK(parser, ':') ||
2905 CHECK(parser, ',') || CHECK(parser, ']') || CHECK(parser, '}') ||
2906 CHECK(parser, '%') || CHECK(parser, '@') || CHECK(parser, '`'))) {
2907 yaml_parser_set_scanner_error(parser, type == YAML_ANCHOR_TOKEN ?
2908 "while scanning an anchor" : "while scanning an alias", start_mark,
2909 "did not find expected alphabetic or numeric character");
2913 /* Create a token. */
2915 token = type == YAML_ANCHOR_TOKEN ?
2916 yaml_anchor_token_new(string.buffer, start_mark, end_mark) :
2917 yaml_alias_token_new(string.buffer, start_mark, end_mark);
2919 parser->error = YAML_MEMORY_ERROR;
2926 yaml_free(string.buffer);
2935 static yaml_token_t *
2936 yaml_parser_scan_tag(yaml_parser_t *parser)
2938 yaml_char_t *handle = NULL;
2939 yaml_char_t *suffix = NULL;
2940 yaml_token_t *token = NULL;
2941 yaml_mark_t start_mark, end_mark;
2943 start_mark = yaml_parser_get_mark(parser);
2945 /* Check if the tag is in the canonical form. */
2947 if (!UPDATE(parser, 2)) goto error;
2949 if (CHECK_AT(parser, '<', 1))
2951 /* Set the handle to '' */
2953 handle = yaml_malloc(1);
2954 if (!handle) goto error;
2962 /* Consume the tag value. */
2964 if (!yaml_parser_scan_tag_uri(parser, 0, NULL, start_mark, &suffix))
2967 /* Check for '>' and eat it. */
2969 if (!CHECK(parser, '>')) {
2970 yaml_parser_set_scanner_error(parser, "while scanning a tag",
2971 start_mark, "did not find the expected '>'");
2979 /* The tag has either the '!suffix' or the '!handle!suffix' form. */
2981 /* First, try to scan a handle. */
2983 if (!yaml_parser_scan_tag_handle(parser, 0, start_mark, &handle))
2986 /* Check if it is, indeed, handle. */
2988 if (handle[0] == '!' && handle[1] != '\0' && handle[strlen((char *)handle)-1] == '!')
2990 /* Scan the suffix now. */
2992 if (!yaml_parser_scan_tag_uri(parser, 0, NULL, start_mark, &suffix))
2997 /* It wasn't a handle after all. Scan the rest of the tag. */
2999 if (!yaml_parser_scan_tag_uri(parser, 0, handle, start_mark, &suffix))
3002 /* Set the handle to '!'. */
3005 handle = yaml_malloc(2);
3006 if (!handle) goto error;
3011 * A special case: the '!' tag.
3014 if (suffix[0] == '\0') {
3015 yaml_char_t *tmp = handle;
3022 /* Check the character which ends the tag. */
3024 if (!UPDATE(parser, 1)) goto error;
3026 if (!IS_BLANKZ(parser)) {
3027 yaml_parser_set_scanner_error(parser, "while scanning a tag",
3028 start_mark, "did not found expected whitespace or line break");
3032 end_mark = yaml_parser_get_mark(parser);
3034 /* Create a token. */
3036 token = yaml_tag_token_new(handle, suffix, start_mark, end_mark);
3038 parser->error = YAML_MEMORY_ERROR;
3051 * Scan a tag handle.
3055 yaml_parser_scan_tag_handle(yaml_parser_t *parser, int directive,
3056 yaml_mark_t start_mark, yaml_char_t **handle)
3058 yaml_string_t string = yaml_parser_new_string(parser);
3060 if (!string.buffer) goto error;
3062 /* Check the initial '!' character. */
3064 if (!UPDATE(parser, 1)) goto error;
3066 if (!CHECK(parser, '!')) {
3067 yaml_parser_set_scanner_error(parser, directive ?
3068 "while scanning a tag directive" : "while scanning a tag",
3069 start_mark, "did not find expected '!'");
3073 /* Copy the '!' character. */
3075 COPY(parser, string);
3077 /* Copy all subsequent alphabetical and numerical characters. */
3079 if (!UPDATE(parser, 1)) goto error;
3081 while (IS_ALPHA(parser))
3083 if (!RESIZE(parser, string)) goto error;
3084 COPY(parser, string);
3085 if (!UPDATE(parser, 1)) goto error;
3088 /* Check if the trailing character is '!' and copy it. */
3090 if (CHECK(parser, '!'))
3092 if (!RESIZE(parser, string)) goto error;
3093 COPY(parser, string);
3098 * It's either the '!' tag or not really a tag handle. If it's a %TAG
3099 * directive, it's an error. If it's a tag token, it must be a part of
3103 if (directive && !(string.buffer[0] == '!' && string.buffer[1] == '\0')) {
3104 yaml_parser_set_scanner_error(parser, "while parsing a tag directive",
3105 start_mark, "did not find expected '!'");
3110 *handle = string.buffer;
3115 yaml_free(string.buffer);
3124 yaml_parser_scan_tag_uri(yaml_parser_t *parser, int directive,
3125 yaml_char_t *head, yaml_mark_t start_mark, yaml_char_t **uri)
3127 size_t length = head ? strlen((char *)head) : 0;
3128 yaml_string_t string = yaml_parser_new_string(parser);
3130 if (!string.buffer) goto error;
3132 /* Resize the string to include the head. */
3134 while (string.size <= length) {
3135 if (!yaml_parser_resize_string(parser, &string)) goto error;
3139 * Copy the head if needed.
3141 * Note that we don't copy the leading '!' character.
3145 memcpy(string.buffer, head+1, length-1);
3146 string.pointer += length-1;
3151 if (!UPDATE(parser, 1)) goto error;
3154 * The set of characters that may appear in URI is as follows:
3156 * '0'-'9', 'A'-'Z', 'a'-'z', '_', '-', ';', '/', '?', ':', '@', '&',
3157 * '=', '+', '$', ',', '.', '!', '~', '*', '\'', '(', ')', '[', ']',
3161 while (IS_ALPHA(parser) || CHECK(parser, ';') || CHECK(parser, '/') ||
3162 CHECK(parser, '?') || CHECK(parser, ':') || CHECK(parser, '@') ||
3163 CHECK(parser, '&') || CHECK(parser, '=') || CHECK(parser, '+') ||
3164 CHECK(parser, '$') || CHECK(parser, ',') || CHECK(parser, '.') ||
3165 CHECK(parser, '!') || CHECK(parser, '~') || CHECK(parser, '*') ||
3166 CHECK(parser, '\'') || CHECK(parser, '(') || CHECK(parser, ')') ||
3167 CHECK(parser, '[') || CHECK(parser, ']') || CHECK(parser, '%'))
3169 if (!RESIZE(parser, string)) goto error;
3171 /* Check if it is a URI-escape sequence. */
3173 if (CHECK(parser, '%')) {
3174 if (!yaml_parser_scan_uri_escapes(parser,
3175 directive, start_mark, &string)) goto error;
3178 COPY(parser, string);
3182 if (!UPDATE(parser, 1)) goto error;
3185 /* Check if the tag is non-empty. */
3188 yaml_parser_set_scanner_error(parser, directive ?
3189 "while parsing a %TAG directive" : "while parsing a tag",
3190 start_mark, "did not find expected tag URI");
3194 *uri = string.buffer;
3199 yaml_free(string.buffer);
3204 * Decode an URI-escape sequence corresponding to a single UTF-8 character.
3208 yaml_parser_scan_uri_escapes(yaml_parser_t *parser, int directive,
3209 yaml_mark_t start_mark, yaml_string_t *string)
3213 /* Decode the required number of characters. */
3217 unsigned char octet = 0;
3219 /* Check for a URI-escaped octet. */
3221 if (!UPDATE(parser, 3)) return 0;
3223 if (!(CHECK(parser, '%') && IS_HEX_AT(parser, 1) && IS_HEX_AT(parser, 2))) {
3224 return yaml_parser_set_scanner_error(parser, directive ?
3225 "while parsing a %TAG directive" : "while parsing a tag",
3226 start_mark, "did not find URI escaped octet");
3229 /* Get the octet. */
3231 octet = (AS_HEX_AT(parser, 1) << 4) + AS_HEX_AT(parser, 2);
3233 /* If it is the leading octet, determine the length of the UTF-8 sequence. */
3237 width = (octet & 0x80) == 0x00 ? 1 :
3238 (octet & 0xE0) == 0xC0 ? 2 :
3239 (octet & 0xF0) == 0xE0 ? 3 :
3240 (octet & 0xF8) == 0xF0 ? 4 : 0;
3242 return yaml_parser_set_scanner_error(parser, directive ?
3243 "while parsing a %TAG directive" : "while parsing a tag",
3244 start_mark, "found an incorrect leading UTF-8 octet");
3249 /* Check if the trailing octet is correct. */
3251 if ((octet & 0xC0) != 0x80) {
3252 return yaml_parser_set_scanner_error(parser, directive ?
3253 "while parsing a %TAG directive" : "while parsing a tag",
3254 start_mark, "found an incorrect trailing UTF-8 octet");
3258 /* Copy the octet and move the pointers. */
3260 *(string->pointer++) = octet;
3271 * Scan a block scalar.
3274 static yaml_token_t *
3275 yaml_parser_scan_block_scalar(yaml_parser_t *parser, int literal)
3277 yaml_mark_t start_mark;
3278 yaml_mark_t end_mark;
3279 yaml_string_t string = yaml_parser_new_string(parser);
3280 yaml_string_t leading_break = yaml_parser_new_string(parser);
3281 yaml_string_t trailing_breaks = yaml_parser_new_string(parser);
3282 yaml_token_t *token = NULL;
3286 int leading_blank = 0;
3287 int trailing_blank = 0;
3289 if (!string.buffer) goto error;
3290 if (!leading_break.buffer) goto error;
3291 if (!trailing_breaks.buffer) goto error;
3293 /* Eat the indicator '|' or '>'. */
3295 start_mark = yaml_parser_get_mark(parser);
3299 /* Scan the additional block scalar indicators. */
3301 if (!UPDATE(parser, 1)) goto error;
3303 /* Check for a chomping indicator. */
3305 if (CHECK(parser, '+') || CHECK(parser, '-'))
3307 /* Set the chomping method and eat the indicator. */
3309 chomping = CHECK(parser, '+') ? +1 : -1;
3313 /* Check for an indentation indicator. */
3315 if (!UPDATE(parser, 1)) goto error;
3317 if (IS_DIGIT(parser))
3319 /* Check that the intendation is greater than 0. */
3321 if (CHECK(parser, '0')) {
3322 yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
3323 start_mark, "found an intendation indicator equal to 0");
3327 /* Get the intendation level and eat the indicator. */
3329 increment = AS_DIGIT(parser);
3335 /* Do the same as above, but in the opposite order. */
3337 else if (IS_DIGIT(parser))
3339 if (CHECK(parser, '0')) {
3340 yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
3341 start_mark, "found an intendation indicator equal to 0");
3345 increment = AS_DIGIT(parser);
3349 if (!UPDATE(parser, 1)) goto error;
3351 if (CHECK(parser, '+') || CHECK(parser, '-')) {
3352 chomping = CHECK(parser, '+') ? +1 : -1;
3357 /* Eat whitespaces and comments to the end of the line. */
3359 if (!UPDATE(parser, 1)) goto error;
3361 while (IS_BLANK(parser)) {
3363 if (!UPDATE(parser, 1)) goto error;
3366 if (CHECK(parser, '#')) {
3367 while (!IS_BREAKZ(parser)) {
3369 if (!UPDATE(parser, 1)) goto error;
3373 /* Check if we are at the end of the line. */
3375 if (!IS_BREAKZ(parser)) {
3376 yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
3377 start_mark, "did not found expected comment or line break");
3381 /* Eat a line break. */
3383 if (IS_BREAK(parser)) {
3384 if (!UPDATE(parser, 2)) goto error;
3385 FORWARD_LINE(parser);
3388 end_mark = yaml_parser_get_mark(parser);
3390 /* Set the intendation level if it was specified. */
3393 indent = parser->indent >= 0 ? parser->indent+increment : increment;
3396 /* Scan the leading line breaks and determine the indentation level if needed. */
3398 if (!yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks,
3399 start_mark, &end_mark)) goto error;
3401 /* Scan the block scalar content. */
3403 if (!UPDATE(parser, 1)) goto error;
3405 while (parser->column == indent && !IS_Z(parser))
3408 * We are at the beginning of a non-empty line.
3411 /* Is it a trailing whitespace? */
3413 trailing_blank = IS_BLANK(parser);
3415 /* Check if we need to fold the leading line break. */
3417 if (!literal && (*leading_break.buffer == '\n')
3418 && !leading_blank && !trailing_blank)
3420 /* Do we need to join the lines by space? */
3422 if (*trailing_breaks.buffer == '\0') {
3423 if (!RESIZE(parser, string)) goto error;
3424 *(string.pointer ++) = ' ';
3427 yaml_parser_clear_string(parser, &leading_break);
3430 if (!JOIN(parser, string, leading_break)) goto error;
3433 /* Append the remaining line breaks. */
3435 if (!JOIN(parser, string, trailing_breaks)) goto error;
3437 /* Is it a leading whitespace? */
3439 leading_blank = IS_BLANK(parser);
3441 /* Consume the current line. */
3443 while (!IS_BREAKZ(parser)) {
3444 if (!RESIZE(parser, string)) goto error;
3445 COPY(parser, string);
3446 if (!UPDATE(parser, 1)) goto error;
3449 /* Consume the line break. */
3451 if (!UPDATE(parser, 2)) goto error;
3453 COPY_LINE(parser, leading_break);
3455 /* Eat the following intendation spaces and line breaks. */
3457 if (!yaml_parser_scan_block_scalar_breaks(parser,
3458 &indent, &trailing_breaks, start_mark, &end_mark)) goto error;
3461 /* Chomp the tail. */
3463 if (chomping != -1) {
3464 if (!JOIN(parser, string, leading_break)) goto error;
3466 if (chomping == 1) {
3467 if (!JOIN(parser, string, trailing_breaks)) goto error;
3470 /* Create a token. */
3472 token = yaml_scalar_token_new(string.buffer, string.pointer-string.buffer,
3473 literal ? YAML_LITERAL_SCALAR_STYLE : YAML_FOLDED_SCALAR_STYLE,
3474 start_mark, end_mark);
3476 parser->error = YAML_MEMORY_ERROR;
3480 yaml_free(leading_break.buffer);
3481 yaml_free(trailing_breaks.buffer);
3486 yaml_free(string.buffer);
3487 yaml_free(leading_break.buffer);
3488 yaml_free(trailing_breaks.buffer);
3494 * Scan intendation spaces and line breaks for a block scalar. Determine the
3495 * intendation level if needed.
3499 yaml_parser_scan_block_scalar_breaks(yaml_parser_t *parser,
3500 int *indent, yaml_string_t *breaks,
3501 yaml_mark_t start_mark, yaml_mark_t *end_mark)
3505 *end_mark = yaml_parser_get_mark(parser);
3507 /* Eat the intendation spaces and line breaks. */
3511 /* Eat the intendation spaces. */
3513 if (!UPDATE(parser, 1)) return 0;
3515 while ((!*indent || parser->column < *indent) && IS_SPACE(parser)) {
3517 if (!UPDATE(parser, 1)) return 0;
3520 if (parser->column > max_indent)
3521 max_indent = parser->column;
3523 /* Check for a tab character messing the intendation. */
3525 if ((!*indent || parser->column < *indent) && IS_TAB(parser)) {
3526 return yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
3527 start_mark, "found a tab character where an intendation space is expected");
3530 /* Have we found a non-empty line? */
3532 if (!IS_BREAK(parser)) break;
3534 /* Consume the line break. */
3536 if (!UPDATE(parser, 2)) return 0;
3537 if (!RESIZE(parser, *breaks)) return 0;
3538 COPY_LINE(parser, *breaks);
3539 *end_mark = yaml_parser_get_mark(parser);
3542 /* Determine the indentation level if needed. */
3545 *indent = max_indent;
3546 if (*indent < parser->indent + 1)
3547 *indent = parser->indent + 1;
3556 * Scan a quoted scalar.
3559 static yaml_token_t *
3560 yaml_parser_scan_flow_scalar(yaml_parser_t *parser, int single)
3562 yaml_mark_t start_mark;
3563 yaml_mark_t end_mark;
3564 yaml_string_t string = yaml_parser_new_string(parser);
3565 yaml_string_t leading_break = yaml_parser_new_string(parser);
3566 yaml_string_t trailing_breaks = yaml_parser_new_string(parser);
3567 yaml_string_t whitespaces = yaml_parser_new_string(parser);
3568 yaml_token_t *token = NULL;
3571 if (!string.buffer) goto error;
3572 if (!leading_break.buffer) goto error;
3573 if (!trailing_breaks.buffer) goto error;
3574 if (!whitespaces.buffer) goto error;
3576 /* Eat the left quote. */
3578 start_mark = yaml_parser_get_mark(parser);
3582 /* Consume the content of the quoted scalar. */
3586 /* Check that there are no document indicators at the beginning of the line. */
3588 if (!UPDATE(parser, 4)) goto error;
3590 if (parser->column == 0 &&
3591 ((CHECK_AT(parser, '-', 0) &&
3592 CHECK_AT(parser, '-', 1) &&
3593 CHECK_AT(parser, '-', 2)) ||
3594 (CHECK_AT(parser, '.', 0) &&
3595 CHECK_AT(parser, '.', 1) &&
3596 CHECK_AT(parser, '.', 2))) &&
3597 IS_BLANKZ_AT(parser, 3))
3599 yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar",
3600 start_mark, "found unexpected document indicator");
3604 /* Check for EOF. */
3607 yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar",
3608 start_mark, "found unexpected end of stream");
3612 /* Consume non-blank characters. */
3614 if (!UPDATE(parser, 2)) goto error;
3615 if (!RESIZE(parser, string)) goto error;
3619 while (!IS_BLANKZ(parser))
3621 /* Check for an escaped single quote. */
3623 if (single && CHECK_AT(parser, '\'', 0) && CHECK_AT(parser, '\'', 1))
3625 *(string.pointer++) = '\'';
3630 /* Check for the right quote. */
3632 else if (CHECK(parser, single ? '\'' : '"'))
3637 /* Check for an escaped line break. */
3639 else if (!single && CHECK(parser, '\\') && IS_BREAK_AT(parser, 1))
3641 if (!UPDATE(parser, 3)) goto error;
3643 FORWARD_LINE(parser);
3648 /* Check for an escape sequence. */
3650 else if (!single && CHECK(parser, '\\'))
3652 int code_length = 0;
3654 /* Check the escape character. */
3656 switch (parser->pointer[1])
3659 *(string.pointer++) = '\0';
3663 *(string.pointer++) = '\x07';
3667 *(string.pointer++) = '\x08';
3672 *(string.pointer++) = '\x09';
3676 *(string.pointer++) = '\x0A';
3680 *(string.pointer++) = '\x0B';
3684 *(string.pointer++) = '\x0C';
3688 *(string.pointer++) = '\x0D';
3692 *(string.pointer++) = '\x1B';
3696 *(string.pointer++) = '\x20';
3700 *(string.pointer++) = '"';
3704 *(string.pointer++) = '\'';
3708 *(string.pointer++) = '\\';
3711 case 'N': /* NEL (#x85) */
3712 *(string.pointer++) = '\xC2';
3713 *(string.pointer++) = '\x85';
3716 case '_': /* #xA0 */
3717 *(string.pointer++) = '\xC2';
3718 *(string.pointer++) = '\xA0';
3721 case 'L': /* LS (#x2028) */
3722 *(string.pointer++) = '\xE2';
3723 *(string.pointer++) = '\x80';
3724 *(string.pointer++) = '\xA8';
3727 case 'P': /* PS (#x2029) */
3728 *(string.pointer++) = '\xE2';
3729 *(string.pointer++) = '\x80';
3730 *(string.pointer++) = '\xA9';
3746 yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar",
3747 start_mark, "found unknown escape character");
3754 /* Consume an arbitrary escape code. */
3758 unsigned int value = 0;
3761 /* Scan the character value. */
3763 if (!UPDATE(parser, code_length)) goto error;
3765 for (k = 0; k < code_length; k ++) {
3766 if (!IS_HEX_AT(parser, k)) {
3767 yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar",
3768 start_mark, "did not find expected hexdecimal number");
3771 value = (value << 4) + AS_HEX_AT(parser, k);
3774 /* Check the value and write the character. */
3776 if ((value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF) {
3777 yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar",
3778 start_mark, "found invalid Unicode character escape code");
3782 if (value <= 0x7F) {
3783 *(string.pointer++) = value;
3785 else if (value <= 0x7FF) {
3786 *(string.pointer++) = 0xC0 + (value >> 6);
3787 *(string.pointer++) = 0x80 + (value & 0x3F);
3789 else if (value <= 0xFFFF) {
3790 *(string.pointer++) = 0xE0 + (value >> 12);
3791 *(string.pointer++) = 0x80 + ((value >> 6) & 0x3F);
3792 *(string.pointer++) = 0x80 + (value & 0x3F);
3795 *(string.pointer++) = 0xF0 + (value >> 18);
3796 *(string.pointer++) = 0x80 + ((value >> 12) & 0x3F);
3797 *(string.pointer++) = 0x80 + ((value >> 6) & 0x3F);
3798 *(string.pointer++) = 0x80 + (value & 0x3F);
3801 /* Advance the pointer. */
3803 for (k = 0; k < code_length; k ++) {
3811 /* It is a non-escaped non-blank character. */
3813 COPY(parser, string);
3816 if (!UPDATE(parser, 2)) goto error;
3817 if (!RESIZE(parser, string)) goto error;
3820 /* Check if we are at the end of the scalar. */
3822 if (CHECK(parser, single ? '\'' : '"'))
3825 /* Consume blank characters. */
3827 if (!UPDATE(parser, 1)) goto error;
3829 while (IS_BLANK(parser) || IS_BREAK(parser))
3831 if (IS_BLANK(parser))
3833 /* Consume a space or a tab character. */
3835 if (!leading_blanks) {
3836 if (!RESIZE(parser, whitespaces)) goto error;
3837 COPY(parser, whitespaces);
3845 if (!UPDATE(parser, 2)) goto error;
3847 /* Check if it is a first line break. */
3849 if (!leading_blanks)
3851 yaml_parser_clear_string(parser, &whitespaces);
3852 COPY_LINE(parser, leading_break);
3857 if (!RESIZE(parser, trailing_breaks)) goto error;
3858 COPY_LINE(parser, trailing_breaks);
3861 if (!UPDATE(parser, 1)) goto error;
3864 /* Join the whitespaces or fold line breaks. */
3866 if (!RESIZE(parser, string)) goto error;
3870 /* Do we need to fold line breaks? */
3872 if (leading_break.buffer[0] == '\n') {
3873 if (trailing_breaks.buffer[0] == '\0') {
3874 *(string.pointer++) = ' ';
3877 if (!JOIN(parser, string, trailing_breaks)) goto error;
3879 yaml_parser_clear_string(parser, &leading_break);
3882 if (!JOIN(parser, string, leading_break)) goto error;
3883 if (!JOIN(parser, string, trailing_breaks)) goto error;
3888 if (!JOIN(parser, string, whitespaces)) goto error;
3892 /* Eat the right quote. */
3896 end_mark = yaml_parser_get_mark(parser);
3898 /* Create a token. */
3900 token = yaml_scalar_token_new(string.buffer, string.pointer-string.buffer,
3901 single ? YAML_SINGLE_QUOTED_SCALAR_STYLE : YAML_DOUBLE_QUOTED_SCALAR_STYLE,
3902 start_mark, end_mark);
3904 parser->error = YAML_MEMORY_ERROR;
3908 yaml_free(leading_break.buffer);
3909 yaml_free(trailing_breaks.buffer);
3910 yaml_free(whitespaces.buffer);
3915 yaml_free(string.buffer);
3916 yaml_free(leading_break.buffer);
3917 yaml_free(trailing_breaks.buffer);
3918 yaml_free(whitespaces.buffer);
3924 * Scan a plain scalar.
3927 static yaml_token_t *
3928 yaml_parser_scan_plain_scalar(yaml_parser_t *parser)
3930 yaml_mark_t start_mark;
3931 yaml_mark_t end_mark;
3932 yaml_string_t string = yaml_parser_new_string(parser);
3933 yaml_string_t leading_break = yaml_parser_new_string(parser);
3934 yaml_string_t trailing_breaks = yaml_parser_new_string(parser);
3935 yaml_string_t whitespaces = yaml_parser_new_string(parser);
3936 yaml_token_t *token = NULL;
3937 int leading_blanks = 0;
3938 int indent = parser->indent+1;
3940 if (!string.buffer) goto error;
3941 if (!leading_break.buffer) goto error;
3942 if (!trailing_breaks.buffer) goto error;
3943 if (!whitespaces.buffer) goto error;
3945 start_mark = yaml_parser_get_mark(parser);
3947 /* Consume the content of the plain scalar. */
3951 /* Check for a document indicator. */
3953 if (!UPDATE(parser, 4)) goto error;
3955 if (parser->column == 0 &&
3956 ((CHECK_AT(parser, '-', 0) &&
3957 CHECK_AT(parser, '-', 1) &&
3958 CHECK_AT(parser, '-', 2)) ||
3959 (CHECK_AT(parser, '.', 0) &&
3960 CHECK_AT(parser, '.', 1) &&
3961 CHECK_AT(parser, '.', 2))) &&
3962 IS_BLANKZ_AT(parser, 3)) break;
3964 /* Check for a comment. */
3966 if (CHECK(parser, '#'))
3969 /* Consume non-blank characters. */
3971 while (!IS_BLANKZ(parser))
3973 /* Check for 'x:x' in the flow context. TODO: Fix the test "spec-08-13". */
3975 if (parser->flow_level && CHECK(parser, ':') && !IS_BLANKZ_AT(parser, 1)) {
3976 yaml_parser_set_scanner_error(parser, "while scanning a plain scalar",
3977 start_mark, "found unexpected ':'");
3981 /* Check for indicators that may end a plain scalar. */
3983 if ((CHECK(parser, ':') && IS_BLANKZ_AT(parser, 1)) ||
3984 (parser->flow_level &&
3985 (CHECK(parser, ',') || CHECK(parser, ':') ||
3986 CHECK(parser, '?') || CHECK(parser, '[') ||
3987 CHECK(parser, ']') || CHECK(parser, '{') ||
3988 CHECK(parser, '}'))))
3991 /* Check if we need to join whitespaces and breaks. */
3993 if (leading_blanks || whitespaces.buffer != whitespaces.pointer)
3995 if (!RESIZE(parser, string)) goto error;
3999 /* Do we need to fold line breaks? */
4001 if (leading_break.buffer[0] == '\n') {
4002 if (trailing_breaks.buffer[0] == '\0') {
4003 *(string.pointer++) = ' ';
4006 if (!JOIN(parser, string, trailing_breaks)) goto error;
4008 yaml_parser_clear_string(parser, &leading_break);
4011 if (!JOIN(parser, string, leading_break)) goto error;
4012 if (!JOIN(parser, string, trailing_breaks)) goto error;
4019 if (!JOIN(parser, string, whitespaces)) goto error;
4023 /* Copy the character. */
4025 if (!RESIZE(parser, string)) goto error;
4027 COPY(parser, string);
4029 end_mark = yaml_parser_get_mark(parser);
4031 if (!UPDATE(parser, 2)) goto error;
4034 /* Is it the end? */
4036 if (!(IS_BLANK(parser) || IS_BREAK(parser)))
4039 /* Consume blank characters. */
4041 if (!UPDATE(parser, 1)) goto error;
4043 while (IS_BLANK(parser) || IS_BREAK(parser))
4045 if (IS_BLANK(parser))
4047 /* Check for tab character that abuse intendation. */
4049 if (leading_blanks && parser->column < indent && IS_TAB(parser)) {
4050 yaml_parser_set_scanner_error(parser, "while scanning a plain scalar",
4051 start_mark, "found a tab character that violate intendation");
4055 /* Consume a space or a tab character. */
4057 if (!leading_blanks) {
4058 if (!RESIZE(parser, whitespaces)) goto error;
4059 COPY(parser, whitespaces);
4067 if (!UPDATE(parser, 2)) goto error;
4069 /* Check if it is a first line break. */
4071 if (!leading_blanks)
4073 yaml_parser_clear_string(parser, &whitespaces);
4074 COPY_LINE(parser, leading_break);
4079 if (!RESIZE(parser, trailing_breaks)) goto error;
4080 COPY_LINE(parser, trailing_breaks);
4083 if (!UPDATE(parser, 1)) goto error;
4086 /* Check intendation level. */
4088 if (!parser->flow_level && parser->column < indent)
4092 /* Create a token. */
4094 token = yaml_scalar_token_new(string.buffer, string.pointer-string.buffer,
4095 YAML_PLAIN_SCALAR_STYLE, start_mark, end_mark);
4097 parser->error = YAML_MEMORY_ERROR;
4101 /* Note that we change the 'simple_key_allowed' flag. */
4103 if (leading_blanks) {
4104 parser->simple_key_allowed = 1;
4107 yaml_free(leading_break.buffer);
4108 yaml_free(trailing_breaks.buffer);
4109 yaml_free(whitespaces.buffer);
4114 yaml_free(string.buffer);
4115 yaml_free(leading_break.buffer);
4116 yaml_free(trailing_breaks.buffer);
4117 yaml_free(whitespaces.buffer);