| 249 | } |
| 250 | |
| 251 | func (p *templateParser) parseFor() (Expression, hcl.Diagnostics) { |
| 252 | open := p.Read() |
| 253 | openFor, isFor := open.(*templateForToken) |
| 254 | if !isFor { |
| 255 | // should never happen if caller is behaving |
| 256 | panic("parseFor called with peeker not pointing at for token") |
| 257 | } |
| 258 | |
| 259 | var contentExprs []Expression |
| 260 | var diags hcl.Diagnostics |
| 261 | var endforRange hcl.Range |
| 262 | |
| 263 | Token: |
| 264 | for { |
| 265 | next := p.Peek() |
| 266 | if end, isEnd := next.(*templateEndToken); isEnd { |
| 267 | diags = append(diags, &hcl.Diagnostic{ |
| 268 | Severity: hcl.DiagError, |
| 269 | Summary: "Unexpected end of template", |
| 270 | Detail: fmt.Sprintf( |
| 271 | "The for directive at %s is missing its corresponding endfor directive.", |
| 272 | openFor.SrcRange, |
| 273 | ), |
| 274 | Subject: &end.SrcRange, |
| 275 | }) |
| 276 | return errPlaceholderExpr(end.SrcRange), diags |
| 277 | } |
| 278 | if end, isCtrlEnd := next.(*templateEndCtrlToken); isCtrlEnd { |
| 279 | p.Read() // eat end directive |
| 280 | |
| 281 | switch end.Type { |
| 282 | |
| 283 | case templateElse: |
| 284 | diags = append(diags, &hcl.Diagnostic{ |
| 285 | Severity: hcl.DiagError, |
| 286 | Summary: "Unexpected else directive", |
| 287 | Detail: "An else clause is not expected for a for directive.", |
| 288 | Subject: &end.SrcRange, |
| 289 | }) |
| 290 | |
| 291 | case templateEndFor: |
| 292 | endforRange = end.SrcRange |
| 293 | break Token |
| 294 | |
| 295 | default: |
| 296 | diags = append(diags, &hcl.Diagnostic{ |
| 297 | Severity: hcl.DiagError, |
| 298 | Summary: fmt.Sprintf("Unexpected %s directive", end.Name()), |
| 299 | Detail: fmt.Sprintf( |
| 300 | "Expecting an endfor directive corresponding to the for directive at %s.", |
| 301 | openFor.SrcRange, |
| 302 | ), |
| 303 | Subject: &end.SrcRange, |
| 304 | }) |
| 305 | } |
| 306 | |
| 307 | return errPlaceholderExpr(end.SrcRange), diags |
| 308 | } |