]> andersk Git - libyaml.git/blob - src/scanner.c
07723bccf7c4d612e548d3c80ab8f5c4d4e84353
[libyaml.git] / src / scanner.c
1
2 /*
3  * Introduction
4  * ************
5  *
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.
9  *
10  * The process of transforming a YAML stream into a sequence of events is
11  * divided on two steps: Scanning and Parsing.
12  *
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.
16  *
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).
20  *
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.
24  *
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.
27  *
28  * Now, tokens:
29  *
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              # '}'
43  *      BLOCK-ENTRY                     # '-'
44  *      FLOW-ENTRY                      # ','
45  *      KEY                             # '?' or nothing (simple keys).
46  *      VALUE                           # ':'
47  *      ALIAS(anchor)                   # '*anchor'
48  *      ANCHOR(anchor)                  # '&anchor'
49  *      TAG(handle,suffix)              # '!handle!suffix'
50  *      SCALAR(value,style)             # A scalar.
51  *
52  * The following two tokens are "virtual" tokens denoting the beginning and the
53  * end of the stream:
54  *
55  *      STREAM-START(encoding)
56  *      STREAM-END
57  *
58  * We pass the information about the input stream encoding with the
59  * STREAM-START token.
60  *
61  * The next two tokens are responsible for tags:
62  *
63  *      VERSION-DIRECTIVE(major,minor)
64  *      TAG-DIRECTIVE(handle,prefix)
65  *
66  * Example:
67  *
68  *      %YAML   1.1
69  *      %TAG    !   !foo
70  *      %TAG    !yaml!  tag:yaml.org,2002:
71  *      ---
72  *
73  * The correspoding sequence of tokens:
74  *
75  *      STREAM-START(utf-8)
76  *      VERSION-DIRECTIVE(1,1)
77  *      TAG-DIRECTIVE("!","!foo")
78  *      TAG-DIRECTIVE("!yaml","tag:yaml.org,2002:")
79  *      DOCUMENT-START
80  *      STREAM-END
81  *
82  * Note that the VERSION-DIRECTIVE and TAG-DIRECTIVE tokens occupy a whole
83  * line.
84  *
85  * The document start and end indicators are represented by:
86  *
87  *      DOCUMENT-START
88  *      DOCUMENT-END
89  *
90  * Note that if a YAML stream contains an implicit document (without '---'
91  * and '...' indicators), no DOCUMENT-START and DOCUMENT-END tokens will be
92  * produced.
93  *
94  * In the following examples, we present whole documents together with the
95  * produced tokens.
96  *
97  *      1. An implicit document:
98  *
99  *          'a scalar'
100  *
101  *      Tokens:
102  *
103  *          STREAM-START(utf-8)
104  *          SCALAR("a scalar",single-quoted)
105  *          STREAM-END
106  *
107  *      2. An explicit document:
108  *
109  *          ---
110  *          'a scalar'
111  *          ...
112  *
113  *      Tokens:
114  *
115  *          STREAM-START(utf-8)
116  *          DOCUMENT-START
117  *          SCALAR("a scalar",single-quoted)
118  *          DOCUMENT-END
119  *          STREAM-END
120  *
121  *      3. Several documents in a stream:
122  *
123  *          'a scalar'
124  *          ---
125  *          'another scalar'
126  *          ---
127  *          'yet another scalar'
128  *
129  *      Tokens:
130  *
131  *          STREAM-START(utf-8)
132  *          SCALAR("a scalar",single-quoted)
133  *          DOCUMENT-START
134  *          SCALAR("another scalar",single-quoted)
135  *          DOCUMENT-START
136  *          SCALAR("yet another scalar",single-quoted)
137  *          STREAM-END
138  *
139  * We have already introduced the SCALAR token above.  The following tokens are
140  * used to describe aliases, anchors, tag, and scalars:
141  *
142  *      ALIAS(anchor)
143  *      ANCHOR(anchor)
144  *      TAG(handle,suffix)
145  *      SCALAR(value,style)
146  *
147  * The following series of examples illustrate the usage of these tokens:
148  *
149  *      1. A recursive sequence:
150  *
151  *          &A [ *A ]
152  *
153  *      Tokens:
154  *
155  *          STREAM-START(utf-8)
156  *          ANCHOR("A")
157  *          FLOW-SEQUENCE-START
158  *          ALIAS("A")
159  *          FLOW-SEQUENCE-END
160  *          STREAM-END
161  *
162  *      2. A tagged scalar:
163  *
164  *          !!float "3.14"  # A good approximation.
165  *
166  *      Tokens:
167  *
168  *          STREAM-START(utf-8)
169  *          TAG("!!","float")
170  *          SCALAR("3.14",double-quoted)
171  *          STREAM-END
172  *
173  *      3. Various scalar styles:
174  *
175  *          --- # Implicit empty plain scalars do not produce tokens.
176  *          --- a plain scalar
177  *          --- 'a single-quoted scalar'
178  *          --- "a double-quoted scalar"
179  *          --- |-
180  *            a literal scalar
181  *          --- >-
182  *            a folded
183  *            scalar
184  *
185  *      Tokens:
186  *
187  *          STREAM-START(utf-8)
188  *          DOCUMENT-START
189  *          DOCUMENT-START
190  *          SCALAR("a plain scalar",plain)
191  *          DOCUMENT-START
192  *          SCALAR("a single-quoted scalar",single-quoted)
193  *          DOCUMENT-START
194  *          SCALAR("a double-quoted scalar",double-quoted)
195  *          DOCUMENT-START
196  *          SCALAR("a literal scalar",literal)
197  *          DOCUMENT-START
198  *          SCALAR("a folded scalar",folded)
199  *          STREAM-END
200  *
201  * Now it's time to review collection-related tokens. We will start with
202  * flow collections:
203  *
204  *      FLOW-SEQUENCE-START
205  *      FLOW-SEQUENCE-END
206  *      FLOW-MAPPING-START
207  *      FLOW-MAPPING-END
208  *      FLOW-ENTRY
209  *      KEY
210  *      VALUE
211  *
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.
217  *
218  * The following examples show flow collections:
219  *
220  *      1. A flow sequence:
221  *
222  *          [item 1, item 2, item 3]
223  *
224  *      Tokens:
225  *
226  *          STREAM-START(utf-8)
227  *          FLOW-SEQUENCE-START
228  *          SCALAR("item 1",plain)
229  *          FLOW-ENTRY
230  *          SCALAR("item 2",plain)
231  *          FLOW-ENTRY
232  *          SCALAR("item 3",plain)
233  *          FLOW-SEQUENCE-END
234  *          STREAM-END
235  *
236  *      2. A flow mapping:
237  *
238  *          {
239  *              a simple key: a value,  # Note that the KEY token is produced.
240  *              ? a complex key: another value,
241  *          }
242  *
243  *      Tokens:
244  *
245  *          STREAM-START(utf-8)
246  *          FLOW-MAPPING-START
247  *          KEY
248  *          SCALAR("a simple key",plain)
249  *          VALUE
250  *          SCALAR("a value",plain)
251  *          FLOW-ENTRY
252  *          KEY
253  *          SCALAR("a complex key",plain)
254  *          VALUE
255  *          SCALAR("another value",plain)
256  *          FLOW-ENTRY
257  *          FLOW-MAPPING-END
258  *          STREAM-END
259  *
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.
262  *
263  * For scanning block collections, the following tokens are used (note that we
264  * repeat KEY and VALUE here):
265  *
266  *      BLOCK-SEQUENCE-START
267  *      BLOCK-MAPPING-START
268  *      BLOCK-END
269  *      BLOCK-ENTRY
270  *      KEY
271  *      VALUE
272  *
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.
278  *
279  * The tokens BLOCK-ENTRY, KEY, and VALUE are used to represent the indicators
280  * '-', '?', and ':' correspondingly.
281  *
282  * The following examples show how the tokens BLOCK-SEQUENCE-START,
283  * BLOCK-MAPPING-START, and BLOCK-END are emitted by the Scanner:
284  *
285  *      1. Block sequences:
286  *
287  *          - item 1
288  *          - item 2
289  *          -
290  *            - item 3.1
291  *            - item 3.2
292  *          -
293  *            key 1: value 1
294  *            key 2: value 2
295  *
296  *      Tokens:
297  *
298  *          STREAM-START(utf-8)
299  *          BLOCK-SEQUENCE-START
300  *          BLOCK-ENTRY
301  *          SCALAR("item 1",plain)
302  *          BLOCK-ENTRY
303  *          SCALAR("item 2",plain)
304  *          BLOCK-ENTRY
305  *          BLOCK-SEQUENCE-START
306  *          BLOCK-ENTRY
307  *          SCALAR("item 3.1",plain)
308  *          BLOCK-ENTRY
309  *          SCALAR("item 3.2",plain)
310  *          BLOCK-END
311  *          BLOCK-ENTRY
312  *          BLOCK-MAPPING-START
313  *          KEY
314  *          SCALAR("key 1",plain)
315  *          VALUE
316  *          SCALAR("value 1",plain)
317  *          KEY
318  *          SCALAR("key 2",plain)
319  *          VALUE
320  *          SCALAR("value 2",plain)
321  *          BLOCK-END
322  *          BLOCK-END
323  *          STREAM-END
324  *
325  *      2. Block mappings:
326  *
327  *          a simple key: a value   # The KEY token is produced here.
328  *          ? a complex key
329  *          : another value
330  *          a mapping:
331  *            key 1: value 1
332  *            key 2: value 2
333  *          a sequence:
334  *            - item 1
335  *            - item 2
336  *
337  *      Tokens:
338  *
339  *          STREAM-START(utf-8)
340  *          BLOCK-MAPPING-START
341  *          KEY
342  *          SCALAR("a simple key",plain)
343  *          VALUE
344  *          SCALAR("a value",plain)
345  *          KEY
346  *          SCALAR("a complex key",plain)
347  *          VALUE
348  *          SCALAR("another value",plain)
349  *          KEY
350  *          SCALAR("a mapping",plain)
351  *          BLOCK-MAPPING-START
352  *          KEY
353  *          SCALAR("key 1",plain)
354  *          VALUE
355  *          SCALAR("value 1",plain)
356  *          KEY
357  *          SCALAR("key 2",plain)
358  *          VALUE
359  *          SCALAR("value 2",plain)
360  *          BLOCK-END
361  *          KEY
362  *          SCALAR("a sequence",plain)
363  *          VALUE
364  *          BLOCK-SEQUENCE-START
365  *          BLOCK-ENTRY
366  *          SCALAR("item 1",plain)
367  *          BLOCK-ENTRY
368  *          SCALAR("item 2",plain)
369  *          BLOCK-END
370  *          BLOCK-END
371  *          STREAM-END
372  *
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:
377  *
378  *      1. Collections in a sequence:
379  *
380  *          - - item 1
381  *            - item 2
382  *          - key 1: value 1
383  *            key 2: value 2
384  *          - ? complex key
385  *            : complex value
386  *
387  *      Tokens:
388  *
389  *          STREAM-START(utf-8)
390  *          BLOCK-SEQUENCE-START
391  *          BLOCK-ENTRY
392  *          BLOCK-SEQUENCE-START
393  *          BLOCK-ENTRY
394  *          SCALAR("item 1",plain)
395  *          BLOCK-ENTRY
396  *          SCALAR("item 2",plain)
397  *          BLOCK-END
398  *          BLOCK-ENTRY
399  *          BLOCK-MAPPING-START
400  *          KEY
401  *          SCALAR("key 1",plain)
402  *          VALUE
403  *          SCALAR("value 1",plain)
404  *          KEY
405  *          SCALAR("key 2",plain)
406  *          VALUE
407  *          SCALAR("value 2",plain)
408  *          BLOCK-END
409  *          BLOCK-ENTRY
410  *          BLOCK-MAPPING-START
411  *          KEY
412  *          SCALAR("complex key")
413  *          VALUE
414  *          SCALAR("complex value")
415  *          BLOCK-END
416  *          BLOCK-END
417  *          STREAM-END
418  *
419  *      2. Collections in a mapping:
420  *
421  *          ? a sequence
422  *          : - item 1
423  *            - item 2
424  *          ? a mapping
425  *          : key 1: value 1
426  *            key 2: value 2
427  *
428  *      Tokens:
429  *
430  *          STREAM-START(utf-8)
431  *          BLOCK-MAPPING-START
432  *          KEY
433  *          SCALAR("a sequence",plain)
434  *          VALUE
435  *          BLOCK-SEQUENCE-START
436  *          BLOCK-ENTRY
437  *          SCALAR("item 1",plain)
438  *          BLOCK-ENTRY
439  *          SCALAR("item 2",plain)
440  *          BLOCK-END
441  *          KEY
442  *          SCALAR("a mapping",plain)
443  *          VALUE
444  *          BLOCK-MAPPING-START
445  *          KEY
446  *          SCALAR("key 1",plain)
447  *          VALUE
448  *          SCALAR("value 1",plain)
449  *          KEY
450  *          SCALAR("key 2",plain)
451  *          VALUE
452  *          SCALAR("value 2",plain)
453  *          BLOCK-END
454  *          BLOCK-END
455  *          STREAM-END
456  *
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:
459  *
460  *      key:
461  *      - item 1    # BLOCK-SEQUENCE-START is NOT produced here.
462  *      - item 2
463  *
464  * Tokens:
465  *
466  *      STREAM-START(utf-8)
467  *      BLOCK-MAPPING-START
468  *      KEY
469  *      SCALAR("key",plain)
470  *      VALUE
471  *      BLOCK-ENTRY
472  *      SCALAR("item 1",plain)
473  *      BLOCK-ENTRY
474  *      SCALAR("item 2",plain)
475  *      BLOCK-END
476  */
477
478 #if HAVE_CONFIG_H
479 #include <config.h>
480 #endif
481
482 #include <yaml/yaml.h>
483
484 #include <assert.h>
485
486 /*
487  * Ensure that the buffer contains the required number of characters.
488  * Return 1 on success, 0 on failure (reader error or memory error).
489  */
490
491 #define UPDATE(parser,length)   \
492     (parser->unread >= (length) \
493         ? 1                     \
494         : yaml_parser_update_buffer(parser, (length)))
495
496 /*
497  * Check the octet at the specified position.
498  */
499
500 #define CHECK_AT(parser,octet,offset)   \
501     (parser->pointer[offset] == (yaml_char_t)(octet))
502
503 /*
504  * Check the current octet in the buffer.
505  */
506
507 #define CHECK(parser,octet) CHECK_AT(parser,(octet),0)
508
509 /*
510  * Check if the character at the specified position is an alphabetical
511  * character, a digit, '_', or '-'.
512  */
513
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] == '-')
523
524 #define IS_ALPHA(parser)    IS_ALPHA_AT(parser,0)
525
526 /*
527  * Check if the character at the specified position is a digit.
528  */
529
530 #define IS_DIGIT_AT(parser,offset)  \
531      ((parser->pointer[offset] >= (yaml_char_t) '0' &&      \
532        parser->pointer[offset] <= (yaml_char_t) '9'))
533
534 #define IS_DIGIT(parser)    IS_DIGIT_AT(parser,0)
535
536 /*
537  * Get the value of a digit.
538  */
539
540 #define AS_DIGIT_AT(parser,offset)  \
541      (parser->pointer[offset] - (yaml_char_t) '0')
542
543 #define AS_DIGIT(parser)    AS_DIGIT_AT(parser,0)
544
545 /*
546  * Check if the character at the specified position is a hex-digit.
547  */
548
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'))
556
557 #define IS_HEX(parser)    IS_HEX_AT(parser,0)
558
559 /*
560  * Get the value of a hex-digit.
561  */
562
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'))
571  
572 #define AS_HEX(parser)  AS_HEX_AT(parser,0)
573  
574 /*
575  * Check if the character at the specified position is NUL.
576  */
577
578 #define IS_Z_AT(parser,offset)    CHECK_AT(parser,'\0',(offset))
579
580 #define IS_Z(parser)    IS_Z_AT(parser,0)
581
582 /*
583  * Check if the character at the specified position is BOM.
584  */
585
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) */
590
591 #define IS_BOM(parser)  IS_BOM_AT(parser,0)
592
593 /*
594  * Check if the character at the specified position is space.
595  */
596
597 #define IS_SPACE_AT(parser,offset)  CHECK_AT(parser,' ',(offset))
598
599 #define IS_SPACE(parser)    IS_SPACE_AT(parser,0)
600
601 /*
602  * Check if the character at the specified position is tab.
603  */
604
605 #define IS_TAB_AT(parser,offset)    CHECK_AT(parser,'\t',(offset))
606
607 #define IS_TAB(parser)  IS_TAB_AT(parser,0)
608
609 /*
610  * Check if the character at the specified position is blank (space or tab).
611  */
612
613 #define IS_BLANK_AT(parser,offset)  \
614     (IS_SPACE_AT(parser,(offset)) || IS_TAB_AT(parser,(offset)))
615
616 #define IS_BLANK(parser)    IS_BLANK_AT(parser,0)
617
618 /*
619  * Check if the character at the specified position is a line break.
620  */
621
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)))    /* LS (#x2029) */
633
634 #define IS_BREAK(parser)    IS_BREAK_AT(parser,0)
635
636 #define IS_CRLF_AT(parser,offset) \
637      (CHECK_AT(parser,'\r',(offset)) && CHECK_AT(parser,'\n',(offset)+1))
638
639 #define IS_CRLF(parser) IS_CRLF_AT(parser,0)
640
641 /*
642  * Check if the character is a line break or NUL.
643  */
644
645 #define IS_BREAKZ_AT(parser,offset) \
646     (IS_BREAK_AT(parser,(offset)) || IS_Z_AT(parser,(offset)))
647
648 #define IS_BREAKZ(parser)   IS_BREAKZ_AT(parser,0)
649
650 /*
651  * Check if the character is a line break, space, or NUL.
652  */
653
654 #define IS_SPACEZ_AT(parser,offset) \
655     (IS_SPACE_AT(parser,(offset)) || IS_BREAKZ_AT(parser,(offset)))
656
657 #define IS_SPACEZ(parser)   IS_SPACEZ_AT(parser,0)
658
659 /*
660  * Check if the character is a line break, space, tab, or NUL.
661  */
662
663 #define IS_BLANKZ_AT(parser,offset) \
664     (IS_BLANK_AT(parser,(offset)) || IS_BREAKZ_AT(parser,(offset)))
665
666 #define IS_BLANKZ(parser)   IS_BLANKZ_AT(parser,0)
667
668 /*
669  * Determine the width of the character.
670  */
671
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)
677
678 #define WIDTH(parser)   WIDTH_AT(parser,0)
679
680 /*
681  * Advance the buffer pointer.
682  */
683
684 #define FORWARD(parser)                             \
685      (parser->index ++,                             \
686       parser->column ++,                            \
687       parser->unread --,                            \
688       parser->pointer += WIDTH(parser))
689
690 #define FORWARD_LINE(parser)                        \
691      (IS_CRLF(parser) ?                             \
692       (parser->index += 2,                          \
693        parser->column = 0,                          \
694        parser->unread -= 2,                         \
695        parser->pointer += 2) :                      \
696       IS_BREAK(parser) ?                            \
697       (parser->index ++,                            \
698        parser->column = 0,                          \
699        parser->unread --,                           \
700        parser->pointer += WIDTH(parser)) : 0)
701
702 /*
703  * Resize a string if needed.
704  */
705
706 #define RESIZE(parser,string)   \
707     (string.pointer-string.buffer+5 < string.size ? 1 :  \
708      yaml_parser_resize_string(parser, &string))
709
710 /*
711  * Copy a character to a string buffer and advance pointers.
712  */
713
714 #define COPY(parser,string)     \
715      (((*parser->pointer & 0x80) == 0x00 ?                  \
716        (*(string.pointer++) = *(parser->pointer++)) :       \
717        (*parser->pointer & 0xE0) == 0xC0 ?                  \
718        (*(string.pointer++) = *(parser->pointer++),         \
719         *(string.pointer++) = *(parser->pointer++)) :       \
720        (*parser->pointer & 0xF0) == 0xE0 ?                  \
721        (*(string.pointer++) = *(parser->pointer++),         \
722         *(string.pointer++) = *(parser->pointer++),         \
723         *(string.pointer++) = *(parser->pointer++)) :       \
724        (*parser->pointer & 0xF8) == 0xF0 ?                  \
725        (*(string.pointer++) = *(parser->pointer++),         \
726         *(string.pointer++) = *(parser->pointer++),         \
727         *(string.pointer++) = *(parser->pointer++),         \
728         *(string.pointer++) = *(parser->pointer++)) : 0),   \
729       parser->index ++,                                     \
730       parser->column ++,                                    \
731       parser->unread --)
732     
733
734 /*
735  * Public API declarations.
736  */
737
738 YAML_DECLARE(yaml_token_t *)
739 yaml_parser_get_token(yaml_parser_t *parser);
740
741 YAML_DECLARE(yaml_token_t *)
742 yaml_parser_peek_token(yaml_parser_t *parser);
743
744 /*
745  * Error handling.
746  */
747
748 static int
749 yaml_parser_set_scanner_error(yaml_parser_t *parser, const char *context,
750         yaml_mark_t context_mark, const char *problem);
751
752 static yaml_mark_t
753 yaml_parser_get_mark(yaml_parser_t *parser);
754
755 /*
756  * Buffers and lists.
757  */
758
759 typedef struct {
760     yaml_char_t *buffer;
761     yaml_char_t *pointer;
762     size_t size;
763 } yaml_string_t;
764
765 static yaml_string_t
766 yaml_parser_new_string(yaml_parser_t *parser);
767
768 static int
769 yaml_parser_resize_string(yaml_parser_t *parser, yaml_string_t *string);
770
771 static int
772 yaml_parser_resize_list(yaml_parser_t *parser, void **buffer, size_t *size,
773         size_t item_size);
774
775 /*
776  * High-level token API.
777  */
778
779 static int
780 yaml_parser_fetch_more_tokens(yaml_parser_t *parser);
781
782 static int
783 yaml_parser_fetch_next_token(yaml_parser_t *parser);
784
785 /*
786  * Potential simple keys.
787  */
788
789 static int
790 yaml_parser_stale_simple_keys(yaml_parser_t *parser);
791
792 static int
793 yaml_parser_save_simple_key(yaml_parser_t *parser);
794
795 static int
796 yaml_parser_remove_simple_key(yaml_parser_t *parser);
797
798 static int
799 yaml_parser_increase_flow_level(yaml_parser_t *parser);
800
801 static int
802 yaml_parser_decrease_flow_level(yaml_parser_t *parser);
803
804 /*
805  * Token manipulation.
806  */
807
808 static int
809 yaml_parser_append_token(yaml_parser_t *parser, yaml_token_t *token);
810
811 static int
812 yaml_parser_insert_token(yaml_parser_t *parser,
813         int number, yaml_token_t *token);
814
815 /*
816  * Indentation treatment.
817  */
818
819 static int
820 yaml_parser_roll_indent(yaml_parser_t *parser, int column,
821         int number, yaml_token_type_t type, yaml_mark_t mark);
822
823 static int
824 yaml_parser_unroll_indent(yaml_parser_t *parser, int column);
825
826 /*
827  * Token fetchers.
828  */
829
830 static int
831 yaml_parser_fetch_stream_start(yaml_parser_t *parser);
832
833 static int
834 yaml_parser_fetch_stream_end(yaml_parser_t *parser);
835
836 static int
837 yaml_parser_fetch_directive(yaml_parser_t *parser);
838
839 static int
840 yaml_parser_fetch_document_indicator(yaml_parser_t *parser,
841         yaml_token_type_t type);
842
843 static int
844 yaml_parser_fetch_flow_collection_start(yaml_parser_t *parser,
845         yaml_token_type_t type);
846
847 static int
848 yaml_parser_fetch_flow_collection_end(yaml_parser_t *parser,
849         yaml_token_type_t type);
850
851 static int
852 yaml_parser_fetch_flow_entry(yaml_parser_t *parser);
853
854 static int
855 yaml_parser_fetch_block_entry(yaml_parser_t *parser);
856
857 static int
858 yaml_parser_fetch_key(yaml_parser_t *parser);
859
860 static int
861 yaml_parser_fetch_value(yaml_parser_t *parser);
862
863 static int
864 yaml_parser_fetch_anchor(yaml_parser_t *parser, yaml_token_type_t type);
865
866 static int
867 yaml_parser_fetch_tag(yaml_parser_t *parser);
868
869 static int
870 yaml_parser_fetch_block_scalar(yaml_parser_t *parser, int literal);
871
872 static int
873 yaml_parser_fetch_flow_scalar(yaml_parser_t *parser, int single);
874
875 static int
876 yaml_parser_fetch_plain_scalar(yaml_parser_t *parser);
877
878 /*
879  * Token scanners.
880  */
881
882 static int
883 yaml_parser_scan_to_next_token(yaml_parser_t *parser);
884
885 static yaml_token_t *
886 yaml_parser_scan_directive(yaml_parser_t *parser);
887
888 static int
889 yaml_parser_scan_directive_name(yaml_parser_t *parser,
890         yaml_mark_t start_mark, yaml_char_t **name);
891
892 static int
893 yaml_parser_scan_version_directive_value(yaml_parser_t *parser,
894         yaml_mark_t start_mark, int *major, int *minor);
895
896 static int
897 yaml_parser_scan_version_directive_number(yaml_parser_t *parser,
898         yaml_mark_t start_mark, int *number);
899
900 static int
901 yaml_parser_scan_tag_directive_value(yaml_parser_t *parser,
902         yaml_mark_t mark, yaml_char_t **handle, yaml_char_t **prefix);
903
904 static yaml_token_t *
905 yaml_parser_scan_anchor(yaml_parser_t *parser,
906         yaml_token_type_t type);
907
908 static yaml_token_t *
909 yaml_parser_scan_tag(yaml_parser_t *parser);
910
911 static int
912 yaml_parser_scan_tag_handle(yaml_parser_t *parser, int directive,
913         yaml_mark_t start_mark, yaml_char_t **handle);
914
915 static int
916 yaml_parser_scan_tag_uri(yaml_parser_t *parser, int directive,
917         yaml_char_t *head, yaml_mark_t start_mark, yaml_char_t **uri);
918
919 static int
920 yaml_parser_scan_uri_escapes(yaml_parser_t *parser, int directive,
921         yaml_mark_t start_mark, yaml_string_t *string);
922
923 static yaml_token_t *
924 yaml_parser_scan_block_scalar(yaml_parser_t *parser, int literal);
925
926 static int
927 yaml_parser_scan_block_scalar_indicators(yaml_parser_t *parser,
928         yaml_mark_t start_mark, int *chomping, int *increment);
929
930 static yaml_token_t *
931 yaml_parser_scan_flow_scalar(yaml_parser_t *parser, int single);
932
933 static yaml_token_t *
934 yaml_parser_scan_plain_scalar(yaml_parser_t *parser);
935
936 /*
937  * Get the next token and remove it from the tokens queue.
938  */
939
940 YAML_DECLARE(yaml_token_t *)
941 yaml_parser_get_token(yaml_parser_t *parser)
942 {
943     yaml_token_t *token;
944
945     assert(parser); /* Non-NULL parser object is expected. */
946     assert(!parser->stream_end_produced);   /* No tokens after STREAM-END. */
947
948     /* Ensure that the tokens queue contains enough tokens. */
949
950     if (!yaml_parser_fetch_more_tokens(parser)) return NULL;
951
952     /* Fetch the next token from the queue. */
953
954     token = parser->tokens[parser->tokens_head];
955
956     /* Move the queue head. */
957
958     parser->tokens[parser->tokens_head++] = NULL;
959     if (parser->tokens_head == parser->tokens_size)
960         parser->tokens_head = 0;
961
962     parser->tokens_parsed++;
963
964     return token;
965 }
966
967 /*
968  * Get the next token, but don't remove it from the queue.
969  */
970
971 YAML_DECLARE(yaml_token_t *)
972 yaml_parser_peek_token(yaml_parser_t *parser)
973 {
974     assert(parser); /* Non-NULL parser object is expected. */
975     assert(!parser->stream_end_produced);   /* No tokens after STREAM-END. */
976
977     /* Ensure that the tokens queue contains enough tokens. */
978
979     if (!yaml_parser_fetch_more_tokens(parser)) return NULL;
980
981     /* Fetch the next token from the queue. */
982
983     return parser->tokens[parser->tokens_head];
984 }
985
986 /*
987  * Create a new string.
988  */
989
990 static yaml_string_t
991 yaml_parser_new_string(yaml_parser_t *parser)
992 {
993     yaml_string_t string = { NULL, NULL, 0 };
994
995     string.buffer = yaml_malloc(YAML_DEFAULT_SIZE);
996     if (!string.buffer) {
997         parser->error = YAML_MEMORY_ERROR;
998         return string;
999     }
1000
1001     memset(string.buffer, 0, YAML_DEFAULT_SIZE);
1002     string.pointer = string.buffer;
1003     string.size = YAML_DEFAULT_SIZE;
1004
1005     return string;
1006 }
1007
1008 /*
1009  * Double the size of a string.
1010  */
1011
1012 static int
1013 yaml_parser_resize_string(yaml_parser_t *parser, yaml_string_t *string)
1014 {
1015     yaml_char_t *new_buffer = yaml_realloc(string->buffer, string->size*2);
1016
1017     if (!new_buffer) {
1018         yaml_free(string->buffer);
1019         string->buffer = NULL;
1020         string->pointer = NULL;
1021         string->size = 0;
1022         parser->error = YAML_MEMORY_ERROR;
1023         return 0;
1024     }
1025
1026     memset(new_buffer+string->size, 0, string->size);
1027
1028     string->pointer = new_buffer + (string->buffer-string->pointer);
1029     string->buffer = new_buffer;
1030     string->size *= 2;
1031
1032     return 1;
1033 }
1034
1035 /*
1036  * Double a list.
1037  */
1038
1039 static int
1040 yaml_parser_resize_list(yaml_parser_t *parser, void **buffer, size_t *size,
1041         size_t item_size)
1042 {
1043     void *new_buffer = yaml_realloc(*buffer, item_size*(*size)*2);
1044
1045     if (!new_buffer) {
1046         parser->error = YAML_MEMORY_ERROR;
1047         return 0;
1048     }
1049
1050     memset(new_buffer+(*size), 0, item_size*(*size));
1051
1052     *buffer = new_buffer;
1053     *size *= 2;
1054
1055     return 1;
1056 }
1057
1058 /*
1059  * Set the scanner error and return 0.
1060  */
1061
1062 static int
1063 yaml_parser_set_scanner_error(yaml_parser_t *parser, const char *context,
1064         yaml_mark_t context_mark, const char *problem)
1065 {
1066     parser->error = YAML_SCANNER_ERROR;
1067     parser->context = context;
1068     parser->context_mark = context_mark;
1069     parser->problem = problem;
1070     parser->problem_mark = yaml_parser_get_mark(parser);
1071 }
1072
1073 /*
1074  * Get the mark for the current buffer position.
1075  */
1076
1077 static yaml_mark_t
1078 yaml_parser_get_mark(yaml_parser_t *parser)
1079 {
1080     yaml_mark_t mark = { parser->index, parser->line, parser->column };
1081
1082     return mark;
1083 }
1084
1085
1086 /*
1087  * Ensure that the tokens queue contains at least one token which can be
1088  * returned to the Parser.
1089  */
1090
1091 static int
1092 yaml_parser_fetch_more_tokens(yaml_parser_t *parser)
1093 {
1094     int need_more_tokens;
1095     int k;
1096
1097     /* While we need more tokens to fetch, do it. */
1098
1099     while (1)
1100     {
1101         /*
1102          * Check if we really need to fetch more tokens.
1103          */
1104
1105         need_more_tokens = 0;
1106
1107         if (parser->tokens_head == parser->tokens_tail)
1108         {
1109             /* Queue is empty. */
1110
1111             need_more_tokens = 1;
1112         }
1113         else
1114         {
1115             /* Check if any potential simple key may occupy the head position. */
1116
1117             for (k = 0; k <= parser->flow_level; k++) {
1118                 yaml_simple_key_t *simple_key = parser->simple_keys[k];
1119                 if (simple_key
1120                         && (simple_key->token_number == parser->tokens_parsed)) {
1121                     need_more_tokens = 1;
1122                     break;
1123                 }
1124             }
1125         }
1126
1127         /* We are finished. */
1128
1129         if (!need_more_tokens)
1130             break;
1131
1132         /* Fetch the next token. */
1133
1134         if (!yaml_parser_fetch_next_token(parser))
1135             return 0;
1136     }
1137
1138     return 1;
1139 }
1140
1141 /*
1142  * The dispatcher for token fetchers.
1143  */
1144
1145 static int
1146 yaml_parser_fetch_next_token(yaml_parser_t *parser)
1147 {
1148     /* Ensure that the buffer is initialized. */
1149
1150     if (!UPDATE(parser, 1))
1151         return 0;
1152
1153     /* Check if we just started scanning.  Fetch STREAM-START then. */
1154
1155     if (!parser->stream_start_produced)
1156         return yaml_parser_fetch_stream_start(parser);
1157
1158     /* Eat whitespaces and comments until we reach the next token. */
1159
1160     if (!yaml_parser_scan_to_next_token(parser))
1161         return 0;
1162
1163     /* Check the indentation level against the current column. */
1164
1165     if (!yaml_parser_unroll_indent(parser, parser->column))
1166         return 0;
1167
1168     /*
1169      * Ensure that the buffer contains at least 4 characters.  4 is the length
1170      * of the longest indicators ('--- ' and '... ').
1171      */
1172
1173     if (!UPDATE(parser, 4))
1174         return 0;
1175
1176     /* Is it the end of the stream? */
1177
1178     if (IS_Z(parser))
1179         return yaml_parser_fetch_stream_end(parser);
1180
1181     /* Is it a directive? */
1182
1183     if (parser->column == 0 && CHECK(parser, '%'))
1184         return yaml_parser_fetch_directive(parser);
1185
1186     /* Is it the document start indicator? */
1187
1188     if (parser->column == 0
1189             && CHECK_AT(parser, '-', 0)
1190             && CHECK_AT(parser, '-', 1)
1191             && CHECK_AT(parser, '-', 2)
1192             && IS_BLANKZ_AT(parser, 3))
1193         return yaml_parser_fetch_document_indicator(parser,
1194                 YAML_DOCUMENT_START_TOKEN);
1195
1196     /* Is it the document end indicator? */
1197
1198     if (parser->column == 0
1199             && CHECK_AT(parser, '.', 0)
1200             && CHECK_AT(parser, '.', 1)
1201             && CHECK_AT(parser, '.', 2)
1202             && IS_BLANKZ_AT(parser, 3))
1203         return yaml_parser_fetch_document_indicator(parser,
1204                 YAML_DOCUMENT_END_TOKEN);
1205
1206     /* Is it the flow sequence start indicator? */
1207
1208     if (CHECK(parser, '['))
1209         return yaml_parser_fetch_flow_collection_start(parser,
1210                 YAML_FLOW_SEQUENCE_START_TOKEN);
1211
1212     /* Is it the flow mapping start indicator? */
1213
1214     if (CHECK(parser, '{'))
1215         return yaml_parser_fetch_flow_collection_start(parser,
1216                 YAML_FLOW_MAPPING_START_TOKEN);
1217
1218     /* Is it the flow sequence end indicator? */
1219
1220     if (CHECK(parser, ']'))
1221         return yaml_parser_fetch_flow_collection_end(parser,
1222                 YAML_FLOW_SEQUENCE_END_TOKEN);
1223
1224     /* Is it the flow mapping end indicator? */
1225
1226     if (CHECK(parser, '}'))
1227         return yaml_parser_fetch_flow_collection_end(parser,
1228                 YAML_FLOW_MAPPING_END_TOKEN);
1229
1230     /* Is it the flow entry indicator? */
1231
1232     if (CHECK(parser, ','))
1233         return yaml_parser_fetch_flow_entry(parser);
1234
1235     /* Is it the block entry indicator? */
1236
1237     if (CHECK(parser, '-') && IS_BLANKZ_AT(parser, 1))
1238         return yaml_parser_fetch_block_entry(parser);
1239
1240     /* Is it the key indicator? */
1241
1242     if (CHECK(parser, '?') && (!parser->flow_level || IS_BLANKZ_AT(parser, 1)))
1243         return yaml_parser_fetch_key(parser);
1244
1245     /* Is it the value indicator? */
1246
1247     if (CHECK(parser, ':') && (!parser->flow_level || IS_BLANKZ_AT(parser, 1)))
1248         return yaml_parser_fetch_value(parser);
1249
1250     /* Is it an alias? */
1251
1252     if (CHECK(parser, '*'))
1253         return yaml_parser_fetch_anchor(parser, YAML_ALIAS_TOKEN);
1254
1255     /* Is it an anchor? */
1256
1257     if (CHECK(parser, '&'))
1258         return yaml_parser_fetch_anchor(parser, YAML_ANCHOR_TOKEN);
1259
1260     /* Is it a tag? */
1261
1262     if (CHECK(parser, '!'))
1263         return yaml_parser_fetch_tag(parser);
1264
1265     /* Is it a literal scalar? */
1266
1267     if (CHECK(parser, '|') && !parser->flow_level)
1268         return yaml_parser_fetch_block_scalar(parser, 1);
1269
1270     /* Is it a folded scalar? */
1271
1272     if (CHECK(parser, '>') && !parser->flow_level)
1273         return yaml_parser_fetch_block_scalar(parser, 0);
1274
1275     /* Is it a single-quoted scalar? */
1276
1277     if (CHECK(parser, '\''))
1278         return yaml_parser_fetch_flow_scalar(parser, 1);
1279
1280     /* Is it a double-quoted scalar? */
1281
1282     if (CHECK(parser, '"'))
1283         return yaml_parser_fetch_flow_scalar(parser, 0);
1284
1285     /*
1286      * Is it a plain scalar?
1287      *
1288      * A plain scalar may start with any non-blank characters except
1289      *
1290      *      '-', '?', ':', ',', '[', ']', '{', '}',
1291      *      '#', '&', '*', '!', '|', '>', '\'', '\"',
1292      *      '%', '@', '`'.
1293      *
1294      * In the block context, it may also start with the characters
1295      *
1296      *      '-', '?', ':'
1297      *
1298      * if it is followed by a non-space character.
1299      *
1300      * The last rule is more restrictive than the specification requires.
1301      */
1302
1303     if (!(IS_BLANKZ(parser) || CHECK(parser, '-') || CHECK(parser, '?')
1304                 || CHECK(parser, ':') || CHECK(parser, ',') || CHECK(parser, '[')
1305                 || CHECK(parser, ']') || CHECK(parser, '{') || CHECK(parser, '}')
1306                 || CHECK(parser, '#') || CHECK(parser, '&') || CHECK(parser, '*')
1307                 || CHECK(parser, '!') || CHECK(parser, '|') || CHECK(parser, '>')
1308                 || CHECK(parser, '\'') || CHECK(parser, '"') || CHECK(parser, '%')
1309                 || CHECK(parser, '@') || CHECK(parser, '`')) ||
1310             (!parser->flow_level &&
1311              (CHECK(parser, '-') || CHECK(parser, '?') || CHECK(parser, ':')) &&
1312              IS_BLANKZ_AT(parser, 1)))
1313         return yaml_parser_fetch_plain_scalar(parser);
1314
1315     /*
1316      * If we don't determine the token type so far, it is an error.
1317      */
1318
1319     return yaml_parser_set_scanner_error(parser, "while scanning for the next token",
1320             yaml_parser_get_mark(parser), "found character that cannot start any token");
1321 }
1322
1323 /*
1324  * Check the list of potential simple keys and remove the positions that
1325  * cannot contain simple keys anymore.
1326  */
1327
1328 static int
1329 yaml_parser_stale_simple_keys(yaml_parser_t *parser)
1330 {
1331     int level;
1332
1333     /* Check for a potential simple key for each flow level. */
1334
1335     for (level = 0; level <= parser->flow_level; level++)
1336     {
1337         yaml_simple_key_t *simple_key = parser->simple_keys[level];
1338
1339         /*
1340          * The specification requires that a simple key
1341          *
1342          *  - is limited to a single line,
1343          *  - is shorter than 1024 characters.
1344          */
1345
1346         if (simple_key && (simple_key->line < parser->line ||
1347                     simple_key->index < parser->index+1024)) {
1348
1349             /* Check if the potential simple key to be removed is required. */
1350
1351             if (simple_key->required) {
1352                 return yaml_parser_set_scanner_error(parser,
1353                         "while scanning a simple key", simple_key->mark,
1354                         "could not found expected ':'");
1355             }
1356
1357             yaml_free(simple_key);
1358             parser->simple_keys[level] = NULL;
1359         }
1360     }
1361
1362     return 1;
1363 }
1364
1365 /*
1366  * Check if a simple key may start at the current position and add it if
1367  * needed.
1368  */
1369
1370 static int
1371 yaml_parser_save_simple_key(yaml_parser_t *parser)
1372 {
1373     /*
1374      * A simple key is required at the current position if the scanner is in
1375      * the block context and the current column coincides with the indentation
1376      * level.
1377      */
1378
1379     int required = (!parser->flow_level && parser->indent == parser->column);
1380
1381     /*
1382      * A simple key is required only when it is the first token in the current
1383      * line.  Therefore it is always allowed.  But we add a check anyway.
1384      */
1385
1386     assert(parser->simple_key_allowed || !required);    /* Impossible. */
1387
1388     /*
1389      * If the current position may start a simple key, save it.
1390      */
1391
1392     if (parser->simple_key_allowed)
1393     {
1394         yaml_simple_key_t simple_key = { required,
1395             parser->tokens_parsed + parser->tokens_tail - parser->tokens_head,
1396             parser->index, parser->line, parser->column,
1397             yaml_parser_get_mark(parser) };
1398
1399         if (!yaml_parser_remove_simple_key(parser)) return 0;
1400
1401         parser->simple_keys[parser->flow_level] =
1402             yaml_malloc(sizeof(yaml_simple_key_t));
1403         if (!parser->simple_keys[parser->flow_level]) {
1404             parser->error = YAML_MEMORY_ERROR;
1405             return 0;
1406         }
1407
1408         *(parser->simple_keys[parser->flow_level]) = simple_key;
1409     }
1410
1411     return 1;
1412 }
1413
1414 /*
1415  * Remove a potential simple key at the current flow level.
1416  */
1417
1418 static int
1419 yaml_parser_remove_simple_key(yaml_parser_t *parser)
1420 {
1421     yaml_simple_key_t *simple_key = parser->simple_keys[parser->flow_level];
1422
1423     if (simple_key)
1424     {
1425         /* If the key is required, it is an error. */
1426
1427         if (simple_key->required) {
1428             return yaml_parser_set_scanner_error(parser,
1429                     "while scanning a simple key", simple_key->mark,
1430                     "could not found expected ':'");
1431         }
1432
1433         /* Remove the key from the list. */
1434
1435         yaml_free(simple_key);
1436         parser->simple_keys[parser->flow_level] = NULL;
1437     }
1438
1439     return 1;
1440 }
1441
1442 /*
1443  * Increase the flow level and resize the simple key list if needed.
1444  */
1445
1446 static int
1447 yaml_parser_increase_flow_level(yaml_parser_t *parser)
1448 {
1449     /* Check if we need to resize the list. */
1450
1451     if (parser->flow_level == parser->simple_keys_size-1) {
1452         if (!yaml_parser_resize_list(parser, (void **)&parser->simple_keys,
1453                     &parser->simple_keys_size, sizeof(yaml_simple_key_t *)))
1454             return 0;
1455     }
1456
1457     /* Increase the flow level and reset the simple key. */
1458
1459     parser->simple_keys[++parser->flow_level] = NULL;
1460
1461     return 1;
1462 }
1463
1464 /*
1465  * Decrease the flow level.
1466  */
1467
1468 static int
1469 yaml_parser_decrease_flow_level(yaml_parser_t *parser)
1470 {
1471     assert(parser->flow_level);                         /* Greater than 0. */
1472     assert(!parser->simple_keys[parser->flow_level]);   /* Must be removed. */
1473
1474     parser->flow_level --;
1475
1476     return 1;
1477 }
1478
1479 /*
1480  * Add a token to the tail of the tokens queue.
1481  */
1482
1483 static int
1484 yaml_parser_append_token(yaml_parser_t *parser, yaml_token_t *token)
1485 {
1486     return yaml_parser_insert_token(parser, -1, token);
1487 }
1488
1489 /*
1490  * Insert the token into the tokens queue.  The number parameter is the
1491  * ordinal number of the token.  If the number is equal to -1, add the token
1492  * to the tail of the queue.
1493  */
1494
1495 static int
1496 yaml_parser_insert_token(yaml_parser_t *parser,
1497         int number, yaml_token_t *token)
1498 {
1499     /* The index of the token in the queue. */
1500
1501     int index = (number == -1)
1502             ? parser->tokens_tail - parser->tokens_head
1503             : number - parser->tokens_parsed;
1504
1505     assert(index >= 0 && index <= (parser->tokens_tail-parser->tokens_head));
1506
1507     /* Check if we need to resize the queue. */
1508
1509     if (parser->tokens_head == 0 && parser->tokens_tail == parser->tokens_size) {
1510         if (!yaml_parser_resize_list(parser, (void **)&parser->tokens,
1511                     &parser->tokens_size, sizeof(yaml_token_t *)))
1512             return 0;
1513     }
1514
1515     /* Check if we need to move the queue to the beginning of the buffer. */
1516
1517     if (parser->tokens_tail == parser->tokens_size)
1518     {
1519         if (parser->tokens_head < parser->tokens_tail) {
1520             memmove(parser->tokens, parser->tokens+parser->tokens_head,
1521                     sizeof(yaml_token_t *)*(parser->tokens_tail-parser->tokens_head));
1522         }
1523         parser->tokens_tail -= parser->tokens_head;
1524         parser->tokens_head = 0;
1525     }
1526
1527     /* Check if we need to free space within the queue. */
1528
1529     if (index < (parser->tokens_tail-parser->tokens_head)) {
1530         memmove(parser->tokens+parser->tokens_head+index+1,
1531                 parser->tokens+parser->tokens_head+index,
1532                 sizeof(yaml_token_t *)*(parser->tokens_tail-parser->tokens_head-index));
1533     }
1534
1535     /* Insert the token. */
1536
1537     parser->tokens[parser->tokens_head+index] = token;
1538     parser->tokens_tail ++;
1539
1540     return 1;
1541 }
1542
1543 /*
1544  * Push the current indentation level to the stack and set the new level
1545  * the current column is greater than the indentation level.  In this case,
1546  * append or insert the specified token into the token queue.
1547  * 
1548  */
1549
1550 static int
1551 yaml_parser_roll_indent(yaml_parser_t *parser, int column,
1552         int number, yaml_token_type_t type, yaml_mark_t mark)
1553 {
1554     yaml_token_t *token;
1555
1556     /* In the flow context, do nothing. */
1557
1558     if (parser->flow_level)
1559         return 1;
1560
1561     if (parser->indent < column)
1562     {
1563         /* Check if we need to expand the indents stack. */
1564
1565         if (parser->indents_length == parser->indents_size) {
1566             if (!yaml_parser_resize_list(parser, (void **)&parser->indents,
1567                         &parser->indents_size, sizeof(int)))
1568                 return 0;
1569         }
1570
1571         /*
1572          * Push the current indentation level to the stack and set the new
1573          * indentation level.
1574          */
1575
1576         parser->indents[parser->indents_length++] = parser->indent;
1577         parser->indent = column;
1578
1579         /* Create a token. */
1580
1581         token = yaml_token_new(type, mark, mark);
1582         if (!token) {
1583             parser->error = YAML_MEMORY_ERROR;
1584             return 0;
1585         }
1586
1587         /* Insert the token into the queue. */
1588
1589         if (!yaml_parser_insert_token(parser, number, token)) {
1590             yaml_token_delete(token);
1591             return 0;
1592         }
1593     }
1594
1595     return 1;
1596 }
1597
1598 /*
1599  * Pop indentation levels from the indents stack until the current level
1600  * becomes less or equal to the column.  For each intendation level, append
1601  * the BLOCK-END token.
1602  */
1603
1604
1605 static int
1606 yaml_parser_unroll_indent(yaml_parser_t *parser, int column)
1607 {
1608     yaml_token_t *token;
1609
1610     /* In the flow context, do nothing. */
1611
1612     if (parser->flow_level)
1613         return 1;
1614
1615     /* Loop through the intendation levels in the stack. */
1616
1617     while (parser->indent > column)
1618     {
1619         yaml_mark_t mark = yaml_parser_get_mark(parser);
1620
1621         /* Create a token. */
1622
1623         token = yaml_token_new(YAML_BLOCK_END_TOKEN, mark, mark);
1624         if (!token) {
1625             parser->error = YAML_MEMORY_ERROR;
1626             return 0;
1627         }
1628
1629         /* Append the token to the queue. */
1630
1631         if (!yaml_parser_append_token(parser, token)) {
1632             yaml_token_delete(token);
1633             return 0;
1634         }
1635
1636         /* Pop the indentation level. */
1637
1638         assert(parser->indents_length);     /* Non-empty stack expected. */
1639
1640         parser->indent = parser->indents[--parser->indents_length];
1641     }
1642
1643     return 1;
1644 }
1645
1646 /*
1647  * Initialize the scanner and produce the STREAM-START token.
1648  */
1649
1650 static int
1651 yaml_parser_fetch_stream_start(yaml_parser_t *parser)
1652 {
1653     yaml_mark_t mark = yaml_parser_get_mark(parser);
1654     yaml_token_t *token;
1655
1656     /* Set the initial indentation. */
1657
1658     parser->indent = -1;
1659
1660     /* A simple key is allowed at the beginning of the stream. */
1661
1662     parser->simple_key_allowed = 1;
1663
1664     /* We have started. */
1665
1666     parser->stream_start_produced = 1;
1667
1668     /* Create the STREAM-START token. */
1669
1670     token = yaml_stream_start_token_new(parser->encoding, mark, mark);
1671     if (!token) {
1672         parser->error = YAML_MEMORY_ERROR;
1673         return 0;
1674     }
1675
1676     /* Append the token to the queue. */
1677
1678     if (!yaml_parser_append_token(parser, token)) {
1679         yaml_token_delete(token);
1680         return 0;
1681     }
1682
1683     return 1;
1684 }
1685
1686 /*
1687  * Produce the STREAM-END token and shut down the scanner.
1688  */
1689
1690 static int
1691 yaml_parser_fetch_stream_end(yaml_parser_t *parser)
1692 {
1693     yaml_mark_t mark = yaml_parser_get_mark(parser);
1694     yaml_token_t *token;
1695
1696     /* Reset the indentation level. */
1697
1698     if (!yaml_parser_unroll_indent(parser, -1))
1699         return 0;
1700
1701     /* We have finished. */
1702
1703     parser->stream_end_produced = 1;
1704
1705     /* Create the STREAM-END token. */
1706
1707     token = yaml_stream_end_token_new(mark, mark);
1708     if (!token) {
1709         parser->error = YAML_MEMORY_ERROR;
1710         return 0;
1711     }
1712
1713     /* Append the token to the queue. */
1714
1715     if (!yaml_parser_append_token(parser, token)) {
1716         yaml_token_delete(token);
1717         return 0;
1718     }
1719
1720     return 1;
1721 }
1722
1723 /*
1724  * Produce the YAML-DIRECTIVE or TAG-DIRECTIVE token.
1725  */
1726
1727 static int
1728 yaml_parser_fetch_directive(yaml_parser_t *parser)
1729 {
1730     yaml_token_t *token;
1731
1732     /* Reset the indentation level. */
1733
1734     if (!yaml_parser_unroll_indent(parser, -1))
1735         return 0;
1736
1737     /* Reset simple keys. */
1738
1739     if (!yaml_parser_remove_simple_key(parser))
1740         return 0;
1741
1742     parser->simple_key_allowed = 0;
1743
1744     /* Create the YAML-DIRECTIVE or TAG-DIRECTIVE token. */
1745
1746     token = yaml_parser_scan_directive(parser);
1747     if (!token) return 0;
1748
1749     /* Append the token to the queue. */
1750
1751     if (!yaml_parser_append_token(parser, token)) {
1752         yaml_token_delete(token);
1753         return 0;
1754     }
1755
1756     return 1;
1757 }
1758
1759 /*
1760  * Produce the DOCUMENT-START or DOCUMENT-END token.
1761  */
1762
1763 static int
1764 yaml_parser_fetch_document_indicator(yaml_parser_t *parser,
1765         yaml_token_type_t type)
1766 {
1767     yaml_mark_t start_mark, end_mark;
1768     yaml_token_t *token;
1769
1770     /* Reset the indentation level. */
1771
1772     if (!yaml_parser_unroll_indent(parser, -1))
1773         return 0;
1774
1775     /* Reset simple keys. */
1776
1777     if (!yaml_parser_remove_simple_key(parser))
1778         return 0;
1779
1780     parser->simple_key_allowed = 0;
1781
1782     /* Consume the token. */
1783
1784     start_mark = yaml_parser_get_mark(parser);
1785
1786     FORWARD(parser);
1787     FORWARD(parser);
1788     FORWARD(parser);
1789
1790     end_mark = yaml_parser_get_mark(parser);
1791
1792     /* Create the DOCUMENT-START or DOCUMENT-END token. */
1793
1794     token = yaml_token_new(type, start_mark, end_mark);
1795     if (!token) {
1796         parser->error = YAML_MEMORY_ERROR;
1797         return 0;
1798     }
1799
1800     /* Append the token to the queue. */
1801
1802     if (!yaml_parser_append_token(parser, token)) {
1803         yaml_token_delete(token);
1804         return 0;
1805     }
1806
1807     return 1;
1808 }
1809
1810 /*
1811  * Produce the FLOW-SEQUENCE-START or FLOW-MAPPING-START token.
1812  */
1813
1814 static int
1815 yaml_parser_fetch_flow_collection_start(yaml_parser_t *parser,
1816         yaml_token_type_t type)
1817 {
1818     yaml_mark_t start_mark, end_mark;
1819     yaml_token_t *token;
1820
1821     /* The indicators '[' and '{' may start a simple key. */
1822
1823     if (!yaml_parser_save_simple_key(parser))
1824         return 0;
1825
1826     /* Increase the flow level. */
1827
1828     if (!yaml_parser_increase_flow_level(parser))
1829         return 0;
1830
1831     /* A simple key may follow the indicators '[' and '{'. */
1832
1833     parser->simple_key_allowed = 1;
1834
1835     /* Consume the token. */
1836
1837     start_mark = yaml_parser_get_mark(parser);
1838     FORWARD(parser);
1839     end_mark = yaml_parser_get_mark(parser);
1840
1841     /* Create the FLOW-SEQUENCE-START of FLOW-MAPPING-START token. */
1842
1843     token = yaml_token_new(type, start_mark, end_mark);
1844     if (!token) {
1845         parser->error = YAML_MEMORY_ERROR;
1846         return 0;
1847     }
1848
1849     /* Append the token to the queue. */
1850
1851     if (!yaml_parser_append_token(parser, token)) {
1852         yaml_token_delete(token);
1853         return 0;
1854     }
1855
1856     return 1;
1857 }
1858
1859 /*
1860  * Produce the FLOW-SEQUENCE-END or FLOW-MAPPING-END token.
1861  */
1862
1863 static int
1864 yaml_parser_fetch_flow_collection_end(yaml_parser_t *parser,
1865         yaml_token_type_t type)
1866 {
1867     yaml_mark_t start_mark, end_mark;
1868     yaml_token_t *token;
1869
1870     /* Reset any potential simple key on the current flow level. */
1871
1872     if (!yaml_parser_remove_simple_key(parser))
1873         return 0;
1874
1875     /* Decrease the flow level. */
1876
1877     if (!yaml_parser_decrease_flow_level(parser))
1878         return 0;
1879
1880     /* No simple keys after the indicators ']' and '}'. */
1881
1882     parser->simple_key_allowed = 0;
1883
1884     /* Consume the token. */
1885
1886     start_mark = yaml_parser_get_mark(parser);
1887     FORWARD(parser);
1888     end_mark = yaml_parser_get_mark(parser);
1889
1890     /* Create the FLOW-SEQUENCE-END of FLOW-MAPPING-END token. */
1891
1892     token = yaml_token_new(type, start_mark, end_mark);
1893     if (!token) {
1894         parser->error = YAML_MEMORY_ERROR;
1895         return 0;
1896     }
1897
1898     /* Append the token to the queue. */
1899
1900     if (!yaml_parser_append_token(parser, token)) {
1901         yaml_token_delete(token);
1902         return 0;
1903     }
1904
1905     return 1;
1906 }
1907
1908 /*
1909  * Produce the FLOW-ENTRY token.
1910  */
1911
1912 static int
1913 yaml_parser_fetch_flow_entry(yaml_parser_t *parser)
1914 {
1915     yaml_mark_t start_mark, end_mark;
1916     yaml_token_t *token;
1917
1918     /* Reset any potential simple keys on the current flow level. */
1919
1920     if (!yaml_parser_remove_simple_key(parser))
1921         return 0;
1922
1923     /* Simple keys are allowed after ','. */
1924
1925     parser->simple_key_allowed = 1;
1926
1927     /* Consume the token. */
1928
1929     start_mark = yaml_parser_get_mark(parser);
1930     FORWARD(parser);
1931     end_mark = yaml_parser_get_mark(parser);
1932
1933     /* Create the FLOW-ENTRY token. */
1934
1935     token = yaml_token_new(YAML_FLOW_ENTRY_TOKEN, start_mark, end_mark);
1936     if (!token) {
1937         parser->error = YAML_MEMORY_ERROR;
1938         return 0;
1939     }
1940
1941     /* Append the token to the queue. */
1942
1943     if (!yaml_parser_append_token(parser, token)) {
1944         yaml_token_delete(token);
1945         return 0;
1946     }
1947
1948     return 1;
1949 }
1950
1951 /*
1952  * Produce the BLOCK-ENTRY token.
1953  */
1954
1955 static int
1956 yaml_parser_fetch_block_entry(yaml_parser_t *parser)
1957 {
1958     yaml_mark_t start_mark, end_mark;
1959     yaml_token_t *token;
1960
1961     /* Check if the scanner is in the block context. */
1962
1963     if (!parser->flow_level)
1964     {
1965         /* Check if we are allowed to start a new entry. */
1966
1967         if (!parser->simple_key_allowed) {
1968             return yaml_parser_set_scanner_error(parser, NULL,
1969                     yaml_parser_get_mark(parser),
1970                     "block sequence entries are not allowed in this context");
1971         }
1972
1973         /* Add the BLOCK-SEQUENCE-START token if needed. */
1974
1975         if (!yaml_parser_roll_indent(parser, parser->column, -1,
1976                     YAML_BLOCK_SEQUENCE_START_TOKEN, yaml_parser_get_mark(parser)))
1977             return 0;
1978     }
1979     else
1980     {
1981         /*
1982          * It is an error for the '-' indicator to occur in the flow context,
1983          * but we let the Parser detect and report about it because the Parser
1984          * is able to point to the context.
1985          */
1986     }
1987
1988     /* Reset any potential simple keys on the current flow level. */
1989
1990     if (!yaml_parser_remove_simple_key(parser))
1991         return 0;
1992
1993     /* Simple keys are allowed after '-'. */
1994
1995     parser->simple_key_allowed = 1;
1996
1997     /* Consume the token. */
1998
1999     start_mark = yaml_parser_get_mark(parser);
2000     FORWARD(parser);
2001     end_mark = yaml_parser_get_mark(parser);
2002
2003     /* Create the BLOCK-ENTRY token. */
2004
2005     token = yaml_token_new(YAML_BLOCK_ENTRY_TOKEN, start_mark, end_mark);
2006     if (!token) {
2007         parser->error = YAML_MEMORY_ERROR;
2008         return 0;
2009     }
2010
2011     /* Append the token to the queue. */
2012
2013     if (!yaml_parser_append_token(parser, token)) {
2014         yaml_token_delete(token);
2015         return 0;
2016     }
2017
2018     return 1;
2019 }
2020
2021 /*
2022  * Produce the KEY token.
2023  */
2024
2025 static int
2026 yaml_parser_fetch_key(yaml_parser_t *parser)
2027 {
2028     yaml_mark_t start_mark, end_mark;
2029     yaml_token_t *token;
2030
2031     /* In the block context, additional checks are required. */
2032
2033     if (!parser->flow_level)
2034     {
2035         /* Check if we are allowed to start a new key (not nessesary simple). */
2036
2037         if (!parser->simple_key_allowed) {
2038             return yaml_parser_set_scanner_error(parser, NULL,
2039                     yaml_parser_get_mark(parser),
2040                     "mapping keys are not allowed in this context");
2041         }
2042
2043         /* Add the BLOCK-MAPPING-START token if needed. */
2044
2045         if (!yaml_parser_roll_indent(parser, parser->column, -1,
2046                     YAML_BLOCK_MAPPING_START_TOKEN, yaml_parser_get_mark(parser)))
2047             return 0;
2048     }
2049
2050     /* Reset any potential simple keys on the current flow level. */
2051
2052     if (!yaml_parser_remove_simple_key(parser))
2053         return 0;
2054
2055     /* Simple keys are allowed after '?' in the block context. */
2056
2057     parser->simple_key_allowed = (!parser->flow_level);
2058
2059     /* Consume the token. */
2060
2061     start_mark = yaml_parser_get_mark(parser);
2062     FORWARD(parser);
2063     end_mark = yaml_parser_get_mark(parser);
2064
2065     /* Create the KEY token. */
2066
2067     token = yaml_token_new(YAML_KEY_TOKEN, start_mark, end_mark);
2068     if (!token) {
2069         parser->error = YAML_MEMORY_ERROR;
2070         return 0;
2071     }
2072
2073     /* Append the token to the queue. */
2074
2075     if (!yaml_parser_append_token(parser, token)) {
2076         yaml_token_delete(token);
2077         return 0;
2078     }
2079
2080     return 1;
2081 }
2082
2083 /*
2084  * Produce the VALUE token.
2085  */
2086
2087 static int
2088 yaml_parser_fetch_value(yaml_parser_t *parser)
2089 {
2090     yaml_mark_t start_mark, end_mark;
2091     yaml_token_t *token;
2092
2093     /* Have we found a simple key? */
2094
2095     if (parser->simple_keys[parser->flow_level])
2096     {
2097         yaml_simple_key_t *simple_key = parser->simple_keys[parser->flow_level];
2098
2099         /* Create the KEY token. */
2100
2101         token = yaml_token_new(YAML_KEY_TOKEN, simple_key->mark, simple_key->mark);
2102         if (!token) {
2103             parser->error = YAML_MEMORY_ERROR;
2104             return 0;
2105         }
2106
2107         /* Insert the token into the queue. */
2108
2109         if (!yaml_parser_insert_token(parser, simple_key->token_number, token)) {
2110             yaml_token_delete(token);
2111             return 0;
2112         }
2113
2114         /* In the block context, we may need to add the BLOCK-MAPPING-START token. */
2115
2116         if (!yaml_parser_roll_indent(parser, parser->column,
2117                     simple_key->token_number,
2118                     YAML_BLOCK_MAPPING_START_TOKEN, simple_key->mark))
2119             return 0;
2120
2121         /* Remove the simple key from the list. */
2122
2123         yaml_free(simple_key);
2124         parser->simple_keys[parser->flow_level] = NULL;
2125
2126         /* A simple key cannot follow another simple key. */
2127
2128         parser->simple_key_allowed = 0;
2129     }
2130     else
2131     {
2132         /* The ':' indicator follows a complex key. */
2133
2134         /* In the block context, extra checks are required. */
2135
2136         if (!parser->flow_level)
2137         {
2138             /* Check if we are allowed to start a complex value. */
2139
2140             if (!parser->simple_key_allowed) {
2141                 return yaml_parser_set_scanner_error(parser, NULL,
2142                         yaml_parser_get_mark(parser),
2143                         "mapping values are not allowed in this context");
2144             }
2145
2146             /* Add the BLOCK-MAPPING-START token if needed. */
2147
2148             if (!yaml_parser_roll_indent(parser, parser->column, -1,
2149                         YAML_BLOCK_MAPPING_START_TOKEN, yaml_parser_get_mark(parser)))
2150                 return 0;
2151         }
2152
2153         /* Simple keys after ':' are allowed in the block context. */
2154
2155         parser->simple_key_allowed = (!parser->flow_level);
2156     }
2157
2158     /* Consume the token. */
2159
2160     start_mark = yaml_parser_get_mark(parser);
2161     FORWARD(parser);
2162     end_mark = yaml_parser_get_mark(parser);
2163
2164     /* Create the VALUE token. */
2165
2166     token = yaml_token_new(YAML_VALUE_TOKEN, start_mark, end_mark);
2167     if (!token) {
2168         parser->error = YAML_MEMORY_ERROR;
2169         return 0;
2170     }
2171
2172     /* Append the token to the queue. */
2173
2174     if (!yaml_parser_append_token(parser, token)) {
2175         yaml_token_delete(token);
2176         return 0;
2177     }
2178
2179     return 1;
2180 }
2181
2182 /*
2183  * Produce the ALIAS or ANCHOR token.
2184  */
2185
2186 static int
2187 yaml_parser_fetch_anchor(yaml_parser_t *parser, yaml_token_type_t type)
2188 {
2189     yaml_token_t *token;
2190
2191     /* An anchor or an alias could be a simple key. */
2192
2193     if (!yaml_parser_save_simple_key(parser))
2194         return 0;
2195
2196     /* A simple key cannot follow an anchor or an alias. */
2197
2198     parser->simple_key_allowed = 0;
2199
2200     /* Create the ALIAS or ANCHOR token. */
2201
2202     token = yaml_parser_scan_anchor(parser, type);
2203     if (!token) return 0;
2204
2205     /* Append the token to the queue. */
2206
2207     if (!yaml_parser_append_token(parser, token)) {
2208         yaml_token_delete(token);
2209         return 0;
2210     }
2211
2212     return 1;
2213 }
2214
2215 /*
2216  * Produce the TAG token.
2217  */
2218
2219 static int
2220 yaml_parser_fetch_tag(yaml_parser_t *parser)
2221 {
2222     yaml_token_t *token;
2223
2224     /* A tag could be a simple key. */
2225
2226     if (!yaml_parser_save_simple_key(parser))
2227         return 0;
2228
2229     /* A simple key cannot follow a tag. */
2230
2231     parser->simple_key_allowed = 0;
2232
2233     /* Create the TAG token. */
2234
2235     token = yaml_parser_scan_tag(parser);
2236     if (!token) return 0;
2237
2238     /* Append the token to the queue. */
2239
2240     if (!yaml_parser_append_token(parser, token)) {
2241         yaml_token_delete(token);
2242         return 0;
2243     }
2244
2245     return 1;
2246 }
2247
2248 /*
2249  * Produce the SCALAR(...,literal) or SCALAR(...,folded) tokens.
2250  */
2251
2252 static int
2253 yaml_parser_fetch_block_scalar(yaml_parser_t *parser, int literal)
2254 {
2255     yaml_token_t *token;
2256
2257     /* Remove any potential simple keys. */
2258
2259     if (!yaml_parser_remove_simple_key(parser))
2260         return 0;
2261
2262     /* A simple key may follow a block scalar. */
2263
2264     parser->simple_key_allowed = 1;
2265
2266     /* Create the SCALAR token. */
2267
2268     token = yaml_parser_scan_block_scalar(parser, literal);
2269     if (!token) return 0;
2270
2271     /* Append the token to the queue. */
2272
2273     if (!yaml_parser_append_token(parser, token)) {
2274         yaml_token_delete(token);
2275         return 0;
2276     }
2277
2278     return 1;
2279 }
2280
2281 /*
2282  * Produce the SCALAR(...,single-quoted) or SCALAR(...,double-quoted) tokens.
2283  */
2284
2285 static int
2286 yaml_parser_fetch_flow_scalar(yaml_parser_t *parser, int single)
2287 {
2288     yaml_token_t *token;
2289
2290     /* A plain scalar could be a simple key. */
2291
2292     if (!yaml_parser_save_simple_key(parser))
2293         return 0;
2294
2295     /* A simple key cannot follow a flow scalar. */
2296
2297     parser->simple_key_allowed = 0;
2298
2299     /* Create the SCALAR token. */
2300
2301     token = yaml_parser_scan_flow_scalar(parser, single);
2302     if (!token) return 0;
2303
2304     /* Append the token to the queue. */
2305
2306     if (!yaml_parser_append_token(parser, token)) {
2307         yaml_token_delete(token);
2308         return 0;
2309     }
2310
2311     return 1;
2312 }
2313
2314 /*
2315  * Produce the SCALAR(...,plain) token.
2316  */
2317
2318 static int
2319 yaml_parser_fetch_plain_scalar(yaml_parser_t *parser)
2320 {
2321     yaml_token_t *token;
2322
2323     /* A plain scalar could be a simple key. */
2324
2325     if (!yaml_parser_save_simple_key(parser))
2326         return 0;
2327
2328     /* A simple key cannot follow a flow scalar. */
2329
2330     parser->simple_key_allowed = 0;
2331
2332     /* Create the SCALAR token. */
2333
2334     token = yaml_parser_scan_plain_scalar(parser);
2335     if (!token) return 0;
2336
2337     /* Append the token to the queue. */
2338
2339     if (!yaml_parser_append_token(parser, token)) {
2340         yaml_token_delete(token);
2341         return 0;
2342     }
2343
2344     return 1;
2345 }
2346
2347 /*
2348  * Eat whitespaces and comments until the next token is found.
2349  */
2350
2351 static int
2352 yaml_parser_scan_to_next_token(yaml_parser_t *parser)
2353 {
2354     /* Until the next token is not found. */
2355
2356     while (1)
2357     {
2358         /* Allow the BOM mark to start a line. */
2359
2360         if (!UPDATE(parser, 1)) return 0;
2361
2362         if (parser->column == 0 && IS_BOM(parser))
2363             FORWARD(parser);
2364
2365         /*
2366          * Eat whitespaces.
2367          *
2368          * Tabs are allowed:
2369          *
2370          *  - in the flow context;
2371          *  - in the block context, but not at the beginning of the line or
2372          *  after '-', '?', or ':' (complex value).  
2373          */
2374
2375         if (!UPDATE(parser, 1)) return 0;
2376
2377         while (CHECK(parser,' ') ||
2378                 ((parser->flow_level || !parser->simple_key_allowed) &&
2379                  CHECK(parser, '\t'))) {
2380             FORWARD(parser);
2381             if (!UPDATE(parser, 1)) return 0;
2382         }
2383
2384         /* Eat a comment until a line break. */
2385
2386         if (CHECK(parser, '#')) {
2387             while (!IS_BREAKZ(parser)) {
2388                 FORWARD(parser);
2389                 if (!UPDATE(parser, 1)) return 0;
2390             }
2391         }
2392
2393         /* If it is a line break, eat it. */
2394
2395         if (IS_BREAK(parser))
2396         {
2397             if (!UPDATE(parser, 2)) return 0;
2398             FORWARD_LINE(parser);
2399
2400             /* In the block context, a new line may start a simple key. */
2401
2402             if (!parser->flow_level) {
2403                 parser->simple_key_allowed = 1;
2404             }
2405         }
2406         else
2407         {
2408             /* We have found a token. */
2409
2410             break;
2411         }
2412     }
2413
2414     return 1;
2415 }
2416
2417 /*
2418  * Scan a YAML-DIRECTIVE or TAG-DIRECTIVE token.
2419  *
2420  * Scope:
2421  *      %YAML    1.1    # a comment \n
2422  *      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2423  *      %TAG    !yaml!  tag:yaml.org,2002:  \n
2424  *      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2425  */
2426
2427 static yaml_token_t *
2428 yaml_parser_scan_directive(yaml_parser_t *parser)
2429 {
2430     yaml_mark_t start_mark, end_mark;
2431     yaml_char_t *name = NULL;
2432     int major, minor;
2433     yaml_char_t *handle = NULL, *prefix = NULL;
2434     yaml_token_t *token = NULL;
2435
2436     /* Eat '%'. */
2437
2438     start_mark = yaml_parser_get_mark(parser);
2439
2440     FORWARD(parser);
2441
2442     /* Scan the directive name. */
2443
2444     if (!yaml_parser_scan_directive_name(parser, start_mark, &name))
2445         goto error;
2446
2447     /* Is it a YAML directive? */
2448
2449     if (strcmp((char *)name, "YAML") == 0)
2450     {
2451         /* Scan the VERSION directive value. */
2452
2453         if (!yaml_parser_scan_version_directive_value(parser, start_mark,
2454                     &major, &minor))
2455             goto error;
2456
2457         end_mark = yaml_parser_get_mark(parser);
2458
2459         /* Create a VERSION-DIRECTIVE token. */
2460
2461         token = yaml_version_directive_token_new(major, minor,
2462                 start_mark, end_mark);
2463         if (!token) goto error;
2464     }
2465
2466     /* Is it a TAG directive? */
2467
2468     else if (strcmp((char *)name, "TAG") == 0)
2469     {
2470         /* Scan the TAG directive value. */
2471
2472         if (!yaml_parser_scan_tag_directive_value(parser, start_mark,
2473                     &handle, &prefix))
2474             goto error;
2475
2476         end_mark = yaml_parser_get_mark(parser);
2477
2478         /* Create a TAG-DIRECTIVE token. */
2479
2480         token = yaml_tag_directive_token_new(handle, prefix,
2481                 start_mark, end_mark);
2482         if (!token) goto error;
2483     }
2484
2485     /* Unknown directive. */
2486
2487     else
2488     {
2489         yaml_parser_set_scanner_error(parser, "While scanning a directive",
2490                 start_mark, "found uknown directive name");
2491         goto error;
2492     }
2493
2494     /* Eat the rest of the line including any comments. */
2495
2496     while (IS_BLANK(parser)) {
2497         FORWARD(parser);
2498         if (!UPDATE(parser, 1)) goto error;
2499     }
2500
2501     if (CHECK(parser, '#')) {
2502         while (!IS_BREAKZ(parser)) {
2503             FORWARD(parser);
2504             if (!UPDATE(parser, 1)) goto error;
2505         }
2506     }
2507
2508     /* Check if we are at the end of the line. */
2509
2510     if (!IS_BREAKZ(parser)) {
2511         yaml_parser_set_scanner_error(parser, "While scanning a directive",
2512                 start_mark, "did not found expected comment or line break");
2513         goto error;
2514     }
2515
2516     /* Eat a line break. */
2517
2518     if (IS_BREAK(parser)) {
2519         if (!UPDATE(parser, 2)) goto error;
2520         FORWARD_LINE(parser);
2521     }
2522
2523     yaml_free(name);
2524
2525     return token;
2526
2527 error:
2528     yaml_free(token);
2529     yaml_free(prefix);
2530     yaml_free(handle);
2531     yaml_free(name);
2532     return NULL;
2533 }
2534
2535 /*
2536  * Scan the directive name.
2537  *
2538  * Scope:
2539  *      %YAML   1.1     # a comment \n
2540  *       ^^^^
2541  *      %TAG    !yaml!  tag:yaml.org,2002:  \n
2542  *       ^^^
2543  */
2544
2545 static int
2546 yaml_parser_scan_directive_name(yaml_parser_t *parser,
2547         yaml_mark_t start_mark, yaml_char_t **name)
2548 {
2549     yaml_string_t string = yaml_parser_new_string(parser);
2550
2551     if (!string.buffer) goto error;
2552
2553     /* Consume the directive name. */
2554
2555     if (!UPDATE(parser, 1)) goto error;
2556
2557     while (IS_ALPHA(parser))
2558     {
2559         if (!RESIZE(parser, string)) goto error;
2560         COPY(parser, string);
2561         if (!UPDATE(parser, 1)) goto error;
2562     }
2563
2564     /* Check if the name is empty. */
2565
2566     if (string.buffer == string.pointer) {
2567         yaml_parser_set_scanner_error(parser, "while scanning a directive",
2568                 start_mark, "cannot found expected directive name");
2569         goto error;
2570     }
2571
2572     /* Check for an blank character after the name. */
2573
2574     if (!IS_BLANKZ(parser)) {
2575         yaml_parser_set_scanner_error(parser, "while scanning a directive",
2576                 start_mark, "found unexpected non-alphabetical character");
2577         goto error;
2578     }
2579
2580     *name = string.buffer;
2581
2582     return 1;
2583
2584 error:
2585     yaml_free(string.buffer);
2586     return 0;
2587 }
2588
2589 /*
2590  * Scan the value of VERSION-DIRECTIVE.
2591  *
2592  * Scope:
2593  *      %YAML   1.1     # a comment \n
2594  *           ^^^^^^
2595  */
2596
2597 static int
2598 yaml_parser_scan_version_directive_value(yaml_parser_t *parser,
2599         yaml_mark_t start_mark, int *major, int *minor)
2600 {
2601     /* Eat whitespaces. */
2602
2603     if (!UPDATE(parser, 1)) return 0;
2604
2605     while (IS_BLANK(parser)) {
2606         FORWARD(parser);
2607         if (!UPDATE(parser, 1)) return 0;
2608     }
2609
2610     /* Consume the major version number. */
2611
2612     if (!yaml_parser_scan_version_directive_number(parser, start_mark, major))
2613         return 0;
2614
2615     /* Eat '.'. */
2616
2617     if (!CHECK(parser, '.')) {
2618         return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
2619                 start_mark, "did not find expected digit or '.' character");
2620     }
2621
2622     FORWARD(parser);
2623
2624     /* Consume the minor version number. */
2625
2626     if (!yaml_parser_scan_version_directive_number(parser, start_mark, minor))
2627         return 0;
2628 }
2629
2630 #define MAX_NUMBER_LENGTH   9
2631
2632 /*
2633  * Scan the version number of VERSION-DIRECTIVE.
2634  *
2635  * Scope:
2636  *      %YAML   1.1     # a comment \n
2637  *              ^
2638  *      %YAML   1.1     # a comment \n
2639  *                ^
2640  */
2641
2642 static int
2643 yaml_parser_scan_version_directive_number(yaml_parser_t *parser,
2644         yaml_mark_t start_mark, int *number)
2645 {
2646     int value = 0;
2647     size_t length = 0;
2648
2649     /* Repeat while the next character is digit. */
2650
2651     if (!UPDATE(parser, 1)) return 0;
2652
2653     while (IS_DIGIT(parser))
2654     {
2655         /* Check if the number is too long. */
2656
2657         if (++length > MAX_NUMBER_LENGTH) {
2658             return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
2659                     start_mark, "found extremely long version number");
2660         }
2661
2662         value = value*10 + AS_DIGIT(parser);
2663
2664         FORWARD(parser);
2665
2666         if (!UPDATE(parser, 1)) return 0;
2667     }
2668
2669     /* Check if the number was present. */
2670
2671     if (!length) {
2672         return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
2673                 start_mark, "did not find expected version number");
2674     }
2675
2676     *number = value;
2677
2678     return 1;
2679 }
2680
2681 /*
2682  * Scan the value of a TAG-DIRECTIVE token.
2683  *
2684  * Scope:
2685  *      %TAG    !yaml!  tag:yaml.org,2002:  \n
2686  *          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2687  */
2688
2689 static int
2690 yaml_parser_scan_tag_directive_value(yaml_parser_t *parser,
2691         yaml_mark_t start_mark, yaml_char_t **handle, yaml_char_t **prefix)
2692 {
2693     yaml_char_t *handle_value = NULL;
2694     yaml_char_t *prefix_value = NULL;
2695
2696     /* Eat whitespaces. */
2697
2698     if (!UPDATE(parser, 1)) goto error;
2699
2700     while (IS_BLANK(parser)) {
2701         FORWARD(parser);
2702         if (!UPDATE(parser, 1)) goto error;
2703     }
2704
2705     /* Scan a handle. */
2706
2707     if (!yaml_parser_scan_tag_handle(parser, 1, start_mark, &handle_value))
2708         goto error;
2709
2710     /* Expect a whitespace. */
2711
2712     if (!UPDATE(parser, 1)) goto error;
2713
2714     if (!IS_BLANK(parser)) {
2715         yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive",
2716                 start_mark, "did not find expected whitespace");
2717         goto error;
2718     }
2719
2720     /* Eat whitespaces. */
2721
2722     while (IS_BLANK(parser)) {
2723         FORWARD(parser);
2724         if (!UPDATE(parser, 1)) goto error;
2725     }
2726
2727     /* Scan a prefix. */
2728
2729     if (!yaml_parser_scan_tag_uri(parser, 1, NULL, start_mark, &prefix_value))
2730         goto error;
2731
2732     /* Expect a whitespace or line break. */
2733
2734     if (!UPDATE(parser, 1)) goto error;
2735
2736     if (!IS_BLANKZ(parser)) {
2737         yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive",
2738                 start_mark, "did not find expected whitespace or line break");
2739         goto error;
2740     }
2741
2742     *handle = handle_value;
2743     *prefix = prefix_value;
2744
2745     return 1;
2746
2747 error:
2748     yaml_free(handle_value);
2749     yaml_free(prefix_value);
2750     return 0;
2751 }
2752
2753 static yaml_token_t *
2754 yaml_parser_scan_anchor(yaml_parser_t *parser,
2755         yaml_token_type_t type)
2756 {
2757     int length = 0;
2758     yaml_mark_t start_mark, end_mark;
2759     yaml_token_t *token = NULL;
2760     yaml_string_t string = yaml_parser_new_string(parser);
2761
2762     if (!string.buffer) goto error;
2763
2764     /* Eat the indicator character. */
2765
2766     start_mark = yaml_parser_get_mark(parser);
2767
2768     FORWARD(parser);
2769
2770     /* Consume the value. */
2771
2772     if (!UPDATE(parser, 1)) goto error;
2773
2774     while (IS_ALPHA(parser)) {
2775         if (!RESIZE(parser, string)) goto error;
2776         COPY(parser, string);
2777         if (!UPDATE(parser, 1)) goto error;
2778         length ++;
2779     }
2780
2781     end_mark = yaml_parser_get_mark(parser);
2782
2783     /*
2784      * Check if length of the anchor is greater than 0 and it is followed by
2785      * a whitespace character or one of the indicators:
2786      *
2787      *      '?', ':', ',', ']', '}', '%', '@', '`'.
2788      */
2789
2790     if (!length || !(IS_BLANKZ(parser) || CHECK(parser, '?') || CHECK(parser, ':') ||
2791                 CHECK(parser, ',') || CHECK(parser, ']') || CHECK(parser, '}') ||
2792                 CHECK(parser, '%') || CHECK(parser, '@') || CHECK(parser, '`'))) {
2793         yaml_parser_set_scanner_error(parser, type == YAML_ANCHOR_TOKEN ?
2794                 "while scanning an anchor" : "while scanning an alias", start_mark,
2795                 "did not find expected alphabetic or numeric character");
2796         goto error;
2797     }
2798
2799     /* Create a token. */
2800
2801     token = type == YAML_ANCHOR_TOKEN ?
2802         yaml_anchor_token_new(string.buffer, start_mark, end_mark) :
2803         yaml_alias_token_new(string.buffer, start_mark, end_mark);
2804     if (!token) goto error;
2805
2806     return token;
2807
2808 error:
2809     yaml_free(string.buffer);
2810     yaml_free(token);
2811     return 0;
2812 }
2813
2814 /*
2815  * Scan a TAG token.
2816  */
2817
2818 static yaml_token_t *
2819 yaml_parser_scan_tag(yaml_parser_t *parser)
2820 {
2821     yaml_char_t *handle = NULL;
2822     yaml_char_t *suffix = NULL;
2823     yaml_token_t *token = NULL;
2824     yaml_mark_t start_mark, end_mark;
2825
2826     start_mark = yaml_parser_get_mark(parser);
2827
2828     /* Check if the tag is in the canonical form. */
2829
2830     if (!UPDATE(parser, 2)) goto error;
2831
2832     if (CHECK_AT(parser, '<', 1))
2833     {
2834         /* Set the handle to '' */
2835
2836         handle = yaml_malloc(1);
2837         if (!handle) goto error;
2838         handle[0] = '\0';
2839
2840         /* Eat '!<' */
2841
2842         FORWARD(parser);
2843         FORWARD(parser);
2844
2845         /* Consume the tag value. */
2846
2847         if (!yaml_parser_scan_tag_uri(parser, 0, NULL, start_mark, &suffix))
2848             goto error;
2849
2850         /* Check for '>' and eat it. */
2851
2852         if (!CHECK(parser, '>')) {
2853             yaml_parser_set_scanner_error(parser, "while scanning a tag",
2854                     start_mark, "did not find the expected '>'");
2855             goto error;
2856         }
2857
2858         FORWARD(parser);
2859     }
2860     else
2861     {
2862         /* The tag has either the '!suffix' or the '!handle!suffix' form. */
2863
2864         /* First, try to scan a handle. */
2865
2866         if (!yaml_parser_scan_tag_handle(parser, 0, start_mark, &handle))
2867             goto error;
2868
2869         /* Check if it is, indeed, handle. */
2870
2871         if (handle[0] == '!' && handle[1] != '\0' && handle[strlen((char *)handle)-1] == '!')
2872         {
2873             /* Scan the suffix now. */
2874
2875             if (!yaml_parser_scan_tag_uri(parser, 0, NULL, start_mark, &suffix))
2876                 goto error;
2877         }
2878         else
2879         {
2880             /* It wasn't a handle after all.  Scan the rest of the tag. */
2881
2882             if (!yaml_parser_scan_tag_uri(parser, 0, handle, start_mark, &suffix))
2883                 goto error;
2884
2885             /* Set the handle to '!'. */
2886
2887             yaml_free(handle);
2888             handle = yaml_malloc(2);
2889             if (!handle) goto error;
2890             handle[0] = '!';
2891             handle[1] = '\0';
2892         }
2893     }
2894
2895     /* Check the character which ends the tag. */
2896
2897     if (!UPDATE(parser, 1)) goto error;
2898
2899     if (!IS_BLANKZ(parser)) {
2900         yaml_parser_set_scanner_error(parser, "while scanning a tag",
2901                 start_mark, "did not found expected whitespace or line break");
2902         goto error;
2903     }
2904
2905     end_mark = yaml_parser_get_mark(parser);
2906
2907     /* Create a token. */
2908
2909     token = yaml_tag_token_new(handle, suffix, start_mark, end_mark);
2910     if (!token) goto error;
2911
2912     return token;
2913
2914 error:
2915     yaml_free(handle);
2916     yaml_free(suffix);
2917     return NULL;
2918 }
2919
2920 /*
2921  * Scan a tag handle.
2922  */
2923
2924 static int
2925 yaml_parser_scan_tag_handle(yaml_parser_t *parser, int directive,
2926         yaml_mark_t start_mark, yaml_char_t **handle)
2927 {
2928     yaml_string_t string = yaml_parser_new_string(parser);
2929
2930     if (!string.buffer) goto error;
2931
2932     /* Check the initial '!' character. */
2933
2934     if (!UPDATE(parser, 1)) goto error;
2935
2936     if (!CHECK(parser, '!')) {
2937         yaml_parser_set_scanner_error(parser, directive ?
2938                 "while scanning a tag directive" : "while scanning a tag",
2939                 start_mark, "did not find expected '!'");
2940         goto error;
2941     }
2942
2943     /* Copy the '!' character. */
2944
2945     COPY(parser, string);
2946
2947     /* Copy all subsequent alphabetical and numerical characters. */
2948
2949     if (!UPDATE(parser, 1)) goto error;
2950
2951     while (IS_ALPHA(parser))
2952     {
2953         if (!RESIZE(parser, string)) goto error;
2954         COPY(parser, string);
2955         if (!UPDATE(parser, 1)) goto error;
2956     }
2957
2958     /* Check if the trailing character is '!' and copy it. */
2959
2960     if (CHECK(parser, '!'))
2961     {
2962         if (!RESIZE(parser, string)) goto error;
2963         COPY(parser, string);
2964     }
2965     else
2966     {
2967         /*
2968          * It's not really a tag handle.  If it's a %TAG directive, it's an
2969          * error.  If it's a tag token, it must be a part of URI.
2970          */
2971
2972         if (directive) {
2973             yaml_parser_set_scanner_error(parser, "while parsing a directive",
2974                     start_mark, "did not find expected '!'");
2975             goto error;
2976         }
2977     }
2978
2979     *handle = string.buffer;
2980
2981     return 1;
2982
2983 error:
2984     yaml_free(string.buffer);
2985     return 0;
2986 }
2987
2988 /*
2989  * Scan a tag.
2990  */
2991
2992 static int
2993 yaml_parser_scan_tag_uri(yaml_parser_t *parser, int directive,
2994         yaml_char_t *head, yaml_mark_t start_mark, yaml_char_t **uri)
2995 {
2996     size_t length = head ? strlen((char *)head) : 0;
2997     yaml_string_t string = yaml_parser_new_string(parser);
2998
2999     if (!string.buffer) goto error;
3000
3001     /* Resize the string to include the head. */
3002
3003     while (string.size <= length) {
3004         if (!yaml_parser_resize_string(parser, &string)) goto error;
3005     }
3006
3007     /* Copy the head if needed. */
3008
3009     if (length) {
3010         memcpy(string.buffer, head, length);
3011         string.pointer += length;
3012     }
3013
3014     /* Scan the tag. */
3015
3016     if (!UPDATE(parser, 1)) goto error;
3017
3018     /*
3019      * The set of characters that may appear in URI is as follows:
3020      *
3021      *      '0'-'9', 'A'-'Z', 'a'-'z', '_', '-', ';', '/', '?', ':', '@', '&',
3022      *      '=', '+', '$', ',', '.', '!', '~', '*', '\'', '(', ')', '[', ']',
3023      *      '%'.
3024      */
3025
3026     while (IS_ALPHA(parser) || CHECK(parser, ';') || CHECK(parser, '/') ||
3027             CHECK(parser, '?') || CHECK(parser, ':') || CHECK(parser, '@') ||
3028             CHECK(parser, '&') || CHECK(parser, '=') || CHECK(parser, '+') ||
3029             CHECK(parser, '$') || CHECK(parser, ',') || CHECK(parser, '.') ||
3030             CHECK(parser, '!') || CHECK(parser, '~') || CHECK(parser, '*') ||
3031             CHECK(parser, '\'') || CHECK(parser, '(') || CHECK(parser, ')') ||
3032             CHECK(parser, '[') || CHECK(parser, ']') || CHECK(parser, '%'))
3033     {
3034         if (!RESIZE(parser, string)) goto error;
3035
3036         /* Check if it is a URI-escape sequence. */
3037
3038         if (CHECK(parser, '%')) {
3039             if (!yaml_parser_scan_uri_escapes(parser,
3040                         directive, start_mark, &string)) goto error;
3041         }
3042         else {
3043             COPY(parser, string);
3044         }
3045
3046         length ++;
3047         if (!UPDATE(parser, 1)) goto error;
3048     }
3049
3050     /* Check if the tag is non-empty. */
3051
3052     if (!length) {
3053         yaml_parser_set_scanner_error(parser, directive ?
3054                 "while parsing a %TAG directive" : "while parsing a tag",
3055                 start_mark, "did not find expected tag URI");
3056         goto error;
3057     }
3058
3059     *uri = string.buffer;
3060
3061     return 1;
3062
3063 error:
3064     yaml_free(string.buffer);
3065     return 0;
3066 }
3067
3068 /*
3069  * Decode an URI-escape sequence corresponding to a single UTF-8 character.
3070  */
3071
3072 static int
3073 yaml_parser_scan_uri_escapes(yaml_parser_t *parser, int directive,
3074         yaml_mark_t start_mark, yaml_string_t *string)
3075 {
3076     int width = 0;
3077
3078     /* Decode the required number of characters. */
3079
3080     do {
3081
3082         unsigned char octet = 0;
3083
3084         /* Check for a URI-escaped octet. */
3085
3086         if (!UPDATE(parser, 3)) return 0;
3087
3088         if (!(CHECK(parser, '%') && IS_HEX_AT(parser, 1) && IS_HEX_AT(parser, 2))) {
3089             return yaml_parser_set_scanner_error(parser, directive ?
3090                     "while parsing a %TAG directive" : "while parsing a tag",
3091                     start_mark, "did not find URI escaped octet");
3092         }
3093
3094         /* Get the octet. */
3095
3096         octet = (AS_HEX_AT(parser, 1) << 4) + AS_HEX_AT(parser, 2);
3097
3098         /* If it is the leading octet, determine the length of the UTF-8 sequence. */
3099
3100         if (!width)
3101         {
3102             width = (octet & 0x80) == 0x00 ? 1 :
3103                     (octet & 0xE0) == 0xC0 ? 2 :
3104                     (octet & 0xF0) == 0xE0 ? 3 :
3105                     (octet & 0xF8) == 0xF0 ? 4 : 0;
3106             if (!width) {
3107                 return yaml_parser_set_scanner_error(parser, directive ?
3108                         "while parsing a %TAG directive" : "while parsing a tag",
3109                         start_mark, "found an incorrect leading UTF-8 octet");
3110             }
3111         }
3112         else
3113         {
3114             /* Check if the trailing octet is correct. */
3115
3116             if ((octet & 0xC0) != 0x80) {
3117                 return yaml_parser_set_scanner_error(parser, directive ?
3118                         "while parsing a %TAG directive" : "while parsing a tag",
3119                         start_mark, "found an incorrect trailing UTF-8 octet");
3120             }
3121         }
3122
3123         /* Copy the octet and move the pointers. */
3124
3125         *(string->pointer++) = octet;
3126         FORWARD(parser);
3127         FORWARD(parser);
3128         FORWARD(parser);
3129
3130     } while (--width);
3131
3132     return 1;
3133 }
3134
This page took 0.327737 seconds and 3 git commands to generate.