gtsocial-umbx

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

scannerc.go (77594B)


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