parserc.go

   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//              ************
 231func yaml_parser_parse_stream_start(parser *yaml_parser_t, event *yaml_event_t) bool {
 232	token := peek_token(parser)
 233	if token == nil {
 234		return false
 235	}
 236	if token.typ != yaml_STREAM_START_TOKEN {
 237		return yaml_parser_set_parser_error(parser, "did not find expected <stream-start>", token.start_mark)
 238	}
 239	parser.state = yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE
 240	*event = yaml_event_t{
 241		typ:        yaml_STREAM_START_EVENT,
 242		start_mark: token.start_mark,
 243		end_mark:   token.end_mark,
 244		encoding:   token.encoding,
 245	}
 246	skip_token(parser)
 247	return true
 248}
 249
 250// Parse the productions:
 251// implicit_document    ::= block_node DOCUMENT-END*
 252//                          *
 253// explicit_document    ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
 254//                          *************************
 255func yaml_parser_parse_document_start(parser *yaml_parser_t, event *yaml_event_t, implicit bool) bool {
 256
 257	token := peek_token(parser)
 258	if token == nil {
 259		return false
 260	}
 261
 262	// Parse extra document end indicators.
 263	if !implicit {
 264		for token.typ == yaml_DOCUMENT_END_TOKEN {
 265			skip_token(parser)
 266			token = peek_token(parser)
 267			if token == nil {
 268				return false
 269			}
 270		}
 271	}
 272
 273	if implicit && token.typ != yaml_VERSION_DIRECTIVE_TOKEN &&
 274		token.typ != yaml_TAG_DIRECTIVE_TOKEN &&
 275		token.typ != yaml_DOCUMENT_START_TOKEN &&
 276		token.typ != yaml_STREAM_END_TOKEN {
 277		// Parse an implicit document.
 278		if !yaml_parser_process_directives(parser, nil, nil) {
 279			return false
 280		}
 281		parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE)
 282		parser.state = yaml_PARSE_BLOCK_NODE_STATE
 283
 284		var head_comment []byte
 285		if len(parser.head_comment) > 0 {
 286			// [Go] Scan the header comment backwards, and if an empty line is found, break
 287			//      the header so the part before the last empty line goes into the
 288			//      document header, while the bottom of it goes into a follow up event.
 289			for i := len(parser.head_comment) - 1; i > 0; i-- {
 290				if parser.head_comment[i] == '\n' {
 291					if i == len(parser.head_comment)-1 {
 292						head_comment = parser.head_comment[:i]
 293						parser.head_comment = parser.head_comment[i+1:]
 294						break
 295					} else if parser.head_comment[i-1] == '\n' {
 296						head_comment = parser.head_comment[:i-1]
 297						parser.head_comment = parser.head_comment[i+1:]
 298						break
 299					}
 300				}
 301			}
 302		}
 303
 304		*event = yaml_event_t{
 305			typ:        yaml_DOCUMENT_START_EVENT,
 306			start_mark: token.start_mark,
 307			end_mark:   token.end_mark,
 308
 309			head_comment: head_comment,
 310		}
 311
 312	} else if token.typ != yaml_STREAM_END_TOKEN {
 313		// Parse an explicit document.
 314		var version_directive *yaml_version_directive_t
 315		var tag_directives []yaml_tag_directive_t
 316		start_mark := token.start_mark
 317		if !yaml_parser_process_directives(parser, &version_directive, &tag_directives) {
 318			return false
 319		}
 320		token = peek_token(parser)
 321		if token == nil {
 322			return false
 323		}
 324		if token.typ != yaml_DOCUMENT_START_TOKEN {
 325			yaml_parser_set_parser_error(parser,
 326				"did not find expected <document start>", token.start_mark)
 327			return false
 328		}
 329		parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE)
 330		parser.state = yaml_PARSE_DOCUMENT_CONTENT_STATE
 331		end_mark := token.end_mark
 332
 333		*event = yaml_event_t{
 334			typ:               yaml_DOCUMENT_START_EVENT,
 335			start_mark:        start_mark,
 336			end_mark:          end_mark,
 337			version_directive: version_directive,
 338			tag_directives:    tag_directives,
 339			implicit:          false,
 340		}
 341		skip_token(parser)
 342
 343	} else {
 344		// Parse the stream end.
 345		parser.state = yaml_PARSE_END_STATE
 346		*event = yaml_event_t{
 347			typ:        yaml_STREAM_END_EVENT,
 348			start_mark: token.start_mark,
 349			end_mark:   token.end_mark,
 350		}
 351		skip_token(parser)
 352	}
 353
 354	return true
 355}
 356
 357// Parse the productions:
 358// explicit_document    ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
 359//                                                    ***********
 360//
 361func yaml_parser_parse_document_content(parser *yaml_parser_t, event *yaml_event_t) bool {
 362	token := peek_token(parser)
 363	if token == nil {
 364		return false
 365	}
 366
 367	if token.typ == yaml_VERSION_DIRECTIVE_TOKEN ||
 368		token.typ == yaml_TAG_DIRECTIVE_TOKEN ||
 369		token.typ == yaml_DOCUMENT_START_TOKEN ||
 370		token.typ == yaml_DOCUMENT_END_TOKEN ||
 371		token.typ == yaml_STREAM_END_TOKEN {
 372		parser.state = parser.states[len(parser.states)-1]
 373		parser.states = parser.states[:len(parser.states)-1]
 374		return yaml_parser_process_empty_scalar(parser, event,
 375			token.start_mark)
 376	}
 377	return yaml_parser_parse_node(parser, event, true, false)
 378}
 379
 380// Parse the productions:
 381// implicit_document    ::= block_node DOCUMENT-END*
 382//                                     *************
 383// explicit_document    ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
 384//
 385func yaml_parser_parse_document_end(parser *yaml_parser_t, event *yaml_event_t) bool {
 386	token := peek_token(parser)
 387	if token == nil {
 388		return false
 389	}
 390
 391	start_mark := token.start_mark
 392	end_mark := token.start_mark
 393
 394	implicit := true
 395	if token.typ == yaml_DOCUMENT_END_TOKEN {
 396		end_mark = token.end_mark
 397		skip_token(parser)
 398		implicit = false
 399	}
 400
 401	parser.tag_directives = parser.tag_directives[:0]
 402
 403	parser.state = yaml_PARSE_DOCUMENT_START_STATE
 404	*event = yaml_event_t{
 405		typ:        yaml_DOCUMENT_END_EVENT,
 406		start_mark: start_mark,
 407		end_mark:   end_mark,
 408		implicit:   implicit,
 409	}
 410	yaml_parser_set_event_comments(parser, event)
 411	if len(event.head_comment) > 0 && len(event.foot_comment) == 0 {
 412		event.foot_comment = event.head_comment
 413		event.head_comment = nil
 414	}
 415	return true
 416}
 417
 418func yaml_parser_set_event_comments(parser *yaml_parser_t, event *yaml_event_t) {
 419	event.head_comment = parser.head_comment
 420	event.line_comment = parser.line_comment
 421	event.foot_comment = parser.foot_comment
 422	parser.head_comment = nil
 423	parser.line_comment = nil
 424	parser.foot_comment = nil
 425	parser.tail_comment = nil
 426	parser.stem_comment = nil
 427}
 428
 429// Parse the productions:
 430// block_node_or_indentless_sequence    ::=
 431//                          ALIAS
 432//                          *****
 433//                          | properties (block_content | indentless_block_sequence)?
 434//                            **********  *
 435//                          | block_content | indentless_block_sequence
 436//                            *
 437// block_node           ::= ALIAS
 438//                          *****
 439//                          | properties block_content?
 440//                            ********** *
 441//                          | block_content
 442//                            *
 443// flow_node            ::= ALIAS
 444//                          *****
 445//                          | properties flow_content?
 446//                            ********** *
 447//                          | flow_content
 448//                            *
 449// properties           ::= TAG ANCHOR? | ANCHOR TAG?
 450//                          *************************
 451// block_content        ::= block_collection | flow_collection | SCALAR
 452//                                                               ******
 453// flow_content         ::= flow_collection | SCALAR
 454//                                            ******
 455func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, indentless_sequence bool) bool {
 456	//defer trace("yaml_parser_parse_node", "block:", block, "indentless_sequence:", indentless_sequence)()
 457
 458	token := peek_token(parser)
 459	if token == nil {
 460		return false
 461	}
 462
 463	if token.typ == yaml_ALIAS_TOKEN {
 464		parser.state = parser.states[len(parser.states)-1]
 465		parser.states = parser.states[:len(parser.states)-1]
 466		*event = yaml_event_t{
 467			typ:        yaml_ALIAS_EVENT,
 468			start_mark: token.start_mark,
 469			end_mark:   token.end_mark,
 470			anchor:     token.value,
 471		}
 472		yaml_parser_set_event_comments(parser, event)
 473		skip_token(parser)
 474		return true
 475	}
 476
 477	start_mark := token.start_mark
 478	end_mark := token.start_mark
 479
 480	var tag_token bool
 481	var tag_handle, tag_suffix, anchor []byte
 482	var tag_mark yaml_mark_t
 483	if token.typ == yaml_ANCHOR_TOKEN {
 484		anchor = token.value
 485		start_mark = token.start_mark
 486		end_mark = token.end_mark
 487		skip_token(parser)
 488		token = peek_token(parser)
 489		if token == nil {
 490			return false
 491		}
 492		if token.typ == yaml_TAG_TOKEN {
 493			tag_token = true
 494			tag_handle = token.value
 495			tag_suffix = token.suffix
 496			tag_mark = token.start_mark
 497			end_mark = token.end_mark
 498			skip_token(parser)
 499			token = peek_token(parser)
 500			if token == nil {
 501				return false
 502			}
 503		}
 504	} else if token.typ == yaml_TAG_TOKEN {
 505		tag_token = true
 506		tag_handle = token.value
 507		tag_suffix = token.suffix
 508		start_mark = token.start_mark
 509		tag_mark = token.start_mark
 510		end_mark = token.end_mark
 511		skip_token(parser)
 512		token = peek_token(parser)
 513		if token == nil {
 514			return false
 515		}
 516		if token.typ == yaml_ANCHOR_TOKEN {
 517			anchor = token.value
 518			end_mark = token.end_mark
 519			skip_token(parser)
 520			token = peek_token(parser)
 521			if token == nil {
 522				return false
 523			}
 524		}
 525	}
 526
 527	var tag []byte
 528	if tag_token {
 529		if len(tag_handle) == 0 {
 530			tag = tag_suffix
 531			tag_suffix = nil
 532		} else {
 533			for i := range parser.tag_directives {
 534				if bytes.Equal(parser.tag_directives[i].handle, tag_handle) {
 535					tag = append([]byte(nil), parser.tag_directives[i].prefix...)
 536					tag = append(tag, tag_suffix...)
 537					break
 538				}
 539			}
 540			if len(tag) == 0 {
 541				yaml_parser_set_parser_error_context(parser,
 542					"while parsing a node", start_mark,
 543					"found undefined tag handle", tag_mark)
 544				return false
 545			}
 546		}
 547	}
 548
 549	implicit := len(tag) == 0
 550	if indentless_sequence && token.typ == yaml_BLOCK_ENTRY_TOKEN {
 551		end_mark = token.end_mark
 552		parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE
 553		*event = yaml_event_t{
 554			typ:        yaml_SEQUENCE_START_EVENT,
 555			start_mark: start_mark,
 556			end_mark:   end_mark,
 557			anchor:     anchor,
 558			tag:        tag,
 559			implicit:   implicit,
 560			style:      yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE),
 561		}
 562		return true
 563	}
 564	if token.typ == yaml_SCALAR_TOKEN {
 565		var plain_implicit, quoted_implicit bool
 566		end_mark = token.end_mark
 567		if (len(tag) == 0 && token.style == yaml_PLAIN_SCALAR_STYLE) || (len(tag) == 1 && tag[0] == '!') {
 568			plain_implicit = true
 569		} else if len(tag) == 0 {
 570			quoted_implicit = true
 571		}
 572		parser.state = parser.states[len(parser.states)-1]
 573		parser.states = parser.states[:len(parser.states)-1]
 574
 575		*event = yaml_event_t{
 576			typ:             yaml_SCALAR_EVENT,
 577			start_mark:      start_mark,
 578			end_mark:        end_mark,
 579			anchor:          anchor,
 580			tag:             tag,
 581			value:           token.value,
 582			implicit:        plain_implicit,
 583			quoted_implicit: quoted_implicit,
 584			style:           yaml_style_t(token.style),
 585		}
 586		yaml_parser_set_event_comments(parser, event)
 587		skip_token(parser)
 588		return true
 589	}
 590	if token.typ == yaml_FLOW_SEQUENCE_START_TOKEN {
 591		// [Go] Some of the events below can be merged as they differ only on style.
 592		end_mark = token.end_mark
 593		parser.state = yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE
 594		*event = yaml_event_t{
 595			typ:        yaml_SEQUENCE_START_EVENT,
 596			start_mark: start_mark,
 597			end_mark:   end_mark,
 598			anchor:     anchor,
 599			tag:        tag,
 600			implicit:   implicit,
 601			style:      yaml_style_t(yaml_FLOW_SEQUENCE_STYLE),
 602		}
 603		yaml_parser_set_event_comments(parser, event)
 604		return true
 605	}
 606	if token.typ == yaml_FLOW_MAPPING_START_TOKEN {
 607		end_mark = token.end_mark
 608		parser.state = yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE
 609		*event = yaml_event_t{
 610			typ:        yaml_MAPPING_START_EVENT,
 611			start_mark: start_mark,
 612			end_mark:   end_mark,
 613			anchor:     anchor,
 614			tag:        tag,
 615			implicit:   implicit,
 616			style:      yaml_style_t(yaml_FLOW_MAPPING_STYLE),
 617		}
 618		yaml_parser_set_event_comments(parser, event)
 619		return true
 620	}
 621	if block && token.typ == yaml_BLOCK_SEQUENCE_START_TOKEN {
 622		end_mark = token.end_mark
 623		parser.state = yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE
 624		*event = yaml_event_t{
 625			typ:        yaml_SEQUENCE_START_EVENT,
 626			start_mark: start_mark,
 627			end_mark:   end_mark,
 628			anchor:     anchor,
 629			tag:        tag,
 630			implicit:   implicit,
 631			style:      yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE),
 632		}
 633		if parser.stem_comment != nil {
 634			event.head_comment = parser.stem_comment
 635			parser.stem_comment = nil
 636		}
 637		return true
 638	}
 639	if block && token.typ == yaml_BLOCK_MAPPING_START_TOKEN {
 640		end_mark = token.end_mark
 641		parser.state = yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE
 642		*event = yaml_event_t{
 643			typ:        yaml_MAPPING_START_EVENT,
 644			start_mark: start_mark,
 645			end_mark:   end_mark,
 646			anchor:     anchor,
 647			tag:        tag,
 648			implicit:   implicit,
 649			style:      yaml_style_t(yaml_BLOCK_MAPPING_STYLE),
 650		}
 651		if parser.stem_comment != nil {
 652			event.head_comment = parser.stem_comment
 653			parser.stem_comment = nil
 654		}
 655		return true
 656	}
 657	if len(anchor) > 0 || len(tag) > 0 {
 658		parser.state = parser.states[len(parser.states)-1]
 659		parser.states = parser.states[:len(parser.states)-1]
 660
 661		*event = yaml_event_t{
 662			typ:             yaml_SCALAR_EVENT,
 663			start_mark:      start_mark,
 664			end_mark:        end_mark,
 665			anchor:          anchor,
 666			tag:             tag,
 667			implicit:        implicit,
 668			quoted_implicit: false,
 669			style:           yaml_style_t(yaml_PLAIN_SCALAR_STYLE),
 670		}
 671		return true
 672	}
 673
 674	context := "while parsing a flow node"
 675	if block {
 676		context = "while parsing a block node"
 677	}
 678	yaml_parser_set_parser_error_context(parser, context, start_mark,
 679		"did not find expected node content", token.start_mark)
 680	return false
 681}
 682
 683// Parse the productions:
 684// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
 685//                    ********************  *********** *             *********
 686//
 687func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
 688	if first {
 689		token := peek_token(parser)
 690		if token == nil {
 691			return false
 692		}
 693		parser.marks = append(parser.marks, token.start_mark)
 694		skip_token(parser)
 695	}
 696
 697	token := peek_token(parser)
 698	if token == nil {
 699		return false
 700	}
 701
 702	if token.typ == yaml_BLOCK_ENTRY_TOKEN {
 703		mark := token.end_mark
 704		prior_head_len := len(parser.head_comment)
 705		skip_token(parser)
 706		yaml_parser_split_stem_comment(parser, prior_head_len)
 707		token = peek_token(parser)
 708		if token == nil {
 709			return false
 710		}
 711		if token.typ != yaml_BLOCK_ENTRY_TOKEN && token.typ != yaml_BLOCK_END_TOKEN {
 712			parser.states = append(parser.states, yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE)
 713			return yaml_parser_parse_node(parser, event, true, false)
 714		} else {
 715			parser.state = yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE
 716			return yaml_parser_process_empty_scalar(parser, event, mark)
 717		}
 718	}
 719	if token.typ == yaml_BLOCK_END_TOKEN {
 720		parser.state = parser.states[len(parser.states)-1]
 721		parser.states = parser.states[:len(parser.states)-1]
 722		parser.marks = parser.marks[:len(parser.marks)-1]
 723
 724		*event = yaml_event_t{
 725			typ:        yaml_SEQUENCE_END_EVENT,
 726			start_mark: token.start_mark,
 727			end_mark:   token.end_mark,
 728		}
 729
 730		skip_token(parser)
 731		return true
 732	}
 733
 734	context_mark := parser.marks[len(parser.marks)-1]
 735	parser.marks = parser.marks[:len(parser.marks)-1]
 736	return yaml_parser_set_parser_error_context(parser,
 737		"while parsing a block collection", context_mark,
 738		"did not find expected '-' indicator", token.start_mark)
 739}
 740
 741// Parse the productions:
 742// indentless_sequence  ::= (BLOCK-ENTRY block_node?)+
 743//                           *********** *
 744func yaml_parser_parse_indentless_sequence_entry(parser *yaml_parser_t, event *yaml_event_t) bool {
 745	token := peek_token(parser)
 746	if token == nil {
 747		return false
 748	}
 749
 750	if token.typ == yaml_BLOCK_ENTRY_TOKEN {
 751		mark := token.end_mark
 752		prior_head_len := len(parser.head_comment)
 753		skip_token(parser)
 754		yaml_parser_split_stem_comment(parser, prior_head_len)
 755		token = peek_token(parser)
 756		if token == nil {
 757			return false
 758		}
 759		if token.typ != yaml_BLOCK_ENTRY_TOKEN &&
 760			token.typ != yaml_KEY_TOKEN &&
 761			token.typ != yaml_VALUE_TOKEN &&
 762			token.typ != yaml_BLOCK_END_TOKEN {
 763			parser.states = append(parser.states, yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE)
 764			return yaml_parser_parse_node(parser, event, true, false)
 765		}
 766		parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE
 767		return yaml_parser_process_empty_scalar(parser, event, mark)
 768	}
 769	parser.state = parser.states[len(parser.states)-1]
 770	parser.states = parser.states[:len(parser.states)-1]
 771
 772	*event = yaml_event_t{
 773		typ:        yaml_SEQUENCE_END_EVENT,
 774		start_mark: token.start_mark,
 775		end_mark:   token.start_mark, // [Go] Shouldn't this be token.end_mark?
 776	}
 777	return true
 778}
 779
 780// Split stem comment from head comment.
 781//
 782// When a sequence or map is found under a sequence entry, the former head comment
 783// is assigned to the underlying sequence or map as a whole, not the individual
 784// sequence or map entry as would be expected otherwise. To handle this case the
 785// previous head comment is moved aside as the stem comment.
 786func yaml_parser_split_stem_comment(parser *yaml_parser_t, stem_len int) {
 787	if stem_len == 0 {
 788		return
 789	}
 790
 791	token := peek_token(parser)
 792	if token == nil || token.typ != yaml_BLOCK_SEQUENCE_START_TOKEN && token.typ != yaml_BLOCK_MAPPING_START_TOKEN {
 793		return
 794	}
 795
 796	parser.stem_comment = parser.head_comment[:stem_len]
 797	if len(parser.head_comment) == stem_len {
 798		parser.head_comment = nil
 799	} else {
 800		// Copy suffix to prevent very strange bugs if someone ever appends
 801		// further bytes to the prefix in the stem_comment slice above.
 802		parser.head_comment = append([]byte(nil), parser.head_comment[stem_len+1:]...)
 803	}
 804}
 805
 806// Parse the productions:
 807// block_mapping        ::= BLOCK-MAPPING_START
 808//                          *******************
 809//                          ((KEY block_node_or_indentless_sequence?)?
 810//                            *** *
 811//                          (VALUE block_node_or_indentless_sequence?)?)*
 812//
 813//                          BLOCK-END
 814//                          *********
 815//
 816func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
 817	if first {
 818		token := peek_token(parser)
 819		if token == nil {
 820			return false
 821		}
 822		parser.marks = append(parser.marks, token.start_mark)
 823		skip_token(parser)
 824	}
 825
 826	token := peek_token(parser)
 827	if token == nil {
 828		return false
 829	}
 830
 831	// [Go] A tail comment was left from the prior mapping value processed. Emit an event
 832	//      as it needs to be processed with that value and not the following key.
 833	if len(parser.tail_comment) > 0 {
 834		*event = yaml_event_t{
 835			typ:          yaml_TAIL_COMMENT_EVENT,
 836			start_mark:   token.start_mark,
 837			end_mark:     token.end_mark,
 838			foot_comment: parser.tail_comment,
 839		}
 840		parser.tail_comment = nil
 841		return true
 842	}
 843
 844	if token.typ == yaml_KEY_TOKEN {
 845		mark := token.end_mark
 846		skip_token(parser)
 847		token = peek_token(parser)
 848		if token == nil {
 849			return false
 850		}
 851		if token.typ != yaml_KEY_TOKEN &&
 852			token.typ != yaml_VALUE_TOKEN &&
 853			token.typ != yaml_BLOCK_END_TOKEN {
 854			parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_VALUE_STATE)
 855			return yaml_parser_parse_node(parser, event, true, true)
 856		} else {
 857			parser.state = yaml_PARSE_BLOCK_MAPPING_VALUE_STATE
 858			return yaml_parser_process_empty_scalar(parser, event, mark)
 859		}
 860	} else if token.typ == yaml_BLOCK_END_TOKEN {
 861		parser.state = parser.states[len(parser.states)-1]
 862		parser.states = parser.states[:len(parser.states)-1]
 863		parser.marks = parser.marks[:len(parser.marks)-1]
 864		*event = yaml_event_t{
 865			typ:        yaml_MAPPING_END_EVENT,
 866			start_mark: token.start_mark,
 867			end_mark:   token.end_mark,
 868		}
 869		yaml_parser_set_event_comments(parser, event)
 870		skip_token(parser)
 871		return true
 872	}
 873
 874	context_mark := parser.marks[len(parser.marks)-1]
 875	parser.marks = parser.marks[:len(parser.marks)-1]
 876	return yaml_parser_set_parser_error_context(parser,
 877		"while parsing a block mapping", context_mark,
 878		"did not find expected key", token.start_mark)
 879}
 880
 881// Parse the productions:
 882// block_mapping        ::= BLOCK-MAPPING_START
 883//
 884//                          ((KEY block_node_or_indentless_sequence?)?
 885//
 886//                          (VALUE block_node_or_indentless_sequence?)?)*
 887//                           ***** *
 888//                          BLOCK-END
 889//
 890//
 891func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool {
 892	token := peek_token(parser)
 893	if token == nil {
 894		return false
 895	}
 896	if token.typ == yaml_VALUE_TOKEN {
 897		mark := token.end_mark
 898		skip_token(parser)
 899		token = peek_token(parser)
 900		if token == nil {
 901			return false
 902		}
 903		if token.typ != yaml_KEY_TOKEN &&
 904			token.typ != yaml_VALUE_TOKEN &&
 905			token.typ != yaml_BLOCK_END_TOKEN {
 906			parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_KEY_STATE)
 907			return yaml_parser_parse_node(parser, event, true, true)
 908		}
 909		parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE
 910		return yaml_parser_process_empty_scalar(parser, event, mark)
 911	}
 912	parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE
 913	return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
 914}
 915
 916// Parse the productions:
 917// flow_sequence        ::= FLOW-SEQUENCE-START
 918//                          *******************
 919//                          (flow_sequence_entry FLOW-ENTRY)*
 920//                           *                   **********
 921//                          flow_sequence_entry?
 922//                          *
 923//                          FLOW-SEQUENCE-END
 924//                          *****************
 925// flow_sequence_entry  ::= flow_node | KEY flow_node? (VALUE flow_node?)?
 926//                          *
 927//
 928func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
 929	if first {
 930		token := peek_token(parser)
 931		if token == nil {
 932			return false
 933		}
 934		parser.marks = append(parser.marks, token.start_mark)
 935		skip_token(parser)
 936	}
 937	token := peek_token(parser)
 938	if token == nil {
 939		return false
 940	}
 941	if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {
 942		if !first {
 943			if token.typ == yaml_FLOW_ENTRY_TOKEN {
 944				skip_token(parser)
 945				token = peek_token(parser)
 946				if token == nil {
 947					return false
 948				}
 949			} else {
 950				context_mark := parser.marks[len(parser.marks)-1]
 951				parser.marks = parser.marks[:len(parser.marks)-1]
 952				return yaml_parser_set_parser_error_context(parser,
 953					"while parsing a flow sequence", context_mark,
 954					"did not find expected ',' or ']'", token.start_mark)
 955			}
 956		}
 957
 958		if token.typ == yaml_KEY_TOKEN {
 959			parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE
 960			*event = yaml_event_t{
 961				typ:        yaml_MAPPING_START_EVENT,
 962				start_mark: token.start_mark,
 963				end_mark:   token.end_mark,
 964				implicit:   true,
 965				style:      yaml_style_t(yaml_FLOW_MAPPING_STYLE),
 966			}
 967			skip_token(parser)
 968			return true
 969		} else if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {
 970			parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE)
 971			return yaml_parser_parse_node(parser, event, false, false)
 972		}
 973	}
 974
 975	parser.state = parser.states[len(parser.states)-1]
 976	parser.states = parser.states[:len(parser.states)-1]
 977	parser.marks = parser.marks[:len(parser.marks)-1]
 978
 979	*event = yaml_event_t{
 980		typ:        yaml_SEQUENCE_END_EVENT,
 981		start_mark: token.start_mark,
 982		end_mark:   token.end_mark,
 983	}
 984	yaml_parser_set_event_comments(parser, event)
 985
 986	skip_token(parser)
 987	return true
 988}
 989
 990//
 991// Parse the productions:
 992// flow_sequence_entry  ::= flow_node | KEY flow_node? (VALUE flow_node?)?
 993//                                      *** *
 994//
 995func yaml_parser_parse_flow_sequence_entry_mapping_key(parser *yaml_parser_t, event *yaml_event_t) bool {
 996	token := peek_token(parser)
 997	if token == nil {
 998		return false
 999	}
1000	if token.typ != yaml_VALUE_TOKEN &&
1001		token.typ != yaml_FLOW_ENTRY_TOKEN &&
1002		token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {
1003		parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE)
1004		return yaml_parser_parse_node(parser, event, false, false)
1005	}
1006	mark := token.end_mark
1007	skip_token(parser)
1008	parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE
1009	return yaml_parser_process_empty_scalar(parser, event, mark)
1010}
1011
1012// Parse the productions:
1013// flow_sequence_entry  ::= flow_node | KEY flow_node? (VALUE flow_node?)?
1014//                                                      ***** *
1015//
1016func yaml_parser_parse_flow_sequence_entry_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool {
1017	token := peek_token(parser)
1018	if token == nil {
1019		return false
1020	}
1021	if token.typ == yaml_VALUE_TOKEN {
1022		skip_token(parser)
1023		token := peek_token(parser)
1024		if token == nil {
1025			return false
1026		}
1027		if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {
1028			parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE)
1029			return yaml_parser_parse_node(parser, event, false, false)
1030		}
1031	}
1032	parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE
1033	return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
1034}
1035
1036// Parse the productions:
1037// flow_sequence_entry  ::= flow_node | KEY flow_node? (VALUE flow_node?)?
1038//                                                                      *
1039//
1040func yaml_parser_parse_flow_sequence_entry_mapping_end(parser *yaml_parser_t, event *yaml_event_t) bool {
1041	token := peek_token(parser)
1042	if token == nil {
1043		return false
1044	}
1045	parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE
1046	*event = yaml_event_t{
1047		typ:        yaml_MAPPING_END_EVENT,
1048		start_mark: token.start_mark,
1049		end_mark:   token.start_mark, // [Go] Shouldn't this be end_mark?
1050	}
1051	return true
1052}
1053
1054// Parse the productions:
1055// flow_mapping         ::= FLOW-MAPPING-START
1056//                          ******************
1057//                          (flow_mapping_entry FLOW-ENTRY)*
1058//                           *                  **********
1059//                          flow_mapping_entry?
1060//                          ******************
1061//                          FLOW-MAPPING-END
1062//                          ****************
1063// flow_mapping_entry   ::= flow_node | KEY flow_node? (VALUE flow_node?)?
1064//                          *           *** *
1065//
1066func yaml_parser_parse_flow_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
1067	if first {
1068		token := peek_token(parser)
1069		parser.marks = append(parser.marks, token.start_mark)
1070		skip_token(parser)
1071	}
1072
1073	token := peek_token(parser)
1074	if token == nil {
1075		return false
1076	}
1077
1078	if token.typ != yaml_FLOW_MAPPING_END_TOKEN {
1079		if !first {
1080			if token.typ == yaml_FLOW_ENTRY_TOKEN {
1081				skip_token(parser)
1082				token = peek_token(parser)
1083				if token == nil {
1084					return false
1085				}
1086			} else {
1087				context_mark := parser.marks[len(parser.marks)-1]
1088				parser.marks = parser.marks[:len(parser.marks)-1]
1089				return yaml_parser_set_parser_error_context(parser,
1090					"while parsing a flow mapping", context_mark,
1091					"did not find expected ',' or '}'", token.start_mark)
1092			}
1093		}
1094
1095		if token.typ == yaml_KEY_TOKEN {
1096			skip_token(parser)
1097			token = peek_token(parser)
1098			if token == nil {
1099				return false
1100			}
1101			if token.typ != yaml_VALUE_TOKEN &&
1102				token.typ != yaml_FLOW_ENTRY_TOKEN &&
1103				token.typ != yaml_FLOW_MAPPING_END_TOKEN {
1104				parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_VALUE_STATE)
1105				return yaml_parser_parse_node(parser, event, false, false)
1106			} else {
1107				parser.state = yaml_PARSE_FLOW_MAPPING_VALUE_STATE
1108				return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
1109			}
1110		} else if token.typ != yaml_FLOW_MAPPING_END_TOKEN {
1111			parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE)
1112			return yaml_parser_parse_node(parser, event, false, false)
1113		}
1114	}
1115
1116	parser.state = parser.states[len(parser.states)-1]
1117	parser.states = parser.states[:len(parser.states)-1]
1118	parser.marks = parser.marks[:len(parser.marks)-1]
1119	*event = yaml_event_t{
1120		typ:        yaml_MAPPING_END_EVENT,
1121		start_mark: token.start_mark,
1122		end_mark:   token.end_mark,
1123	}
1124	yaml_parser_set_event_comments(parser, event)
1125	skip_token(parser)
1126	return true
1127}
1128
1129// Parse the productions:
1130// flow_mapping_entry   ::= flow_node | KEY flow_node? (VALUE flow_node?)?
1131//                                   *                  ***** *
1132//
1133func yaml_parser_parse_flow_mapping_value(parser *yaml_parser_t, event *yaml_event_t, empty bool) bool {
1134	token := peek_token(parser)
1135	if token == nil {
1136		return false
1137	}
1138	if empty {
1139		parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE
1140		return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
1141	}
1142	if token.typ == yaml_VALUE_TOKEN {
1143		skip_token(parser)
1144		token = peek_token(parser)
1145		if token == nil {
1146			return false
1147		}
1148		if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_MAPPING_END_TOKEN {
1149			parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_KEY_STATE)
1150			return yaml_parser_parse_node(parser, event, false, false)
1151		}
1152	}
1153	parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE
1154	return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
1155}
1156
1157// Generate an empty scalar event.
1158func yaml_parser_process_empty_scalar(parser *yaml_parser_t, event *yaml_event_t, mark yaml_mark_t) bool {
1159	*event = yaml_event_t{
1160		typ:        yaml_SCALAR_EVENT,
1161		start_mark: mark,
1162		end_mark:   mark,
1163		value:      nil, // Empty
1164		implicit:   true,
1165		style:      yaml_style_t(yaml_PLAIN_SCALAR_STYLE),
1166	}
1167	return true
1168}
1169
1170var default_tag_directives = []yaml_tag_directive_t{
1171	{[]byte("!"), []byte("!")},
1172	{[]byte("!!"), []byte("tag:yaml.org,2002:")},
1173}
1174
1175// Parse directives.
1176func yaml_parser_process_directives(parser *yaml_parser_t,
1177	version_directive_ref **yaml_version_directive_t,
1178	tag_directives_ref *[]yaml_tag_directive_t) bool {
1179
1180	var version_directive *yaml_version_directive_t
1181	var tag_directives []yaml_tag_directive_t
1182
1183	token := peek_token(parser)
1184	if token == nil {
1185		return false
1186	}
1187
1188	for token.typ == yaml_VERSION_DIRECTIVE_TOKEN || token.typ == yaml_TAG_DIRECTIVE_TOKEN {
1189		if token.typ == yaml_VERSION_DIRECTIVE_TOKEN {
1190			if version_directive != nil {
1191				yaml_parser_set_parser_error(parser,
1192					"found duplicate %YAML directive", token.start_mark)
1193				return false
1194			}
1195			if token.major != 1 || token.minor != 1 {
1196				yaml_parser_set_parser_error(parser,
1197					"found incompatible YAML document", token.start_mark)
1198				return false
1199			}
1200			version_directive = &yaml_version_directive_t{
1201				major: token.major,
1202				minor: token.minor,
1203			}
1204		} else if token.typ == yaml_TAG_DIRECTIVE_TOKEN {
1205			value := yaml_tag_directive_t{
1206				handle: token.value,
1207				prefix: token.prefix,
1208			}
1209			if !yaml_parser_append_tag_directive(parser, value, false, token.start_mark) {
1210				return false
1211			}
1212			tag_directives = append(tag_directives, value)
1213		}
1214
1215		skip_token(parser)
1216		token = peek_token(parser)
1217		if token == nil {
1218			return false
1219		}
1220	}
1221
1222	for i := range default_tag_directives {
1223		if !yaml_parser_append_tag_directive(parser, default_tag_directives[i], true, token.start_mark) {
1224			return false
1225		}
1226	}
1227
1228	if version_directive_ref != nil {
1229		*version_directive_ref = version_directive
1230	}
1231	if tag_directives_ref != nil {
1232		*tag_directives_ref = tag_directives
1233	}
1234	return true
1235}
1236
1237// Append a tag directive to the directives stack.
1238func yaml_parser_append_tag_directive(parser *yaml_parser_t, value yaml_tag_directive_t, allow_duplicates bool, mark yaml_mark_t) bool {
1239	for i := range parser.tag_directives {
1240		if bytes.Equal(value.handle, parser.tag_directives[i].handle) {
1241			if allow_duplicates {
1242				return true
1243			}
1244			return yaml_parser_set_parser_error(parser, "found duplicate %TAG directive", mark)
1245		}
1246	}
1247
1248	// [Go] I suspect the copy is unnecessary. This was likely done
1249	// because there was no way to track ownership of the data.
1250	value_copy := yaml_tag_directive_t{
1251		handle: make([]byte, len(value.handle)),
1252		prefix: make([]byte, len(value.prefix)),
1253	}
1254	copy(value_copy.handle, value.handle)
1255	copy(value_copy.prefix, value.prefix)
1256	parser.tag_directives = append(parser.tag_directives, value_copy)
1257	return true
1258}