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