flake-update-20260201
   1//
   2// Copyright (c) 2011-2019 Canonical Ltd
   3// Copyright (c) 2006-2010 Kirill Simonov
   4//
   5// Permission is hereby granted, free of charge, to any person obtaining a copy of
   6// this software and associated documentation files (the "Software"), to deal in
   7// the Software without restriction, including without limitation the rights to
   8// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
   9// of the Software, and to permit persons to whom the Software is furnished to do
  10// so, subject to the following conditions:
  11//
  12// The above copyright notice and this permission notice shall be included in all
  13// copies or substantial portions of the Software.
  14//
  15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  21// SOFTWARE.
  22
  23package yaml
  24
  25import (
  26	"bytes"
  27)
  28
  29// The parser implements the following grammar:
  30//
  31// stream               ::= STREAM-START implicit_document? explicit_document* STREAM-END
  32// implicit_document    ::= block_node DOCUMENT-END*
  33// explicit_document    ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
  34// block_node_or_indentless_sequence    ::=
  35//                          ALIAS
  36//                          | properties (block_content | indentless_block_sequence)?
  37//                          | block_content
  38//                          | indentless_block_sequence
  39// block_node           ::= ALIAS
  40//                          | properties block_content?
  41//                          | block_content
  42// flow_node            ::= ALIAS
  43//                          | properties flow_content?
  44//                          | flow_content
  45// properties           ::= TAG ANCHOR? | ANCHOR TAG?
  46// block_content        ::= block_collection | flow_collection | SCALAR
  47// flow_content         ::= flow_collection | SCALAR
  48// block_collection     ::= block_sequence | block_mapping
  49// flow_collection      ::= flow_sequence | flow_mapping
  50// block_sequence       ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
  51// indentless_sequence  ::= (BLOCK-ENTRY block_node?)+
  52// block_mapping        ::= BLOCK-MAPPING_START
  53//                          ((KEY block_node_or_indentless_sequence?)?
  54//                          (VALUE block_node_or_indentless_sequence?)?)*
  55//                          BLOCK-END
  56// flow_sequence        ::= FLOW-SEQUENCE-START
  57//                          (flow_sequence_entry FLOW-ENTRY)*
  58//                          flow_sequence_entry?
  59//                          FLOW-SEQUENCE-END
  60// flow_sequence_entry  ::= flow_node | KEY flow_node? (VALUE flow_node?)?
  61// flow_mapping         ::= FLOW-MAPPING-START
  62//                          (flow_mapping_entry FLOW-ENTRY)*
  63//                          flow_mapping_entry?
  64//                          FLOW-MAPPING-END
  65// flow_mapping_entry   ::= flow_node | KEY flow_node? (VALUE flow_node?)?
  66
  67// Peek the next token in the token queue.
  68func peek_token(parser *yaml_parser_t) *yaml_token_t {
  69	if parser.token_available || yaml_parser_fetch_more_tokens(parser) {
  70		token := &parser.tokens[parser.tokens_head]
  71		yaml_parser_unfold_comments(parser, token)
  72		return token
  73	}
  74	return nil
  75}
  76
  77// yaml_parser_unfold_comments walks through the comments queue and joins all
  78// comments behind the position of the provided token into the respective
  79// top-level comment slices in the parser.
  80func yaml_parser_unfold_comments(parser *yaml_parser_t, token *yaml_token_t) {
  81	for parser.comments_head < len(parser.comments) && token.start_mark.index >= parser.comments[parser.comments_head].token_mark.index {
  82		comment := &parser.comments[parser.comments_head]
  83		if len(comment.head) > 0 {
  84			if token.typ == yaml_BLOCK_END_TOKEN {
  85				// No heads on ends, so keep comment.head for a follow up token.
  86				break
  87			}
  88			if len(parser.head_comment) > 0 {
  89				parser.head_comment = append(parser.head_comment, '\n')
  90			}
  91			parser.head_comment = append(parser.head_comment, comment.head...)
  92		}
  93		if len(comment.foot) > 0 {
  94			if len(parser.foot_comment) > 0 {
  95				parser.foot_comment = append(parser.foot_comment, '\n')
  96			}
  97			parser.foot_comment = append(parser.foot_comment, comment.foot...)
  98		}
  99		if len(comment.line) > 0 {
 100			if len(parser.line_comment) > 0 {
 101				parser.line_comment = append(parser.line_comment, '\n')
 102			}
 103			parser.line_comment = append(parser.line_comment, comment.line...)
 104		}
 105		*comment = yaml_comment_t{}
 106		parser.comments_head++
 107	}
 108}
 109
 110// Remove the next token from the queue (must be called after peek_token).
 111func skip_token(parser *yaml_parser_t) {
 112	parser.token_available = false
 113	parser.tokens_parsed++
 114	parser.stream_end_produced = parser.tokens[parser.tokens_head].typ == yaml_STREAM_END_TOKEN
 115	parser.tokens_head++
 116}
 117
 118// Get the next event.
 119func yaml_parser_parse(parser *yaml_parser_t, event *yaml_event_t) bool {
 120	// Erase the event object.
 121	*event = yaml_event_t{}
 122
 123	// No events after the end of the stream or error.
 124	if parser.stream_end_produced || parser.error != yaml_NO_ERROR || parser.state == yaml_PARSE_END_STATE {
 125		return true
 126	}
 127
 128	// Generate the next event.
 129	return yaml_parser_state_machine(parser, event)
 130}
 131
 132// Set parser error.
 133func yaml_parser_set_parser_error(parser *yaml_parser_t, problem string, problem_mark yaml_mark_t) bool {
 134	parser.error = yaml_PARSER_ERROR
 135	parser.problem = problem
 136	parser.problem_mark = problem_mark
 137	return false
 138}
 139
 140func yaml_parser_set_parser_error_context(parser *yaml_parser_t, context string, context_mark yaml_mark_t, problem string, problem_mark yaml_mark_t) bool {
 141	parser.error = yaml_PARSER_ERROR
 142	parser.context = context
 143	parser.context_mark = context_mark
 144	parser.problem = problem
 145	parser.problem_mark = problem_mark
 146	return false
 147}
 148
 149// State dispatcher.
 150func yaml_parser_state_machine(parser *yaml_parser_t, event *yaml_event_t) bool {
 151	//trace("yaml_parser_state_machine", "state:", parser.state.String())
 152
 153	switch parser.state {
 154	case yaml_PARSE_STREAM_START_STATE:
 155		return yaml_parser_parse_stream_start(parser, event)
 156
 157	case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE:
 158		return yaml_parser_parse_document_start(parser, event, true)
 159
 160	case yaml_PARSE_DOCUMENT_START_STATE:
 161		return yaml_parser_parse_document_start(parser, event, false)
 162
 163	case yaml_PARSE_DOCUMENT_CONTENT_STATE:
 164		return yaml_parser_parse_document_content(parser, event)
 165
 166	case yaml_PARSE_DOCUMENT_END_STATE:
 167		return yaml_parser_parse_document_end(parser, event)
 168
 169	case yaml_PARSE_BLOCK_NODE_STATE:
 170		return yaml_parser_parse_node(parser, event, true, false)
 171
 172	case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE:
 173		return yaml_parser_parse_node(parser, event, true, true)
 174
 175	case yaml_PARSE_FLOW_NODE_STATE:
 176		return yaml_parser_parse_node(parser, event, false, false)
 177
 178	case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE:
 179		return yaml_parser_parse_block_sequence_entry(parser, event, true)
 180
 181	case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE:
 182		return yaml_parser_parse_block_sequence_entry(parser, event, false)
 183
 184	case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE:
 185		return yaml_parser_parse_indentless_sequence_entry(parser, event)
 186
 187	case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE:
 188		return yaml_parser_parse_block_mapping_key(parser, event, true)
 189
 190	case yaml_PARSE_BLOCK_MAPPING_KEY_STATE:
 191		return yaml_parser_parse_block_mapping_key(parser, event, false)
 192
 193	case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE:
 194		return yaml_parser_parse_block_mapping_value(parser, event)
 195
 196	case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE:
 197		return yaml_parser_parse_flow_sequence_entry(parser, event, true)
 198
 199	case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE:
 200		return yaml_parser_parse_flow_sequence_entry(parser, event, false)
 201
 202	case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE:
 203		return yaml_parser_parse_flow_sequence_entry_mapping_key(parser, event)
 204
 205	case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE:
 206		return yaml_parser_parse_flow_sequence_entry_mapping_value(parser, event)
 207
 208	case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE:
 209		return yaml_parser_parse_flow_sequence_entry_mapping_end(parser, event)
 210
 211	case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE:
 212		return yaml_parser_parse_flow_mapping_key(parser, event, true)
 213
 214	case yaml_PARSE_FLOW_MAPPING_KEY_STATE:
 215		return yaml_parser_parse_flow_mapping_key(parser, event, false)
 216
 217	case yaml_PARSE_FLOW_MAPPING_VALUE_STATE:
 218		return yaml_parser_parse_flow_mapping_value(parser, event, false)
 219
 220	case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE:
 221		return yaml_parser_parse_flow_mapping_value(parser, event, true)
 222
 223	default:
 224		panic("invalid parser state")
 225	}
 226}
 227
 228// Parse the production:
 229// stream   ::= STREAM-START implicit_document? explicit_document* STREAM-END
 230//
 231//	************
 232func yaml_parser_parse_stream_start(parser *yaml_parser_t, event *yaml_event_t) bool {
 233	token := peek_token(parser)
 234	if token == nil {
 235		return false
 236	}
 237	if token.typ != yaml_STREAM_START_TOKEN {
 238		return yaml_parser_set_parser_error(parser, "did not find expected <stream-start>", token.start_mark)
 239	}
 240	parser.state = yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE
 241	*event = yaml_event_t{
 242		typ:        yaml_STREAM_START_EVENT,
 243		start_mark: token.start_mark,
 244		end_mark:   token.end_mark,
 245		encoding:   token.encoding,
 246	}
 247	skip_token(parser)
 248	return true
 249}
 250
 251// Parse the productions:
 252// implicit_document    ::= block_node DOCUMENT-END*
 253//
 254//	*
 255//
 256// explicit_document    ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
 257//
 258//	*************************
 259func yaml_parser_parse_document_start(parser *yaml_parser_t, event *yaml_event_t, implicit bool) bool {
 260
 261	token := peek_token(parser)
 262	if token == nil {
 263		return false
 264	}
 265
 266	// Parse extra document end indicators.
 267	if !implicit {
 268		for token.typ == yaml_DOCUMENT_END_TOKEN {
 269			skip_token(parser)
 270			token = peek_token(parser)
 271			if token == nil {
 272				return false
 273			}
 274		}
 275	}
 276
 277	if implicit && token.typ != yaml_VERSION_DIRECTIVE_TOKEN &&
 278		token.typ != yaml_TAG_DIRECTIVE_TOKEN &&
 279		token.typ != yaml_DOCUMENT_START_TOKEN &&
 280		token.typ != yaml_STREAM_END_TOKEN {
 281		// Parse an implicit document.
 282		if !yaml_parser_process_directives(parser, nil, nil) {
 283			return false
 284		}
 285		parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE)
 286		parser.state = yaml_PARSE_BLOCK_NODE_STATE
 287
 288		var head_comment []byte
 289		if len(parser.head_comment) > 0 {
 290			// [Go] Scan the header comment backwards, and if an empty line is found, break
 291			//      the header so the part before the last empty line goes into the
 292			//      document header, while the bottom of it goes into a follow up event.
 293			for i := len(parser.head_comment) - 1; i > 0; i-- {
 294				if parser.head_comment[i] == '\n' {
 295					if i == len(parser.head_comment)-1 {
 296						head_comment = parser.head_comment[:i]
 297						parser.head_comment = parser.head_comment[i+1:]
 298						break
 299					} else if parser.head_comment[i-1] == '\n' {
 300						head_comment = parser.head_comment[:i-1]
 301						parser.head_comment = parser.head_comment[i+1:]
 302						break
 303					}
 304				}
 305			}
 306		}
 307
 308		*event = yaml_event_t{
 309			typ:        yaml_DOCUMENT_START_EVENT,
 310			start_mark: token.start_mark,
 311			end_mark:   token.end_mark,
 312
 313			head_comment: head_comment,
 314		}
 315
 316	} else if token.typ != yaml_STREAM_END_TOKEN {
 317		// Parse an explicit document.
 318		var version_directive *yaml_version_directive_t
 319		var tag_directives []yaml_tag_directive_t
 320		start_mark := token.start_mark
 321		if !yaml_parser_process_directives(parser, &version_directive, &tag_directives) {
 322			return false
 323		}
 324		token = peek_token(parser)
 325		if token == nil {
 326			return false
 327		}
 328		if token.typ != yaml_DOCUMENT_START_TOKEN {
 329			yaml_parser_set_parser_error(parser,
 330				"did not find expected <document start>", token.start_mark)
 331			return false
 332		}
 333		parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE)
 334		parser.state = yaml_PARSE_DOCUMENT_CONTENT_STATE
 335		end_mark := token.end_mark
 336
 337		*event = yaml_event_t{
 338			typ:               yaml_DOCUMENT_START_EVENT,
 339			start_mark:        start_mark,
 340			end_mark:          end_mark,
 341			version_directive: version_directive,
 342			tag_directives:    tag_directives,
 343			implicit:          false,
 344		}
 345		skip_token(parser)
 346
 347	} else {
 348		// Parse the stream end.
 349		parser.state = yaml_PARSE_END_STATE
 350		*event = yaml_event_t{
 351			typ:        yaml_STREAM_END_EVENT,
 352			start_mark: token.start_mark,
 353			end_mark:   token.end_mark,
 354		}
 355		skip_token(parser)
 356	}
 357
 358	return true
 359}
 360
 361// Parse the productions:
 362// explicit_document    ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
 363//
 364//	***********
 365func yaml_parser_parse_document_content(parser *yaml_parser_t, event *yaml_event_t) bool {
 366	token := peek_token(parser)
 367	if token == nil {
 368		return false
 369	}
 370
 371	if token.typ == yaml_VERSION_DIRECTIVE_TOKEN ||
 372		token.typ == yaml_TAG_DIRECTIVE_TOKEN ||
 373		token.typ == yaml_DOCUMENT_START_TOKEN ||
 374		token.typ == yaml_DOCUMENT_END_TOKEN ||
 375		token.typ == yaml_STREAM_END_TOKEN {
 376		parser.state = parser.states[len(parser.states)-1]
 377		parser.states = parser.states[:len(parser.states)-1]
 378		return yaml_parser_process_empty_scalar(parser, event,
 379			token.start_mark)
 380	}
 381	return yaml_parser_parse_node(parser, event, true, false)
 382}
 383
 384// Parse the productions:
 385// implicit_document    ::= block_node DOCUMENT-END*
 386//
 387//	*************
 388//
 389// explicit_document    ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
 390func yaml_parser_parse_document_end(parser *yaml_parser_t, event *yaml_event_t) bool {
 391	token := peek_token(parser)
 392	if token == nil {
 393		return false
 394	}
 395
 396	start_mark := token.start_mark
 397	end_mark := token.start_mark
 398
 399	implicit := true
 400	if token.typ == yaml_DOCUMENT_END_TOKEN {
 401		end_mark = token.end_mark
 402		skip_token(parser)
 403		implicit = false
 404	}
 405
 406	parser.tag_directives = parser.tag_directives[:0]
 407
 408	parser.state = yaml_PARSE_DOCUMENT_START_STATE
 409	*event = yaml_event_t{
 410		typ:        yaml_DOCUMENT_END_EVENT,
 411		start_mark: start_mark,
 412		end_mark:   end_mark,
 413		implicit:   implicit,
 414	}
 415	yaml_parser_set_event_comments(parser, event)
 416	if len(event.head_comment) > 0 && len(event.foot_comment) == 0 {
 417		event.foot_comment = event.head_comment
 418		event.head_comment = nil
 419	}
 420	return true
 421}
 422
 423func yaml_parser_set_event_comments(parser *yaml_parser_t, event *yaml_event_t) {
 424	event.head_comment = parser.head_comment
 425	event.line_comment = parser.line_comment
 426	event.foot_comment = parser.foot_comment
 427	parser.head_comment = nil
 428	parser.line_comment = nil
 429	parser.foot_comment = nil
 430	parser.tail_comment = nil
 431	parser.stem_comment = nil
 432}
 433
 434// Parse the productions:
 435// block_node_or_indentless_sequence    ::=
 436//
 437//	ALIAS
 438//	*****
 439//	| properties (block_content | indentless_block_sequence)?
 440//	  **********  *
 441//	| block_content | indentless_block_sequence
 442//	  *
 443//
 444// block_node           ::= ALIAS
 445//
 446//	*****
 447//	| properties block_content?
 448//	  ********** *
 449//	| block_content
 450//	  *
 451//
 452// flow_node            ::= ALIAS
 453//
 454//	*****
 455//	| properties flow_content?
 456//	  ********** *
 457//	| flow_content
 458//	  *
 459//
 460// properties           ::= TAG ANCHOR? | ANCHOR TAG?
 461//
 462//	*************************
 463//
 464// block_content        ::= block_collection | flow_collection | SCALAR
 465//
 466//	******
 467//
 468// flow_content         ::= flow_collection | SCALAR
 469//
 470//	******
 471func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, indentless_sequence bool) bool {
 472	//defer trace("yaml_parser_parse_node", "block:", block, "indentless_sequence:", indentless_sequence)()
 473
 474	token := peek_token(parser)
 475	if token == nil {
 476		return false
 477	}
 478
 479	if token.typ == yaml_ALIAS_TOKEN {
 480		parser.state = parser.states[len(parser.states)-1]
 481		parser.states = parser.states[:len(parser.states)-1]
 482		*event = yaml_event_t{
 483			typ:        yaml_ALIAS_EVENT,
 484			start_mark: token.start_mark,
 485			end_mark:   token.end_mark,
 486			anchor:     token.value,
 487		}
 488		yaml_parser_set_event_comments(parser, event)
 489		skip_token(parser)
 490		return true
 491	}
 492
 493	start_mark := token.start_mark
 494	end_mark := token.start_mark
 495
 496	var tag_token bool
 497	var tag_handle, tag_suffix, anchor []byte
 498	var tag_mark yaml_mark_t
 499	if token.typ == yaml_ANCHOR_TOKEN {
 500		anchor = token.value
 501		start_mark = token.start_mark
 502		end_mark = token.end_mark
 503		skip_token(parser)
 504		token = peek_token(parser)
 505		if token == nil {
 506			return false
 507		}
 508		if token.typ == yaml_TAG_TOKEN {
 509			tag_token = true
 510			tag_handle = token.value
 511			tag_suffix = token.suffix
 512			tag_mark = token.start_mark
 513			end_mark = token.end_mark
 514			skip_token(parser)
 515			token = peek_token(parser)
 516			if token == nil {
 517				return false
 518			}
 519		}
 520	} else if token.typ == yaml_TAG_TOKEN {
 521		tag_token = true
 522		tag_handle = token.value
 523		tag_suffix = token.suffix
 524		start_mark = token.start_mark
 525		tag_mark = token.start_mark
 526		end_mark = token.end_mark
 527		skip_token(parser)
 528		token = peek_token(parser)
 529		if token == nil {
 530			return false
 531		}
 532		if token.typ == yaml_ANCHOR_TOKEN {
 533			anchor = token.value
 534			end_mark = token.end_mark
 535			skip_token(parser)
 536			token = peek_token(parser)
 537			if token == nil {
 538				return false
 539			}
 540		}
 541	}
 542
 543	var tag []byte
 544	if tag_token {
 545		if len(tag_handle) == 0 {
 546			tag = tag_suffix
 547			tag_suffix = nil
 548		} else {
 549			for i := range parser.tag_directives {
 550				if bytes.Equal(parser.tag_directives[i].handle, tag_handle) {
 551					tag = append([]byte(nil), parser.tag_directives[i].prefix...)
 552					tag = append(tag, tag_suffix...)
 553					break
 554				}
 555			}
 556			if len(tag) == 0 {
 557				yaml_parser_set_parser_error_context(parser,
 558					"while parsing a node", start_mark,
 559					"found undefined tag handle", tag_mark)
 560				return false
 561			}
 562		}
 563	}
 564
 565	implicit := len(tag) == 0
 566	if indentless_sequence && token.typ == yaml_BLOCK_ENTRY_TOKEN {
 567		end_mark = token.end_mark
 568		parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE
 569		*event = yaml_event_t{
 570			typ:        yaml_SEQUENCE_START_EVENT,
 571			start_mark: start_mark,
 572			end_mark:   end_mark,
 573			anchor:     anchor,
 574			tag:        tag,
 575			implicit:   implicit,
 576			style:      yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE),
 577		}
 578		return true
 579	}
 580	if token.typ == yaml_SCALAR_TOKEN {
 581		var plain_implicit, quoted_implicit bool
 582		end_mark = token.end_mark
 583		if (len(tag) == 0 && token.style == yaml_PLAIN_SCALAR_STYLE) || (len(tag) == 1 && tag[0] == '!') {
 584			plain_implicit = true
 585		} else if len(tag) == 0 {
 586			quoted_implicit = true
 587		}
 588		parser.state = parser.states[len(parser.states)-1]
 589		parser.states = parser.states[:len(parser.states)-1]
 590
 591		*event = yaml_event_t{
 592			typ:             yaml_SCALAR_EVENT,
 593			start_mark:      start_mark,
 594			end_mark:        end_mark,
 595			anchor:          anchor,
 596			tag:             tag,
 597			value:           token.value,
 598			implicit:        plain_implicit,
 599			quoted_implicit: quoted_implicit,
 600			style:           yaml_style_t(token.style),
 601		}
 602		yaml_parser_set_event_comments(parser, event)
 603		skip_token(parser)
 604		return true
 605	}
 606	if token.typ == yaml_FLOW_SEQUENCE_START_TOKEN {
 607		// [Go] Some of the events below can be merged as they differ only on style.
 608		end_mark = token.end_mark
 609		parser.state = yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE
 610		*event = yaml_event_t{
 611			typ:        yaml_SEQUENCE_START_EVENT,
 612			start_mark: start_mark,
 613			end_mark:   end_mark,
 614			anchor:     anchor,
 615			tag:        tag,
 616			implicit:   implicit,
 617			style:      yaml_style_t(yaml_FLOW_SEQUENCE_STYLE),
 618		}
 619		yaml_parser_set_event_comments(parser, event)
 620		return true
 621	}
 622	if token.typ == yaml_FLOW_MAPPING_START_TOKEN {
 623		end_mark = token.end_mark
 624		parser.state = yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE
 625		*event = yaml_event_t{
 626			typ:        yaml_MAPPING_START_EVENT,
 627			start_mark: start_mark,
 628			end_mark:   end_mark,
 629			anchor:     anchor,
 630			tag:        tag,
 631			implicit:   implicit,
 632			style:      yaml_style_t(yaml_FLOW_MAPPING_STYLE),
 633		}
 634		yaml_parser_set_event_comments(parser, event)
 635		return true
 636	}
 637	if block && token.typ == yaml_BLOCK_SEQUENCE_START_TOKEN {
 638		end_mark = token.end_mark
 639		parser.state = yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE
 640		*event = yaml_event_t{
 641			typ:        yaml_SEQUENCE_START_EVENT,
 642			start_mark: start_mark,
 643			end_mark:   end_mark,
 644			anchor:     anchor,
 645			tag:        tag,
 646			implicit:   implicit,
 647			style:      yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE),
 648		}
 649		if parser.stem_comment != nil {
 650			event.head_comment = parser.stem_comment
 651			parser.stem_comment = nil
 652		}
 653		return true
 654	}
 655	if block && token.typ == yaml_BLOCK_MAPPING_START_TOKEN {
 656		end_mark = token.end_mark
 657		parser.state = yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE
 658		*event = yaml_event_t{
 659			typ:        yaml_MAPPING_START_EVENT,
 660			start_mark: start_mark,
 661			end_mark:   end_mark,
 662			anchor:     anchor,
 663			tag:        tag,
 664			implicit:   implicit,
 665			style:      yaml_style_t(yaml_BLOCK_MAPPING_STYLE),
 666		}
 667		if parser.stem_comment != nil {
 668			event.head_comment = parser.stem_comment
 669			parser.stem_comment = nil
 670		}
 671		return true
 672	}
 673	if len(anchor) > 0 || len(tag) > 0 {
 674		parser.state = parser.states[len(parser.states)-1]
 675		parser.states = parser.states[:len(parser.states)-1]
 676
 677		*event = yaml_event_t{
 678			typ:             yaml_SCALAR_EVENT,
 679			start_mark:      start_mark,
 680			end_mark:        end_mark,
 681			anchor:          anchor,
 682			tag:             tag,
 683			implicit:        implicit,
 684			quoted_implicit: false,
 685			style:           yaml_style_t(yaml_PLAIN_SCALAR_STYLE),
 686		}
 687		return true
 688	}
 689
 690	context := "while parsing a flow node"
 691	if block {
 692		context = "while parsing a block node"
 693	}
 694	yaml_parser_set_parser_error_context(parser, context, start_mark,
 695		"did not find expected node content", token.start_mark)
 696	return false
 697}
 698
 699// Parse the productions:
 700// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
 701//
 702//	********************  *********** *             *********
 703func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
 704	if first {
 705		token := peek_token(parser)
 706		if token == nil {
 707			return false
 708		}
 709		parser.marks = append(parser.marks, token.start_mark)
 710		skip_token(parser)
 711	}
 712
 713	token := peek_token(parser)
 714	if token == nil {
 715		return false
 716	}
 717
 718	if token.typ == yaml_BLOCK_ENTRY_TOKEN {
 719		mark := token.end_mark
 720		prior_head_len := len(parser.head_comment)
 721		skip_token(parser)
 722		yaml_parser_split_stem_comment(parser, prior_head_len)
 723		token = peek_token(parser)
 724		if token == nil {
 725			return false
 726		}
 727		if token.typ != yaml_BLOCK_ENTRY_TOKEN && token.typ != yaml_BLOCK_END_TOKEN {
 728			parser.states = append(parser.states, yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE)
 729			return yaml_parser_parse_node(parser, event, true, false)
 730		} else {
 731			parser.state = yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE
 732			return yaml_parser_process_empty_scalar(parser, event, mark)
 733		}
 734	}
 735	if token.typ == yaml_BLOCK_END_TOKEN {
 736		parser.state = parser.states[len(parser.states)-1]
 737		parser.states = parser.states[:len(parser.states)-1]
 738		parser.marks = parser.marks[:len(parser.marks)-1]
 739
 740		*event = yaml_event_t{
 741			typ:        yaml_SEQUENCE_END_EVENT,
 742			start_mark: token.start_mark,
 743			end_mark:   token.end_mark,
 744		}
 745
 746		skip_token(parser)
 747		return true
 748	}
 749
 750	context_mark := parser.marks[len(parser.marks)-1]
 751	parser.marks = parser.marks[:len(parser.marks)-1]
 752	return yaml_parser_set_parser_error_context(parser,
 753		"while parsing a block collection", context_mark,
 754		"did not find expected '-' indicator", token.start_mark)
 755}
 756
 757// Parse the productions:
 758// indentless_sequence  ::= (BLOCK-ENTRY block_node?)+
 759//
 760//	*********** *
 761func yaml_parser_parse_indentless_sequence_entry(parser *yaml_parser_t, event *yaml_event_t) bool {
 762	token := peek_token(parser)
 763	if token == nil {
 764		return false
 765	}
 766
 767	if token.typ == yaml_BLOCK_ENTRY_TOKEN {
 768		mark := token.end_mark
 769		prior_head_len := len(parser.head_comment)
 770		skip_token(parser)
 771		yaml_parser_split_stem_comment(parser, prior_head_len)
 772		token = peek_token(parser)
 773		if token == nil {
 774			return false
 775		}
 776		if token.typ != yaml_BLOCK_ENTRY_TOKEN &&
 777			token.typ != yaml_KEY_TOKEN &&
 778			token.typ != yaml_VALUE_TOKEN &&
 779			token.typ != yaml_BLOCK_END_TOKEN {
 780			parser.states = append(parser.states, yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE)
 781			return yaml_parser_parse_node(parser, event, true, false)
 782		}
 783		parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE
 784		return yaml_parser_process_empty_scalar(parser, event, mark)
 785	}
 786	parser.state = parser.states[len(parser.states)-1]
 787	parser.states = parser.states[:len(parser.states)-1]
 788
 789	*event = yaml_event_t{
 790		typ:        yaml_SEQUENCE_END_EVENT,
 791		start_mark: token.start_mark,
 792		end_mark:   token.start_mark, // [Go] Shouldn't this be token.end_mark?
 793	}
 794	return true
 795}
 796
 797// Split stem comment from head comment.
 798//
 799// When a sequence or map is found under a sequence entry, the former head comment
 800// is assigned to the underlying sequence or map as a whole, not the individual
 801// sequence or map entry as would be expected otherwise. To handle this case the
 802// previous head comment is moved aside as the stem comment.
 803func yaml_parser_split_stem_comment(parser *yaml_parser_t, stem_len int) {
 804	if stem_len == 0 {
 805		return
 806	}
 807
 808	token := peek_token(parser)
 809	if token == nil || token.typ != yaml_BLOCK_SEQUENCE_START_TOKEN && token.typ != yaml_BLOCK_MAPPING_START_TOKEN {
 810		return
 811	}
 812
 813	parser.stem_comment = parser.head_comment[:stem_len]
 814	if len(parser.head_comment) == stem_len {
 815		parser.head_comment = nil
 816	} else {
 817		// Copy suffix to prevent very strange bugs if someone ever appends
 818		// further bytes to the prefix in the stem_comment slice above.
 819		parser.head_comment = append([]byte(nil), parser.head_comment[stem_len+1:]...)
 820	}
 821}
 822
 823// Parse the productions:
 824// block_mapping        ::= BLOCK-MAPPING_START
 825//
 826//	*******************
 827//	((KEY block_node_or_indentless_sequence?)?
 828//	  *** *
 829//	(VALUE block_node_or_indentless_sequence?)?)*
 830//
 831//	BLOCK-END
 832//	*********
 833func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
 834	if first {
 835		token := peek_token(parser)
 836		if token == nil {
 837			return false
 838		}
 839		parser.marks = append(parser.marks, token.start_mark)
 840		skip_token(parser)
 841	}
 842
 843	token := peek_token(parser)
 844	if token == nil {
 845		return false
 846	}
 847
 848	// [Go] A tail comment was left from the prior mapping value processed. Emit an event
 849	//      as it needs to be processed with that value and not the following key.
 850	if len(parser.tail_comment) > 0 {
 851		*event = yaml_event_t{
 852			typ:          yaml_TAIL_COMMENT_EVENT,
 853			start_mark:   token.start_mark,
 854			end_mark:     token.end_mark,
 855			foot_comment: parser.tail_comment,
 856		}
 857		parser.tail_comment = nil
 858		return true
 859	}
 860
 861	if token.typ == yaml_KEY_TOKEN {
 862		mark := token.end_mark
 863		skip_token(parser)
 864		token = peek_token(parser)
 865		if token == nil {
 866			return false
 867		}
 868		if token.typ != yaml_KEY_TOKEN &&
 869			token.typ != yaml_VALUE_TOKEN &&
 870			token.typ != yaml_BLOCK_END_TOKEN {
 871			parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_VALUE_STATE)
 872			return yaml_parser_parse_node(parser, event, true, true)
 873		} else {
 874			parser.state = yaml_PARSE_BLOCK_MAPPING_VALUE_STATE
 875			return yaml_parser_process_empty_scalar(parser, event, mark)
 876		}
 877	} else if token.typ == yaml_BLOCK_END_TOKEN {
 878		parser.state = parser.states[len(parser.states)-1]
 879		parser.states = parser.states[:len(parser.states)-1]
 880		parser.marks = parser.marks[:len(parser.marks)-1]
 881		*event = yaml_event_t{
 882			typ:        yaml_MAPPING_END_EVENT,
 883			start_mark: token.start_mark,
 884			end_mark:   token.end_mark,
 885		}
 886		yaml_parser_set_event_comments(parser, event)
 887		skip_token(parser)
 888		return true
 889	}
 890
 891	context_mark := parser.marks[len(parser.marks)-1]
 892	parser.marks = parser.marks[:len(parser.marks)-1]
 893	return yaml_parser_set_parser_error_context(parser,
 894		"while parsing a block mapping", context_mark,
 895		"did not find expected key", token.start_mark)
 896}
 897
 898// Parse the productions:
 899// block_mapping        ::= BLOCK-MAPPING_START
 900//
 901//	((KEY block_node_or_indentless_sequence?)?
 902//
 903//	(VALUE block_node_or_indentless_sequence?)?)*
 904//	 ***** *
 905//	BLOCK-END
 906func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool {
 907	token := peek_token(parser)
 908	if token == nil {
 909		return false
 910	}
 911	if token.typ == yaml_VALUE_TOKEN {
 912		mark := token.end_mark
 913		skip_token(parser)
 914		token = peek_token(parser)
 915		if token == nil {
 916			return false
 917		}
 918		if token.typ != yaml_KEY_TOKEN &&
 919			token.typ != yaml_VALUE_TOKEN &&
 920			token.typ != yaml_BLOCK_END_TOKEN {
 921			parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_KEY_STATE)
 922			return yaml_parser_parse_node(parser, event, true, true)
 923		}
 924		parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE
 925		return yaml_parser_process_empty_scalar(parser, event, mark)
 926	}
 927	parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE
 928	return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
 929}
 930
 931// Parse the productions:
 932// flow_sequence        ::= FLOW-SEQUENCE-START
 933//
 934//	*******************
 935//	(flow_sequence_entry FLOW-ENTRY)*
 936//	 *                   **********
 937//	flow_sequence_entry?
 938//	*
 939//	FLOW-SEQUENCE-END
 940//	*****************
 941//
 942// flow_sequence_entry  ::= flow_node | KEY flow_node? (VALUE flow_node?)?
 943//
 944//	*
 945func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
 946	if first {
 947		token := peek_token(parser)
 948		if token == nil {
 949			return false
 950		}
 951		parser.marks = append(parser.marks, token.start_mark)
 952		skip_token(parser)
 953	}
 954	token := peek_token(parser)
 955	if token == nil {
 956		return false
 957	}
 958	if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {
 959		if !first {
 960			if token.typ == yaml_FLOW_ENTRY_TOKEN {
 961				skip_token(parser)
 962				token = peek_token(parser)
 963				if token == nil {
 964					return false
 965				}
 966			} else {
 967				context_mark := parser.marks[len(parser.marks)-1]
 968				parser.marks = parser.marks[:len(parser.marks)-1]
 969				return yaml_parser_set_parser_error_context(parser,
 970					"while parsing a flow sequence", context_mark,
 971					"did not find expected ',' or ']'", token.start_mark)
 972			}
 973		}
 974
 975		if token.typ == yaml_KEY_TOKEN {
 976			parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE
 977			*event = yaml_event_t{
 978				typ:        yaml_MAPPING_START_EVENT,
 979				start_mark: token.start_mark,
 980				end_mark:   token.end_mark,
 981				implicit:   true,
 982				style:      yaml_style_t(yaml_FLOW_MAPPING_STYLE),
 983			}
 984			skip_token(parser)
 985			return true
 986		} else if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {
 987			parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE)
 988			return yaml_parser_parse_node(parser, event, false, false)
 989		}
 990	}
 991
 992	parser.state = parser.states[len(parser.states)-1]
 993	parser.states = parser.states[:len(parser.states)-1]
 994	parser.marks = parser.marks[:len(parser.marks)-1]
 995
 996	*event = yaml_event_t{
 997		typ:        yaml_SEQUENCE_END_EVENT,
 998		start_mark: token.start_mark,
 999		end_mark:   token.end_mark,
1000	}
1001	yaml_parser_set_event_comments(parser, event)
1002
1003	skip_token(parser)
1004	return true
1005}
1006
1007// Parse the productions:
1008// flow_sequence_entry  ::= flow_node | KEY flow_node? (VALUE flow_node?)?
1009//
1010//	*** *
1011func yaml_parser_parse_flow_sequence_entry_mapping_key(parser *yaml_parser_t, event *yaml_event_t) bool {
1012	token := peek_token(parser)
1013	if token == nil {
1014		return false
1015	}
1016	if token.typ != yaml_VALUE_TOKEN &&
1017		token.typ != yaml_FLOW_ENTRY_TOKEN &&
1018		token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {
1019		parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE)
1020		return yaml_parser_parse_node(parser, event, false, false)
1021	}
1022	mark := token.end_mark
1023	skip_token(parser)
1024	parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE
1025	return yaml_parser_process_empty_scalar(parser, event, mark)
1026}
1027
1028// Parse the productions:
1029// flow_sequence_entry  ::= flow_node | KEY flow_node? (VALUE flow_node?)?
1030//
1031//	***** *
1032func yaml_parser_parse_flow_sequence_entry_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool {
1033	token := peek_token(parser)
1034	if token == nil {
1035		return false
1036	}
1037	if token.typ == yaml_VALUE_TOKEN {
1038		skip_token(parser)
1039		token := peek_token(parser)
1040		if token == nil {
1041			return false
1042		}
1043		if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {
1044			parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE)
1045			return yaml_parser_parse_node(parser, event, false, false)
1046		}
1047	}
1048	parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE
1049	return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
1050}
1051
1052// Parse the productions:
1053// flow_sequence_entry  ::= flow_node | KEY flow_node? (VALUE flow_node?)?
1054//
1055//	*
1056func yaml_parser_parse_flow_sequence_entry_mapping_end(parser *yaml_parser_t, event *yaml_event_t) bool {
1057	token := peek_token(parser)
1058	if token == nil {
1059		return false
1060	}
1061	parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE
1062	*event = yaml_event_t{
1063		typ:        yaml_MAPPING_END_EVENT,
1064		start_mark: token.start_mark,
1065		end_mark:   token.start_mark, // [Go] Shouldn't this be end_mark?
1066	}
1067	return true
1068}
1069
1070// Parse the productions:
1071// flow_mapping         ::= FLOW-MAPPING-START
1072//
1073//	******************
1074//	(flow_mapping_entry FLOW-ENTRY)*
1075//	 *                  **********
1076//	flow_mapping_entry?
1077//	******************
1078//	FLOW-MAPPING-END
1079//	****************
1080//
1081// flow_mapping_entry   ::= flow_node | KEY flow_node? (VALUE flow_node?)?
1082//   - *** *
1083func yaml_parser_parse_flow_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
1084	if first {
1085		token := peek_token(parser)
1086		parser.marks = append(parser.marks, token.start_mark)
1087		skip_token(parser)
1088	}
1089
1090	token := peek_token(parser)
1091	if token == nil {
1092		return false
1093	}
1094
1095	if token.typ != yaml_FLOW_MAPPING_END_TOKEN {
1096		if !first {
1097			if token.typ == yaml_FLOW_ENTRY_TOKEN {
1098				skip_token(parser)
1099				token = peek_token(parser)
1100				if token == nil {
1101					return false
1102				}
1103			} else {
1104				context_mark := parser.marks[len(parser.marks)-1]
1105				parser.marks = parser.marks[:len(parser.marks)-1]
1106				return yaml_parser_set_parser_error_context(parser,
1107					"while parsing a flow mapping", context_mark,
1108					"did not find expected ',' or '}'", token.start_mark)
1109			}
1110		}
1111
1112		if token.typ == yaml_KEY_TOKEN {
1113			skip_token(parser)
1114			token = peek_token(parser)
1115			if token == nil {
1116				return false
1117			}
1118			if token.typ != yaml_VALUE_TOKEN &&
1119				token.typ != yaml_FLOW_ENTRY_TOKEN &&
1120				token.typ != yaml_FLOW_MAPPING_END_TOKEN {
1121				parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_VALUE_STATE)
1122				return yaml_parser_parse_node(parser, event, false, false)
1123			} else {
1124				parser.state = yaml_PARSE_FLOW_MAPPING_VALUE_STATE
1125				return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
1126			}
1127		} else if token.typ != yaml_FLOW_MAPPING_END_TOKEN {
1128			parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE)
1129			return yaml_parser_parse_node(parser, event, false, false)
1130		}
1131	}
1132
1133	parser.state = parser.states[len(parser.states)-1]
1134	parser.states = parser.states[:len(parser.states)-1]
1135	parser.marks = parser.marks[:len(parser.marks)-1]
1136	*event = yaml_event_t{
1137		typ:        yaml_MAPPING_END_EVENT,
1138		start_mark: token.start_mark,
1139		end_mark:   token.end_mark,
1140	}
1141	yaml_parser_set_event_comments(parser, event)
1142	skip_token(parser)
1143	return true
1144}
1145
1146// Parse the productions:
1147// flow_mapping_entry   ::= flow_node | KEY flow_node? (VALUE flow_node?)?
1148//   - ***** *
1149func yaml_parser_parse_flow_mapping_value(parser *yaml_parser_t, event *yaml_event_t, empty bool) bool {
1150	token := peek_token(parser)
1151	if token == nil {
1152		return false
1153	}
1154	if empty {
1155		parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE
1156		return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
1157	}
1158	if token.typ == yaml_VALUE_TOKEN {
1159		skip_token(parser)
1160		token = peek_token(parser)
1161		if token == nil {
1162			return false
1163		}
1164		if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_MAPPING_END_TOKEN {
1165			parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_KEY_STATE)
1166			return yaml_parser_parse_node(parser, event, false, false)
1167		}
1168	}
1169	parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE
1170	return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
1171}
1172
1173// Generate an empty scalar event.
1174func yaml_parser_process_empty_scalar(parser *yaml_parser_t, event *yaml_event_t, mark yaml_mark_t) bool {
1175	*event = yaml_event_t{
1176		typ:        yaml_SCALAR_EVENT,
1177		start_mark: mark,
1178		end_mark:   mark,
1179		value:      nil, // Empty
1180		implicit:   true,
1181		style:      yaml_style_t(yaml_PLAIN_SCALAR_STYLE),
1182	}
1183	return true
1184}
1185
1186var default_tag_directives = []yaml_tag_directive_t{
1187	{[]byte("!"), []byte("!")},
1188	{[]byte("!!"), []byte("tag:yaml.org,2002:")},
1189}
1190
1191// Parse directives.
1192func yaml_parser_process_directives(parser *yaml_parser_t,
1193	version_directive_ref **yaml_version_directive_t,
1194	tag_directives_ref *[]yaml_tag_directive_t) bool {
1195
1196	var version_directive *yaml_version_directive_t
1197	var tag_directives []yaml_tag_directive_t
1198
1199	token := peek_token(parser)
1200	if token == nil {
1201		return false
1202	}
1203
1204	for token.typ == yaml_VERSION_DIRECTIVE_TOKEN || token.typ == yaml_TAG_DIRECTIVE_TOKEN {
1205		if token.typ == yaml_VERSION_DIRECTIVE_TOKEN {
1206			if version_directive != nil {
1207				yaml_parser_set_parser_error(parser,
1208					"found duplicate %YAML directive", token.start_mark)
1209				return false
1210			}
1211			if token.major != 1 || token.minor != 1 {
1212				yaml_parser_set_parser_error(parser,
1213					"found incompatible YAML document", token.start_mark)
1214				return false
1215			}
1216			version_directive = &yaml_version_directive_t{
1217				major: token.major,
1218				minor: token.minor,
1219			}
1220		} else if token.typ == yaml_TAG_DIRECTIVE_TOKEN {
1221			value := yaml_tag_directive_t{
1222				handle: token.value,
1223				prefix: token.prefix,
1224			}
1225			if !yaml_parser_append_tag_directive(parser, value, false, token.start_mark) {
1226				return false
1227			}
1228			tag_directives = append(tag_directives, value)
1229		}
1230
1231		skip_token(parser)
1232		token = peek_token(parser)
1233		if token == nil {
1234			return false
1235		}
1236	}
1237
1238	for i := range default_tag_directives {
1239		if !yaml_parser_append_tag_directive(parser, default_tag_directives[i], true, token.start_mark) {
1240			return false
1241		}
1242	}
1243
1244	if version_directive_ref != nil {
1245		*version_directive_ref = version_directive
1246	}
1247	if tag_directives_ref != nil {
1248		*tag_directives_ref = tag_directives
1249	}
1250	return true
1251}
1252
1253// Append a tag directive to the directives stack.
1254func yaml_parser_append_tag_directive(parser *yaml_parser_t, value yaml_tag_directive_t, allow_duplicates bool, mark yaml_mark_t) bool {
1255	for i := range parser.tag_directives {
1256		if bytes.Equal(value.handle, parser.tag_directives[i].handle) {
1257			if allow_duplicates {
1258				return true
1259			}
1260			return yaml_parser_set_parser_error(parser, "found duplicate %TAG directive", mark)
1261		}
1262	}
1263
1264	// [Go] I suspect the copy is unnecessary. This was likely done
1265	// because there was no way to track ownership of the data.
1266	value_copy := yaml_tag_directive_t{
1267		handle: make([]byte, len(value.handle)),
1268		prefix: make([]byte, len(value.prefix)),
1269	}
1270	copy(value_copy.handle, value.handle)
1271	copy(value_copy.prefix, value.prefix)
1272	parser.tag_directives = append(parser.tag_directives, value_copy)
1273	return true
1274}