code: func (p *parser) aggrExpr() *AggregateExpr {
  	const ctx = "aggregation"
  
  	agop := p.next()
  	if !agop.typ.isAggregator() {
  		p.errorf("expected aggregation operator but got %s", agop)
  	}
  	var grouping []string
  	var without bool
  
  	modifiersFirst := false
  
  	if t := p.peek().typ; t == ItemBy || t == ItemWithout {
  		if t == ItemWithout {
  			without = true
  		}
  		p.next()
  		grouping = p.labels()
  		modifiersFirst = true
  	}
  
  	p.expect(ItemLeftParen, ctx)
  	var param Expr
  	if agop.typ.isAggregatorWithParam() {
  		param = p.expr()
  		p.expect(ItemComma, ctx)
  	}
  	e := p.expr()
  	p.expect(ItemRightParen, ctx)
  
  	if !modifiersFirst {
  		if t := p.peek().typ; t == ItemBy || t == ItemWithout {
  			if len(grouping) > 0 {
  				p.errorf("aggregation must only contain one grouping clause")
  			}
  			if t == ItemWithout {
  				without = true
  			}
  			p.next()
  			grouping = p.labels()
  		}
  	}
  
  	return &AggregateExpr{
  		Op:       agop.typ,
  		Expr:     e,
  		Param:    param,
  		Grouping: grouping,
  		Without:  without,
  	}
  }
docs: // aggrExpr parses an aggregation expression.
  //
  //		<aggr_op> (<Vector_expr>) [by|without <labels>]
  //		<aggr_op> [by|without <labels>] (<Vector_expr>)
  //