gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

scannerc.go (87960B)


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