ast.go raw
1 package ast
2
3 import (
4 "fmt"
5 "io"
6 "math"
7 "strconv"
8 "strings"
9
10 "github.com/goccy/go-yaml/token"
11 "golang.org/x/xerrors"
12 )
13
14 var (
15 ErrInvalidTokenType = xerrors.New("invalid token type")
16 ErrInvalidAnchorName = xerrors.New("invalid anchor name")
17 ErrInvalidAliasName = xerrors.New("invalid alias name")
18 )
19
20 // NodeType type identifier of node
21 type NodeType int
22
23 const (
24 // UnknownNodeType type identifier for default
25 UnknownNodeType NodeType = iota
26 // DocumentType type identifier for document node
27 DocumentType
28 // NullType type identifier for null node
29 NullType
30 // BoolType type identifier for boolean node
31 BoolType
32 // IntegerType type identifier for integer node
33 IntegerType
34 // FloatType type identifier for float node
35 FloatType
36 // InfinityType type identifier for infinity node
37 InfinityType
38 // NanType type identifier for nan node
39 NanType
40 // StringType type identifier for string node
41 StringType
42 // MergeKeyType type identifier for merge key node
43 MergeKeyType
44 // LiteralType type identifier for literal node
45 LiteralType
46 // MappingType type identifier for mapping node
47 MappingType
48 // MappingKeyType type identifier for mapping key node
49 MappingKeyType
50 // MappingValueType type identifier for mapping value node
51 MappingValueType
52 // SequenceType type identifier for sequence node
53 SequenceType
54 // AnchorType type identifier for anchor node
55 AnchorType
56 // AliasType type identifier for alias node
57 AliasType
58 // DirectiveType type identifier for directive node
59 DirectiveType
60 // TagType type identifier for tag node
61 TagType
62 // CommentType type identifier for comment node
63 CommentType
64 // CommentGroupType type identifier for comment group node
65 CommentGroupType
66 )
67
68 // String node type identifier to text
69 func (t NodeType) String() string {
70 switch t {
71 case UnknownNodeType:
72 return "UnknownNode"
73 case DocumentType:
74 return "Document"
75 case NullType:
76 return "Null"
77 case BoolType:
78 return "Bool"
79 case IntegerType:
80 return "Integer"
81 case FloatType:
82 return "Float"
83 case InfinityType:
84 return "Infinity"
85 case NanType:
86 return "Nan"
87 case StringType:
88 return "String"
89 case MergeKeyType:
90 return "MergeKey"
91 case LiteralType:
92 return "Literal"
93 case MappingType:
94 return "Mapping"
95 case MappingKeyType:
96 return "MappingKey"
97 case MappingValueType:
98 return "MappingValue"
99 case SequenceType:
100 return "Sequence"
101 case AnchorType:
102 return "Anchor"
103 case AliasType:
104 return "Alias"
105 case DirectiveType:
106 return "Directive"
107 case TagType:
108 return "Tag"
109 case CommentType:
110 return "Comment"
111 case CommentGroupType:
112 return "CommentGroup"
113 }
114 return ""
115 }
116
117 // String node type identifier to YAML Structure name
118 // based on https://yaml.org/spec/1.2/spec.html
119 func (t NodeType) YAMLName() string {
120 switch t {
121 case UnknownNodeType:
122 return "unknown"
123 case DocumentType:
124 return "document"
125 case NullType:
126 return "null"
127 case BoolType:
128 return "boolean"
129 case IntegerType:
130 return "int"
131 case FloatType:
132 return "float"
133 case InfinityType:
134 return "inf"
135 case NanType:
136 return "nan"
137 case StringType:
138 return "string"
139 case MergeKeyType:
140 return "merge key"
141 case LiteralType:
142 return "scalar"
143 case MappingType:
144 return "mapping"
145 case MappingKeyType:
146 return "key"
147 case MappingValueType:
148 return "value"
149 case SequenceType:
150 return "sequence"
151 case AnchorType:
152 return "anchor"
153 case AliasType:
154 return "alias"
155 case DirectiveType:
156 return "directive"
157 case TagType:
158 return "tag"
159 case CommentType:
160 return "comment"
161 case CommentGroupType:
162 return "comment"
163 }
164 return ""
165 }
166
167 // Node type of node
168 type Node interface {
169 io.Reader
170 // String node to text
171 String() string
172 // GetToken returns token instance
173 GetToken() *token.Token
174 // Type returns type of node
175 Type() NodeType
176 // AddColumn add column number to child nodes recursively
177 AddColumn(int)
178 // SetComment set comment token to node
179 SetComment(*CommentGroupNode) error
180 // Comment returns comment token instance
181 GetComment() *CommentGroupNode
182 // GetPath returns YAMLPath for the current node
183 GetPath() string
184 // SetPath set YAMLPath for the current node
185 SetPath(string)
186 // MarshalYAML
187 MarshalYAML() ([]byte, error)
188 // already read length
189 readLen() int
190 // append read length
191 addReadLen(int)
192 // clean read length
193 clearLen()
194 }
195
196 // MapKeyNode type for map key node
197 type MapKeyNode interface {
198 Node
199 // String node to text without comment
200 stringWithoutComment() string
201 }
202
203 // ScalarNode type for scalar node
204 type ScalarNode interface {
205 MapKeyNode
206 GetValue() interface{}
207 }
208
209 type BaseNode struct {
210 Path string
211 Comment *CommentGroupNode
212 read int
213 }
214
215 func addCommentString(base string, node *CommentGroupNode) string {
216 return fmt.Sprintf("%s %s", base, node.String())
217 }
218
219 func (n *BaseNode) readLen() int {
220 return n.read
221 }
222
223 func (n *BaseNode) clearLen() {
224 n.read = 0
225 }
226
227 func (n *BaseNode) addReadLen(len int) {
228 n.read += len
229 }
230
231 // GetPath returns YAMLPath for the current node.
232 func (n *BaseNode) GetPath() string {
233 if n == nil {
234 return ""
235 }
236 return n.Path
237 }
238
239 // SetPath set YAMLPath for the current node.
240 func (n *BaseNode) SetPath(path string) {
241 if n == nil {
242 return
243 }
244 n.Path = path
245 }
246
247 // GetComment returns comment token instance
248 func (n *BaseNode) GetComment() *CommentGroupNode {
249 return n.Comment
250 }
251
252 // SetComment set comment token
253 func (n *BaseNode) SetComment(node *CommentGroupNode) error {
254 n.Comment = node
255 return nil
256 }
257
258 func min(a, b int) int {
259 if a < b {
260 return a
261 }
262 return b
263 }
264
265 func readNode(p []byte, node Node) (int, error) {
266 s := node.String()
267 readLen := node.readLen()
268 remain := len(s) - readLen
269 if remain == 0 {
270 node.clearLen()
271 return 0, io.EOF
272 }
273 size := min(remain, len(p))
274 for idx, b := range []byte(s[readLen : readLen+size]) {
275 p[idx] = byte(b)
276 }
277 node.addReadLen(size)
278 return size, nil
279 }
280
281 // Null create node for null value
282 func Null(tk *token.Token) *NullNode {
283 return &NullNode{
284 BaseNode: &BaseNode{},
285 Token: tk,
286 }
287 }
288
289 // Bool create node for boolean value
290 func Bool(tk *token.Token) *BoolNode {
291 b, _ := strconv.ParseBool(tk.Value)
292 return &BoolNode{
293 BaseNode: &BaseNode{},
294 Token: tk,
295 Value: b,
296 }
297 }
298
299 // Integer create node for integer value
300 func Integer(tk *token.Token) *IntegerNode {
301 value := removeUnderScoreFromNumber(tk.Value)
302 switch tk.Type {
303 case token.BinaryIntegerType:
304 // skip two characters because binary token starts with '0b'
305 skipCharacterNum := 2
306 negativePrefix := ""
307 if value[0] == '-' {
308 skipCharacterNum++
309 negativePrefix = "-"
310 }
311 if len(negativePrefix) > 0 {
312 i, _ := strconv.ParseInt(negativePrefix+value[skipCharacterNum:], 2, 64)
313 return &IntegerNode{
314 BaseNode: &BaseNode{},
315 Token: tk,
316 Value: i,
317 }
318 }
319 i, _ := strconv.ParseUint(negativePrefix+value[skipCharacterNum:], 2, 64)
320 return &IntegerNode{
321 BaseNode: &BaseNode{},
322 Token: tk,
323 Value: i,
324 }
325 case token.OctetIntegerType:
326 // octet token starts with '0o' or '-0o' or '0' or '-0'
327 skipCharacterNum := 1
328 negativePrefix := ""
329 if value[0] == '-' {
330 skipCharacterNum++
331 if len(value) > 2 && value[2] == 'o' {
332 skipCharacterNum++
333 }
334 negativePrefix = "-"
335 } else {
336 if value[1] == 'o' {
337 skipCharacterNum++
338 }
339 }
340 if len(negativePrefix) > 0 {
341 i, _ := strconv.ParseInt(negativePrefix+value[skipCharacterNum:], 8, 64)
342 return &IntegerNode{
343 BaseNode: &BaseNode{},
344 Token: tk,
345 Value: i,
346 }
347 }
348 i, _ := strconv.ParseUint(value[skipCharacterNum:], 8, 64)
349 return &IntegerNode{
350 BaseNode: &BaseNode{},
351 Token: tk,
352 Value: i,
353 }
354 case token.HexIntegerType:
355 // hex token starts with '0x' or '-0x'
356 skipCharacterNum := 2
357 negativePrefix := ""
358 if value[0] == '-' {
359 skipCharacterNum++
360 negativePrefix = "-"
361 }
362 if len(negativePrefix) > 0 {
363 i, _ := strconv.ParseInt(negativePrefix+value[skipCharacterNum:], 16, 64)
364 return &IntegerNode{
365 BaseNode: &BaseNode{},
366 Token: tk,
367 Value: i,
368 }
369 }
370 i, _ := strconv.ParseUint(value[skipCharacterNum:], 16, 64)
371 return &IntegerNode{
372 BaseNode: &BaseNode{},
373 Token: tk,
374 Value: i,
375 }
376 }
377 if value[0] == '-' || value[0] == '+' {
378 i, _ := strconv.ParseInt(value, 10, 64)
379 return &IntegerNode{
380 BaseNode: &BaseNode{},
381 Token: tk,
382 Value: i,
383 }
384 }
385 i, _ := strconv.ParseUint(value, 10, 64)
386 return &IntegerNode{
387 BaseNode: &BaseNode{},
388 Token: tk,
389 Value: i,
390 }
391 }
392
393 // Float create node for float value
394 func Float(tk *token.Token) *FloatNode {
395 f, _ := strconv.ParseFloat(removeUnderScoreFromNumber(tk.Value), 64)
396 return &FloatNode{
397 BaseNode: &BaseNode{},
398 Token: tk,
399 Value: f,
400 }
401 }
402
403 // Infinity create node for .inf or -.inf value
404 func Infinity(tk *token.Token) *InfinityNode {
405 node := &InfinityNode{
406 BaseNode: &BaseNode{},
407 Token: tk,
408 }
409 switch tk.Value {
410 case ".inf", ".Inf", ".INF":
411 node.Value = math.Inf(0)
412 case "-.inf", "-.Inf", "-.INF":
413 node.Value = math.Inf(-1)
414 }
415 return node
416 }
417
418 // Nan create node for .nan value
419 func Nan(tk *token.Token) *NanNode {
420 return &NanNode{
421 BaseNode: &BaseNode{},
422 Token: tk,
423 }
424 }
425
426 // String create node for string value
427 func String(tk *token.Token) *StringNode {
428 return &StringNode{
429 BaseNode: &BaseNode{},
430 Token: tk,
431 Value: tk.Value,
432 }
433 }
434
435 // Comment create node for comment
436 func Comment(tk *token.Token) *CommentNode {
437 return &CommentNode{
438 BaseNode: &BaseNode{},
439 Token: tk,
440 }
441 }
442
443 func CommentGroup(comments []*token.Token) *CommentGroupNode {
444 nodes := []*CommentNode{}
445 for _, comment := range comments {
446 nodes = append(nodes, Comment(comment))
447 }
448 return &CommentGroupNode{
449 BaseNode: &BaseNode{},
450 Comments: nodes,
451 }
452 }
453
454 // MergeKey create node for merge key ( << )
455 func MergeKey(tk *token.Token) *MergeKeyNode {
456 return &MergeKeyNode{
457 BaseNode: &BaseNode{},
458 Token: tk,
459 }
460 }
461
462 // Mapping create node for map
463 func Mapping(tk *token.Token, isFlowStyle bool, values ...*MappingValueNode) *MappingNode {
464 node := &MappingNode{
465 BaseNode: &BaseNode{},
466 Start: tk,
467 IsFlowStyle: isFlowStyle,
468 Values: []*MappingValueNode{},
469 }
470 node.Values = append(node.Values, values...)
471 return node
472 }
473
474 // MappingValue create node for mapping value
475 func MappingValue(tk *token.Token, key MapKeyNode, value Node) *MappingValueNode {
476 return &MappingValueNode{
477 BaseNode: &BaseNode{},
478 Start: tk,
479 Key: key,
480 Value: value,
481 }
482 }
483
484 // MappingKey create node for map key ( '?' ).
485 func MappingKey(tk *token.Token) *MappingKeyNode {
486 return &MappingKeyNode{
487 BaseNode: &BaseNode{},
488 Start: tk,
489 }
490 }
491
492 // Sequence create node for sequence
493 func Sequence(tk *token.Token, isFlowStyle bool) *SequenceNode {
494 return &SequenceNode{
495 BaseNode: &BaseNode{},
496 Start: tk,
497 IsFlowStyle: isFlowStyle,
498 Values: []Node{},
499 }
500 }
501
502 func Anchor(tk *token.Token) *AnchorNode {
503 return &AnchorNode{
504 BaseNode: &BaseNode{},
505 Start: tk,
506 }
507 }
508
509 func Alias(tk *token.Token) *AliasNode {
510 return &AliasNode{
511 BaseNode: &BaseNode{},
512 Start: tk,
513 }
514 }
515
516 func Document(tk *token.Token, body Node) *DocumentNode {
517 return &DocumentNode{
518 BaseNode: &BaseNode{},
519 Start: tk,
520 Body: body,
521 }
522 }
523
524 func Directive(tk *token.Token) *DirectiveNode {
525 return &DirectiveNode{
526 BaseNode: &BaseNode{},
527 Start: tk,
528 }
529 }
530
531 func Literal(tk *token.Token) *LiteralNode {
532 return &LiteralNode{
533 BaseNode: &BaseNode{},
534 Start: tk,
535 }
536 }
537
538 func Tag(tk *token.Token) *TagNode {
539 return &TagNode{
540 BaseNode: &BaseNode{},
541 Start: tk,
542 }
543 }
544
545 // File contains all documents in YAML file
546 type File struct {
547 Name string
548 Docs []*DocumentNode
549 }
550
551 // Read implements (io.Reader).Read
552 func (f *File) Read(p []byte) (int, error) {
553 for _, doc := range f.Docs {
554 n, err := doc.Read(p)
555 if err == io.EOF {
556 continue
557 }
558 return n, nil
559 }
560 return 0, io.EOF
561 }
562
563 // String all documents to text
564 func (f *File) String() string {
565 docs := []string{}
566 for _, doc := range f.Docs {
567 docs = append(docs, doc.String())
568 }
569 if len(docs) > 0 {
570 return strings.Join(docs, "\n") + "\n"
571 } else {
572 return ""
573 }
574 }
575
576 // DocumentNode type of Document
577 type DocumentNode struct {
578 *BaseNode
579 Start *token.Token // position of DocumentHeader ( `---` )
580 End *token.Token // position of DocumentEnd ( `...` )
581 Body Node
582 }
583
584 // Read implements (io.Reader).Read
585 func (d *DocumentNode) Read(p []byte) (int, error) {
586 return readNode(p, d)
587 }
588
589 // Type returns DocumentNodeType
590 func (d *DocumentNode) Type() NodeType { return DocumentType }
591
592 // GetToken returns token instance
593 func (d *DocumentNode) GetToken() *token.Token {
594 return d.Body.GetToken()
595 }
596
597 // AddColumn add column number to child nodes recursively
598 func (d *DocumentNode) AddColumn(col int) {
599 if d.Body != nil {
600 d.Body.AddColumn(col)
601 }
602 }
603
604 // String document to text
605 func (d *DocumentNode) String() string {
606 doc := []string{}
607 if d.Start != nil {
608 doc = append(doc, d.Start.Value)
609 }
610 doc = append(doc, d.Body.String())
611 if d.End != nil {
612 doc = append(doc, d.End.Value)
613 }
614 return strings.Join(doc, "\n")
615 }
616
617 // MarshalYAML encodes to a YAML text
618 func (d *DocumentNode) MarshalYAML() ([]byte, error) {
619 return []byte(d.String()), nil
620 }
621
622 func removeUnderScoreFromNumber(num string) string {
623 return strings.ReplaceAll(num, "_", "")
624 }
625
626 // NullNode type of null node
627 type NullNode struct {
628 *BaseNode
629 Token *token.Token
630 }
631
632 // Read implements (io.Reader).Read
633 func (n *NullNode) Read(p []byte) (int, error) {
634 return readNode(p, n)
635 }
636
637 // Type returns NullType
638 func (n *NullNode) Type() NodeType { return NullType }
639
640 // GetToken returns token instance
641 func (n *NullNode) GetToken() *token.Token {
642 return n.Token
643 }
644
645 // AddColumn add column number to child nodes recursively
646 func (n *NullNode) AddColumn(col int) {
647 n.Token.AddColumn(col)
648 }
649
650 // GetValue returns nil value
651 func (n *NullNode) GetValue() interface{} {
652 return nil
653 }
654
655 // String returns `null` text
656 func (n *NullNode) String() string {
657 if n.Comment != nil {
658 return fmt.Sprintf("null %s", n.Comment.String())
659 }
660 return n.stringWithoutComment()
661 }
662
663 func (n *NullNode) stringWithoutComment() string {
664 return "null"
665 }
666
667 // MarshalYAML encodes to a YAML text
668 func (n *NullNode) MarshalYAML() ([]byte, error) {
669 return []byte(n.String()), nil
670 }
671
672 // IntegerNode type of integer node
673 type IntegerNode struct {
674 *BaseNode
675 Token *token.Token
676 Value interface{} // int64 or uint64 value
677 }
678
679 // Read implements (io.Reader).Read
680 func (n *IntegerNode) Read(p []byte) (int, error) {
681 return readNode(p, n)
682 }
683
684 // Type returns IntegerType
685 func (n *IntegerNode) Type() NodeType { return IntegerType }
686
687 // GetToken returns token instance
688 func (n *IntegerNode) GetToken() *token.Token {
689 return n.Token
690 }
691
692 // AddColumn add column number to child nodes recursively
693 func (n *IntegerNode) AddColumn(col int) {
694 n.Token.AddColumn(col)
695 }
696
697 // GetValue returns int64 value
698 func (n *IntegerNode) GetValue() interface{} {
699 return n.Value
700 }
701
702 // String int64 to text
703 func (n *IntegerNode) String() string {
704 if n.Comment != nil {
705 return addCommentString(n.Token.Value, n.Comment)
706 }
707 return n.stringWithoutComment()
708 }
709
710 func (n *IntegerNode) stringWithoutComment() string {
711 return n.Token.Value
712 }
713
714 // MarshalYAML encodes to a YAML text
715 func (n *IntegerNode) MarshalYAML() ([]byte, error) {
716 return []byte(n.String()), nil
717 }
718
719 // FloatNode type of float node
720 type FloatNode struct {
721 *BaseNode
722 Token *token.Token
723 Precision int
724 Value float64
725 }
726
727 // Read implements (io.Reader).Read
728 func (n *FloatNode) Read(p []byte) (int, error) {
729 return readNode(p, n)
730 }
731
732 // Type returns FloatType
733 func (n *FloatNode) Type() NodeType { return FloatType }
734
735 // GetToken returns token instance
736 func (n *FloatNode) GetToken() *token.Token {
737 return n.Token
738 }
739
740 // AddColumn add column number to child nodes recursively
741 func (n *FloatNode) AddColumn(col int) {
742 n.Token.AddColumn(col)
743 }
744
745 // GetValue returns float64 value
746 func (n *FloatNode) GetValue() interface{} {
747 return n.Value
748 }
749
750 // String float64 to text
751 func (n *FloatNode) String() string {
752 if n.Comment != nil {
753 return addCommentString(n.Token.Value, n.Comment)
754 }
755 return n.stringWithoutComment()
756 }
757
758 func (n *FloatNode) stringWithoutComment() string {
759 return n.Token.Value
760 }
761
762 // MarshalYAML encodes to a YAML text
763 func (n *FloatNode) MarshalYAML() ([]byte, error) {
764 return []byte(n.String()), nil
765 }
766
767 // StringNode type of string node
768 type StringNode struct {
769 *BaseNode
770 Token *token.Token
771 Value string
772 }
773
774 // Read implements (io.Reader).Read
775 func (n *StringNode) Read(p []byte) (int, error) {
776 return readNode(p, n)
777 }
778
779 // Type returns StringType
780 func (n *StringNode) Type() NodeType { return StringType }
781
782 // GetToken returns token instance
783 func (n *StringNode) GetToken() *token.Token {
784 return n.Token
785 }
786
787 // AddColumn add column number to child nodes recursively
788 func (n *StringNode) AddColumn(col int) {
789 n.Token.AddColumn(col)
790 }
791
792 // GetValue returns string value
793 func (n *StringNode) GetValue() interface{} {
794 return n.Value
795 }
796
797 // escapeSingleQuote escapes s to a single quoted scalar.
798 // https://yaml.org/spec/1.2.2/#732-single-quoted-style
799 func escapeSingleQuote(s string) string {
800 var sb strings.Builder
801 growLen := len(s) + // s includes also one ' from the doubled pair
802 2 + // opening and closing '
803 strings.Count(s, "'") // ' added by ReplaceAll
804 sb.Grow(growLen)
805 sb.WriteString("'")
806 sb.WriteString(strings.ReplaceAll(s, "'", "''"))
807 sb.WriteString("'")
808 return sb.String()
809 }
810
811 // String string value to text with quote or literal header if required
812 func (n *StringNode) String() string {
813 switch n.Token.Type {
814 case token.SingleQuoteType:
815 quoted := escapeSingleQuote(n.Value)
816 if n.Comment != nil {
817 return addCommentString(quoted, n.Comment)
818 }
819 return quoted
820 case token.DoubleQuoteType:
821 quoted := strconv.Quote(n.Value)
822 if n.Comment != nil {
823 return addCommentString(quoted, n.Comment)
824 }
825 return quoted
826 }
827
828 lbc := token.DetectLineBreakCharacter(n.Value)
829 if strings.Contains(n.Value, lbc) {
830 // This block assumes that the line breaks in this inside scalar content and the Outside scalar content are the same.
831 // It works mostly, but inconsistencies occur if line break characters are mixed.
832 header := token.LiteralBlockHeader(n.Value)
833 space := strings.Repeat(" ", n.Token.Position.Column-1)
834 values := []string{}
835 for _, v := range strings.Split(n.Value, lbc) {
836 values = append(values, fmt.Sprintf("%s %s", space, v))
837 }
838 block := strings.TrimSuffix(strings.TrimSuffix(strings.Join(values, lbc), fmt.Sprintf("%s %s", lbc, space)), fmt.Sprintf(" %s", space))
839 return fmt.Sprintf("%s%s%s", header, lbc, block)
840 } else if len(n.Value) > 0 && (n.Value[0] == '{' || n.Value[0] == '[') {
841 return fmt.Sprintf(`'%s'`, n.Value)
842 }
843 if n.Comment != nil {
844 return addCommentString(n.Value, n.Comment)
845 }
846 return n.Value
847 }
848
849 func (n *StringNode) stringWithoutComment() string {
850 switch n.Token.Type {
851 case token.SingleQuoteType:
852 quoted := fmt.Sprintf(`'%s'`, n.Value)
853 return quoted
854 case token.DoubleQuoteType:
855 quoted := strconv.Quote(n.Value)
856 return quoted
857 }
858
859 lbc := token.DetectLineBreakCharacter(n.Value)
860 if strings.Contains(n.Value, lbc) {
861 // This block assumes that the line breaks in this inside scalar content and the Outside scalar content are the same.
862 // It works mostly, but inconsistencies occur if line break characters are mixed.
863 header := token.LiteralBlockHeader(n.Value)
864 space := strings.Repeat(" ", n.Token.Position.Column-1)
865 values := []string{}
866 for _, v := range strings.Split(n.Value, lbc) {
867 values = append(values, fmt.Sprintf("%s %s", space, v))
868 }
869 block := strings.TrimSuffix(strings.TrimSuffix(strings.Join(values, lbc), fmt.Sprintf("%s %s", lbc, space)), fmt.Sprintf(" %s", space))
870 return fmt.Sprintf("%s%s%s", header, lbc, block)
871 } else if len(n.Value) > 0 && (n.Value[0] == '{' || n.Value[0] == '[') {
872 return fmt.Sprintf(`'%s'`, n.Value)
873 }
874 return n.Value
875 }
876
877 // MarshalYAML encodes to a YAML text
878 func (n *StringNode) MarshalYAML() ([]byte, error) {
879 return []byte(n.String()), nil
880 }
881
882 // LiteralNode type of literal node
883 type LiteralNode struct {
884 *BaseNode
885 Start *token.Token
886 Value *StringNode
887 }
888
889 // Read implements (io.Reader).Read
890 func (n *LiteralNode) Read(p []byte) (int, error) {
891 return readNode(p, n)
892 }
893
894 // Type returns LiteralType
895 func (n *LiteralNode) Type() NodeType { return LiteralType }
896
897 // GetToken returns token instance
898 func (n *LiteralNode) GetToken() *token.Token {
899 return n.Start
900 }
901
902 // AddColumn add column number to child nodes recursively
903 func (n *LiteralNode) AddColumn(col int) {
904 n.Start.AddColumn(col)
905 if n.Value != nil {
906 n.Value.AddColumn(col)
907 }
908 }
909
910 // GetValue returns string value
911 func (n *LiteralNode) GetValue() interface{} {
912 return n.String()
913 }
914
915 // String literal to text
916 func (n *LiteralNode) String() string {
917 origin := n.Value.GetToken().Origin
918 lit := strings.TrimRight(strings.TrimRight(origin, " "), "\n")
919 if n.Comment != nil {
920 return fmt.Sprintf("%s %s\n%s", n.Start.Value, n.Comment.String(), lit)
921 }
922 return fmt.Sprintf("%s\n%s", n.Start.Value, lit)
923 }
924
925 func (n *LiteralNode) stringWithoutComment() string {
926 return n.String()
927 }
928
929 // MarshalYAML encodes to a YAML text
930 func (n *LiteralNode) MarshalYAML() ([]byte, error) {
931 return []byte(n.String()), nil
932 }
933
934 // MergeKeyNode type of merge key node
935 type MergeKeyNode struct {
936 *BaseNode
937 Token *token.Token
938 }
939
940 // Read implements (io.Reader).Read
941 func (n *MergeKeyNode) Read(p []byte) (int, error) {
942 return readNode(p, n)
943 }
944
945 // Type returns MergeKeyType
946 func (n *MergeKeyNode) Type() NodeType { return MergeKeyType }
947
948 // GetToken returns token instance
949 func (n *MergeKeyNode) GetToken() *token.Token {
950 return n.Token
951 }
952
953 // GetValue returns '<<' value
954 func (n *MergeKeyNode) GetValue() interface{} {
955 return n.Token.Value
956 }
957
958 // String returns '<<' value
959 func (n *MergeKeyNode) String() string {
960 return n.stringWithoutComment()
961 }
962
963 func (n *MergeKeyNode) stringWithoutComment() string {
964 return n.Token.Value
965 }
966
967 // AddColumn add column number to child nodes recursively
968 func (n *MergeKeyNode) AddColumn(col int) {
969 n.Token.AddColumn(col)
970 }
971
972 // MarshalYAML encodes to a YAML text
973 func (n *MergeKeyNode) MarshalYAML() ([]byte, error) {
974 return []byte(n.String()), nil
975 }
976
977 // BoolNode type of boolean node
978 type BoolNode struct {
979 *BaseNode
980 Token *token.Token
981 Value bool
982 }
983
984 // Read implements (io.Reader).Read
985 func (n *BoolNode) Read(p []byte) (int, error) {
986 return readNode(p, n)
987 }
988
989 // Type returns BoolType
990 func (n *BoolNode) Type() NodeType { return BoolType }
991
992 // GetToken returns token instance
993 func (n *BoolNode) GetToken() *token.Token {
994 return n.Token
995 }
996
997 // AddColumn add column number to child nodes recursively
998 func (n *BoolNode) AddColumn(col int) {
999 n.Token.AddColumn(col)
1000 }
1001
1002 // GetValue returns boolean value
1003 func (n *BoolNode) GetValue() interface{} {
1004 return n.Value
1005 }
1006
1007 // String boolean to text
1008 func (n *BoolNode) String() string {
1009 if n.Comment != nil {
1010 return addCommentString(n.Token.Value, n.Comment)
1011 }
1012 return n.stringWithoutComment()
1013 }
1014
1015 func (n *BoolNode) stringWithoutComment() string {
1016 return n.Token.Value
1017 }
1018
1019 // MarshalYAML encodes to a YAML text
1020 func (n *BoolNode) MarshalYAML() ([]byte, error) {
1021 return []byte(n.String()), nil
1022 }
1023
1024 // InfinityNode type of infinity node
1025 type InfinityNode struct {
1026 *BaseNode
1027 Token *token.Token
1028 Value float64
1029 }
1030
1031 // Read implements (io.Reader).Read
1032 func (n *InfinityNode) Read(p []byte) (int, error) {
1033 return readNode(p, n)
1034 }
1035
1036 // Type returns InfinityType
1037 func (n *InfinityNode) Type() NodeType { return InfinityType }
1038
1039 // GetToken returns token instance
1040 func (n *InfinityNode) GetToken() *token.Token {
1041 return n.Token
1042 }
1043
1044 // AddColumn add column number to child nodes recursively
1045 func (n *InfinityNode) AddColumn(col int) {
1046 n.Token.AddColumn(col)
1047 }
1048
1049 // GetValue returns math.Inf(0) or math.Inf(-1)
1050 func (n *InfinityNode) GetValue() interface{} {
1051 return n.Value
1052 }
1053
1054 // String infinity to text
1055 func (n *InfinityNode) String() string {
1056 if n.Comment != nil {
1057 return addCommentString(n.Token.Value, n.Comment)
1058 }
1059 return n.stringWithoutComment()
1060 }
1061
1062 func (n *InfinityNode) stringWithoutComment() string {
1063 return n.Token.Value
1064 }
1065
1066 // MarshalYAML encodes to a YAML text
1067 func (n *InfinityNode) MarshalYAML() ([]byte, error) {
1068 return []byte(n.String()), nil
1069 }
1070
1071 // NanNode type of nan node
1072 type NanNode struct {
1073 *BaseNode
1074 Token *token.Token
1075 }
1076
1077 // Read implements (io.Reader).Read
1078 func (n *NanNode) Read(p []byte) (int, error) {
1079 return readNode(p, n)
1080 }
1081
1082 // Type returns NanType
1083 func (n *NanNode) Type() NodeType { return NanType }
1084
1085 // GetToken returns token instance
1086 func (n *NanNode) GetToken() *token.Token {
1087 return n.Token
1088 }
1089
1090 // AddColumn add column number to child nodes recursively
1091 func (n *NanNode) AddColumn(col int) {
1092 n.Token.AddColumn(col)
1093 }
1094
1095 // GetValue returns math.NaN()
1096 func (n *NanNode) GetValue() interface{} {
1097 return math.NaN()
1098 }
1099
1100 // String returns .nan
1101 func (n *NanNode) String() string {
1102 if n.Comment != nil {
1103 return addCommentString(n.Token.Value, n.Comment)
1104 }
1105 return n.stringWithoutComment()
1106 }
1107
1108 func (n *NanNode) stringWithoutComment() string {
1109 return n.Token.Value
1110 }
1111
1112 // MarshalYAML encodes to a YAML text
1113 func (n *NanNode) MarshalYAML() ([]byte, error) {
1114 return []byte(n.String()), nil
1115 }
1116
1117 // MapNode interface of MappingValueNode / MappingNode
1118 type MapNode interface {
1119 MapRange() *MapNodeIter
1120 }
1121
1122 // MapNodeIter is an iterator for ranging over a MapNode
1123 type MapNodeIter struct {
1124 values []*MappingValueNode
1125 idx int
1126 }
1127
1128 const (
1129 startRangeIndex = -1
1130 )
1131
1132 // Next advances the map iterator and reports whether there is another entry.
1133 // It returns false when the iterator is exhausted.
1134 func (m *MapNodeIter) Next() bool {
1135 m.idx++
1136 next := m.idx < len(m.values)
1137 return next
1138 }
1139
1140 // Key returns the key of the iterator's current map node entry.
1141 func (m *MapNodeIter) Key() MapKeyNode {
1142 return m.values[m.idx].Key
1143 }
1144
1145 // Value returns the value of the iterator's current map node entry.
1146 func (m *MapNodeIter) Value() Node {
1147 return m.values[m.idx].Value
1148 }
1149
1150 // MappingNode type of mapping node
1151 type MappingNode struct {
1152 *BaseNode
1153 Start *token.Token
1154 End *token.Token
1155 IsFlowStyle bool
1156 Values []*MappingValueNode
1157 }
1158
1159 func (n *MappingNode) startPos() *token.Position {
1160 if len(n.Values) == 0 {
1161 return n.Start.Position
1162 }
1163 return n.Values[0].Key.GetToken().Position
1164 }
1165
1166 // Merge merge key/value of map.
1167 func (n *MappingNode) Merge(target *MappingNode) {
1168 keyToMapValueMap := map[string]*MappingValueNode{}
1169 for _, value := range n.Values {
1170 key := value.Key.String()
1171 keyToMapValueMap[key] = value
1172 }
1173 column := n.startPos().Column - target.startPos().Column
1174 target.AddColumn(column)
1175 for _, value := range target.Values {
1176 mapValue, exists := keyToMapValueMap[value.Key.String()]
1177 if exists {
1178 mapValue.Value = value.Value
1179 } else {
1180 n.Values = append(n.Values, value)
1181 }
1182 }
1183 }
1184
1185 // SetIsFlowStyle set value to IsFlowStyle field recursively.
1186 func (n *MappingNode) SetIsFlowStyle(isFlow bool) {
1187 n.IsFlowStyle = isFlow
1188 for _, value := range n.Values {
1189 value.SetIsFlowStyle(isFlow)
1190 }
1191 }
1192
1193 // Read implements (io.Reader).Read
1194 func (n *MappingNode) Read(p []byte) (int, error) {
1195 return readNode(p, n)
1196 }
1197
1198 // Type returns MappingType
1199 func (n *MappingNode) Type() NodeType { return MappingType }
1200
1201 // GetToken returns token instance
1202 func (n *MappingNode) GetToken() *token.Token {
1203 return n.Start
1204 }
1205
1206 // AddColumn add column number to child nodes recursively
1207 func (n *MappingNode) AddColumn(col int) {
1208 n.Start.AddColumn(col)
1209 n.End.AddColumn(col)
1210 for _, value := range n.Values {
1211 value.AddColumn(col)
1212 }
1213 }
1214
1215 func (n *MappingNode) flowStyleString(commentMode bool) string {
1216 values := []string{}
1217 for _, value := range n.Values {
1218 values = append(values, strings.TrimLeft(value.String(), " "))
1219 }
1220 mapText := fmt.Sprintf("{%s}", strings.Join(values, ", "))
1221 if commentMode && n.Comment != nil {
1222 return addCommentString(mapText, n.Comment)
1223 }
1224 return mapText
1225 }
1226
1227 func (n *MappingNode) blockStyleString(commentMode bool) string {
1228 values := []string{}
1229 for _, value := range n.Values {
1230 values = append(values, value.String())
1231 }
1232 mapText := strings.Join(values, "\n")
1233 if commentMode && n.Comment != nil {
1234 value := values[0]
1235 var spaceNum int
1236 for i := 0; i < len(value); i++ {
1237 if value[i] != ' ' {
1238 break
1239 }
1240 spaceNum++
1241 }
1242 comment := n.Comment.StringWithSpace(spaceNum)
1243 return fmt.Sprintf("%s\n%s", comment, mapText)
1244 }
1245 return mapText
1246 }
1247
1248 // String mapping values to text
1249 func (n *MappingNode) String() string {
1250 if len(n.Values) == 0 {
1251 if n.Comment != nil {
1252 return addCommentString("{}", n.Comment)
1253 }
1254 return "{}"
1255 }
1256
1257 commentMode := true
1258 if n.IsFlowStyle || len(n.Values) == 0 {
1259 return n.flowStyleString(commentMode)
1260 }
1261 return n.blockStyleString(commentMode)
1262 }
1263
1264 // MapRange implements MapNode protocol
1265 func (n *MappingNode) MapRange() *MapNodeIter {
1266 return &MapNodeIter{
1267 idx: startRangeIndex,
1268 values: n.Values,
1269 }
1270 }
1271
1272 // MarshalYAML encodes to a YAML text
1273 func (n *MappingNode) MarshalYAML() ([]byte, error) {
1274 return []byte(n.String()), nil
1275 }
1276
1277 // MappingKeyNode type of tag node
1278 type MappingKeyNode struct {
1279 *BaseNode
1280 Start *token.Token
1281 Value Node
1282 }
1283
1284 // Read implements (io.Reader).Read
1285 func (n *MappingKeyNode) Read(p []byte) (int, error) {
1286 return readNode(p, n)
1287 }
1288
1289 // Type returns MappingKeyType
1290 func (n *MappingKeyNode) Type() NodeType { return MappingKeyType }
1291
1292 // GetToken returns token instance
1293 func (n *MappingKeyNode) GetToken() *token.Token {
1294 return n.Start
1295 }
1296
1297 // AddColumn add column number to child nodes recursively
1298 func (n *MappingKeyNode) AddColumn(col int) {
1299 n.Start.AddColumn(col)
1300 if n.Value != nil {
1301 n.Value.AddColumn(col)
1302 }
1303 }
1304
1305 // String tag to text
1306 func (n *MappingKeyNode) String() string {
1307 return n.stringWithoutComment()
1308 }
1309
1310 func (n *MappingKeyNode) stringWithoutComment() string {
1311 return fmt.Sprintf("%s %s", n.Start.Value, n.Value.String())
1312 }
1313
1314 // MarshalYAML encodes to a YAML text
1315 func (n *MappingKeyNode) MarshalYAML() ([]byte, error) {
1316 return []byte(n.String()), nil
1317 }
1318
1319 // MappingValueNode type of mapping value
1320 type MappingValueNode struct {
1321 *BaseNode
1322 Start *token.Token
1323 Key MapKeyNode
1324 Value Node
1325 }
1326
1327 // Replace replace value node.
1328 func (n *MappingValueNode) Replace(value Node) error {
1329 column := n.Value.GetToken().Position.Column - value.GetToken().Position.Column
1330 value.AddColumn(column)
1331 n.Value = value
1332 return nil
1333 }
1334
1335 // Read implements (io.Reader).Read
1336 func (n *MappingValueNode) Read(p []byte) (int, error) {
1337 return readNode(p, n)
1338 }
1339
1340 // Type returns MappingValueType
1341 func (n *MappingValueNode) Type() NodeType { return MappingValueType }
1342
1343 // GetToken returns token instance
1344 func (n *MappingValueNode) GetToken() *token.Token {
1345 return n.Start
1346 }
1347
1348 // AddColumn add column number to child nodes recursively
1349 func (n *MappingValueNode) AddColumn(col int) {
1350 n.Start.AddColumn(col)
1351 if n.Key != nil {
1352 n.Key.AddColumn(col)
1353 }
1354 if n.Value != nil {
1355 n.Value.AddColumn(col)
1356 }
1357 }
1358
1359 // SetIsFlowStyle set value to IsFlowStyle field recursively.
1360 func (n *MappingValueNode) SetIsFlowStyle(isFlow bool) {
1361 switch value := n.Value.(type) {
1362 case *MappingNode:
1363 value.SetIsFlowStyle(isFlow)
1364 case *MappingValueNode:
1365 value.SetIsFlowStyle(isFlow)
1366 case *SequenceNode:
1367 value.SetIsFlowStyle(isFlow)
1368 }
1369 }
1370
1371 // String mapping value to text
1372 func (n *MappingValueNode) String() string {
1373 if n.Comment != nil {
1374 return fmt.Sprintf(
1375 "%s\n%s",
1376 n.Comment.StringWithSpace(n.Key.GetToken().Position.Column-1),
1377 n.toString(),
1378 )
1379 }
1380 return n.toString()
1381 }
1382
1383 func (n *MappingValueNode) toString() string {
1384 space := strings.Repeat(" ", n.Key.GetToken().Position.Column-1)
1385 keyIndentLevel := n.Key.GetToken().Position.IndentLevel
1386 valueIndentLevel := n.Value.GetToken().Position.IndentLevel
1387 keyComment := n.Key.GetComment()
1388 if _, ok := n.Value.(ScalarNode); ok {
1389 return fmt.Sprintf("%s%s: %s", space, n.Key.String(), n.Value.String())
1390 } else if keyIndentLevel < valueIndentLevel {
1391 if keyComment != nil {
1392 return fmt.Sprintf(
1393 "%s%s: %s\n%s",
1394 space,
1395 n.Key.stringWithoutComment(),
1396 keyComment.String(),
1397 n.Value.String(),
1398 )
1399 }
1400 return fmt.Sprintf("%s%s:\n%s", space, n.Key.String(), n.Value.String())
1401 } else if m, ok := n.Value.(*MappingNode); ok && (m.IsFlowStyle || len(m.Values) == 0) {
1402 return fmt.Sprintf("%s%s: %s", space, n.Key.String(), n.Value.String())
1403 } else if s, ok := n.Value.(*SequenceNode); ok && (s.IsFlowStyle || len(s.Values) == 0) {
1404 return fmt.Sprintf("%s%s: %s", space, n.Key.String(), n.Value.String())
1405 } else if _, ok := n.Value.(*AnchorNode); ok {
1406 return fmt.Sprintf("%s%s: %s", space, n.Key.String(), n.Value.String())
1407 } else if _, ok := n.Value.(*AliasNode); ok {
1408 return fmt.Sprintf("%s%s: %s", space, n.Key.String(), n.Value.String())
1409 }
1410 if keyComment != nil {
1411 return fmt.Sprintf(
1412 "%s%s: %s\n%s",
1413 space,
1414 n.Key.stringWithoutComment(),
1415 keyComment.String(),
1416 n.Value.String(),
1417 )
1418 }
1419 if m, ok := n.Value.(*MappingNode); ok && m.Comment != nil {
1420 return fmt.Sprintf(
1421 "%s%s: %s",
1422 space,
1423 n.Key.String(),
1424 strings.TrimLeft(n.Value.String(), " "),
1425 )
1426 }
1427 return fmt.Sprintf("%s%s:\n%s", space, n.Key.String(), n.Value.String())
1428 }
1429
1430 // MapRange implements MapNode protocol
1431 func (n *MappingValueNode) MapRange() *MapNodeIter {
1432 return &MapNodeIter{
1433 idx: startRangeIndex,
1434 values: []*MappingValueNode{n},
1435 }
1436 }
1437
1438 // MarshalYAML encodes to a YAML text
1439 func (n *MappingValueNode) MarshalYAML() ([]byte, error) {
1440 return []byte(n.String()), nil
1441 }
1442
1443 // ArrayNode interface of SequenceNode
1444 type ArrayNode interface {
1445 ArrayRange() *ArrayNodeIter
1446 }
1447
1448 // ArrayNodeIter is an iterator for ranging over a ArrayNode
1449 type ArrayNodeIter struct {
1450 values []Node
1451 idx int
1452 }
1453
1454 // Next advances the array iterator and reports whether there is another entry.
1455 // It returns false when the iterator is exhausted.
1456 func (m *ArrayNodeIter) Next() bool {
1457 m.idx++
1458 next := m.idx < len(m.values)
1459 return next
1460 }
1461
1462 // Value returns the value of the iterator's current array entry.
1463 func (m *ArrayNodeIter) Value() Node {
1464 return m.values[m.idx]
1465 }
1466
1467 // Len returns length of array
1468 func (m *ArrayNodeIter) Len() int {
1469 return len(m.values)
1470 }
1471
1472 // SequenceNode type of sequence node
1473 type SequenceNode struct {
1474 *BaseNode
1475 Start *token.Token
1476 End *token.Token
1477 IsFlowStyle bool
1478 Values []Node
1479 ValueComments []*CommentGroupNode
1480 }
1481
1482 // Replace replace value node.
1483 func (n *SequenceNode) Replace(idx int, value Node) error {
1484 if len(n.Values) <= idx {
1485 return xerrors.Errorf(
1486 "invalid index for sequence: sequence length is %d, but specified %d index",
1487 len(n.Values), idx,
1488 )
1489 }
1490 column := n.Values[idx].GetToken().Position.Column - value.GetToken().Position.Column
1491 value.AddColumn(column)
1492 n.Values[idx] = value
1493 return nil
1494 }
1495
1496 // Merge merge sequence value.
1497 func (n *SequenceNode) Merge(target *SequenceNode) {
1498 column := n.Start.Position.Column - target.Start.Position.Column
1499 target.AddColumn(column)
1500 for _, value := range target.Values {
1501 n.Values = append(n.Values, value)
1502 }
1503 }
1504
1505 // SetIsFlowStyle set value to IsFlowStyle field recursively.
1506 func (n *SequenceNode) SetIsFlowStyle(isFlow bool) {
1507 n.IsFlowStyle = isFlow
1508 for _, value := range n.Values {
1509 switch value := value.(type) {
1510 case *MappingNode:
1511 value.SetIsFlowStyle(isFlow)
1512 case *MappingValueNode:
1513 value.SetIsFlowStyle(isFlow)
1514 case *SequenceNode:
1515 value.SetIsFlowStyle(isFlow)
1516 }
1517 }
1518 }
1519
1520 // Read implements (io.Reader).Read
1521 func (n *SequenceNode) Read(p []byte) (int, error) {
1522 return readNode(p, n)
1523 }
1524
1525 // Type returns SequenceType
1526 func (n *SequenceNode) Type() NodeType { return SequenceType }
1527
1528 // GetToken returns token instance
1529 func (n *SequenceNode) GetToken() *token.Token {
1530 return n.Start
1531 }
1532
1533 // AddColumn add column number to child nodes recursively
1534 func (n *SequenceNode) AddColumn(col int) {
1535 n.Start.AddColumn(col)
1536 n.End.AddColumn(col)
1537 for _, value := range n.Values {
1538 value.AddColumn(col)
1539 }
1540 }
1541
1542 func (n *SequenceNode) flowStyleString() string {
1543 values := []string{}
1544 for _, value := range n.Values {
1545 values = append(values, value.String())
1546 }
1547 return fmt.Sprintf("[%s]", strings.Join(values, ", "))
1548 }
1549
1550 func (n *SequenceNode) blockStyleString() string {
1551 space := strings.Repeat(" ", n.Start.Position.Column-1)
1552 values := []string{}
1553 if n.Comment != nil {
1554 values = append(values, n.Comment.StringWithSpace(n.Start.Position.Column-1))
1555 }
1556
1557 for idx, value := range n.Values {
1558 valueStr := value.String()
1559 splittedValues := strings.Split(valueStr, "\n")
1560 trimmedFirstValue := strings.TrimLeft(splittedValues[0], " ")
1561 diffLength := len(splittedValues[0]) - len(trimmedFirstValue)
1562 if len(splittedValues) > 1 && value.Type() == StringType || value.Type() == LiteralType {
1563 // If multi-line string, the space characters for indent have already been added, so delete them.
1564 for i := 1; i < len(splittedValues); i++ {
1565 splittedValues[i] = strings.TrimLeft(splittedValues[i], " ")
1566 }
1567 }
1568 newValues := []string{trimmedFirstValue}
1569 for i := 1; i < len(splittedValues); i++ {
1570 if len(splittedValues[i]) <= diffLength {
1571 // this line is \n or white space only
1572 newValues = append(newValues, "")
1573 continue
1574 }
1575 trimmed := splittedValues[i][diffLength:]
1576 newValues = append(newValues, fmt.Sprintf("%s %s", space, trimmed))
1577 }
1578 newValue := strings.Join(newValues, "\n")
1579 if len(n.ValueComments) == len(n.Values) && n.ValueComments[idx] != nil {
1580 values = append(values, n.ValueComments[idx].StringWithSpace(n.Start.Position.Column-1))
1581 }
1582 values = append(values, fmt.Sprintf("%s- %s", space, newValue))
1583 }
1584 return strings.Join(values, "\n")
1585 }
1586
1587 // String sequence to text
1588 func (n *SequenceNode) String() string {
1589 if n.IsFlowStyle || len(n.Values) == 0 {
1590 return n.flowStyleString()
1591 }
1592 return n.blockStyleString()
1593 }
1594
1595 // ArrayRange implements ArrayNode protocol
1596 func (n *SequenceNode) ArrayRange() *ArrayNodeIter {
1597 return &ArrayNodeIter{
1598 idx: startRangeIndex,
1599 values: n.Values,
1600 }
1601 }
1602
1603 // MarshalYAML encodes to a YAML text
1604 func (n *SequenceNode) MarshalYAML() ([]byte, error) {
1605 return []byte(n.String()), nil
1606 }
1607
1608 // AnchorNode type of anchor node
1609 type AnchorNode struct {
1610 *BaseNode
1611 Start *token.Token
1612 Name Node
1613 Value Node
1614 }
1615
1616 func (n *AnchorNode) SetName(name string) error {
1617 if n.Name == nil {
1618 return ErrInvalidAnchorName
1619 }
1620 s, ok := n.Name.(*StringNode)
1621 if !ok {
1622 return ErrInvalidAnchorName
1623 }
1624 s.Value = name
1625 return nil
1626 }
1627
1628 // Read implements (io.Reader).Read
1629 func (n *AnchorNode) Read(p []byte) (int, error) {
1630 return readNode(p, n)
1631 }
1632
1633 // Type returns AnchorType
1634 func (n *AnchorNode) Type() NodeType { return AnchorType }
1635
1636 // GetToken returns token instance
1637 func (n *AnchorNode) GetToken() *token.Token {
1638 return n.Start
1639 }
1640
1641 // AddColumn add column number to child nodes recursively
1642 func (n *AnchorNode) AddColumn(col int) {
1643 n.Start.AddColumn(col)
1644 if n.Name != nil {
1645 n.Name.AddColumn(col)
1646 }
1647 if n.Value != nil {
1648 n.Value.AddColumn(col)
1649 }
1650 }
1651
1652 // String anchor to text
1653 func (n *AnchorNode) String() string {
1654 value := n.Value.String()
1655 if len(strings.Split(value, "\n")) > 1 {
1656 return fmt.Sprintf("&%s\n%s", n.Name.String(), value)
1657 } else if s, ok := n.Value.(*SequenceNode); ok && !s.IsFlowStyle {
1658 return fmt.Sprintf("&%s\n%s", n.Name.String(), value)
1659 } else if m, ok := n.Value.(*MappingNode); ok && !m.IsFlowStyle {
1660 return fmt.Sprintf("&%s\n%s", n.Name.String(), value)
1661 }
1662 return fmt.Sprintf("&%s %s", n.Name.String(), value)
1663 }
1664
1665 // MarshalYAML encodes to a YAML text
1666 func (n *AnchorNode) MarshalYAML() ([]byte, error) {
1667 return []byte(n.String()), nil
1668 }
1669
1670 // AliasNode type of alias node
1671 type AliasNode struct {
1672 *BaseNode
1673 Start *token.Token
1674 Value Node
1675 }
1676
1677 func (n *AliasNode) SetName(name string) error {
1678 if n.Value == nil {
1679 return ErrInvalidAliasName
1680 }
1681 s, ok := n.Value.(*StringNode)
1682 if !ok {
1683 return ErrInvalidAliasName
1684 }
1685 s.Value = name
1686 return nil
1687 }
1688
1689 // Read implements (io.Reader).Read
1690 func (n *AliasNode) Read(p []byte) (int, error) {
1691 return readNode(p, n)
1692 }
1693
1694 // Type returns AliasType
1695 func (n *AliasNode) Type() NodeType { return AliasType }
1696
1697 // GetToken returns token instance
1698 func (n *AliasNode) GetToken() *token.Token {
1699 return n.Start
1700 }
1701
1702 // AddColumn add column number to child nodes recursively
1703 func (n *AliasNode) AddColumn(col int) {
1704 n.Start.AddColumn(col)
1705 if n.Value != nil {
1706 n.Value.AddColumn(col)
1707 }
1708 }
1709
1710 // String alias to text
1711 func (n *AliasNode) String() string {
1712 return fmt.Sprintf("*%s", n.Value.String())
1713 }
1714
1715 // MarshalYAML encodes to a YAML text
1716 func (n *AliasNode) MarshalYAML() ([]byte, error) {
1717 return []byte(n.String()), nil
1718 }
1719
1720 // DirectiveNode type of directive node
1721 type DirectiveNode struct {
1722 *BaseNode
1723 Start *token.Token
1724 Value Node
1725 }
1726
1727 // Read implements (io.Reader).Read
1728 func (n *DirectiveNode) Read(p []byte) (int, error) {
1729 return readNode(p, n)
1730 }
1731
1732 // Type returns DirectiveType
1733 func (n *DirectiveNode) Type() NodeType { return DirectiveType }
1734
1735 // GetToken returns token instance
1736 func (n *DirectiveNode) GetToken() *token.Token {
1737 return n.Start
1738 }
1739
1740 // AddColumn add column number to child nodes recursively
1741 func (n *DirectiveNode) AddColumn(col int) {
1742 if n.Value != nil {
1743 n.Value.AddColumn(col)
1744 }
1745 }
1746
1747 // String directive to text
1748 func (n *DirectiveNode) String() string {
1749 return fmt.Sprintf("%s%s", n.Start.Value, n.Value.String())
1750 }
1751
1752 // MarshalYAML encodes to a YAML text
1753 func (n *DirectiveNode) MarshalYAML() ([]byte, error) {
1754 return []byte(n.String()), nil
1755 }
1756
1757 // TagNode type of tag node
1758 type TagNode struct {
1759 *BaseNode
1760 Start *token.Token
1761 Value Node
1762 }
1763
1764 // Read implements (io.Reader).Read
1765 func (n *TagNode) Read(p []byte) (int, error) {
1766 return readNode(p, n)
1767 }
1768
1769 // Type returns TagType
1770 func (n *TagNode) Type() NodeType { return TagType }
1771
1772 // GetToken returns token instance
1773 func (n *TagNode) GetToken() *token.Token {
1774 return n.Start
1775 }
1776
1777 // AddColumn add column number to child nodes recursively
1778 func (n *TagNode) AddColumn(col int) {
1779 n.Start.AddColumn(col)
1780 if n.Value != nil {
1781 n.Value.AddColumn(col)
1782 }
1783 }
1784
1785 // String tag to text
1786 func (n *TagNode) String() string {
1787 return fmt.Sprintf("%s %s", n.Start.Value, n.Value.String())
1788 }
1789
1790 // MarshalYAML encodes to a YAML text
1791 func (n *TagNode) MarshalYAML() ([]byte, error) {
1792 return []byte(n.String()), nil
1793 }
1794
1795 // CommentNode type of comment node
1796 type CommentNode struct {
1797 *BaseNode
1798 Token *token.Token
1799 }
1800
1801 // Read implements (io.Reader).Read
1802 func (n *CommentNode) Read(p []byte) (int, error) {
1803 return readNode(p, n)
1804 }
1805
1806 // Type returns TagType
1807 func (n *CommentNode) Type() NodeType { return CommentType }
1808
1809 // GetToken returns token instance
1810 func (n *CommentNode) GetToken() *token.Token { return n.Token }
1811
1812 // AddColumn add column number to child nodes recursively
1813 func (n *CommentNode) AddColumn(col int) {
1814 if n.Token == nil {
1815 return
1816 }
1817 n.Token.AddColumn(col)
1818 }
1819
1820 // String comment to text
1821 func (n *CommentNode) String() string {
1822 return fmt.Sprintf("#%s", n.Token.Value)
1823 }
1824
1825 // MarshalYAML encodes to a YAML text
1826 func (n *CommentNode) MarshalYAML() ([]byte, error) {
1827 return []byte(n.String()), nil
1828 }
1829
1830 // CommentGroupNode type of comment node
1831 type CommentGroupNode struct {
1832 *BaseNode
1833 Comments []*CommentNode
1834 }
1835
1836 // Read implements (io.Reader).Read
1837 func (n *CommentGroupNode) Read(p []byte) (int, error) {
1838 return readNode(p, n)
1839 }
1840
1841 // Type returns TagType
1842 func (n *CommentGroupNode) Type() NodeType { return CommentType }
1843
1844 // GetToken returns token instance
1845 func (n *CommentGroupNode) GetToken() *token.Token {
1846 if len(n.Comments) > 0 {
1847 return n.Comments[0].Token
1848 }
1849 return nil
1850 }
1851
1852 // AddColumn add column number to child nodes recursively
1853 func (n *CommentGroupNode) AddColumn(col int) {
1854 for _, comment := range n.Comments {
1855 comment.AddColumn(col)
1856 }
1857 }
1858
1859 // String comment to text
1860 func (n *CommentGroupNode) String() string {
1861 values := []string{}
1862 for _, comment := range n.Comments {
1863 values = append(values, comment.String())
1864 }
1865 return strings.Join(values, "\n")
1866 }
1867
1868 func (n *CommentGroupNode) StringWithSpace(col int) string {
1869 space := strings.Repeat(" ", col)
1870 values := []string{}
1871 for _, comment := range n.Comments {
1872 values = append(values, space+comment.String())
1873 }
1874 return strings.Join(values, "\n")
1875
1876 }
1877
1878 // MarshalYAML encodes to a YAML text
1879 func (n *CommentGroupNode) MarshalYAML() ([]byte, error) {
1880 return []byte(n.String()), nil
1881 }
1882
1883 // Visitor has Visit method that is invokded for each node encountered by Walk.
1884 // If the result visitor w is not nil, Walk visits each of the children of node with the visitor w,
1885 // followed by a call of w.Visit(nil).
1886 type Visitor interface {
1887 Visit(Node) Visitor
1888 }
1889
1890 // Walk traverses an AST in depth-first order: It starts by calling v.Visit(node); node must not be nil.
1891 // If the visitor w returned by v.Visit(node) is not nil,
1892 // Walk is invoked recursively with visitor w for each of the non-nil children of node,
1893 // followed by a call of w.Visit(nil).
1894 func Walk(v Visitor, node Node) {
1895 if v = v.Visit(node); v == nil {
1896 return
1897 }
1898
1899 switch n := node.(type) {
1900 case *CommentNode:
1901 case *NullNode:
1902 walkComment(v, n.BaseNode)
1903 case *IntegerNode:
1904 walkComment(v, n.BaseNode)
1905 case *FloatNode:
1906 walkComment(v, n.BaseNode)
1907 case *StringNode:
1908 walkComment(v, n.BaseNode)
1909 case *MergeKeyNode:
1910 walkComment(v, n.BaseNode)
1911 case *BoolNode:
1912 walkComment(v, n.BaseNode)
1913 case *InfinityNode:
1914 walkComment(v, n.BaseNode)
1915 case *NanNode:
1916 walkComment(v, n.BaseNode)
1917 case *LiteralNode:
1918 walkComment(v, n.BaseNode)
1919 Walk(v, n.Value)
1920 case *DirectiveNode:
1921 walkComment(v, n.BaseNode)
1922 Walk(v, n.Value)
1923 case *TagNode:
1924 walkComment(v, n.BaseNode)
1925 Walk(v, n.Value)
1926 case *DocumentNode:
1927 walkComment(v, n.BaseNode)
1928 Walk(v, n.Body)
1929 case *MappingNode:
1930 walkComment(v, n.BaseNode)
1931 for _, value := range n.Values {
1932 Walk(v, value)
1933 }
1934 case *MappingKeyNode:
1935 walkComment(v, n.BaseNode)
1936 Walk(v, n.Value)
1937 case *MappingValueNode:
1938 walkComment(v, n.BaseNode)
1939 Walk(v, n.Key)
1940 Walk(v, n.Value)
1941 case *SequenceNode:
1942 walkComment(v, n.BaseNode)
1943 for _, value := range n.Values {
1944 Walk(v, value)
1945 }
1946 case *AnchorNode:
1947 walkComment(v, n.BaseNode)
1948 Walk(v, n.Name)
1949 Walk(v, n.Value)
1950 case *AliasNode:
1951 walkComment(v, n.BaseNode)
1952 Walk(v, n.Value)
1953 }
1954 }
1955
1956 func walkComment(v Visitor, base *BaseNode) {
1957 if base == nil {
1958 return
1959 }
1960 if base.Comment == nil {
1961 return
1962 }
1963 Walk(v, base.Comment)
1964 }
1965
1966 type filterWalker struct {
1967 typ NodeType
1968 results []Node
1969 }
1970
1971 func (v *filterWalker) Visit(n Node) Visitor {
1972 if v.typ == n.Type() {
1973 v.results = append(v.results, n)
1974 }
1975 return v
1976 }
1977
1978 type parentFinder struct {
1979 target Node
1980 }
1981
1982 func (f *parentFinder) walk(parent, node Node) Node {
1983 if f.target == node {
1984 return parent
1985 }
1986 switch n := node.(type) {
1987 case *CommentNode:
1988 return nil
1989 case *NullNode:
1990 return nil
1991 case *IntegerNode:
1992 return nil
1993 case *FloatNode:
1994 return nil
1995 case *StringNode:
1996 return nil
1997 case *MergeKeyNode:
1998 return nil
1999 case *BoolNode:
2000 return nil
2001 case *InfinityNode:
2002 return nil
2003 case *NanNode:
2004 return nil
2005 case *LiteralNode:
2006 return f.walk(node, n.Value)
2007 case *DirectiveNode:
2008 return f.walk(node, n.Value)
2009 case *TagNode:
2010 return f.walk(node, n.Value)
2011 case *DocumentNode:
2012 return f.walk(node, n.Body)
2013 case *MappingNode:
2014 for _, value := range n.Values {
2015 if found := f.walk(node, value); found != nil {
2016 return found
2017 }
2018 }
2019 case *MappingKeyNode:
2020 return f.walk(node, n.Value)
2021 case *MappingValueNode:
2022 if found := f.walk(node, n.Key); found != nil {
2023 return found
2024 }
2025 return f.walk(node, n.Value)
2026 case *SequenceNode:
2027 for _, value := range n.Values {
2028 if found := f.walk(node, value); found != nil {
2029 return found
2030 }
2031 }
2032 case *AnchorNode:
2033 if found := f.walk(node, n.Name); found != nil {
2034 return found
2035 }
2036 return f.walk(node, n.Value)
2037 case *AliasNode:
2038 return f.walk(node, n.Value)
2039 }
2040 return nil
2041 }
2042
2043 // Parent get parent node from child node.
2044 func Parent(root, child Node) Node {
2045 finder := &parentFinder{target: child}
2046 return finder.walk(root, root)
2047 }
2048
2049 // Filter returns a list of nodes that match the given type.
2050 func Filter(typ NodeType, node Node) []Node {
2051 walker := &filterWalker{typ: typ}
2052 Walk(walker, node)
2053 return walker.results
2054 }
2055
2056 // FilterFile returns a list of nodes that match the given type.
2057 func FilterFile(typ NodeType, file *File) []Node {
2058 results := []Node{}
2059 for _, doc := range file.Docs {
2060 walker := &filterWalker{typ: typ}
2061 Walk(walker, doc)
2062 results = append(results, walker.results...)
2063 }
2064 return results
2065 }
2066
2067 type ErrInvalidMergeType struct {
2068 dst Node
2069 src Node
2070 }
2071
2072 func (e *ErrInvalidMergeType) Error() string {
2073 return fmt.Sprintf("cannot merge %s into %s", e.src.Type(), e.dst.Type())
2074 }
2075
2076 // Merge merge document, map, sequence node.
2077 func Merge(dst Node, src Node) error {
2078 if doc, ok := src.(*DocumentNode); ok {
2079 src = doc.Body
2080 }
2081 err := &ErrInvalidMergeType{dst: dst, src: src}
2082 switch dst.Type() {
2083 case DocumentType:
2084 node := dst.(*DocumentNode)
2085 return Merge(node.Body, src)
2086 case MappingType:
2087 node := dst.(*MappingNode)
2088 target, ok := src.(*MappingNode)
2089 if !ok {
2090 return err
2091 }
2092 node.Merge(target)
2093 return nil
2094 case SequenceType:
2095 node := dst.(*SequenceNode)
2096 target, ok := src.(*SequenceNode)
2097 if !ok {
2098 return err
2099 }
2100 node.Merge(target)
2101 return nil
2102 }
2103 return err
2104 }
2105