scannerc.go raw

   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  }
2712