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		parser.marks = append(parser.marks, token.start_mark)
691		skip_token(parser)
692	}
693
694	token := peek_token(parser)
695	if token == nil {
696		return false
697	}
698
699	if token.typ == yaml_BLOCK_ENTRY_TOKEN {
700		mark := token.end_mark
701		prior_head_len := len(parser.head_comment)
702		skip_token(parser)
703		yaml_parser_split_stem_comment(parser, prior_head_len)
704		token = peek_token(parser)
705		if token == nil {
706			return false
707		}
708		if token.typ != yaml_BLOCK_ENTRY_TOKEN && token.typ != yaml_BLOCK_END_TOKEN {
709			parser.states = append(parser.states, yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE)
710			return yaml_parser_parse_node(parser, event, true, false)
711		} else {
712			parser.state = yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE
713			return yaml_parser_process_empty_scalar(parser, event, mark)
714		}
715	}
716	if token.typ == yaml_BLOCK_END_TOKEN {
717		parser.state = parser.states[len(parser.states)-1]
718		parser.states = parser.states[:len(parser.states)-1]
719		parser.marks = parser.marks[:len(parser.marks)-1]
720
721		*event = yaml_event_t{
722			typ:        yaml_SEQUENCE_END_EVENT,
723			start_mark: token.start_mark,
724			end_mark:   token.end_mark,
725		}
726
727		skip_token(parser)
728		return true
729	}
730
731	context_mark := parser.marks[len(parser.marks)-1]
732	parser.marks = parser.marks[:len(parser.marks)-1]
733	return yaml_parser_set_parser_error_context(parser,
734		"while parsing a block collection", context_mark,
735		"did not find expected '-' indicator", token.start_mark)
736}
737
738// Parse the productions:
739// indentless_sequence  ::= (BLOCK-ENTRY block_node?)+
740//                           *********** *
741func yaml_parser_parse_indentless_sequence_entry(parser *yaml_parser_t, event *yaml_event_t) bool {
742	token := peek_token(parser)
743	if token == nil {
744		return false
745	}
746
747	if token.typ == yaml_BLOCK_ENTRY_TOKEN {
748		mark := token.end_mark
749		prior_head_len := len(parser.head_comment)
750		skip_token(parser)
751		yaml_parser_split_stem_comment(parser, prior_head_len)
752		token = peek_token(parser)
753		if token == nil {
754			return false
755		}
756		if token.typ != yaml_BLOCK_ENTRY_TOKEN &&
757			token.typ != yaml_KEY_TOKEN &&
758			token.typ != yaml_VALUE_TOKEN &&
759			token.typ != yaml_BLOCK_END_TOKEN {
760			parser.states = append(parser.states, yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE)
761			return yaml_parser_parse_node(parser, event, true, false)
762		}
763		parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE
764		return yaml_parser_process_empty_scalar(parser, event, mark)
765	}
766	parser.state = parser.states[len(parser.states)-1]
767	parser.states = parser.states[:len(parser.states)-1]
768
769	*event = yaml_event_t{
770		typ:        yaml_SEQUENCE_END_EVENT,
771		start_mark: token.start_mark,
772		end_mark:   token.start_mark, // [Go] Shouldn't this be token.end_mark?
773	}
774	return true
775}
776
777// Split stem comment from head comment.
778//
779// When a sequence or map is found under a sequence entry, the former head comment
780// is assigned to the underlying sequence or map as a whole, not the individual
781// sequence or map entry as would be expected otherwise. To handle this case the
782// previous head comment is moved aside as the stem comment.
783func yaml_parser_split_stem_comment(parser *yaml_parser_t, stem_len int) {
784	if stem_len == 0 {
785		return
786	}
787
788	token := peek_token(parser)
789	if token.typ != yaml_BLOCK_SEQUENCE_START_TOKEN && token.typ != yaml_BLOCK_MAPPING_START_TOKEN {
790		return
791	}
792
793	parser.stem_comment = parser.head_comment[:stem_len]
794	if len(parser.head_comment) == stem_len {
795		parser.head_comment = nil
796	} else {
797		// Copy suffix to prevent very strange bugs if someone ever appends
798		// further bytes to the prefix in the stem_comment slice above.
799		parser.head_comment = append([]byte(nil), parser.head_comment[stem_len+1:]...)
800	}
801}
802
803// Parse the productions:
804// block_mapping        ::= BLOCK-MAPPING_START
805//                          *******************
806//                          ((KEY block_node_or_indentless_sequence?)?
807//                            *** *
808//                          (VALUE block_node_or_indentless_sequence?)?)*
809//
810//                          BLOCK-END
811//                          *********
812//
813func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
814	if first {
815		token := peek_token(parser)
816		parser.marks = append(parser.marks, token.start_mark)
817		skip_token(parser)
818	}
819
820	token := peek_token(parser)
821	if token == nil {
822		return false
823	}
824
825	// [Go] A tail comment was left from the prior mapping value processed. Emit an event
826	//      as it needs to be processed with that value and not the following key.
827	if len(parser.tail_comment) > 0 {
828		*event = yaml_event_t{
829			typ:          yaml_TAIL_COMMENT_EVENT,
830			start_mark:   token.start_mark,
831			end_mark:     token.end_mark,
832			foot_comment: parser.tail_comment,
833		}
834		parser.tail_comment = nil
835		return true
836	}
837
838	if token.typ == yaml_KEY_TOKEN {
839		mark := token.end_mark
840		skip_token(parser)
841		token = peek_token(parser)
842		if token == nil {
843			return false
844		}
845		if token.typ != yaml_KEY_TOKEN &&
846			token.typ != yaml_VALUE_TOKEN &&
847			token.typ != yaml_BLOCK_END_TOKEN {
848			parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_VALUE_STATE)
849			return yaml_parser_parse_node(parser, event, true, true)
850		} else {
851			parser.state = yaml_PARSE_BLOCK_MAPPING_VALUE_STATE
852			return yaml_parser_process_empty_scalar(parser, event, mark)
853		}
854	} else if token.typ == yaml_BLOCK_END_TOKEN {
855		parser.state = parser.states[len(parser.states)-1]
856		parser.states = parser.states[:len(parser.states)-1]
857		parser.marks = parser.marks[:len(parser.marks)-1]
858		*event = yaml_event_t{
859			typ:        yaml_MAPPING_END_EVENT,
860			start_mark: token.start_mark,
861			end_mark:   token.end_mark,
862		}
863		yaml_parser_set_event_comments(parser, event)
864		skip_token(parser)
865		return true
866	}
867
868	context_mark := parser.marks[len(parser.marks)-1]
869	parser.marks = parser.marks[:len(parser.marks)-1]
870	return yaml_parser_set_parser_error_context(parser,
871		"while parsing a block mapping", context_mark,
872		"did not find expected key", token.start_mark)
873}
874
875// Parse the productions:
876// block_mapping        ::= BLOCK-MAPPING_START
877//
878//                          ((KEY block_node_or_indentless_sequence?)?
879//
880//                          (VALUE block_node_or_indentless_sequence?)?)*
881//                           ***** *
882//                          BLOCK-END
883//
884//
885func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool {
886	token := peek_token(parser)
887	if token == nil {
888		return false
889	}
890	if token.typ == yaml_VALUE_TOKEN {
891		mark := token.end_mark
892		skip_token(parser)
893		token = peek_token(parser)
894		if token == nil {
895			return false
896		}
897		if token.typ != yaml_KEY_TOKEN &&
898			token.typ != yaml_VALUE_TOKEN &&
899			token.typ != yaml_BLOCK_END_TOKEN {
900			parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_KEY_STATE)
901			return yaml_parser_parse_node(parser, event, true, true)
902		}
903		parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE
904		return yaml_parser_process_empty_scalar(parser, event, mark)
905	}
906	parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE
907	return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
908}
909
910// Parse the productions:
911// flow_sequence        ::= FLOW-SEQUENCE-START
912//                          *******************
913//                          (flow_sequence_entry FLOW-ENTRY)*
914//                           *                   **********
915//                          flow_sequence_entry?
916//                          *
917//                          FLOW-SEQUENCE-END
918//                          *****************
919// flow_sequence_entry  ::= flow_node | KEY flow_node? (VALUE flow_node?)?
920//                          *
921//
922func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
923	if first {
924		token := peek_token(parser)
925		parser.marks = append(parser.marks, token.start_mark)
926		skip_token(parser)
927	}
928	token := peek_token(parser)
929	if token == nil {
930		return false
931	}
932	if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {
933		if !first {
934			if token.typ == yaml_FLOW_ENTRY_TOKEN {
935				skip_token(parser)
936				token = peek_token(parser)
937				if token == nil {
938					return false
939				}
940			} else {
941				context_mark := parser.marks[len(parser.marks)-1]
942				parser.marks = parser.marks[:len(parser.marks)-1]
943				return yaml_parser_set_parser_error_context(parser,
944					"while parsing a flow sequence", context_mark,
945					"did not find expected ',' or ']'", token.start_mark)
946			}
947		}
948
949		if token.typ == yaml_KEY_TOKEN {
950			parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE
951			*event = yaml_event_t{
952				typ:        yaml_MAPPING_START_EVENT,
953				start_mark: token.start_mark,
954				end_mark:   token.end_mark,
955				implicit:   true,
956				style:      yaml_style_t(yaml_FLOW_MAPPING_STYLE),
957			}
958			skip_token(parser)
959			return true
960		} else if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {
961			parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE)
962			return yaml_parser_parse_node(parser, event, false, false)
963		}
964	}
965
966	parser.state = parser.states[len(parser.states)-1]
967	parser.states = parser.states[:len(parser.states)-1]
968	parser.marks = parser.marks[:len(parser.marks)-1]
969
970	*event = yaml_event_t{
971		typ:        yaml_SEQUENCE_END_EVENT,
972		start_mark: token.start_mark,
973		end_mark:   token.end_mark,
974	}
975	yaml_parser_set_event_comments(parser, event)
976
977	skip_token(parser)
978	return true
979}
980
981//
982// Parse the productions:
983// flow_sequence_entry  ::= flow_node | KEY flow_node? (VALUE flow_node?)?
984//                                      *** *
985//
986func yaml_parser_parse_flow_sequence_entry_mapping_key(parser *yaml_parser_t, event *yaml_event_t) bool {
987	token := peek_token(parser)
988	if token == nil {
989		return false
990	}
991	if token.typ != yaml_VALUE_TOKEN &&
992		token.typ != yaml_FLOW_ENTRY_TOKEN &&
993		token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {
994		parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE)
995		return yaml_parser_parse_node(parser, event, false, false)
996	}
997	mark := token.end_mark
998	skip_token(parser)
999	parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE
1000	return yaml_parser_process_empty_scalar(parser, event, mark)
1001}
1002
1003// Parse the productions:
1004// flow_sequence_entry  ::= flow_node | KEY flow_node? (VALUE flow_node?)?
1005//                                                      ***** *
1006//
1007func yaml_parser_parse_flow_sequence_entry_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool {
1008	token := peek_token(parser)
1009	if token == nil {
1010		return false
1011	}
1012	if token.typ == yaml_VALUE_TOKEN {
1013		skip_token(parser)
1014		token := peek_token(parser)
1015		if token == nil {
1016			return false
1017		}
1018		if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {
1019			parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE)
1020			return yaml_parser_parse_node(parser, event, false, false)
1021		}
1022	}
1023	parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE
1024	return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
1025}
1026
1027// Parse the productions:
1028// flow_sequence_entry  ::= flow_node | KEY flow_node? (VALUE flow_node?)?
1029//                                                                      *
1030//
1031func yaml_parser_parse_flow_sequence_entry_mapping_end(parser *yaml_parser_t, event *yaml_event_t) bool {
1032	token := peek_token(parser)
1033	if token == nil {
1034		return false
1035	}
1036	parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE
1037	*event = yaml_event_t{
1038		typ:        yaml_MAPPING_END_EVENT,
1039		start_mark: token.start_mark,
1040		end_mark:   token.start_mark, // [Go] Shouldn't this be end_mark?
1041	}
1042	return true
1043}
1044
1045// Parse the productions:
1046// flow_mapping         ::= FLOW-MAPPING-START
1047//                          ******************
1048//                          (flow_mapping_entry FLOW-ENTRY)*
1049//                           *                  **********
1050//                          flow_mapping_entry?
1051//                          ******************
1052//                          FLOW-MAPPING-END
1053//                          ****************
1054// flow_mapping_entry   ::= flow_node | KEY flow_node? (VALUE flow_node?)?
1055//                          *           *** *
1056//
1057func yaml_parser_parse_flow_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
1058	if first {
1059		token := peek_token(parser)
1060		parser.marks = append(parser.marks, token.start_mark)
1061		skip_token(parser)
1062	}
1063
1064	token := peek_token(parser)
1065	if token == nil {
1066		return false
1067	}
1068
1069	if token.typ != yaml_FLOW_MAPPING_END_TOKEN {
1070		if !first {
1071			if token.typ == yaml_FLOW_ENTRY_TOKEN {
1072				skip_token(parser)
1073				token = peek_token(parser)
1074				if token == nil {
1075					return false
1076				}
1077			} else {
1078				context_mark := parser.marks[len(parser.marks)-1]
1079				parser.marks = parser.marks[:len(parser.marks)-1]
1080				return yaml_parser_set_parser_error_context(parser,
1081					"while parsing a flow mapping", context_mark,
1082					"did not find expected ',' or '}'", token.start_mark)
1083			}
1084		}
1085
1086		if token.typ == yaml_KEY_TOKEN {
1087			skip_token(parser)
1088			token = peek_token(parser)
1089			if token == nil {
1090				return false
1091			}
1092			if token.typ != yaml_VALUE_TOKEN &&
1093				token.typ != yaml_FLOW_ENTRY_TOKEN &&
1094				token.typ != yaml_FLOW_MAPPING_END_TOKEN {
1095				parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_VALUE_STATE)
1096				return yaml_parser_parse_node(parser, event, false, false)
1097			} else {
1098				parser.state = yaml_PARSE_FLOW_MAPPING_VALUE_STATE
1099				return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
1100			}
1101		} else if token.typ != yaml_FLOW_MAPPING_END_TOKEN {
1102			parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE)
1103			return yaml_parser_parse_node(parser, event, false, false)
1104		}
1105	}
1106
1107	parser.state = parser.states[len(parser.states)-1]
1108	parser.states = parser.states[:len(parser.states)-1]
1109	parser.marks = parser.marks[:len(parser.marks)-1]
1110	*event = yaml_event_t{
1111		typ:        yaml_MAPPING_END_EVENT,
1112		start_mark: token.start_mark,
1113		end_mark:   token.end_mark,
1114	}
1115	yaml_parser_set_event_comments(parser, event)
1116	skip_token(parser)
1117	return true
1118}
1119
1120// Parse the productions:
1121// flow_mapping_entry   ::= flow_node | KEY flow_node? (VALUE flow_node?)?
1122//                                   *                  ***** *
1123//
1124func yaml_parser_parse_flow_mapping_value(parser *yaml_parser_t, event *yaml_event_t, empty bool) bool {
1125	token := peek_token(parser)
1126	if token == nil {
1127		return false
1128	}
1129	if empty {
1130		parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE
1131		return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
1132	}
1133	if token.typ == yaml_VALUE_TOKEN {
1134		skip_token(parser)
1135		token = peek_token(parser)
1136		if token == nil {
1137			return false
1138		}
1139		if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_MAPPING_END_TOKEN {
1140			parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_KEY_STATE)
1141			return yaml_parser_parse_node(parser, event, false, false)
1142		}
1143	}
1144	parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE
1145	return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
1146}
1147
1148// Generate an empty scalar event.
1149func yaml_parser_process_empty_scalar(parser *yaml_parser_t, event *yaml_event_t, mark yaml_mark_t) bool {
1150	*event = yaml_event_t{
1151		typ:        yaml_SCALAR_EVENT,
1152		start_mark: mark,
1153		end_mark:   mark,
1154		value:      nil, // Empty
1155		implicit:   true,
1156		style:      yaml_style_t(yaml_PLAIN_SCALAR_STYLE),
1157	}
1158	return true
1159}
1160
1161var default_tag_directives = []yaml_tag_directive_t{
1162	{[]byte("!"), []byte("!")},
1163	{[]byte("!!"), []byte("tag:yaml.org,2002:")},
1164}
1165
1166// Parse directives.
1167func yaml_parser_process_directives(parser *yaml_parser_t,
1168	version_directive_ref **yaml_version_directive_t,
1169	tag_directives_ref *[]yaml_tag_directive_t) bool {
1170
1171	var version_directive *yaml_version_directive_t
1172	var tag_directives []yaml_tag_directive_t
1173
1174	token := peek_token(parser)
1175	if token == nil {
1176		return false
1177	}
1178
1179	for token.typ == yaml_VERSION_DIRECTIVE_TOKEN || token.typ == yaml_TAG_DIRECTIVE_TOKEN {
1180		if token.typ == yaml_VERSION_DIRECTIVE_TOKEN {
1181			if version_directive != nil {
1182				yaml_parser_set_parser_error(parser,
1183					"found duplicate %YAML directive", token.start_mark)
1184				return false
1185			}
1186			if token.major != 1 || token.minor != 1 {
1187				yaml_parser_set_parser_error(parser,
1188					"found incompatible YAML document", token.start_mark)
1189				return false
1190			}
1191			version_directive = &yaml_version_directive_t{
1192				major: token.major,
1193				minor: token.minor,
1194			}
1195		} else if token.typ == yaml_TAG_DIRECTIVE_TOKEN {
1196			value := yaml_tag_directive_t{
1197				handle: token.value,
1198				prefix: token.prefix,
1199			}
1200			if !yaml_parser_append_tag_directive(parser, value, false, token.start_mark) {
1201				return false
1202			}
1203			tag_directives = append(tag_directives, value)
1204		}
1205
1206		skip_token(parser)
1207		token = peek_token(parser)
1208		if token == nil {
1209			return false
1210		}
1211	}
1212
1213	for i := range default_tag_directives {
1214		if !yaml_parser_append_tag_directive(parser, default_tag_directives[i], true, token.start_mark) {
1215			return false
1216		}
1217	}
1218
1219	if version_directive_ref != nil {
1220		*version_directive_ref = version_directive
1221	}
1222	if tag_directives_ref != nil {
1223		*tag_directives_ref = tag_directives
1224	}
1225	return true
1226}
1227
1228// Append a tag directive to the directives stack.
1229func yaml_parser_append_tag_directive(parser *yaml_parser_t, value yaml_tag_directive_t, allow_duplicates bool, mark yaml_mark_t) bool {
1230	for i := range parser.tag_directives {
1231		if bytes.Equal(value.handle, parser.tag_directives[i].handle) {
1232			if allow_duplicates {
1233				return true
1234			}
1235			return yaml_parser_set_parser_error(parser, "found duplicate %TAG directive", mark)
1236		}
1237	}
1238
1239	// [Go] I suspect the copy is unnecessary. This was likely done
1240	// because there was no way to track ownership of the data.
1241	value_copy := yaml_tag_directive_t{
1242		handle: make([]byte, len(value.handle)),
1243		prefix: make([]byte, len(value.prefix)),
1244	}
1245	copy(value_copy.handle, value.handle)
1246	copy(value_copy.prefix, value.prefix)
1247	parser.tag_directives = append(parser.tag_directives, value_copy)
1248	return true
1249}
1250