operand: term .Field* An operand is a space-separated component of a command, a term possibly followed by field accesses. A nil return means the next item is not an operand.
(context string)
| 783 | // a term possibly followed by field accesses. |
| 784 | // A nil return means the next item is not an operand. |
| 785 | func (t *Template) operand(context string) Expression { |
| 786 | node := t.term() |
| 787 | if node == nil { |
| 788 | t.unexpected(t.next(), context, "term") |
| 789 | } |
| 790 | RESET: |
| 791 | if t.peek().typ == itemField { |
| 792 | chain := t.newChain(t.peek().pos, t.lex.lineNumber(), node) |
| 793 | for t.peekNonSpace().typ == itemField { |
| 794 | chain.Add(t.next().val) |
| 795 | } |
| 796 | // Compatibility with original API: If the term is of type NodeField |
| 797 | // or NodeVariable, just put more fields on the original. |
| 798 | // Otherwise, keep the Chain node. |
| 799 | // Obvious parsing errors involving literal values are detected here. |
| 800 | // More complex error cases will have to be handled at execution time. |
| 801 | switch node.Type() { |
| 802 | case NodeField: |
| 803 | node = t.newField(chain.Position(), t.lex.lineNumber(), chain.String()) |
| 804 | case NodeBool, NodeString, NodeNumber, NodeNil: |
| 805 | t.errorf("unexpected . after term %q", node.String()) |
| 806 | default: |
| 807 | node = chain |
| 808 | } |
| 809 | } |
| 810 | nodeTYPE := node.Type() |
| 811 | if nodeTYPE == NodeIdentifier || |
| 812 | nodeTYPE == NodeCallExpr || |
| 813 | nodeTYPE == NodeField || |
| 814 | nodeTYPE == NodeChain || |
| 815 | nodeTYPE == NodeIndexExpr { |
| 816 | switch t.nextNonSpace().typ { |
| 817 | case itemLeftParen: |
| 818 | callExpr := t.newCallExpr(node.Position(), t.lex.lineNumber(), node) |
| 819 | callExpr.CallArgs = t.parseArguments() |
| 820 | t.expect(itemRightParen, "call expression", "closing parenthesis") |
| 821 | node = callExpr |
| 822 | goto RESET |
| 823 | case itemLeftBrackets: |
| 824 | base := node |
| 825 | var index Expression |
| 826 | var next item |
| 827 | |
| 828 | //found colon is slice expression |
| 829 | if t.peekNonSpace().typ != itemColon { |
| 830 | index, next = t.parseExpression("index|slice expression") |
| 831 | } else { |
| 832 | next = t.nextNonSpace() |
| 833 | } |
| 834 | |
| 835 | switch next.typ { |
| 836 | case itemColon: |
| 837 | var endIndex Expression |
| 838 | if t.peekNonSpace().typ != itemRightBrackets { |
| 839 | endIndex = t.expression("slice expression", "end indexß") |
| 840 | } |
| 841 | node = t.newSliceExpr(node.Position(), node.line(), base, index, endIndex) |
| 842 | case itemRightBrackets: |
no test coverage detected