promql/parse.go
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,
	}
}
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,
	}
}
func ( p * parser ) aggrExpr ( ) * AggregateExpr { const ctx = " " agop := p . next ( ) if ! agop . typ . isAggregator ( ) { p . errorf ( " " , 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 ( " " ) } if t == ItemWithout { without = true } p . next ( ) grouping = p . labels ( ) } } return & AggregateExpr { Op : agop . typ , Expr : e , Param : param , Grouping : grouping , Without : without , } }
// aggrExpr parses an aggregation expression.
//
//		<aggr_op> (<Vector_expr>) [by|without <labels>]
//		<aggr_op> [by|without <labels>] (<Vector_expr>)
//
aggrExpr parses an aggregation expression . <aggr_op > ( <Vector_expr > ) [ by|without <labels > ] <aggr_op > [ by|without <labels > ] ( <Vector_expr > )