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