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