(from Expression)
| 623 | } |
| 624 | |
| 625 | func (p *parser) parseExpressionTraversals(from Expression) (Expression, hcl.Diagnostics) { |
| 626 | var diags hcl.Diagnostics |
| 627 | ret := from |
| 628 | |
| 629 | Traversal: |
| 630 | for { |
| 631 | next := p.Peek() |
| 632 | |
| 633 | switch next.Type { |
| 634 | case TokenDot: |
| 635 | // Attribute access or splat |
| 636 | dot := p.Read() |
| 637 | attrTok := p.Peek() |
| 638 | |
| 639 | switch attrTok.Type { |
| 640 | case TokenIdent: |
| 641 | attrTok = p.Read() // eat token |
| 642 | name := string(attrTok.Bytes) |
| 643 | rng := hcl.RangeBetween(dot.Range, attrTok.Range) |
| 644 | step := hcl.TraverseAttr{ |
| 645 | Name: name, |
| 646 | SrcRange: rng, |
| 647 | } |
| 648 | |
| 649 | ret = makeRelativeTraversal(ret, step, rng) |
| 650 | |
| 651 | case TokenNumberLit: |
| 652 | // This is a weird form we inherited from HIL, allowing numbers |
| 653 | // to be used as attributes as a weird way of writing [n]. |
| 654 | // This was never actually a first-class thing in HIL, but |
| 655 | // HIL tolerated sequences like .0. in its variable names and |
| 656 | // calling applications like Terraform exploited that to |
| 657 | // introduce indexing syntax where none existed. |
| 658 | numTok := p.Read() // eat token |
| 659 | attrTok = numTok |
| 660 | |
| 661 | // This syntax is ambiguous if multiple indices are used in |
| 662 | // succession, like foo.0.1.baz: that actually parses as |
| 663 | // a fractional number 0.1. Since we're only supporting this |
| 664 | // syntax for compatibility with legacy Terraform |
| 665 | // configurations, and Terraform does not tend to have lists |
| 666 | // of lists, we'll choose to reject that here with a helpful |
| 667 | // error message, rather than failing later because the index |
| 668 | // isn't a whole number. |
| 669 | if dotIdx := bytes.IndexByte(numTok.Bytes, '.'); dotIdx >= 0 { |
| 670 | first := numTok.Bytes[:dotIdx] |
| 671 | second := numTok.Bytes[dotIdx+1:] |
| 672 | diags = append(diags, &hcl.Diagnostic{ |
| 673 | Severity: hcl.DiagError, |
| 674 | Summary: "Invalid legacy index syntax", |
| 675 | Detail: fmt.Sprintf("When using the legacy index syntax, chaining two indexes together is not permitted. Use the proper index syntax instead, like [%s][%s].", first, second), |
| 676 | Subject: &attrTok.Range, |
| 677 | }) |
| 678 | rng := hcl.RangeBetween(dot.Range, numTok.Range) |
| 679 | step := hcl.TraverseIndex{ |
| 680 | Key: cty.DynamicVal, |
| 681 | SrcRange: rng, |
| 682 | } |
no test coverage detected