1package yaml
   2
   3import (
   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).
 485func 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.
 491func 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
 498func 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.
 515func 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.
 538func 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.
 571func 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.
 600func 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
 609func 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
 617func 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.
 626func 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.
 652func 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
 822func 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.
 850func 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.
 878func 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
 895const max_flow_level = 10000
 896
 897// Increase the flow level and resize the simple key list if needed.
 898func 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.
 918func 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
 929const 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.
 934func 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.
 968func 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.
 992func 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.
1020func 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.
1051func 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.
1075func 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.
1109func 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.
1140func 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.
1172func 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.
1197func 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.
1239func 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.
1278func 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.
1348func 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.
1367func 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.
1386func 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.
1405func 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.
1424func 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.
1443func 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//
1508func 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//
1609func 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//           ^^^^^^
1645func 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
1677const 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//                ^
1686func 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//
1722func 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
1780func 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
1838func 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.
1923func 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.
1968func 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.
2026func 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.
2072func 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.
2260func 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.
2314func 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.
2570func 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}