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