code: func (t *tree) parseFor(token item) ast.Node {
  	var ctx = token.val
  	// for and foreach have the same syntax, differing only in the requirement they impose:
  	// - for requires the collection to be a function call to "range"
  	// - foreach requires the collection to be a variable reference.
  	var vartoken = t.expect(itemDollarIdent, ctx)
  	var intoken = t.expect(itemIdent, ctx)
  	if intoken.val != "in" {
  		t.unexpected(intoken, "for loop (expected 'in')")
  	}
  
  	// get the collection to iterate through and enforce the requirements
  	var collection = t.parseExpr(0)
  	t.expect(itemRightDelim, "foreach")
  	if token.typ == itemFor {
  		f, ok := collection.(*ast.FunctionNode)
  		if !ok || f.Name != "range" {
  			t.errorf("for: expected to iterate through range()")
  		}
  	}
  
  	var body = t.itemList(itemIfempty, itemForeachEnd, itemForEnd)
  	t.backup()
  	var ifempty ast.Node
  	if t.next().typ == itemIfempty {
  		t.expect(itemRightDelim, "ifempty")
  		ifempty = t.itemList(itemForeachEnd, itemForEnd)
  	}
  	t.expect(itemRightDelim, "/foreach")
  	return &ast.ForNode{token.pos, vartoken.val[1:], collection, body, ifempty}
  }
docs: // "for" or "foreach" has just been read.