OSDN Git Service

new repo
[bytom/vapor.git] / vendor / gopkg.in / yaml.v2 / scannerc.go
1 package yaml
2
3 import (
4         "bytes"
5         "fmt"
6 )
7
8 // Introduction
9 // ************
10 //
11 // The following notes assume that you are familiar with the YAML specification
12 // (http://yaml.org/spec/1.2/spec.html).  We mostly follow it, although in
13 // some cases we are less restrictive that it requires.
14 //
15 // The process of transforming a YAML stream into a sequence of events is
16 // divided on two steps: Scanning and Parsing.
17 //
18 // The Scanner transforms the input stream into a sequence of tokens, while the
19 // parser transform the sequence of tokens produced by the Scanner into a
20 // sequence of parsing events.
21 //
22 // The Scanner is rather clever and complicated. The Parser, on the contrary,
23 // is a straightforward implementation of a recursive-descendant parser (or,
24 // LL(1) parser, as it is usually called).
25 //
26 // Actually there are two issues of Scanning that might be called "clever", the
27 // rest is quite straightforward.  The issues are "block collection start" and
28 // "simple keys".  Both issues are explained below in details.
29 //
30 // Here the Scanning step is explained and implemented.  We start with the list
31 // of all the tokens produced by the Scanner together with short descriptions.
32 //
33 // Now, tokens:
34 //
35 //      STREAM-START(encoding)          # The stream start.
36 //      STREAM-END                      # The stream end.
37 //      VERSION-DIRECTIVE(major,minor)  # The '%YAML' directive.
38 //      TAG-DIRECTIVE(handle,prefix)    # The '%TAG' directive.
39 //      DOCUMENT-START                  # '---'
40 //      DOCUMENT-END                    # '...'
41 //      BLOCK-SEQUENCE-START            # Indentation increase denoting a block
42 //      BLOCK-MAPPING-START             # sequence or a block mapping.
43 //      BLOCK-END                       # Indentation decrease.
44 //      FLOW-SEQUENCE-START             # '['
45 //      FLOW-SEQUENCE-END               # ']'
46 //      BLOCK-SEQUENCE-START            # '{'
47 //      BLOCK-SEQUENCE-END              # '}'
48 //      BLOCK-ENTRY                     # '-'
49 //      FLOW-ENTRY                      # ','
50 //      KEY                             # '?' or nothing (simple keys).
51 //      VALUE                           # ':'
52 //      ALIAS(anchor)                   # '*anchor'
53 //      ANCHOR(anchor)                  # '&anchor'
54 //      TAG(handle,suffix)              # '!handle!suffix'
55 //      SCALAR(value,style)             # A scalar.
56 //
57 // The following two tokens are "virtual" tokens denoting the beginning and the
58 // end of the stream:
59 //
60 //      STREAM-START(encoding)
61 //      STREAM-END
62 //
63 // We pass the information about the input stream encoding with the
64 // STREAM-START token.
65 //
66 // The next two tokens are responsible for tags:
67 //
68 //      VERSION-DIRECTIVE(major,minor)
69 //      TAG-DIRECTIVE(handle,prefix)
70 //
71 // Example:
72 //
73 //      %YAML   1.1
74 //      %TAG    !   !foo
75 //      %TAG    !yaml!  tag:yaml.org,2002:
76 //      ---
77 //
78 // The correspoding sequence of tokens:
79 //
80 //      STREAM-START(utf-8)
81 //      VERSION-DIRECTIVE(1,1)
82 //      TAG-DIRECTIVE("!","!foo")
83 //      TAG-DIRECTIVE("!yaml","tag:yaml.org,2002:")
84 //      DOCUMENT-START
85 //      STREAM-END
86 //
87 // Note that the VERSION-DIRECTIVE and TAG-DIRECTIVE tokens occupy a whole
88 // line.
89 //
90 // The document start and end indicators are represented by:
91 //
92 //      DOCUMENT-START
93 //      DOCUMENT-END
94 //
95 // Note that if a YAML stream contains an implicit document (without '---'
96 // and '...' indicators), no DOCUMENT-START and DOCUMENT-END tokens will be
97 // produced.
98 //
99 // In the following examples, we present whole documents together with the
100 // produced tokens.
101 //
102 //      1. An implicit document:
103 //
104 //          'a scalar'
105 //
106 //      Tokens:
107 //
108 //          STREAM-START(utf-8)
109 //          SCALAR("a scalar",single-quoted)
110 //          STREAM-END
111 //
112 //      2. An explicit document:
113 //
114 //          ---
115 //          'a scalar'
116 //          ...
117 //
118 //      Tokens:
119 //
120 //          STREAM-START(utf-8)
121 //          DOCUMENT-START
122 //          SCALAR("a scalar",single-quoted)
123 //          DOCUMENT-END
124 //          STREAM-END
125 //
126 //      3. Several documents in a stream:
127 //
128 //          'a scalar'
129 //          ---
130 //          'another scalar'
131 //          ---
132 //          'yet another scalar'
133 //
134 //      Tokens:
135 //
136 //          STREAM-START(utf-8)
137 //          SCALAR("a scalar",single-quoted)
138 //          DOCUMENT-START
139 //          SCALAR("another scalar",single-quoted)
140 //          DOCUMENT-START
141 //          SCALAR("yet another scalar",single-quoted)
142 //          STREAM-END
143 //
144 // We have already introduced the SCALAR token above.  The following tokens are
145 // used to describe aliases, anchors, tag, and scalars:
146 //
147 //      ALIAS(anchor)
148 //      ANCHOR(anchor)
149 //      TAG(handle,suffix)
150 //      SCALAR(value,style)
151 //
152 // The following series of examples illustrate the usage of these tokens:
153 //
154 //      1. A recursive sequence:
155 //
156 //          &A [ *A ]
157 //
158 //      Tokens:
159 //
160 //          STREAM-START(utf-8)
161 //          ANCHOR("A")
162 //          FLOW-SEQUENCE-START
163 //          ALIAS("A")
164 //          FLOW-SEQUENCE-END
165 //          STREAM-END
166 //
167 //      2. A tagged scalar:
168 //
169 //          !!float "3.14"  # A good approximation.
170 //
171 //      Tokens:
172 //
173 //          STREAM-START(utf-8)
174 //          TAG("!!","float")
175 //          SCALAR("3.14",double-quoted)
176 //          STREAM-END
177 //
178 //      3. Various scalar styles:
179 //
180 //          --- # Implicit empty plain scalars do not produce tokens.
181 //          --- a plain scalar
182 //          --- 'a single-quoted scalar'
183 //          --- "a double-quoted scalar"
184 //          --- |-
185 //            a literal scalar
186 //          --- >-
187 //            a folded
188 //            scalar
189 //
190 //      Tokens:
191 //
192 //          STREAM-START(utf-8)
193 //          DOCUMENT-START
194 //          DOCUMENT-START
195 //          SCALAR("a plain scalar",plain)
196 //          DOCUMENT-START
197 //          SCALAR("a single-quoted scalar",single-quoted)
198 //          DOCUMENT-START
199 //          SCALAR("a double-quoted scalar",double-quoted)
200 //          DOCUMENT-START
201 //          SCALAR("a literal scalar",literal)
202 //          DOCUMENT-START
203 //          SCALAR("a folded scalar",folded)
204 //          STREAM-END
205 //
206 // Now it's time to review collection-related tokens. We will start with
207 // flow collections:
208 //
209 //      FLOW-SEQUENCE-START
210 //      FLOW-SEQUENCE-END
211 //      FLOW-MAPPING-START
212 //      FLOW-MAPPING-END
213 //      FLOW-ENTRY
214 //      KEY
215 //      VALUE
216 //
217 // The tokens FLOW-SEQUENCE-START, FLOW-SEQUENCE-END, FLOW-MAPPING-START, and
218 // FLOW-MAPPING-END represent the indicators '[', ']', '{', and '}'
219 // correspondingly.  FLOW-ENTRY represent the ',' indicator.  Finally the
220 // indicators '?' and ':', which are used for denoting mapping keys and values,
221 // are represented by the KEY and VALUE tokens.
222 //
223 // The following examples show flow collections:
224 //
225 //      1. A flow sequence:
226 //
227 //          [item 1, item 2, item 3]
228 //
229 //      Tokens:
230 //
231 //          STREAM-START(utf-8)
232 //          FLOW-SEQUENCE-START
233 //          SCALAR("item 1",plain)
234 //          FLOW-ENTRY
235 //          SCALAR("item 2",plain)
236 //          FLOW-ENTRY
237 //          SCALAR("item 3",plain)
238 //          FLOW-SEQUENCE-END
239 //          STREAM-END
240 //
241 //      2. A flow mapping:
242 //
243 //          {
244 //              a simple key: a value,  # Note that the KEY token is produced.
245 //              ? a complex key: another value,
246 //          }
247 //
248 //      Tokens:
249 //
250 //          STREAM-START(utf-8)
251 //          FLOW-MAPPING-START
252 //          KEY
253 //          SCALAR("a simple key",plain)
254 //          VALUE
255 //          SCALAR("a value",plain)
256 //          FLOW-ENTRY
257 //          KEY
258 //          SCALAR("a complex key",plain)
259 //          VALUE
260 //          SCALAR("another value",plain)
261 //          FLOW-ENTRY
262 //          FLOW-MAPPING-END
263 //          STREAM-END
264 //
265 // A simple key is a key which is not denoted by the '?' indicator.  Note that
266 // the Scanner still produce the KEY token whenever it encounters a simple key.
267 //
268 // For scanning block collections, the following tokens are used (note that we
269 // repeat KEY and VALUE here):
270 //
271 //      BLOCK-SEQUENCE-START
272 //      BLOCK-MAPPING-START
273 //      BLOCK-END
274 //      BLOCK-ENTRY
275 //      KEY
276 //      VALUE
277 //
278 // The tokens BLOCK-SEQUENCE-START and BLOCK-MAPPING-START denote indentation
279 // increase that precedes a block collection (cf. the INDENT token in Python).
280 // The token BLOCK-END denote indentation decrease that ends a block collection
281 // (cf. the DEDENT token in Python).  However YAML has some syntax pecularities
282 // that makes detections of these tokens more complex.
283 //
284 // The tokens BLOCK-ENTRY, KEY, and VALUE are used to represent the indicators
285 // '-', '?', and ':' correspondingly.
286 //
287 // The following examples show how the tokens BLOCK-SEQUENCE-START,
288 // BLOCK-MAPPING-START, and BLOCK-END are emitted by the Scanner:
289 //
290 //      1. Block sequences:
291 //
292 //          - item 1
293 //          - item 2
294 //          -
295 //            - item 3.1
296 //            - item 3.2
297 //          -
298 //            key 1: value 1
299 //            key 2: value 2
300 //
301 //      Tokens:
302 //
303 //          STREAM-START(utf-8)
304 //          BLOCK-SEQUENCE-START
305 //          BLOCK-ENTRY
306 //          SCALAR("item 1",plain)
307 //          BLOCK-ENTRY
308 //          SCALAR("item 2",plain)
309 //          BLOCK-ENTRY
310 //          BLOCK-SEQUENCE-START
311 //          BLOCK-ENTRY
312 //          SCALAR("item 3.1",plain)
313 //          BLOCK-ENTRY
314 //          SCALAR("item 3.2",plain)
315 //          BLOCK-END
316 //          BLOCK-ENTRY
317 //          BLOCK-MAPPING-START
318 //          KEY
319 //          SCALAR("key 1",plain)
320 //          VALUE
321 //          SCALAR("value 1",plain)
322 //          KEY
323 //          SCALAR("key 2",plain)
324 //          VALUE
325 //          SCALAR("value 2",plain)
326 //          BLOCK-END
327 //          BLOCK-END
328 //          STREAM-END
329 //
330 //      2. Block mappings:
331 //
332 //          a simple key: a value   # The KEY token is produced here.
333 //          ? a complex key
334 //          : another value
335 //          a mapping:
336 //            key 1: value 1
337 //            key 2: value 2
338 //          a sequence:
339 //            - item 1
340 //            - item 2
341 //
342 //      Tokens:
343 //
344 //          STREAM-START(utf-8)
345 //          BLOCK-MAPPING-START
346 //          KEY
347 //          SCALAR("a simple key",plain)
348 //          VALUE
349 //          SCALAR("a value",plain)
350 //          KEY
351 //          SCALAR("a complex key",plain)
352 //          VALUE
353 //          SCALAR("another value",plain)
354 //          KEY
355 //          SCALAR("a mapping",plain)
356 //          BLOCK-MAPPING-START
357 //          KEY
358 //          SCALAR("key 1",plain)
359 //          VALUE
360 //          SCALAR("value 1",plain)
361 //          KEY
362 //          SCALAR("key 2",plain)
363 //          VALUE
364 //          SCALAR("value 2",plain)
365 //          BLOCK-END
366 //          KEY
367 //          SCALAR("a sequence",plain)
368 //          VALUE
369 //          BLOCK-SEQUENCE-START
370 //          BLOCK-ENTRY
371 //          SCALAR("item 1",plain)
372 //          BLOCK-ENTRY
373 //          SCALAR("item 2",plain)
374 //          BLOCK-END
375 //          BLOCK-END
376 //          STREAM-END
377 //
378 // YAML does not always require to start a new block collection from a new
379 // line.  If the current line contains only '-', '?', and ':' indicators, a new
380 // block collection may start at the current line.  The following examples
381 // illustrate this case:
382 //
383 //      1. Collections in a sequence:
384 //
385 //          - - item 1
386 //            - item 2
387 //          - key 1: value 1
388 //            key 2: value 2
389 //          - ? complex key
390 //            : complex value
391 //
392 //      Tokens:
393 //
394 //          STREAM-START(utf-8)
395 //          BLOCK-SEQUENCE-START
396 //          BLOCK-ENTRY
397 //          BLOCK-SEQUENCE-START
398 //          BLOCK-ENTRY
399 //          SCALAR("item 1",plain)
400 //          BLOCK-ENTRY
401 //          SCALAR("item 2",plain)
402 //          BLOCK-END
403 //          BLOCK-ENTRY
404 //          BLOCK-MAPPING-START
405 //          KEY
406 //          SCALAR("key 1",plain)
407 //          VALUE
408 //          SCALAR("value 1",plain)
409 //          KEY
410 //          SCALAR("key 2",plain)
411 //          VALUE
412 //          SCALAR("value 2",plain)
413 //          BLOCK-END
414 //          BLOCK-ENTRY
415 //          BLOCK-MAPPING-START
416 //          KEY
417 //          SCALAR("complex key")
418 //          VALUE
419 //          SCALAR("complex value")
420 //          BLOCK-END
421 //          BLOCK-END
422 //          STREAM-END
423 //
424 //      2. Collections in a mapping:
425 //
426 //          ? a sequence
427 //          : - item 1
428 //            - item 2
429 //          ? a mapping
430 //          : key 1: value 1
431 //            key 2: value 2
432 //
433 //      Tokens:
434 //
435 //          STREAM-START(utf-8)
436 //          BLOCK-MAPPING-START
437 //          KEY
438 //          SCALAR("a sequence",plain)
439 //          VALUE
440 //          BLOCK-SEQUENCE-START
441 //          BLOCK-ENTRY
442 //          SCALAR("item 1",plain)
443 //          BLOCK-ENTRY
444 //          SCALAR("item 2",plain)
445 //          BLOCK-END
446 //          KEY
447 //          SCALAR("a mapping",plain)
448 //          VALUE
449 //          BLOCK-MAPPING-START
450 //          KEY
451 //          SCALAR("key 1",plain)
452 //          VALUE
453 //          SCALAR("value 1",plain)
454 //          KEY
455 //          SCALAR("key 2",plain)
456 //          VALUE
457 //          SCALAR("value 2",plain)
458 //          BLOCK-END
459 //          BLOCK-END
460 //          STREAM-END
461 //
462 // YAML also permits non-indented sequences if they are included into a block
463 // mapping.  In this case, the token BLOCK-SEQUENCE-START is not produced:
464 //
465 //      key:
466 //      - item 1    # BLOCK-SEQUENCE-START is NOT produced here.
467 //      - item 2
468 //
469 // Tokens:
470 //
471 //      STREAM-START(utf-8)
472 //      BLOCK-MAPPING-START
473 //      KEY
474 //      SCALAR("key",plain)
475 //      VALUE
476 //      BLOCK-ENTRY
477 //      SCALAR("item 1",plain)
478 //      BLOCK-ENTRY
479 //      SCALAR("item 2",plain)
480 //      BLOCK-END
481 //
482
483 // Ensure that the buffer contains the required number of characters.
484 // Return true on success, false on failure (reader error or memory error).
485 func cache(parser *yaml_parser_t, length int) bool {
486         // [Go] This was inlined: !cache(A, B) -> unread < B && !update(A, B)
487         return parser.unread >= length || yaml_parser_update_buffer(parser, length)
488 }
489
490 // Advance the buffer pointer.
491 func skip(parser *yaml_parser_t) {
492         parser.mark.index++
493         parser.mark.column++
494         parser.unread--
495         parser.buffer_pos += width(parser.buffer[parser.buffer_pos])
496 }
497
498 func skip_line(parser *yaml_parser_t) {
499         if is_crlf(parser.buffer, parser.buffer_pos) {
500                 parser.mark.index += 2
501                 parser.mark.column = 0
502                 parser.mark.line++
503                 parser.unread -= 2
504                 parser.buffer_pos += 2
505         } else if is_break(parser.buffer, parser.buffer_pos) {
506                 parser.mark.index++
507                 parser.mark.column = 0
508                 parser.mark.line++
509                 parser.unread--
510                 parser.buffer_pos += width(parser.buffer[parser.buffer_pos])
511         }
512 }
513
514 // Copy a character to a string buffer and advance pointers.
515 func read(parser *yaml_parser_t, s []byte) []byte {
516         w := width(parser.buffer[parser.buffer_pos])
517         if w == 0 {
518                 panic("invalid character sequence")
519         }
520         if len(s) == 0 {
521                 s = make([]byte, 0, 32)
522         }
523         if w == 1 && len(s)+w <= cap(s) {
524                 s = s[:len(s)+1]
525                 s[len(s)-1] = parser.buffer[parser.buffer_pos]
526                 parser.buffer_pos++
527         } else {
528                 s = append(s, parser.buffer[parser.buffer_pos:parser.buffer_pos+w]...)
529                 parser.buffer_pos += w
530         }
531         parser.mark.index++
532         parser.mark.column++
533         parser.unread--
534         return s
535 }
536
537 // Copy a line break character to a string buffer and advance pointers.
538 func read_line(parser *yaml_parser_t, s []byte) []byte {
539         buf := parser.buffer
540         pos := parser.buffer_pos
541         switch {
542         case buf[pos] == '\r' && buf[pos+1] == '\n':
543                 // CR LF . LF
544                 s = append(s, '\n')
545                 parser.buffer_pos += 2
546                 parser.mark.index++
547                 parser.unread--
548         case buf[pos] == '\r' || buf[pos] == '\n':
549                 // CR|LF . LF
550                 s = append(s, '\n')
551                 parser.buffer_pos += 1
552         case buf[pos] == '\xC2' && buf[pos+1] == '\x85':
553                 // NEL . LF
554                 s = append(s, '\n')
555                 parser.buffer_pos += 2
556         case buf[pos] == '\xE2' && buf[pos+1] == '\x80' && (buf[pos+2] == '\xA8' || buf[pos+2] == '\xA9'):
557                 // LS|PS . LS|PS
558                 s = append(s, buf[parser.buffer_pos:pos+3]...)
559                 parser.buffer_pos += 3
560         default:
561                 return s
562         }
563         parser.mark.index++
564         parser.mark.column = 0
565         parser.mark.line++
566         parser.unread--
567         return s
568 }
569
570 // Get the next token.
571 func yaml_parser_scan(parser *yaml_parser_t, token *yaml_token_t) bool {
572         // Erase the token object.
573         *token = yaml_token_t{} // [Go] Is this necessary?
574
575         // No tokens after STREAM-END or error.
576         if parser.stream_end_produced || parser.error != yaml_NO_ERROR {
577                 return true
578         }
579
580         // Ensure that the tokens queue contains enough tokens.
581         if !parser.token_available {
582                 if !yaml_parser_fetch_more_tokens(parser) {
583                         return false
584                 }
585         }
586
587         // Fetch the next token from the queue.
588         *token = parser.tokens[parser.tokens_head]
589         parser.tokens_head++
590         parser.tokens_parsed++
591         parser.token_available = false
592
593         if token.typ == yaml_STREAM_END_TOKEN {
594                 parser.stream_end_produced = true
595         }
596         return true
597 }
598
599 // Set the scanner error and return false.
600 func yaml_parser_set_scanner_error(parser *yaml_parser_t, context string, context_mark yaml_mark_t, problem string) bool {
601         parser.error = yaml_SCANNER_ERROR
602         parser.context = context
603         parser.context_mark = context_mark
604         parser.problem = problem
605         parser.problem_mark = parser.mark
606         return false
607 }
608
609 func yaml_parser_set_scanner_tag_error(parser *yaml_parser_t, directive bool, context_mark yaml_mark_t, problem string) bool {
610         context := "while parsing a tag"
611         if directive {
612                 context = "while parsing a %TAG directive"
613         }
614         return yaml_parser_set_scanner_error(parser, context, context_mark, problem)
615 }
616
617 func trace(args ...interface{}) func() {
618         pargs := append([]interface{}{"+++"}, args...)
619         fmt.Println(pargs...)
620         pargs = append([]interface{}{"---"}, args...)
621         return func() { fmt.Println(pargs...) }
622 }
623
624 // Ensure that the tokens queue contains at least one token which can be
625 // returned to the Parser.
626 func yaml_parser_fetch_more_tokens(parser *yaml_parser_t) bool {
627         // While we need more tokens to fetch, do it.
628         for {
629                 // Check if we really need to fetch more tokens.
630                 need_more_tokens := false
631
632                 if parser.tokens_head == len(parser.tokens) {
633                         // Queue is empty.
634                         need_more_tokens = true
635                 } else {
636                         // Check if any potential simple key may occupy the head position.
637                         if !yaml_parser_stale_simple_keys(parser) {
638                                 return false
639                         }
640
641                         for i := range parser.simple_keys {
642                                 simple_key := &parser.simple_keys[i]
643                                 if simple_key.possible && simple_key.token_number == parser.tokens_parsed {
644                                         need_more_tokens = true
645                                         break
646                                 }
647                         }
648                 }
649
650                 // We are finished.
651                 if !need_more_tokens {
652                         break
653                 }
654                 // Fetch the next token.
655                 if !yaml_parser_fetch_next_token(parser) {
656                         return false
657                 }
658         }
659
660         parser.token_available = true
661         return true
662 }
663
664 // The dispatcher for token fetchers.
665 func yaml_parser_fetch_next_token(parser *yaml_parser_t) bool {
666         // Ensure that the buffer is initialized.
667         if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
668                 return false
669         }
670
671         // Check if we just started scanning.  Fetch STREAM-START then.
672         if !parser.stream_start_produced {
673                 return yaml_parser_fetch_stream_start(parser)
674         }
675
676         // Eat whitespaces and comments until we reach the next token.
677         if !yaml_parser_scan_to_next_token(parser) {
678                 return false
679         }
680
681         // Remove obsolete potential simple keys.
682         if !yaml_parser_stale_simple_keys(parser) {
683                 return false
684         }
685
686         // Check the indentation level against the current column.
687         if !yaml_parser_unroll_indent(parser, parser.mark.column) {
688                 return false
689         }
690
691         // Ensure that the buffer contains at least 4 characters.  4 is the length
692         // of the longest indicators ('--- ' and '... ').
693         if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) {
694                 return false
695         }
696
697         // Is it the end of the stream?
698         if is_z(parser.buffer, parser.buffer_pos) {
699                 return yaml_parser_fetch_stream_end(parser)
700         }
701
702         // Is it a directive?
703         if parser.mark.column == 0 && parser.buffer[parser.buffer_pos] == '%' {
704                 return yaml_parser_fetch_directive(parser)
705         }
706
707         buf := parser.buffer
708         pos := parser.buffer_pos
709
710         // Is it the document start indicator?
711         if parser.mark.column == 0 && buf[pos] == '-' && buf[pos+1] == '-' && buf[pos+2] == '-' && is_blankz(buf, pos+3) {
712                 return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_START_TOKEN)
713         }
714
715         // Is it the document end indicator?
716         if parser.mark.column == 0 && buf[pos] == '.' && buf[pos+1] == '.' && buf[pos+2] == '.' && is_blankz(buf, pos+3) {
717                 return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_END_TOKEN)
718         }
719
720         // Is it the flow sequence start indicator?
721         if buf[pos] == '[' {
722                 return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_SEQUENCE_START_TOKEN)
723         }
724
725         // Is it the flow mapping start indicator?
726         if parser.buffer[parser.buffer_pos] == '{' {
727                 return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_MAPPING_START_TOKEN)
728         }
729
730         // Is it the flow sequence end indicator?
731         if parser.buffer[parser.buffer_pos] == ']' {
732                 return yaml_parser_fetch_flow_collection_end(parser,
733                         yaml_FLOW_SEQUENCE_END_TOKEN)
734         }
735
736         // Is it the flow mapping end indicator?
737         if parser.buffer[parser.buffer_pos] == '}' {
738                 return yaml_parser_fetch_flow_collection_end(parser,
739                         yaml_FLOW_MAPPING_END_TOKEN)
740         }
741
742         // Is it the flow entry indicator?
743         if parser.buffer[parser.buffer_pos] == ',' {
744                 return yaml_parser_fetch_flow_entry(parser)
745         }
746
747         // Is it the block entry indicator?
748         if parser.buffer[parser.buffer_pos] == '-' && is_blankz(parser.buffer, parser.buffer_pos+1) {
749                 return yaml_parser_fetch_block_entry(parser)
750         }
751
752         // Is it the key indicator?
753         if parser.buffer[parser.buffer_pos] == '?' && (parser.flow_level > 0 || is_blankz(parser.buffer, parser.buffer_pos+1)) {
754                 return yaml_parser_fetch_key(parser)
755         }
756
757         // Is it the value indicator?
758         if parser.buffer[parser.buffer_pos] == ':' && (parser.flow_level > 0 || is_blankz(parser.buffer, parser.buffer_pos+1)) {
759                 return yaml_parser_fetch_value(parser)
760         }
761
762         // Is it an alias?
763         if parser.buffer[parser.buffer_pos] == '*' {
764                 return yaml_parser_fetch_anchor(parser, yaml_ALIAS_TOKEN)
765         }
766
767         // Is it an anchor?
768         if parser.buffer[parser.buffer_pos] == '&' {
769                 return yaml_parser_fetch_anchor(parser, yaml_ANCHOR_TOKEN)
770         }
771
772         // Is it a tag?
773         if parser.buffer[parser.buffer_pos] == '!' {
774                 return yaml_parser_fetch_tag(parser)
775         }
776
777         // Is it a literal scalar?
778         if parser.buffer[parser.buffer_pos] == '|' && parser.flow_level == 0 {
779                 return yaml_parser_fetch_block_scalar(parser, true)
780         }
781
782         // Is it a folded scalar?
783         if parser.buffer[parser.buffer_pos] == '>' && parser.flow_level == 0 {
784                 return yaml_parser_fetch_block_scalar(parser, false)
785         }
786
787         // Is it a single-quoted scalar?
788         if parser.buffer[parser.buffer_pos] == '\'' {
789                 return yaml_parser_fetch_flow_scalar(parser, true)
790         }
791
792         // Is it a double-quoted scalar?
793         if parser.buffer[parser.buffer_pos] == '"' {
794                 return yaml_parser_fetch_flow_scalar(parser, false)
795         }
796
797         // Is it a plain scalar?
798         //
799         // A plain scalar may start with any non-blank characters except
800         //
801         //      '-', '?', ':', ',', '[', ']', '{', '}',
802         //      '#', '&', '*', '!', '|', '>', '\'', '\"',
803         //      '%', '@', '`'.
804         //
805         // In the block context (and, for the '-' indicator, in the flow context
806         // too), it may also start with the characters
807         //
808         //      '-', '?', ':'
809         //
810         // if it is followed by a non-space character.
811         //
812         // The last rule is more restrictive than the specification requires.
813         // [Go] Make this logic more reasonable.
814         //switch parser.buffer[parser.buffer_pos] {
815         //case '-', '?', ':', ',', '?', '-', ',', ':', ']', '[', '}', '{', '&', '#', '!', '*', '>', '|', '"', '\'', '@', '%', '-', '`':
816         //}
817         if !(is_blankz(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '-' ||
818                 parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':' ||
819                 parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '[' ||
820                 parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' ||
821                 parser.buffer[parser.buffer_pos] == '}' || parser.buffer[parser.buffer_pos] == '#' ||
822                 parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '*' ||
823                 parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '|' ||
824                 parser.buffer[parser.buffer_pos] == '>' || parser.buffer[parser.buffer_pos] == '\'' ||
825                 parser.buffer[parser.buffer_pos] == '"' || parser.buffer[parser.buffer_pos] == '%' ||
826                 parser.buffer[parser.buffer_pos] == '@' || parser.buffer[parser.buffer_pos] == '`') ||
827                 (parser.buffer[parser.buffer_pos] == '-' && !is_blank(parser.buffer, parser.buffer_pos+1)) ||
828                 (parser.flow_level == 0 &&
829                         (parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':') &&
830                         !is_blankz(parser.buffer, parser.buffer_pos+1)) {
831                 return yaml_parser_fetch_plain_scalar(parser)
832         }
833
834         // If we don't determine the token type so far, it is an error.
835         return yaml_parser_set_scanner_error(parser,
836                 "while scanning for the next token", parser.mark,
837                 "found character that cannot start any token")
838 }
839
840 // Check the list of potential simple keys and remove the positions that
841 // cannot contain simple keys anymore.
842 func yaml_parser_stale_simple_keys(parser *yaml_parser_t) bool {
843         // Check for a potential simple key for each flow level.
844         for i := range parser.simple_keys {
845                 simple_key := &parser.simple_keys[i]
846
847                 // The specification requires that a simple key
848                 //
849                 //  - is limited to a single line,
850                 //  - is shorter than 1024 characters.
851                 if simple_key.possible && (simple_key.mark.line < parser.mark.line || simple_key.mark.index+1024 < parser.mark.index) {
852
853                         // Check if the potential simple key to be removed is required.
854                         if simple_key.required {
855                                 return yaml_parser_set_scanner_error(parser,
856                                         "while scanning a simple key", simple_key.mark,
857                                         "could not find expected ':'")
858                         }
859                         simple_key.possible = false
860                 }
861         }
862         return true
863 }
864
865 // Check if a simple key may start at the current position and add it if
866 // needed.
867 func yaml_parser_save_simple_key(parser *yaml_parser_t) bool {
868         // A simple key is required at the current position if the scanner is in
869         // the block context and the current column coincides with the indentation
870         // level.
871
872         required := parser.flow_level == 0 && parser.indent == parser.mark.column
873
874         // A simple key is required only when it is the first token in the current
875         // line.  Therefore it is always allowed.  But we add a check anyway.
876         if required && !parser.simple_key_allowed {
877                 panic("should not happen")
878         }
879
880         //
881         // If the current position may start a simple key, save it.
882         //
883         if parser.simple_key_allowed {
884                 simple_key := yaml_simple_key_t{
885                         possible:     true,
886                         required:     required,
887                         token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head),
888                 }
889                 simple_key.mark = parser.mark
890
891                 if !yaml_parser_remove_simple_key(parser) {
892                         return false
893                 }
894                 parser.simple_keys[len(parser.simple_keys)-1] = simple_key
895         }
896         return true
897 }
898
899 // Remove a potential simple key at the current flow level.
900 func yaml_parser_remove_simple_key(parser *yaml_parser_t) bool {
901         i := len(parser.simple_keys) - 1
902         if parser.simple_keys[i].possible {
903                 // If the key is required, it is an error.
904                 if parser.simple_keys[i].required {
905                         return yaml_parser_set_scanner_error(parser,
906                                 "while scanning a simple key", parser.simple_keys[i].mark,
907                                 "could not find expected ':'")
908                 }
909         }
910         // Remove the key from the stack.
911         parser.simple_keys[i].possible = false
912         return true
913 }
914
915 // Increase the flow level and resize the simple key list if needed.
916 func yaml_parser_increase_flow_level(parser *yaml_parser_t) bool {
917         // Reset the simple key on the next level.
918         parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{})
919
920         // Increase the flow level.
921         parser.flow_level++
922         return true
923 }
924
925 // Decrease the flow level.
926 func yaml_parser_decrease_flow_level(parser *yaml_parser_t) bool {
927         if parser.flow_level > 0 {
928                 parser.flow_level--
929                 parser.simple_keys = parser.simple_keys[:len(parser.simple_keys)-1]
930         }
931         return true
932 }
933
934 // Push the current indentation level to the stack and set the new level
935 // the current column is greater than the indentation level.  In this case,
936 // append or insert the specified token into the token queue.
937 func yaml_parser_roll_indent(parser *yaml_parser_t, column, number int, typ yaml_token_type_t, mark yaml_mark_t) bool {
938         // In the flow context, do nothing.
939         if parser.flow_level > 0 {
940                 return true
941         }
942
943         if parser.indent < column {
944                 // Push the current indentation level to the stack and set the new
945                 // indentation level.
946                 parser.indents = append(parser.indents, parser.indent)
947                 parser.indent = column
948
949                 // Create a token and insert it into the queue.
950                 token := yaml_token_t{
951                         typ:        typ,
952                         start_mark: mark,
953                         end_mark:   mark,
954                 }
955                 if number > -1 {
956                         number -= parser.tokens_parsed
957                 }
958                 yaml_insert_token(parser, number, &token)
959         }
960         return true
961 }
962
963 // Pop indentation levels from the indents stack until the current level
964 // becomes less or equal to the column.  For each indentation level, append
965 // the BLOCK-END token.
966 func yaml_parser_unroll_indent(parser *yaml_parser_t, column int) bool {
967         // In the flow context, do nothing.
968         if parser.flow_level > 0 {
969                 return true
970         }
971
972         // Loop through the indentation levels in the stack.
973         for parser.indent > column {
974                 // Create a token and append it to the queue.
975                 token := yaml_token_t{
976                         typ:        yaml_BLOCK_END_TOKEN,
977                         start_mark: parser.mark,
978                         end_mark:   parser.mark,
979                 }
980                 yaml_insert_token(parser, -1, &token)
981
982                 // Pop the indentation level.
983                 parser.indent = parser.indents[len(parser.indents)-1]
984                 parser.indents = parser.indents[:len(parser.indents)-1]
985         }
986         return true
987 }
988
989 // Initialize the scanner and produce the STREAM-START token.
990 func yaml_parser_fetch_stream_start(parser *yaml_parser_t) bool {
991
992         // Set the initial indentation.
993         parser.indent = -1
994
995         // Initialize the simple key stack.
996         parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{})
997
998         // A simple key is allowed at the beginning of the stream.
999         parser.simple_key_allowed = true
1000
1001         // We have started.
1002         parser.stream_start_produced = true
1003
1004         // Create the STREAM-START token and append it to the queue.
1005         token := yaml_token_t{
1006                 typ:        yaml_STREAM_START_TOKEN,
1007                 start_mark: parser.mark,
1008                 end_mark:   parser.mark,
1009                 encoding:   parser.encoding,
1010         }
1011         yaml_insert_token(parser, -1, &token)
1012         return true
1013 }
1014
1015 // Produce the STREAM-END token and shut down the scanner.
1016 func yaml_parser_fetch_stream_end(parser *yaml_parser_t) bool {
1017
1018         // Force new line.
1019         if parser.mark.column != 0 {
1020                 parser.mark.column = 0
1021                 parser.mark.line++
1022         }
1023
1024         // Reset the indentation level.
1025         if !yaml_parser_unroll_indent(parser, -1) {
1026                 return false
1027         }
1028
1029         // Reset simple keys.
1030         if !yaml_parser_remove_simple_key(parser) {
1031                 return false
1032         }
1033
1034         parser.simple_key_allowed = false
1035
1036         // Create the STREAM-END token and append it to the queue.
1037         token := yaml_token_t{
1038                 typ:        yaml_STREAM_END_TOKEN,
1039                 start_mark: parser.mark,
1040                 end_mark:   parser.mark,
1041         }
1042         yaml_insert_token(parser, -1, &token)
1043         return true
1044 }
1045
1046 // Produce a VERSION-DIRECTIVE or TAG-DIRECTIVE token.
1047 func yaml_parser_fetch_directive(parser *yaml_parser_t) bool {
1048         // Reset the indentation level.
1049         if !yaml_parser_unroll_indent(parser, -1) {
1050                 return false
1051         }
1052
1053         // Reset simple keys.
1054         if !yaml_parser_remove_simple_key(parser) {
1055                 return false
1056         }
1057
1058         parser.simple_key_allowed = false
1059
1060         // Create the YAML-DIRECTIVE or TAG-DIRECTIVE token.
1061         token := yaml_token_t{}
1062         if !yaml_parser_scan_directive(parser, &token) {
1063                 return false
1064         }
1065         // Append the token to the queue.
1066         yaml_insert_token(parser, -1, &token)
1067         return true
1068 }
1069
1070 // Produce the DOCUMENT-START or DOCUMENT-END token.
1071 func yaml_parser_fetch_document_indicator(parser *yaml_parser_t, typ yaml_token_type_t) bool {
1072         // Reset the indentation level.
1073         if !yaml_parser_unroll_indent(parser, -1) {
1074                 return false
1075         }
1076
1077         // Reset simple keys.
1078         if !yaml_parser_remove_simple_key(parser) {
1079                 return false
1080         }
1081
1082         parser.simple_key_allowed = false
1083
1084         // Consume the token.
1085         start_mark := parser.mark
1086
1087         skip(parser)
1088         skip(parser)
1089         skip(parser)
1090
1091         end_mark := parser.mark
1092
1093         // Create the DOCUMENT-START or DOCUMENT-END token.
1094         token := yaml_token_t{
1095                 typ:        typ,
1096                 start_mark: start_mark,
1097                 end_mark:   end_mark,
1098         }
1099         // Append the token to the queue.
1100         yaml_insert_token(parser, -1, &token)
1101         return true
1102 }
1103
1104 // Produce the FLOW-SEQUENCE-START or FLOW-MAPPING-START token.
1105 func yaml_parser_fetch_flow_collection_start(parser *yaml_parser_t, typ yaml_token_type_t) bool {
1106         // The indicators '[' and '{' may start a simple key.
1107         if !yaml_parser_save_simple_key(parser) {
1108                 return false
1109         }
1110
1111         // Increase the flow level.
1112         if !yaml_parser_increase_flow_level(parser) {
1113                 return false
1114         }
1115
1116         // A simple key may follow the indicators '[' and '{'.
1117         parser.simple_key_allowed = true
1118
1119         // Consume the token.
1120         start_mark := parser.mark
1121         skip(parser)
1122         end_mark := parser.mark
1123
1124         // Create the FLOW-SEQUENCE-START of FLOW-MAPPING-START token.
1125         token := yaml_token_t{
1126                 typ:        typ,
1127                 start_mark: start_mark,
1128                 end_mark:   end_mark,
1129         }
1130         // Append the token to the queue.
1131         yaml_insert_token(parser, -1, &token)
1132         return true
1133 }
1134
1135 // Produce the FLOW-SEQUENCE-END or FLOW-MAPPING-END token.
1136 func yaml_parser_fetch_flow_collection_end(parser *yaml_parser_t, typ yaml_token_type_t) bool {
1137         // Reset any potential simple key on the current flow level.
1138         if !yaml_parser_remove_simple_key(parser) {
1139                 return false
1140         }
1141
1142         // Decrease the flow level.
1143         if !yaml_parser_decrease_flow_level(parser) {
1144                 return false
1145         }
1146
1147         // No simple keys after the indicators ']' and '}'.
1148         parser.simple_key_allowed = false
1149
1150         // Consume the token.
1151
1152         start_mark := parser.mark
1153         skip(parser)
1154         end_mark := parser.mark
1155
1156         // Create the FLOW-SEQUENCE-END of FLOW-MAPPING-END token.
1157         token := yaml_token_t{
1158                 typ:        typ,
1159                 start_mark: start_mark,
1160                 end_mark:   end_mark,
1161         }
1162         // Append the token to the queue.
1163         yaml_insert_token(parser, -1, &token)
1164         return true
1165 }
1166
1167 // Produce the FLOW-ENTRY token.
1168 func yaml_parser_fetch_flow_entry(parser *yaml_parser_t) bool {
1169         // Reset any potential simple keys on the current flow level.
1170         if !yaml_parser_remove_simple_key(parser) {
1171                 return false
1172         }
1173
1174         // Simple keys are allowed after ','.
1175         parser.simple_key_allowed = true
1176
1177         // Consume the token.
1178         start_mark := parser.mark
1179         skip(parser)
1180         end_mark := parser.mark
1181
1182         // Create the FLOW-ENTRY token and append it to the queue.
1183         token := yaml_token_t{
1184                 typ:        yaml_FLOW_ENTRY_TOKEN,
1185                 start_mark: start_mark,
1186                 end_mark:   end_mark,
1187         }
1188         yaml_insert_token(parser, -1, &token)
1189         return true
1190 }
1191
1192 // Produce the BLOCK-ENTRY token.
1193 func yaml_parser_fetch_block_entry(parser *yaml_parser_t) bool {
1194         // Check if the scanner is in the block context.
1195         if parser.flow_level == 0 {
1196                 // Check if we are allowed to start a new entry.
1197                 if !parser.simple_key_allowed {
1198                         return yaml_parser_set_scanner_error(parser, "", parser.mark,
1199                                 "block sequence entries are not allowed in this context")
1200                 }
1201                 // Add the BLOCK-SEQUENCE-START token if needed.
1202                 if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_SEQUENCE_START_TOKEN, parser.mark) {
1203                         return false
1204                 }
1205         } else {
1206                 // It is an error for the '-' indicator to occur in the flow context,
1207                 // but we let the Parser detect and report about it because the Parser
1208                 // is able to point to the context.
1209         }
1210
1211         // Reset any potential simple keys on the current flow level.
1212         if !yaml_parser_remove_simple_key(parser) {
1213                 return false
1214         }
1215
1216         // Simple keys are allowed after '-'.
1217         parser.simple_key_allowed = true
1218
1219         // Consume the token.
1220         start_mark := parser.mark
1221         skip(parser)
1222         end_mark := parser.mark
1223
1224         // Create the BLOCK-ENTRY token and append it to the queue.
1225         token := yaml_token_t{
1226                 typ:        yaml_BLOCK_ENTRY_TOKEN,
1227                 start_mark: start_mark,
1228                 end_mark:   end_mark,
1229         }
1230         yaml_insert_token(parser, -1, &token)
1231         return true
1232 }
1233
1234 // Produce the KEY token.
1235 func yaml_parser_fetch_key(parser *yaml_parser_t) bool {
1236
1237         // In the block context, additional checks are required.
1238         if parser.flow_level == 0 {
1239                 // Check if we are allowed to start a new key (not nessesary simple).
1240                 if !parser.simple_key_allowed {
1241                         return yaml_parser_set_scanner_error(parser, "", parser.mark,
1242                                 "mapping keys are not allowed in this context")
1243                 }
1244                 // Add the BLOCK-MAPPING-START token if needed.
1245                 if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_MAPPING_START_TOKEN, parser.mark) {
1246                         return false
1247                 }
1248         }
1249
1250         // Reset any potential simple keys on the current flow level.
1251         if !yaml_parser_remove_simple_key(parser) {
1252                 return false
1253         }
1254
1255         // Simple keys are allowed after '?' in the block context.
1256         parser.simple_key_allowed = parser.flow_level == 0
1257
1258         // Consume the token.
1259         start_mark := parser.mark
1260         skip(parser)
1261         end_mark := parser.mark
1262
1263         // Create the KEY token and append it to the queue.
1264         token := yaml_token_t{
1265                 typ:        yaml_KEY_TOKEN,
1266                 start_mark: start_mark,
1267                 end_mark:   end_mark,
1268         }
1269         yaml_insert_token(parser, -1, &token)
1270         return true
1271 }
1272
1273 // Produce the VALUE token.
1274 func yaml_parser_fetch_value(parser *yaml_parser_t) bool {
1275
1276         simple_key := &parser.simple_keys[len(parser.simple_keys)-1]
1277
1278         // Have we found a simple key?
1279         if simple_key.possible {
1280                 // Create the KEY token and insert it into the queue.
1281                 token := yaml_token_t{
1282                         typ:        yaml_KEY_TOKEN,
1283                         start_mark: simple_key.mark,
1284                         end_mark:   simple_key.mark,
1285                 }
1286                 yaml_insert_token(parser, simple_key.token_number-parser.tokens_parsed, &token)
1287
1288                 // In the block context, we may need to add the BLOCK-MAPPING-START token.
1289                 if !yaml_parser_roll_indent(parser, simple_key.mark.column,
1290                         simple_key.token_number,
1291                         yaml_BLOCK_MAPPING_START_TOKEN, simple_key.mark) {
1292                         return false
1293                 }
1294
1295                 // Remove the simple key.
1296                 simple_key.possible = false
1297
1298                 // A simple key cannot follow another simple key.
1299                 parser.simple_key_allowed = false
1300
1301         } else {
1302                 // The ':' indicator follows a complex key.
1303
1304                 // In the block context, extra checks are required.
1305                 if parser.flow_level == 0 {
1306
1307                         // Check if we are allowed to start a complex value.
1308                         if !parser.simple_key_allowed {
1309                                 return yaml_parser_set_scanner_error(parser, "", parser.mark,
1310                                         "mapping values are not allowed in this context")
1311                         }
1312
1313                         // Add the BLOCK-MAPPING-START token if needed.
1314                         if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_MAPPING_START_TOKEN, parser.mark) {
1315                                 return false
1316                         }
1317                 }
1318
1319                 // Simple keys after ':' are allowed in the block context.
1320                 parser.simple_key_allowed = parser.flow_level == 0
1321         }
1322
1323         // Consume the token.
1324         start_mark := parser.mark
1325         skip(parser)
1326         end_mark := parser.mark
1327
1328         // Create the VALUE token and append it to the queue.
1329         token := yaml_token_t{
1330                 typ:        yaml_VALUE_TOKEN,
1331                 start_mark: start_mark,
1332                 end_mark:   end_mark,
1333         }
1334         yaml_insert_token(parser, -1, &token)
1335         return true
1336 }
1337
1338 // Produce the ALIAS or ANCHOR token.
1339 func yaml_parser_fetch_anchor(parser *yaml_parser_t, typ yaml_token_type_t) bool {
1340         // An anchor or an alias could be a simple key.
1341         if !yaml_parser_save_simple_key(parser) {
1342                 return false
1343         }
1344
1345         // A simple key cannot follow an anchor or an alias.
1346         parser.simple_key_allowed = false
1347
1348         // Create the ALIAS or ANCHOR token and append it to the queue.
1349         var token yaml_token_t
1350         if !yaml_parser_scan_anchor(parser, &token, typ) {
1351                 return false
1352         }
1353         yaml_insert_token(parser, -1, &token)
1354         return true
1355 }
1356
1357 // Produce the TAG token.
1358 func yaml_parser_fetch_tag(parser *yaml_parser_t) bool {
1359         // A tag could be a simple key.
1360         if !yaml_parser_save_simple_key(parser) {
1361                 return false
1362         }
1363
1364         // A simple key cannot follow a tag.
1365         parser.simple_key_allowed = false
1366
1367         // Create the TAG token and append it to the queue.
1368         var token yaml_token_t
1369         if !yaml_parser_scan_tag(parser, &token) {
1370                 return false
1371         }
1372         yaml_insert_token(parser, -1, &token)
1373         return true
1374 }
1375
1376 // Produce the SCALAR(...,literal) or SCALAR(...,folded) tokens.
1377 func yaml_parser_fetch_block_scalar(parser *yaml_parser_t, literal bool) bool {
1378         // Remove any potential simple keys.
1379         if !yaml_parser_remove_simple_key(parser) {
1380                 return false
1381         }
1382
1383         // A simple key may follow a block scalar.
1384         parser.simple_key_allowed = true
1385
1386         // Create the SCALAR token and append it to the queue.
1387         var token yaml_token_t
1388         if !yaml_parser_scan_block_scalar(parser, &token, literal) {
1389                 return false
1390         }
1391         yaml_insert_token(parser, -1, &token)
1392         return true
1393 }
1394
1395 // Produce the SCALAR(...,single-quoted) or SCALAR(...,double-quoted) tokens.
1396 func yaml_parser_fetch_flow_scalar(parser *yaml_parser_t, single bool) bool {
1397         // A plain scalar could be a simple key.
1398         if !yaml_parser_save_simple_key(parser) {
1399                 return false
1400         }
1401
1402         // A simple key cannot follow a flow scalar.
1403         parser.simple_key_allowed = false
1404
1405         // Create the SCALAR token and append it to the queue.
1406         var token yaml_token_t
1407         if !yaml_parser_scan_flow_scalar(parser, &token, single) {
1408                 return false
1409         }
1410         yaml_insert_token(parser, -1, &token)
1411         return true
1412 }
1413
1414 // Produce the SCALAR(...,plain) token.
1415 func yaml_parser_fetch_plain_scalar(parser *yaml_parser_t) bool {
1416         // A plain scalar could be a simple key.
1417         if !yaml_parser_save_simple_key(parser) {
1418                 return false
1419         }
1420
1421         // A simple key cannot follow a flow scalar.
1422         parser.simple_key_allowed = false
1423
1424         // Create the SCALAR token and append it to the queue.
1425         var token yaml_token_t
1426         if !yaml_parser_scan_plain_scalar(parser, &token) {
1427                 return false
1428         }
1429         yaml_insert_token(parser, -1, &token)
1430         return true
1431 }
1432
1433 // Eat whitespaces and comments until the next token is found.
1434 func yaml_parser_scan_to_next_token(parser *yaml_parser_t) bool {
1435
1436         // Until the next token is not found.
1437         for {
1438                 // Allow the BOM mark to start a line.
1439                 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1440                         return false
1441                 }
1442                 if parser.mark.column == 0 && is_bom(parser.buffer, parser.buffer_pos) {
1443                         skip(parser)
1444                 }
1445
1446                 // Eat whitespaces.
1447                 // Tabs are allowed:
1448                 //  - in the flow context
1449                 //  - in the block context, but not at the beginning of the line or
1450                 //  after '-', '?', or ':' (complex value).
1451                 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1452                         return false
1453                 }
1454
1455                 for parser.buffer[parser.buffer_pos] == ' ' || ((parser.flow_level > 0 || !parser.simple_key_allowed) && parser.buffer[parser.buffer_pos] == '\t') {
1456                         skip(parser)
1457                         if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1458                                 return false
1459                         }
1460                 }
1461
1462                 // Eat a comment until a line break.
1463                 if parser.buffer[parser.buffer_pos] == '#' {
1464                         for !is_breakz(parser.buffer, parser.buffer_pos) {
1465                                 skip(parser)
1466                                 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1467                                         return false
1468                                 }
1469                         }
1470                 }
1471
1472                 // If it is a line break, eat it.
1473                 if is_break(parser.buffer, parser.buffer_pos) {
1474                         if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
1475                                 return false
1476                         }
1477                         skip_line(parser)
1478
1479                         // In the block context, a new line may start a simple key.
1480                         if parser.flow_level == 0 {
1481                                 parser.simple_key_allowed = true
1482                         }
1483                 } else {
1484                         break // We have found a token.
1485                 }
1486         }
1487
1488         return true
1489 }
1490
1491 // Scan a YAML-DIRECTIVE or TAG-DIRECTIVE token.
1492 //
1493 // Scope:
1494 //      %YAML    1.1    # a comment \n
1495 //      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1496 //      %TAG    !yaml!  tag:yaml.org,2002:  \n
1497 //      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1498 //
1499 func yaml_parser_scan_directive(parser *yaml_parser_t, token *yaml_token_t) bool {
1500         // Eat '%'.
1501         start_mark := parser.mark
1502         skip(parser)
1503
1504         // Scan the directive name.
1505         var name []byte
1506         if !yaml_parser_scan_directive_name(parser, start_mark, &name) {
1507                 return false
1508         }
1509
1510         // Is it a YAML directive?
1511         if bytes.Equal(name, []byte("YAML")) {
1512                 // Scan the VERSION directive value.
1513                 var major, minor int8
1514                 if !yaml_parser_scan_version_directive_value(parser, start_mark, &major, &minor) {
1515                         return false
1516                 }
1517                 end_mark := parser.mark
1518
1519                 // Create a VERSION-DIRECTIVE token.
1520                 *token = yaml_token_t{
1521                         typ:        yaml_VERSION_DIRECTIVE_TOKEN,
1522                         start_mark: start_mark,
1523                         end_mark:   end_mark,
1524                         major:      major,
1525                         minor:      minor,
1526                 }
1527
1528                 // Is it a TAG directive?
1529         } else if bytes.Equal(name, []byte("TAG")) {
1530                 // Scan the TAG directive value.
1531                 var handle, prefix []byte
1532                 if !yaml_parser_scan_tag_directive_value(parser, start_mark, &handle, &prefix) {
1533                         return false
1534                 }
1535                 end_mark := parser.mark
1536
1537                 // Create a TAG-DIRECTIVE token.
1538                 *token = yaml_token_t{
1539                         typ:        yaml_TAG_DIRECTIVE_TOKEN,
1540                         start_mark: start_mark,
1541                         end_mark:   end_mark,
1542                         value:      handle,
1543                         prefix:     prefix,
1544                 }
1545
1546                 // Unknown directive.
1547         } else {
1548                 yaml_parser_set_scanner_error(parser, "while scanning a directive",
1549                         start_mark, "found unknown directive name")
1550                 return false
1551         }
1552
1553         // Eat the rest of the line including any comments.
1554         if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1555                 return false
1556         }
1557
1558         for is_blank(parser.buffer, parser.buffer_pos) {
1559                 skip(parser)
1560                 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1561                         return false
1562                 }
1563         }
1564
1565         if parser.buffer[parser.buffer_pos] == '#' {
1566                 for !is_breakz(parser.buffer, parser.buffer_pos) {
1567                         skip(parser)
1568                         if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1569                                 return false
1570                         }
1571                 }
1572         }
1573
1574         // Check if we are at the end of the line.
1575         if !is_breakz(parser.buffer, parser.buffer_pos) {
1576                 yaml_parser_set_scanner_error(parser, "while scanning a directive",
1577                         start_mark, "did not find expected comment or line break")
1578                 return false
1579         }
1580
1581         // Eat a line break.
1582         if is_break(parser.buffer, parser.buffer_pos) {
1583                 if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
1584                         return false
1585                 }
1586                 skip_line(parser)
1587         }
1588
1589         return true
1590 }
1591
1592 // Scan the directive name.
1593 //
1594 // Scope:
1595 //      %YAML   1.1     # a comment \n
1596 //       ^^^^
1597 //      %TAG    !yaml!  tag:yaml.org,2002:  \n
1598 //       ^^^
1599 //
1600 func yaml_parser_scan_directive_name(parser *yaml_parser_t, start_mark yaml_mark_t, name *[]byte) bool {
1601         // Consume the directive name.
1602         if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1603                 return false
1604         }
1605
1606         var s []byte
1607         for is_alpha(parser.buffer, parser.buffer_pos) {
1608                 s = read(parser, s)
1609                 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1610                         return false
1611                 }
1612         }
1613
1614         // Check if the name is empty.
1615         if len(s) == 0 {
1616                 yaml_parser_set_scanner_error(parser, "while scanning a directive",
1617                         start_mark, "could not find expected directive name")
1618                 return false
1619         }
1620
1621         // Check for an blank character after the name.
1622         if !is_blankz(parser.buffer, parser.buffer_pos) {
1623                 yaml_parser_set_scanner_error(parser, "while scanning a directive",
1624                         start_mark, "found unexpected non-alphabetical character")
1625                 return false
1626         }
1627         *name = s
1628         return true
1629 }
1630
1631 // Scan the value of VERSION-DIRECTIVE.
1632 //
1633 // Scope:
1634 //      %YAML   1.1     # a comment \n
1635 //           ^^^^^^
1636 func yaml_parser_scan_version_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, major, minor *int8) bool {
1637         // Eat whitespaces.
1638         if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1639                 return false
1640         }
1641         for is_blank(parser.buffer, parser.buffer_pos) {
1642                 skip(parser)
1643                 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1644                         return false
1645                 }
1646         }
1647
1648         // Consume the major version number.
1649         if !yaml_parser_scan_version_directive_number(parser, start_mark, major) {
1650                 return false
1651         }
1652
1653         // Eat '.'.
1654         if parser.buffer[parser.buffer_pos] != '.' {
1655                 return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
1656                         start_mark, "did not find expected digit or '.' character")
1657         }
1658
1659         skip(parser)
1660
1661         // Consume the minor version number.
1662         if !yaml_parser_scan_version_directive_number(parser, start_mark, minor) {
1663                 return false
1664         }
1665         return true
1666 }
1667
1668 const max_number_length = 2
1669
1670 // Scan the version number of VERSION-DIRECTIVE.
1671 //
1672 // Scope:
1673 //      %YAML   1.1     # a comment \n
1674 //              ^
1675 //      %YAML   1.1     # a comment \n
1676 //                ^
1677 func yaml_parser_scan_version_directive_number(parser *yaml_parser_t, start_mark yaml_mark_t, number *int8) bool {
1678
1679         // Repeat while the next character is digit.
1680         if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1681                 return false
1682         }
1683         var value, length int8
1684         for is_digit(parser.buffer, parser.buffer_pos) {
1685                 // Check if the number is too long.
1686                 length++
1687                 if length > max_number_length {
1688                         return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
1689                                 start_mark, "found extremely long version number")
1690                 }
1691                 value = value*10 + int8(as_digit(parser.buffer, parser.buffer_pos))
1692                 skip(parser)
1693                 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1694                         return false
1695                 }
1696         }
1697
1698         // Check if the number was present.
1699         if length == 0 {
1700                 return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
1701                         start_mark, "did not find expected version number")
1702         }
1703         *number = value
1704         return true
1705 }
1706
1707 // Scan the value of a TAG-DIRECTIVE token.
1708 //
1709 // Scope:
1710 //      %TAG    !yaml!  tag:yaml.org,2002:  \n
1711 //          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1712 //
1713 func yaml_parser_scan_tag_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, handle, prefix *[]byte) bool {
1714         var handle_value, prefix_value []byte
1715
1716         // Eat whitespaces.
1717         if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1718                 return false
1719         }
1720
1721         for is_blank(parser.buffer, parser.buffer_pos) {
1722                 skip(parser)
1723                 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1724                         return false
1725                 }
1726         }
1727
1728         // Scan a handle.
1729         if !yaml_parser_scan_tag_handle(parser, true, start_mark, &handle_value) {
1730                 return false
1731         }
1732
1733         // Expect a whitespace.
1734         if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1735                 return false
1736         }
1737         if !is_blank(parser.buffer, parser.buffer_pos) {
1738                 yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive",
1739                         start_mark, "did not find expected whitespace")
1740                 return false
1741         }
1742
1743         // Eat whitespaces.
1744         for is_blank(parser.buffer, parser.buffer_pos) {
1745                 skip(parser)
1746                 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1747                         return false
1748                 }
1749         }
1750
1751         // Scan a prefix.
1752         if !yaml_parser_scan_tag_uri(parser, true, nil, start_mark, &prefix_value) {
1753                 return false
1754         }
1755
1756         // Expect a whitespace or line break.
1757         if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1758                 return false
1759         }
1760         if !is_blankz(parser.buffer, parser.buffer_pos) {
1761                 yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive",
1762                         start_mark, "did not find expected whitespace or line break")
1763                 return false
1764         }
1765
1766         *handle = handle_value
1767         *prefix = prefix_value
1768         return true
1769 }
1770
1771 func yaml_parser_scan_anchor(parser *yaml_parser_t, token *yaml_token_t, typ yaml_token_type_t) bool {
1772         var s []byte
1773
1774         // Eat the indicator character.
1775         start_mark := parser.mark
1776         skip(parser)
1777
1778         // Consume the value.
1779         if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1780                 return false
1781         }
1782
1783         for is_alpha(parser.buffer, parser.buffer_pos) {
1784                 s = read(parser, s)
1785                 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1786                         return false
1787                 }
1788         }
1789
1790         end_mark := parser.mark
1791
1792         /*
1793          * Check if length of the anchor is greater than 0 and it is followed by
1794          * a whitespace character or one of the indicators:
1795          *
1796          *      '?', ':', ',', ']', '}', '%', '@', '`'.
1797          */
1798
1799         if len(s) == 0 ||
1800                 !(is_blankz(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '?' ||
1801                         parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == ',' ||
1802                         parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '}' ||
1803                         parser.buffer[parser.buffer_pos] == '%' || parser.buffer[parser.buffer_pos] == '@' ||
1804                         parser.buffer[parser.buffer_pos] == '`') {
1805                 context := "while scanning an alias"
1806                 if typ == yaml_ANCHOR_TOKEN {
1807                         context = "while scanning an anchor"
1808                 }
1809                 yaml_parser_set_scanner_error(parser, context, start_mark,
1810                         "did not find expected alphabetic or numeric character")
1811                 return false
1812         }
1813
1814         // Create a token.
1815         *token = yaml_token_t{
1816                 typ:        typ,
1817                 start_mark: start_mark,
1818                 end_mark:   end_mark,
1819                 value:      s,
1820         }
1821
1822         return true
1823 }
1824
1825 /*
1826  * Scan a TAG token.
1827  */
1828
1829 func yaml_parser_scan_tag(parser *yaml_parser_t, token *yaml_token_t) bool {
1830         var handle, suffix []byte
1831
1832         start_mark := parser.mark
1833
1834         // Check if the tag is in the canonical form.
1835         if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
1836                 return false
1837         }
1838
1839         if parser.buffer[parser.buffer_pos+1] == '<' {
1840                 // Keep the handle as ''
1841
1842                 // Eat '!<'
1843                 skip(parser)
1844                 skip(parser)
1845
1846                 // Consume the tag value.
1847                 if !yaml_parser_scan_tag_uri(parser, false, nil, start_mark, &suffix) {
1848                         return false
1849                 }
1850
1851                 // Check for '>' and eat it.
1852                 if parser.buffer[parser.buffer_pos] != '>' {
1853                         yaml_parser_set_scanner_error(parser, "while scanning a tag",
1854                                 start_mark, "did not find the expected '>'")
1855                         return false
1856                 }
1857
1858                 skip(parser)
1859         } else {
1860                 // The tag has either the '!suffix' or the '!handle!suffix' form.
1861
1862                 // First, try to scan a handle.
1863                 if !yaml_parser_scan_tag_handle(parser, false, start_mark, &handle) {
1864                         return false
1865                 }
1866
1867                 // Check if it is, indeed, handle.
1868                 if handle[0] == '!' && len(handle) > 1 && handle[len(handle)-1] == '!' {
1869                         // Scan the suffix now.
1870                         if !yaml_parser_scan_tag_uri(parser, false, nil, start_mark, &suffix) {
1871                                 return false
1872                         }
1873                 } else {
1874                         // It wasn't a handle after all.  Scan the rest of the tag.
1875                         if !yaml_parser_scan_tag_uri(parser, false, handle, start_mark, &suffix) {
1876                                 return false
1877                         }
1878
1879                         // Set the handle to '!'.
1880                         handle = []byte{'!'}
1881
1882                         // A special case: the '!' tag.  Set the handle to '' and the
1883                         // suffix to '!'.
1884                         if len(suffix) == 0 {
1885                                 handle, suffix = suffix, handle
1886                         }
1887                 }
1888         }
1889
1890         // Check the character which ends the tag.
1891         if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1892                 return false
1893         }
1894         if !is_blankz(parser.buffer, parser.buffer_pos) {
1895                 yaml_parser_set_scanner_error(parser, "while scanning a tag",
1896                         start_mark, "did not find expected whitespace or line break")
1897                 return false
1898         }
1899
1900         end_mark := parser.mark
1901
1902         // Create a token.
1903         *token = yaml_token_t{
1904                 typ:        yaml_TAG_TOKEN,
1905                 start_mark: start_mark,
1906                 end_mark:   end_mark,
1907                 value:      handle,
1908                 suffix:     suffix,
1909         }
1910         return true
1911 }
1912
1913 // Scan a tag handle.
1914 func yaml_parser_scan_tag_handle(parser *yaml_parser_t, directive bool, start_mark yaml_mark_t, handle *[]byte) bool {
1915         // Check the initial '!' character.
1916         if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1917                 return false
1918         }
1919         if parser.buffer[parser.buffer_pos] != '!' {
1920                 yaml_parser_set_scanner_tag_error(parser, directive,
1921                         start_mark, "did not find expected '!'")
1922                 return false
1923         }
1924
1925         var s []byte
1926
1927         // Copy the '!' character.
1928         s = read(parser, s)
1929
1930         // Copy all subsequent alphabetical and numerical characters.
1931         if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1932                 return false
1933         }
1934         for is_alpha(parser.buffer, parser.buffer_pos) {
1935                 s = read(parser, s)
1936                 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1937                         return false
1938                 }
1939         }
1940
1941         // Check if the trailing character is '!' and copy it.
1942         if parser.buffer[parser.buffer_pos] == '!' {
1943                 s = read(parser, s)
1944         } else {
1945                 // It's either the '!' tag or not really a tag handle.  If it's a %TAG
1946                 // directive, it's an error.  If it's a tag token, it must be a part of URI.
1947                 if directive && string(s) != "!" {
1948                         yaml_parser_set_scanner_tag_error(parser, directive,
1949                                 start_mark, "did not find expected '!'")
1950                         return false
1951                 }
1952         }
1953
1954         *handle = s
1955         return true
1956 }
1957
1958 // Scan a tag.
1959 func yaml_parser_scan_tag_uri(parser *yaml_parser_t, directive bool, head []byte, start_mark yaml_mark_t, uri *[]byte) bool {
1960         //size_t length = head ? strlen((char *)head) : 0
1961         var s []byte
1962         hasTag := len(head) > 0
1963
1964         // Copy the head if needed.
1965         //
1966         // Note that we don't copy the leading '!' character.
1967         if len(head) > 1 {
1968                 s = append(s, head[1:]...)
1969         }
1970
1971         // Scan the tag.
1972         if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1973                 return false
1974         }
1975
1976         // The set of characters that may appear in URI is as follows:
1977         //
1978         //      '0'-'9', 'A'-'Z', 'a'-'z', '_', '-', ';', '/', '?', ':', '@', '&',
1979         //      '=', '+', '$', ',', '.', '!', '~', '*', '\'', '(', ')', '[', ']',
1980         //      '%'.
1981         // [Go] Convert this into more reasonable logic.
1982         for is_alpha(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == ';' ||
1983                 parser.buffer[parser.buffer_pos] == '/' || parser.buffer[parser.buffer_pos] == '?' ||
1984                 parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == '@' ||
1985                 parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '=' ||
1986                 parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '$' ||
1987                 parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '.' ||
1988                 parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '~' ||
1989                 parser.buffer[parser.buffer_pos] == '*' || parser.buffer[parser.buffer_pos] == '\'' ||
1990                 parser.buffer[parser.buffer_pos] == '(' || parser.buffer[parser.buffer_pos] == ')' ||
1991                 parser.buffer[parser.buffer_pos] == '[' || parser.buffer[parser.buffer_pos] == ']' ||
1992                 parser.buffer[parser.buffer_pos] == '%' {
1993                 // Check if it is a URI-escape sequence.
1994                 if parser.buffer[parser.buffer_pos] == '%' {
1995                         if !yaml_parser_scan_uri_escapes(parser, directive, start_mark, &s) {
1996                                 return false
1997                         }
1998                 } else {
1999                         s = read(parser, s)
2000                 }
2001                 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
2002                         return false
2003                 }
2004                 hasTag = true
2005         }
2006
2007         if !hasTag {
2008                 yaml_parser_set_scanner_tag_error(parser, directive,
2009                         start_mark, "did not find expected tag URI")
2010                 return false
2011         }
2012         *uri = s
2013         return true
2014 }
2015
2016 // Decode an URI-escape sequence corresponding to a single UTF-8 character.
2017 func yaml_parser_scan_uri_escapes(parser *yaml_parser_t, directive bool, start_mark yaml_mark_t, s *[]byte) bool {
2018
2019         // Decode the required number of characters.
2020         w := 1024
2021         for w > 0 {
2022                 // Check for a URI-escaped octet.
2023                 if parser.unread < 3 && !yaml_parser_update_buffer(parser, 3) {
2024                         return false
2025                 }
2026
2027                 if !(parser.buffer[parser.buffer_pos] == '%' &&
2028                         is_hex(parser.buffer, parser.buffer_pos+1) &&
2029                         is_hex(parser.buffer, parser.buffer_pos+2)) {
2030                         return yaml_parser_set_scanner_tag_error(parser, directive,
2031                                 start_mark, "did not find URI escaped octet")
2032                 }
2033
2034                 // Get the octet.
2035                 octet := byte((as_hex(parser.buffer, parser.buffer_pos+1) << 4) + as_hex(parser.buffer, parser.buffer_pos+2))
2036
2037                 // If it is the leading octet, determine the length of the UTF-8 sequence.
2038                 if w == 1024 {
2039                         w = width(octet)
2040                         if w == 0 {
2041                                 return yaml_parser_set_scanner_tag_error(parser, directive,
2042                                         start_mark, "found an incorrect leading UTF-8 octet")
2043                         }
2044                 } else {
2045                         // Check if the trailing octet is correct.
2046                         if octet&0xC0 != 0x80 {
2047                                 return yaml_parser_set_scanner_tag_error(parser, directive,
2048                                         start_mark, "found an incorrect trailing UTF-8 octet")
2049                         }
2050                 }
2051
2052                 // Copy the octet and move the pointers.
2053                 *s = append(*s, octet)
2054                 skip(parser)
2055                 skip(parser)
2056                 skip(parser)
2057                 w--
2058         }
2059         return true
2060 }
2061
2062 // Scan a block scalar.
2063 func yaml_parser_scan_block_scalar(parser *yaml_parser_t, token *yaml_token_t, literal bool) bool {
2064         // Eat the indicator '|' or '>'.
2065         start_mark := parser.mark
2066         skip(parser)
2067
2068         // Scan the additional block scalar indicators.
2069         if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
2070                 return false
2071         }
2072
2073         // Check for a chomping indicator.
2074         var chomping, increment int
2075         if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' {
2076                 // Set the chomping method and eat the indicator.
2077                 if parser.buffer[parser.buffer_pos] == '+' {
2078                         chomping = +1
2079                 } else {
2080                         chomping = -1
2081                 }
2082                 skip(parser)
2083
2084                 // Check for an indentation indicator.
2085                 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
2086                         return false
2087                 }
2088                 if is_digit(parser.buffer, parser.buffer_pos) {
2089                         // Check that the indentation is greater than 0.
2090                         if parser.buffer[parser.buffer_pos] == '0' {
2091                                 yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
2092                                         start_mark, "found an indentation indicator equal to 0")
2093                                 return false
2094                         }
2095
2096                         // Get the indentation level and eat the indicator.
2097                         increment = as_digit(parser.buffer, parser.buffer_pos)
2098                         skip(parser)
2099                 }
2100
2101         } else if is_digit(parser.buffer, parser.buffer_pos) {
2102                 // Do the same as above, but in the opposite order.
2103
2104                 if parser.buffer[parser.buffer_pos] == '0' {
2105                         yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
2106                                 start_mark, "found an indentation indicator equal to 0")
2107                         return false
2108                 }
2109                 increment = as_digit(parser.buffer, parser.buffer_pos)
2110                 skip(parser)
2111
2112                 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
2113                         return false
2114                 }
2115                 if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' {
2116                         if parser.buffer[parser.buffer_pos] == '+' {
2117                                 chomping = +1
2118                         } else {
2119                                 chomping = -1
2120                         }
2121                         skip(parser)
2122                 }
2123         }
2124
2125         // Eat whitespaces and comments to the end of the line.
2126         if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
2127                 return false
2128         }
2129         for is_blank(parser.buffer, parser.buffer_pos) {
2130                 skip(parser)
2131                 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
2132                         return false
2133                 }
2134         }
2135         if parser.buffer[parser.buffer_pos] == '#' {
2136                 for !is_breakz(parser.buffer, parser.buffer_pos) {
2137                         skip(parser)
2138                         if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
2139                                 return false
2140                         }
2141                 }
2142         }
2143
2144         // Check if we are at the end of the line.
2145         if !is_breakz(parser.buffer, parser.buffer_pos) {
2146                 yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
2147                         start_mark, "did not find expected comment or line break")
2148                 return false
2149         }
2150
2151         // Eat a line break.
2152         if is_break(parser.buffer, parser.buffer_pos) {
2153                 if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
2154                         return false
2155                 }
2156                 skip_line(parser)
2157         }
2158
2159         end_mark := parser.mark
2160
2161         // Set the indentation level if it was specified.
2162         var indent int
2163         if increment > 0 {
2164                 if parser.indent >= 0 {
2165                         indent = parser.indent + increment
2166                 } else {
2167                         indent = increment
2168                 }
2169         }
2170
2171         // Scan the leading line breaks and determine the indentation level if needed.
2172         var s, leading_break, trailing_breaks []byte
2173         if !yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark) {
2174                 return false
2175         }
2176
2177         // Scan the block scalar content.
2178         if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
2179                 return false
2180         }
2181         var leading_blank, trailing_blank bool
2182         for parser.mark.column == indent && !is_z(parser.buffer, parser.buffer_pos) {
2183                 // We are at the beginning of a non-empty line.
2184
2185                 // Is it a trailing whitespace?
2186                 trailing_blank = is_blank(parser.buffer, parser.buffer_pos)
2187
2188                 // Check if we need to fold the leading line break.
2189                 if !literal && !leading_blank && !trailing_blank && len(leading_break) > 0 && leading_break[0] == '\n' {
2190                         // Do we need to join the lines by space?
2191                         if len(trailing_breaks) == 0 {
2192                                 s = append(s, ' ')
2193                         }
2194                 } else {
2195                         s = append(s, leading_break...)
2196                 }
2197                 leading_break = leading_break[:0]
2198
2199                 // Append the remaining line breaks.
2200                 s = append(s, trailing_breaks...)
2201                 trailing_breaks = trailing_breaks[:0]
2202
2203                 // Is it a leading whitespace?
2204                 leading_blank = is_blank(parser.buffer, parser.buffer_pos)
2205
2206                 // Consume the current line.
2207                 for !is_breakz(parser.buffer, parser.buffer_pos) {
2208                         s = read(parser, s)
2209                         if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
2210                                 return false
2211                         }
2212                 }
2213
2214                 // Consume the line break.
2215                 if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
2216                         return false
2217                 }
2218
2219                 leading_break = read_line(parser, leading_break)
2220
2221                 // Eat the following indentation spaces and line breaks.
2222                 if !yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark) {
2223                         return false
2224                 }
2225         }
2226
2227         // Chomp the tail.
2228         if chomping != -1 {
2229                 s = append(s, leading_break...)
2230         }
2231         if chomping == 1 {
2232                 s = append(s, trailing_breaks...)
2233         }
2234
2235         // Create a token.
2236         *token = yaml_token_t{
2237                 typ:        yaml_SCALAR_TOKEN,
2238                 start_mark: start_mark,
2239                 end_mark:   end_mark,
2240                 value:      s,
2241                 style:      yaml_LITERAL_SCALAR_STYLE,
2242         }
2243         if !literal {
2244                 token.style = yaml_FOLDED_SCALAR_STYLE
2245         }
2246         return true
2247 }
2248
2249 // Scan indentation spaces and line breaks for a block scalar.  Determine the
2250 // indentation level if needed.
2251 func yaml_parser_scan_block_scalar_breaks(parser *yaml_parser_t, indent *int, breaks *[]byte, start_mark yaml_mark_t, end_mark *yaml_mark_t) bool {
2252         *end_mark = parser.mark
2253
2254         // Eat the indentation spaces and line breaks.
2255         max_indent := 0
2256         for {
2257                 // Eat the indentation spaces.
2258                 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
2259                         return false
2260                 }
2261                 for (*indent == 0 || parser.mark.column < *indent) && is_space(parser.buffer, parser.buffer_pos) {
2262                         skip(parser)
2263                         if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
2264                                 return false
2265                         }
2266                 }
2267                 if parser.mark.column > max_indent {
2268                         max_indent = parser.mark.column
2269                 }
2270
2271                 // Check for a tab character messing the indentation.
2272                 if (*indent == 0 || parser.mark.column < *indent) && is_tab(parser.buffer, parser.buffer_pos) {
2273                         return yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
2274                                 start_mark, "found a tab character where an indentation space is expected")
2275                 }
2276
2277                 // Have we found a non-empty line?
2278                 if !is_break(parser.buffer, parser.buffer_pos) {
2279                         break
2280                 }
2281
2282                 // Consume the line break.
2283                 if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
2284                         return false
2285                 }
2286                 // [Go] Should really be returning breaks instead.
2287                 *breaks = read_line(parser, *breaks)
2288                 *end_mark = parser.mark
2289         }
2290
2291         // Determine the indentation level if needed.
2292         if *indent == 0 {
2293                 *indent = max_indent
2294                 if *indent < parser.indent+1 {
2295                         *indent = parser.indent + 1
2296                 }
2297                 if *indent < 1 {
2298                         *indent = 1
2299                 }
2300         }
2301         return true
2302 }
2303
2304 // Scan a quoted scalar.
2305 func yaml_parser_scan_flow_scalar(parser *yaml_parser_t, token *yaml_token_t, single bool) bool {
2306         // Eat the left quote.
2307         start_mark := parser.mark
2308         skip(parser)
2309
2310         // Consume the content of the quoted scalar.
2311         var s, leading_break, trailing_breaks, whitespaces []byte
2312         for {
2313                 // Check that there are no document indicators at the beginning of the line.
2314                 if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) {
2315                         return false
2316                 }
2317
2318                 if parser.mark.column == 0 &&
2319                         ((parser.buffer[parser.buffer_pos+0] == '-' &&
2320                                 parser.buffer[parser.buffer_pos+1] == '-' &&
2321                                 parser.buffer[parser.buffer_pos+2] == '-') ||
2322                                 (parser.buffer[parser.buffer_pos+0] == '.' &&
2323                                         parser.buffer[parser.buffer_pos+1] == '.' &&
2324                                         parser.buffer[parser.buffer_pos+2] == '.')) &&
2325                         is_blankz(parser.buffer, parser.buffer_pos+3) {
2326                         yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar",
2327                                 start_mark, "found unexpected document indicator")
2328                         return false
2329                 }
2330
2331                 // Check for EOF.
2332                 if is_z(parser.buffer, parser.buffer_pos) {
2333                         yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar",
2334                                 start_mark, "found unexpected end of stream")
2335                         return false
2336                 }
2337
2338                 // Consume non-blank characters.
2339                 leading_blanks := false
2340                 for !is_blankz(parser.buffer, parser.buffer_pos) {
2341                         if single && parser.buffer[parser.buffer_pos] == '\'' && parser.buffer[parser.buffer_pos+1] == '\'' {
2342                                 // Is is an escaped single quote.
2343                                 s = append(s, '\'')
2344                                 skip(parser)
2345                                 skip(parser)
2346
2347                         } else if single && parser.buffer[parser.buffer_pos] == '\'' {
2348                                 // It is a right single quote.
2349                                 break
2350                         } else if !single && parser.buffer[parser.buffer_pos] == '"' {
2351                                 // It is a right double quote.
2352                                 break
2353
2354                         } else if !single && parser.buffer[parser.buffer_pos] == '\\' && is_break(parser.buffer, parser.buffer_pos+1) {
2355                                 // It is an escaped line break.
2356                                 if parser.unread < 3 && !yaml_parser_update_buffer(parser, 3) {
2357                                         return false
2358                                 }
2359                                 skip(parser)
2360                                 skip_line(parser)
2361                                 leading_blanks = true
2362                                 break
2363
2364                         } else if !single && parser.buffer[parser.buffer_pos] == '\\' {
2365                                 // It is an escape sequence.
2366                                 code_length := 0
2367
2368                                 // Check the escape character.
2369                                 switch parser.buffer[parser.buffer_pos+1] {
2370                                 case '0':
2371                                         s = append(s, 0)
2372                                 case 'a':
2373                                         s = append(s, '\x07')
2374                                 case 'b':
2375                                         s = append(s, '\x08')
2376                                 case 't', '\t':
2377                                         s = append(s, '\x09')
2378                                 case 'n':
2379                                         s = append(s, '\x0A')
2380                                 case 'v':
2381                                         s = append(s, '\x0B')
2382                                 case 'f':
2383                                         s = append(s, '\x0C')
2384                                 case 'r':
2385                                         s = append(s, '\x0D')
2386                                 case 'e':
2387                                         s = append(s, '\x1B')
2388                                 case ' ':
2389                                         s = append(s, '\x20')
2390                                 case '"':
2391                                         s = append(s, '"')
2392                                 case '\'':
2393                                         s = append(s, '\'')
2394                                 case '\\':
2395                                         s = append(s, '\\')
2396                                 case 'N': // NEL (#x85)
2397                                         s = append(s, '\xC2')
2398                                         s = append(s, '\x85')
2399                                 case '_': // #xA0
2400                                         s = append(s, '\xC2')
2401                                         s = append(s, '\xA0')
2402                                 case 'L': // LS (#x2028)
2403                                         s = append(s, '\xE2')
2404                                         s = append(s, '\x80')
2405                                         s = append(s, '\xA8')
2406                                 case 'P': // PS (#x2029)
2407                                         s = append(s, '\xE2')
2408                                         s = append(s, '\x80')
2409                                         s = append(s, '\xA9')
2410                                 case 'x':
2411                                         code_length = 2
2412                                 case 'u':
2413                                         code_length = 4
2414                                 case 'U':
2415                                         code_length = 8
2416                                 default:
2417                                         yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar",
2418                                                 start_mark, "found unknown escape character")
2419                                         return false
2420                                 }
2421
2422                                 skip(parser)
2423                                 skip(parser)
2424
2425                                 // Consume an arbitrary escape code.
2426                                 if code_length > 0 {
2427                                         var value int
2428
2429                                         // Scan the character value.
2430                                         if parser.unread < code_length && !yaml_parser_update_buffer(parser, code_length) {
2431                                                 return false
2432                                         }
2433                                         for k := 0; k < code_length; k++ {
2434                                                 if !is_hex(parser.buffer, parser.buffer_pos+k) {
2435                                                         yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar",
2436                                                                 start_mark, "did not find expected hexdecimal number")
2437                                                         return false
2438                                                 }
2439                                                 value = (value << 4) + as_hex(parser.buffer, parser.buffer_pos+k)
2440                                         }
2441
2442                                         // Check the value and write the character.
2443                                         if (value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF {
2444                                                 yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar",
2445                                                         start_mark, "found invalid Unicode character escape code")
2446                                                 return false
2447                                         }
2448                                         if value <= 0x7F {
2449                                                 s = append(s, byte(value))
2450                                         } else if value <= 0x7FF {
2451                                                 s = append(s, byte(0xC0+(value>>6)))
2452                                                 s = append(s, byte(0x80+(value&0x3F)))
2453                                         } else if value <= 0xFFFF {
2454                                                 s = append(s, byte(0xE0+(value>>12)))
2455                                                 s = append(s, byte(0x80+((value>>6)&0x3F)))
2456                                                 s = append(s, byte(0x80+(value&0x3F)))
2457                                         } else {
2458                                                 s = append(s, byte(0xF0+(value>>18)))
2459                                                 s = append(s, byte(0x80+((value>>12)&0x3F)))
2460                                                 s = append(s, byte(0x80+((value>>6)&0x3F)))
2461                                                 s = append(s, byte(0x80+(value&0x3F)))
2462                                         }
2463
2464                                         // Advance the pointer.
2465                                         for k := 0; k < code_length; k++ {
2466                                                 skip(parser)
2467                                         }
2468                                 }
2469                         } else {
2470                                 // It is a non-escaped non-blank character.
2471                                 s = read(parser, s)
2472                         }
2473                         if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
2474                                 return false
2475                         }
2476                 }
2477
2478                 // Check if we are at the end of the scalar.
2479                 if single {
2480                         if parser.buffer[parser.buffer_pos] == '\'' {
2481                                 break
2482                         }
2483                 } else {
2484                         if parser.buffer[parser.buffer_pos] == '"' {
2485                                 break
2486                         }
2487                 }
2488
2489                 // Consume blank characters.
2490                 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
2491                         return false
2492                 }
2493
2494                 for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) {
2495                         if is_blank(parser.buffer, parser.buffer_pos) {
2496                                 // Consume a space or a tab character.
2497                                 if !leading_blanks {
2498                                         whitespaces = read(parser, whitespaces)
2499                                 } else {
2500                                         skip(parser)
2501                                 }
2502                         } else {
2503                                 if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
2504                                         return false
2505                                 }
2506
2507                                 // Check if it is a first line break.
2508                                 if !leading_blanks {
2509                                         whitespaces = whitespaces[:0]
2510                                         leading_break = read_line(parser, leading_break)
2511                                         leading_blanks = true
2512                                 } else {
2513                                         trailing_breaks = read_line(parser, trailing_breaks)
2514                                 }
2515                         }
2516                         if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
2517                                 return false
2518                         }
2519                 }
2520
2521                 // Join the whitespaces or fold line breaks.
2522                 if leading_blanks {
2523                         // Do we need to fold line breaks?
2524                         if len(leading_break) > 0 && leading_break[0] == '\n' {
2525                                 if len(trailing_breaks) == 0 {
2526                                         s = append(s, ' ')
2527                                 } else {
2528                                         s = append(s, trailing_breaks...)
2529                                 }
2530                         } else {
2531                                 s = append(s, leading_break...)
2532                                 s = append(s, trailing_breaks...)
2533                         }
2534                         trailing_breaks = trailing_breaks[:0]
2535                         leading_break = leading_break[:0]
2536                 } else {
2537                         s = append(s, whitespaces...)
2538                         whitespaces = whitespaces[:0]
2539                 }
2540         }
2541
2542         // Eat the right quote.
2543         skip(parser)
2544         end_mark := parser.mark
2545
2546         // Create a token.
2547         *token = yaml_token_t{
2548                 typ:        yaml_SCALAR_TOKEN,
2549                 start_mark: start_mark,
2550                 end_mark:   end_mark,
2551                 value:      s,
2552                 style:      yaml_SINGLE_QUOTED_SCALAR_STYLE,
2553         }
2554         if !single {
2555                 token.style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
2556         }
2557         return true
2558 }
2559
2560 // Scan a plain scalar.
2561 func yaml_parser_scan_plain_scalar(parser *yaml_parser_t, token *yaml_token_t) bool {
2562
2563         var s, leading_break, trailing_breaks, whitespaces []byte
2564         var leading_blanks bool
2565         var indent = parser.indent + 1
2566
2567         start_mark := parser.mark
2568         end_mark := parser.mark
2569
2570         // Consume the content of the plain scalar.
2571         for {
2572                 // Check for a document indicator.
2573                 if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) {
2574                         return false
2575                 }
2576                 if parser.mark.column == 0 &&
2577                         ((parser.buffer[parser.buffer_pos+0] == '-' &&
2578                                 parser.buffer[parser.buffer_pos+1] == '-' &&
2579                                 parser.buffer[parser.buffer_pos+2] == '-') ||
2580                                 (parser.buffer[parser.buffer_pos+0] == '.' &&
2581                                         parser.buffer[parser.buffer_pos+1] == '.' &&
2582                                         parser.buffer[parser.buffer_pos+2] == '.')) &&
2583                         is_blankz(parser.buffer, parser.buffer_pos+3) {
2584                         break
2585                 }
2586
2587                 // Check for a comment.
2588                 if parser.buffer[parser.buffer_pos] == '#' {
2589                         break
2590                 }
2591
2592                 // Consume non-blank characters.
2593                 for !is_blankz(parser.buffer, parser.buffer_pos) {
2594
2595                         // Check for 'x:x' in the flow context. TODO: Fix the test "spec-08-13".
2596                         if parser.flow_level > 0 &&
2597                                 parser.buffer[parser.buffer_pos] == ':' &&
2598                                 !is_blankz(parser.buffer, parser.buffer_pos+1) {
2599                                 yaml_parser_set_scanner_error(parser, "while scanning a plain scalar",
2600                                         start_mark, "found unexpected ':'")
2601                                 return false
2602                         }
2603
2604                         // Check for indicators that may end a plain scalar.
2605                         if (parser.buffer[parser.buffer_pos] == ':' && is_blankz(parser.buffer, parser.buffer_pos+1)) ||
2606                                 (parser.flow_level > 0 &&
2607                                         (parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == ':' ||
2608                                                 parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == '[' ||
2609                                                 parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' ||
2610                                                 parser.buffer[parser.buffer_pos] == '}')) {
2611                                 break
2612                         }
2613
2614                         // Check if we need to join whitespaces and breaks.
2615                         if leading_blanks || len(whitespaces) > 0 {
2616                                 if leading_blanks {
2617                                         // Do we need to fold line breaks?
2618                                         if leading_break[0] == '\n' {
2619                                                 if len(trailing_breaks) == 0 {
2620                                                         s = append(s, ' ')
2621                                                 } else {
2622                                                         s = append(s, trailing_breaks...)
2623                                                 }
2624                                         } else {
2625                                                 s = append(s, leading_break...)
2626                                                 s = append(s, trailing_breaks...)
2627                                         }
2628                                         trailing_breaks = trailing_breaks[:0]
2629                                         leading_break = leading_break[:0]
2630                                         leading_blanks = false
2631                                 } else {
2632                                         s = append(s, whitespaces...)
2633                                         whitespaces = whitespaces[:0]
2634                                 }
2635                         }
2636
2637                         // Copy the character.
2638                         s = read(parser, s)
2639
2640                         end_mark = parser.mark
2641                         if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
2642                                 return false
2643                         }
2644                 }
2645
2646                 // Is it the end?
2647                 if !(is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos)) {
2648                         break
2649                 }
2650
2651                 // Consume blank characters.
2652                 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
2653                         return false
2654                 }
2655
2656                 for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) {
2657                         if is_blank(parser.buffer, parser.buffer_pos) {
2658
2659                                 // Check for tab character that abuse indentation.
2660                                 if leading_blanks && parser.mark.column < indent && is_tab(parser.buffer, parser.buffer_pos) {
2661                                         yaml_parser_set_scanner_error(parser, "while scanning a plain scalar",
2662                                                 start_mark, "found a tab character that violate indentation")
2663                                         return false
2664                                 }
2665
2666                                 // Consume a space or a tab character.
2667                                 if !leading_blanks {
2668                                         whitespaces = read(parser, whitespaces)
2669                                 } else {
2670                                         skip(parser)
2671                                 }
2672                         } else {
2673                                 if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
2674                                         return false
2675                                 }
2676
2677                                 // Check if it is a first line break.
2678                                 if !leading_blanks {
2679                                         whitespaces = whitespaces[:0]
2680                                         leading_break = read_line(parser, leading_break)
2681                                         leading_blanks = true
2682                                 } else {
2683                                         trailing_breaks = read_line(parser, trailing_breaks)
2684                                 }
2685                         }
2686                         if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
2687                                 return false
2688                         }
2689                 }
2690
2691                 // Check indentation level.
2692                 if parser.flow_level == 0 && parser.mark.column < indent {
2693                         break
2694                 }
2695         }
2696
2697         // Create a token.
2698         *token = yaml_token_t{
2699                 typ:        yaml_SCALAR_TOKEN,
2700                 start_mark: start_mark,
2701                 end_mark:   end_mark,
2702                 value:      s,
2703                 style:      yaml_PLAIN_SCALAR_STYLE,
2704         }
2705
2706         // Note that we change the 'simple_key_allowed' flag.
2707         if leading_blanks {
2708                 parser.simple_key_allowed = true
2709         }
2710         return true
2711 }