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