| 85 | } |
| 86 | |
| 87 | func (p *templateParser) parseExpr() (Expression, hcl.Diagnostics) { |
| 88 | next := p.Peek() |
| 89 | switch tok := next.(type) { |
| 90 | |
| 91 | case *templateLiteralToken: |
| 92 | p.Read() // eat literal |
| 93 | return &LiteralValueExpr{ |
| 94 | Val: cty.StringVal(tok.Val), |
| 95 | SrcRange: tok.SrcRange, |
| 96 | }, nil |
| 97 | |
| 98 | case *templateInterpToken: |
| 99 | p.Read() // eat interp |
| 100 | return tok.Expr, nil |
| 101 | |
| 102 | case *templateIfToken: |
| 103 | return p.parseIf() |
| 104 | |
| 105 | case *templateForToken: |
| 106 | return p.parseFor() |
| 107 | |
| 108 | case *templateEndToken: |
| 109 | p.Read() // eat erroneous token |
| 110 | return errPlaceholderExpr(tok.SrcRange), hcl.Diagnostics{ |
| 111 | { |
| 112 | // This is a particularly unhelpful diagnostic, so callers |
| 113 | // should attempt to pre-empt it and produce a more helpful |
| 114 | // diagnostic that is context-aware. |
| 115 | Severity: hcl.DiagError, |
| 116 | Summary: "Unexpected end of template", |
| 117 | Detail: "The control directives within this template are unbalanced.", |
| 118 | Subject: &tok.SrcRange, |
| 119 | }, |
| 120 | } |
| 121 | |
| 122 | case *templateEndCtrlToken: |
| 123 | p.Read() // eat erroneous token |
| 124 | return errPlaceholderExpr(tok.SrcRange), hcl.Diagnostics{ |
| 125 | { |
| 126 | Severity: hcl.DiagError, |
| 127 | Summary: fmt.Sprintf("Unexpected %s directive", tok.Name()), |
| 128 | Detail: "The control directives within this template are unbalanced.", |
| 129 | Subject: &tok.SrcRange, |
| 130 | }, |
| 131 | } |
| 132 | |
| 133 | default: |
| 134 | // should never happen, because above should be exhaustive |
| 135 | panic(fmt.Sprintf("unhandled template token type %T", next)) |
| 136 | } |
| 137 | } |
| 138 | |
| 139 | func (p *templateParser) parseIf() (Expression, hcl.Diagnostics) { |
| 140 | open := p.Read() |