blob: aea9050b833ae384db24407a6226608515cfd358 [file] [log] [blame]
mpagenkoaf801632020-07-03 10:00:42 +00001//
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
Holger Hildebrandtda7758b2020-03-16 11:30:03 +000023package 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) {
mpagenkoaf801632020-07-03 10:00:42 +000070 token := &parser.tokens[parser.tokens_head]
71 yaml_parser_unfold_comments(parser, token)
72 return token
Holger Hildebrandtda7758b2020-03-16 11:30:03 +000073 }
74 return nil
75}
76
mpagenkoaf801632020-07-03 10:00:42 +000077// 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
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000110// 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
mpagenkoaf801632020-07-03 10:00:42 +0000284 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
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000304 *event = yaml_event_t{
305 typ: yaml_DOCUMENT_START_EVENT,
306 start_mark: token.start_mark,
307 end_mark: token.end_mark,
mpagenkoaf801632020-07-03 10:00:42 +0000308
309 head_comment: head_comment,
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000310 }
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 }
mpagenkoaf801632020-07-03 10:00:42 +0000366
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000367 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 }
mpagenkoaf801632020-07-03 10:00:42 +0000410 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 }
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000415 return true
416}
417
mpagenkoaf801632020-07-03 10:00:42 +0000418func 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
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000429// 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 }
mpagenkoaf801632020-07-03 10:00:42 +0000472 yaml_parser_set_event_comments(parser, event)
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000473 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 }
mpagenkoaf801632020-07-03 10:00:42 +0000586 yaml_parser_set_event_comments(parser, event)
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000587 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 }
mpagenkoaf801632020-07-03 10:00:42 +0000603 yaml_parser_set_event_comments(parser, event)
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000604 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 }
mpagenkoaf801632020-07-03 10:00:42 +0000618 yaml_parser_set_event_comments(parser, event)
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000619 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 }
mpagenkoaf801632020-07-03 10:00:42 +0000633 if parser.stem_comment != nil {
634 event.head_comment = parser.stem_comment
635 parser.stem_comment = nil
636 }
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000637 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
mpagenkoaf801632020-07-03 10:00:42 +0000697 prior_head := len(parser.head_comment)
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000698 skip_token(parser)
699 token = peek_token(parser)
700 if token == nil {
701 return false
702 }
mpagenkoaf801632020-07-03 10:00:42 +0000703 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 }
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000716 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
mpagenkoaf801632020-07-03 10:00:42 +0000805 // [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
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000818 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 }
mpagenkoaf801632020-07-03 10:00:42 +0000843 yaml_parser_set_event_comments(parser, event)
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000844 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 }
mpagenkoaf801632020-07-03 10:00:42 +0000955 yaml_parser_set_event_comments(parser, event)
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000956
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 }
mpagenkoaf801632020-07-03 10:00:42 +00001095 yaml_parser_set_event_comments(parser, event)
Holger Hildebrandtda7758b2020-03-16 11:30:03 +00001096 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}