Expose lexer item types (#5358)

* Expose lexer item types

We have generally agreed to expose AST types / values that are necessary
to make sense of the AST outside of the promql package. Currently the
`UnaryExpr`, `BinaryExpr`, and `AggregateExpr` AST nodes store the lexer
item type to indicate the operator type, but since the individual item
types aren't exposed, an external user of the package cannot determine
the operator type. So this PR exposes them.

Although not all item types are required to make sense of the AST (some
are really only used in the lexer), I decided to expose them all here to
be somewhat more consistent. Another option would be to not use lexer
item types at all in AST nodes.

The concrete motivation is my work on the PromQL->Flux transpiler, but
this ought to be useful for other cases as well.

Signed-off-by: Julius Volz <julius.volz@gmail.com>

* Fix item type names in tests

Signed-off-by: Julius Volz <julius.volz@gmail.com>
This commit is contained in:
Julius Volz 2019-03-14 20:53:55 +01:00 committed by GitHub
parent 985eaa8194
commit 8155cc4992
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 615 additions and 617 deletions

View file

@ -36,7 +36,6 @@ import (
"github.com/prometheus/prometheus/pkg/timestamp"
"github.com/prometheus/prometheus/pkg/value"
"github.com/prometheus/prometheus/storage"
"github.com/prometheus/prometheus/util/stats"
)
@ -1040,7 +1039,7 @@ func (ev *evaluator) eval(expr Expr) Value {
case *UnaryExpr:
mat := ev.eval(e.Expr).(Matrix)
if e.Op == itemSUB {
if e.Op == ItemSUB {
for i := range mat {
mat[i].Metric = dropMetricName(mat[i].Metric)
for j := range mat[i].Points {
@ -1062,15 +1061,15 @@ func (ev *evaluator) eval(expr Expr) Value {
}, e.LHS, e.RHS)
case lt == ValueTypeVector && rt == ValueTypeVector:
switch e.Op {
case itemLAND:
case ItemLAND:
return ev.rangeEval(func(v []Value, enh *EvalNodeHelper) Vector {
return ev.VectorAnd(v[0].(Vector), v[1].(Vector), e.VectorMatching, enh)
}, e.LHS, e.RHS)
case itemLOR:
case ItemLOR:
return ev.rangeEval(func(v []Value, enh *EvalNodeHelper) Vector {
return ev.VectorOr(v[0].(Vector), v[1].(Vector), e.VectorMatching, enh)
}, e.LHS, e.RHS)
case itemLUnless:
case ItemLUnless:
return ev.rangeEval(func(v []Value, enh *EvalNodeHelper) Vector {
return ev.VectorUnless(v[0].(Vector), v[1].(Vector), e.VectorMatching, enh)
}, e.LHS, e.RHS)
@ -1605,29 +1604,29 @@ func dropMetricName(l labels.Labels) labels.Labels {
// scalarBinop evaluates a binary operation between two Scalars.
func scalarBinop(op ItemType, lhs, rhs float64) float64 {
switch op {
case itemADD:
case ItemADD:
return lhs + rhs
case itemSUB:
case ItemSUB:
return lhs - rhs
case itemMUL:
case ItemMUL:
return lhs * rhs
case itemDIV:
case ItemDIV:
return lhs / rhs
case itemPOW:
case ItemPOW:
return math.Pow(lhs, rhs)
case itemMOD:
case ItemMOD:
return math.Mod(lhs, rhs)
case itemEQL:
case ItemEQL:
return btos(lhs == rhs)
case itemNEQ:
case ItemNEQ:
return btos(lhs != rhs)
case itemGTR:
case ItemGTR:
return btos(lhs > rhs)
case itemLSS:
case ItemLSS:
return btos(lhs < rhs)
case itemGTE:
case ItemGTE:
return btos(lhs >= rhs)
case itemLTE:
case ItemLTE:
return btos(lhs <= rhs)
}
panic(fmt.Errorf("operator %q not allowed for Scalar operations", op))
@ -1636,29 +1635,29 @@ func scalarBinop(op ItemType, lhs, rhs float64) float64 {
// vectorElemBinop evaluates a binary operation between two Vector elements.
func vectorElemBinop(op ItemType, lhs, rhs float64) (float64, bool) {
switch op {
case itemADD:
case ItemADD:
return lhs + rhs, true
case itemSUB:
case ItemSUB:
return lhs - rhs, true
case itemMUL:
case ItemMUL:
return lhs * rhs, true
case itemDIV:
case ItemDIV:
return lhs / rhs, true
case itemPOW:
case ItemPOW:
return math.Pow(lhs, rhs), true
case itemMOD:
case ItemMOD:
return math.Mod(lhs, rhs), true
case itemEQL:
case ItemEQL:
return lhs, lhs == rhs
case itemNEQ:
case ItemNEQ:
return lhs, lhs != rhs
case itemGTR:
case ItemGTR:
return lhs, lhs > rhs
case itemLSS:
case ItemLSS:
return lhs, lhs < rhs
case itemGTE:
case ItemGTE:
return lhs, lhs >= rhs
case itemLTE:
case ItemLTE:
return lhs, lhs <= rhs
}
panic(fmt.Errorf("operator %q not allowed for operations between Vectors", op))
@ -1678,7 +1677,7 @@ func (ev *evaluator) aggregation(op ItemType, grouping []string, without bool, p
result := map[uint64]*groupedAggregation{}
var k int64
if op == itemTopK || op == itemBottomK {
if op == ItemTopK || op == ItemBottomK {
f := param.(float64)
if !convertibleToInt64(f) {
ev.errorf("Scalar value %v overflows int64", f)
@ -1689,11 +1688,11 @@ func (ev *evaluator) aggregation(op ItemType, grouping []string, without bool, p
}
}
var q float64
if op == itemQuantile {
if op == ItemQuantile {
q = param.(float64)
}
var valueLabel string
if op == itemCountValues {
if op == ItemCountValues {
valueLabel = param.(string)
if !model.LabelName(valueLabel).IsValid() {
ev.errorf("invalid label name %q", valueLabel)
@ -1706,7 +1705,7 @@ func (ev *evaluator) aggregation(op ItemType, grouping []string, without bool, p
for _, s := range vec {
metric := s.Metric
if op == itemCountValues {
if op == ItemCountValues {
lb := labels.NewBuilder(metric)
lb.Set(valueLabel, strconv.FormatFloat(s.V, 'f', -1, 64))
metric = lb.Labels()
@ -1754,15 +1753,15 @@ func (ev *evaluator) aggregation(op ItemType, grouping []string, without bool, p
if k > inputVecLen {
resultSize = inputVecLen
}
if op == itemStdvar || op == itemStddev {
if op == ItemStdvar || op == ItemStddev {
result[groupingKey].value = 0.0
} else if op == itemTopK || op == itemQuantile {
} else if op == ItemTopK || op == ItemQuantile {
result[groupingKey].heap = make(vectorByValueHeap, 0, resultSize)
heap.Push(&result[groupingKey].heap, &Sample{
Point: Point{V: s.V},
Metric: s.Metric,
})
} else if op == itemBottomK {
} else if op == ItemBottomK {
result[groupingKey].reverseHeap = make(vectorByReverseValueHeap, 0, resultSize)
heap.Push(&result[groupingKey].reverseHeap, &Sample{
Point: Point{V: s.V},
@ -1773,33 +1772,33 @@ func (ev *evaluator) aggregation(op ItemType, grouping []string, without bool, p
}
switch op {
case itemSum:
case ItemSum:
group.value += s.V
case itemAvg:
case ItemAvg:
group.groupCount++
group.mean += (s.V - group.mean) / float64(group.groupCount)
case itemMax:
case ItemMax:
if group.value < s.V || math.IsNaN(group.value) {
group.value = s.V
}
case itemMin:
case ItemMin:
if group.value > s.V || math.IsNaN(group.value) {
group.value = s.V
}
case itemCount, itemCountValues:
case ItemCount, ItemCountValues:
group.groupCount++
case itemStdvar, itemStddev:
case ItemStdvar, ItemStddev:
group.groupCount++
delta := s.V - group.mean
group.mean += delta / float64(group.groupCount)
group.value += delta * (s.V - group.mean)
case itemTopK:
case ItemTopK:
if int64(len(group.heap)) < k || group.heap[0].V < s.V || math.IsNaN(group.heap[0].V) {
if int64(len(group.heap)) == k {
heap.Pop(&group.heap)
@ -1810,7 +1809,7 @@ func (ev *evaluator) aggregation(op ItemType, grouping []string, without bool, p
})
}
case itemBottomK:
case ItemBottomK:
if int64(len(group.reverseHeap)) < k || group.reverseHeap[0].V > s.V || math.IsNaN(group.reverseHeap[0].V) {
if int64(len(group.reverseHeap)) == k {
heap.Pop(&group.reverseHeap)
@ -1821,7 +1820,7 @@ func (ev *evaluator) aggregation(op ItemType, grouping []string, without bool, p
})
}
case itemQuantile:
case ItemQuantile:
group.heap = append(group.heap, s)
default:
@ -1832,19 +1831,19 @@ func (ev *evaluator) aggregation(op ItemType, grouping []string, without bool, p
// Construct the result Vector from the aggregated groups.
for _, aggr := range result {
switch op {
case itemAvg:
case ItemAvg:
aggr.value = aggr.mean
case itemCount, itemCountValues:
case ItemCount, ItemCountValues:
aggr.value = float64(aggr.groupCount)
case itemStdvar:
case ItemStdvar:
aggr.value = aggr.value / float64(aggr.groupCount)
case itemStddev:
case ItemStddev:
aggr.value = math.Sqrt(aggr.value / float64(aggr.groupCount))
case itemTopK:
case ItemTopK:
// The heap keeps the lowest value on top, so reverse it.
sort.Sort(sort.Reverse(aggr.heap))
for _, v := range aggr.heap {
@ -1855,7 +1854,7 @@ func (ev *evaluator) aggregation(op ItemType, grouping []string, without bool, p
}
continue // Bypass default append.
case itemBottomK:
case ItemBottomK:
// The heap keeps the lowest value on top, so reverse it.
sort.Sort(sort.Reverse(aggr.reverseHeap))
for _, v := range aggr.reverseHeap {
@ -1866,7 +1865,7 @@ func (ev *evaluator) aggregation(op ItemType, grouping []string, without bool, p
}
continue // Bypass default append.
case itemQuantile:
case ItemQuantile:
aggr.value = quantile(q, aggr.heap)
default:
@ -1893,7 +1892,7 @@ func btos(b bool) float64 {
// result of the op operation.
func shouldDropMetricName(op ItemType) bool {
switch op {
case itemADD, itemSUB, itemDIV, itemMUL, itemPOW, itemMOD:
case ItemADD, ItemSUB, ItemDIV, ItemMUL, ItemPOW, ItemMOD:
return true
default:
return false

View file

@ -30,11 +30,11 @@ type item struct {
// String returns a descriptive string for the item.
func (i item) String() string {
switch {
case i.typ == itemEOF:
case i.typ == ItemEOF:
return "EOF"
case i.typ == itemError:
case i.typ == ItemError:
return i.val
case i.typ == itemIdentifier || i.typ == itemMetricIdentifier:
case i.typ == ItemIdentifier || i.typ == ItemMetricIdentifier:
return fmt.Sprintf("%q", i.val)
case i.typ.isKeyword():
return fmt.Sprintf("<%s>", i.val)
@ -59,7 +59,7 @@ func (i ItemType) isAggregator() bool { return i > aggregatorsStart && i < aggre
// isAggregator returns true if the item is an aggregator that takes a parameter.
// Returns false otherwise
func (i ItemType) isAggregatorWithParam() bool {
return i == itemTopK || i == itemBottomK || i == itemCountValues || i == itemQuantile
return i == ItemTopK || i == ItemBottomK || i == ItemCountValues || i == ItemQuantile
}
// isKeyword returns true if the item corresponds to a keyword.
@ -70,7 +70,7 @@ func (i ItemType) isKeyword() bool { return i > keywordsStart && i < keywordsEnd
// Returns false otherwise.
func (i ItemType) isComparisonOperator() bool {
switch i {
case itemEQL, itemNEQ, itemLTE, itemLSS, itemGTE, itemGTR:
case ItemEQL, ItemNEQ, ItemLTE, ItemLSS, ItemGTE, ItemGTR:
return true
default:
return false
@ -80,7 +80,7 @@ func (i ItemType) isComparisonOperator() bool {
// isSetOperator returns whether the item corresponds to a set operator.
func (i ItemType) isSetOperator() bool {
switch i {
case itemLAND, itemLOR, itemLUnless:
case ItemLAND, ItemLOR, ItemLUnless:
return true
}
return false
@ -94,17 +94,17 @@ const LowestPrec = 0 // Non-operators.
// is LowestPrec.
func (i ItemType) precedence() int {
switch i {
case itemLOR:
case ItemLOR:
return 1
case itemLAND, itemLUnless:
case ItemLAND, ItemLUnless:
return 2
case itemEQL, itemNEQ, itemLTE, itemLSS, itemGTE, itemGTR:
case ItemEQL, ItemNEQ, ItemLTE, ItemLSS, ItemGTE, ItemGTR:
return 3
case itemADD, itemSUB:
case ItemADD, ItemSUB:
return 4
case itemMUL, itemDIV, itemMOD:
case ItemMUL, ItemDIV, ItemMOD:
return 5
case itemPOW:
case ItemPOW:
return 6
default:
return LowestPrec
@ -113,7 +113,7 @@ func (i ItemType) precedence() int {
func (i ItemType) isRightAssociative() bool {
switch i {
case itemPOW:
case ItemPOW:
return true
default:
return false
@ -124,138 +124,138 @@ func (i ItemType) isRightAssociative() bool {
type ItemType int
const (
itemError ItemType = iota // Error occurred, value is error message
itemEOF
itemComment
itemIdentifier
itemMetricIdentifier
itemLeftParen
itemRightParen
itemLeftBrace
itemRightBrace
itemLeftBracket
itemRightBracket
itemComma
itemAssign
itemColon
itemSemicolon
itemString
itemNumber
itemDuration
itemBlank
itemTimes
itemSpace
ItemError ItemType = iota // Error occurred, value is error message
ItemEOF
ItemComment
ItemIdentifier
ItemMetricIdentifier
ItemLeftParen
ItemRightParen
ItemLeftBrace
ItemRightBrace
ItemLeftBracket
ItemRightBracket
ItemComma
ItemAssign
ItemColon
ItemSemicolon
ItemString
ItemNumber
ItemDuration
ItemBlank
ItemTimes
ItemSpace
operatorsStart
// Operators.
itemSUB
itemADD
itemMUL
itemMOD
itemDIV
itemLAND
itemLOR
itemLUnless
itemEQL
itemNEQ
itemLTE
itemLSS
itemGTE
itemGTR
itemEQLRegex
itemNEQRegex
itemPOW
ItemSUB
ItemADD
ItemMUL
ItemMOD
ItemDIV
ItemLAND
ItemLOR
ItemLUnless
ItemEQL
ItemNEQ
ItemLTE
ItemLSS
ItemGTE
ItemGTR
ItemEQLRegex
ItemNEQRegex
ItemPOW
operatorsEnd
aggregatorsStart
// Aggregators.
itemAvg
itemCount
itemSum
itemMin
itemMax
itemStddev
itemStdvar
itemTopK
itemBottomK
itemCountValues
itemQuantile
ItemAvg
ItemCount
ItemSum
ItemMin
ItemMax
ItemStddev
ItemStdvar
ItemTopK
ItemBottomK
ItemCountValues
ItemQuantile
aggregatorsEnd
keywordsStart
// Keywords.
itemOffset
itemBy
itemWithout
itemOn
itemIgnoring
itemGroupLeft
itemGroupRight
itemBool
ItemOffset
ItemBy
ItemWithout
ItemOn
ItemIgnoring
ItemGroupLeft
ItemGroupRight
ItemBool
keywordsEnd
)
var key = map[string]ItemType{
// Operators.
"and": itemLAND,
"or": itemLOR,
"unless": itemLUnless,
"and": ItemLAND,
"or": ItemLOR,
"unless": ItemLUnless,
// Aggregators.
"sum": itemSum,
"avg": itemAvg,
"count": itemCount,
"min": itemMin,
"max": itemMax,
"stddev": itemStddev,
"stdvar": itemStdvar,
"topk": itemTopK,
"bottomk": itemBottomK,
"count_values": itemCountValues,
"quantile": itemQuantile,
"sum": ItemSum,
"avg": ItemAvg,
"count": ItemCount,
"min": ItemMin,
"max": ItemMax,
"stddev": ItemStddev,
"stdvar": ItemStdvar,
"topk": ItemTopK,
"bottomk": ItemBottomK,
"count_values": ItemCountValues,
"quantile": ItemQuantile,
// Keywords.
"offset": itemOffset,
"by": itemBy,
"without": itemWithout,
"on": itemOn,
"ignoring": itemIgnoring,
"group_left": itemGroupLeft,
"group_right": itemGroupRight,
"bool": itemBool,
"offset": ItemOffset,
"by": ItemBy,
"without": ItemWithout,
"on": ItemOn,
"ignoring": ItemIgnoring,
"group_left": ItemGroupLeft,
"group_right": ItemGroupRight,
"bool": ItemBool,
}
// These are the default string representations for common items. It does not
// imply that those are the only character sequences that can be lexed to such an item.
var itemTypeStr = map[ItemType]string{
itemLeftParen: "(",
itemRightParen: ")",
itemLeftBrace: "{",
itemRightBrace: "}",
itemLeftBracket: "[",
itemRightBracket: "]",
itemComma: ",",
itemAssign: "=",
itemColon: ":",
itemSemicolon: ";",
itemBlank: "_",
itemTimes: "x",
itemSpace: "<space>",
ItemLeftParen: "(",
ItemRightParen: ")",
ItemLeftBrace: "{",
ItemRightBrace: "}",
ItemLeftBracket: "[",
ItemRightBracket: "]",
ItemComma: ",",
ItemAssign: "=",
ItemColon: ":",
ItemSemicolon: ";",
ItemBlank: "_",
ItemTimes: "x",
ItemSpace: "<space>",
itemSUB: "-",
itemADD: "+",
itemMUL: "*",
itemMOD: "%",
itemDIV: "/",
itemEQL: "==",
itemNEQ: "!=",
itemLTE: "<=",
itemLSS: "<",
itemGTE: ">=",
itemGTR: ">",
itemEQLRegex: "=~",
itemNEQRegex: "!~",
itemPOW: "^",
ItemSUB: "-",
ItemADD: "+",
ItemMUL: "*",
ItemMOD: "%",
ItemDIV: "/",
ItemEQL: "==",
ItemNEQ: "!=",
ItemLTE: "<=",
ItemLSS: "<",
ItemGTE: ">=",
ItemGTR: ">",
ItemEQLRegex: "=~",
ItemNEQRegex: "!~",
ItemPOW: "^",
}
func init() {
@ -264,8 +264,8 @@ func init() {
itemTypeStr[ty] = s
}
// Special numbers.
key["inf"] = itemNumber
key["nan"] = itemNumber
key["inf"] = ItemNumber
key["nan"] = ItemNumber
}
func (i ItemType) String() string {
@ -279,7 +279,7 @@ func (i item) desc() string {
if _, ok := itemTypeStr[i.typ]; ok {
return i.String()
}
if i.typ == itemEOF {
if i.typ == ItemEOF {
return i.typ.desc()
}
return fmt.Sprintf("%s %s", i.typ.desc(), i)
@ -287,21 +287,21 @@ func (i item) desc() string {
func (i ItemType) desc() string {
switch i {
case itemError:
case ItemError:
return "error"
case itemEOF:
case ItemEOF:
return "end of input"
case itemComment:
case ItemComment:
return "comment"
case itemIdentifier:
case ItemIdentifier:
return "identifier"
case itemMetricIdentifier:
case ItemMetricIdentifier:
return "metric identifier"
case itemString:
case ItemString:
return "string"
case itemNumber:
case ItemNumber:
return "number"
case itemDuration:
case ItemDuration:
return "duration"
}
return fmt.Sprintf("%q", i)
@ -408,7 +408,7 @@ func (l *lexer) linePosition() int {
// errorf returns an error token and terminates the scan by passing
// back a nil pointer that will be the next state, terminating l.nextItem.
func (l *lexer) errorf(format string, args ...interface{}) stateFn {
l.items <- item{itemError, l.start, fmt.Sprintf(format, args...)}
l.items <- item{ItemError, l.start, fmt.Sprintf(format, args...)}
return nil
}
@ -463,52 +463,52 @@ func lexStatements(l *lexer) stateFn {
} else if l.bracketOpen {
return l.errorf("unclosed left bracket")
}
l.emit(itemEOF)
l.emit(ItemEOF)
return nil
case r == ',':
l.emit(itemComma)
l.emit(ItemComma)
case isSpace(r):
return lexSpace
case r == '*':
l.emit(itemMUL)
l.emit(ItemMUL)
case r == '/':
l.emit(itemDIV)
l.emit(ItemDIV)
case r == '%':
l.emit(itemMOD)
l.emit(ItemMOD)
case r == '+':
l.emit(itemADD)
l.emit(ItemADD)
case r == '-':
l.emit(itemSUB)
l.emit(ItemSUB)
case r == '^':
l.emit(itemPOW)
l.emit(ItemPOW)
case r == '=':
if t := l.peek(); t == '=' {
l.next()
l.emit(itemEQL)
l.emit(ItemEQL)
} else if t == '~' {
return l.errorf("unexpected character after '=': %q", t)
} else {
l.emit(itemAssign)
l.emit(ItemAssign)
}
case r == '!':
if t := l.next(); t == '=' {
l.emit(itemNEQ)
l.emit(ItemNEQ)
} else {
return l.errorf("unexpected character after '!': %q", t)
}
case r == '<':
if t := l.peek(); t == '=' {
l.next()
l.emit(itemLTE)
l.emit(ItemLTE)
} else {
l.emit(itemLSS)
l.emit(ItemLSS)
}
case r == '>':
if t := l.peek(); t == '=' {
l.next()
l.emit(itemGTE)
l.emit(ItemGTE)
} else {
l.emit(itemGTR)
l.emit(ItemGTR)
}
case isDigit(r) || (r == '.' && isDigit(l.peek())):
l.backup()
@ -527,21 +527,21 @@ func lexStatements(l *lexer) stateFn {
if l.gotColon {
return l.errorf("unexpected colon %q", r)
}
l.emit(itemColon)
l.emit(ItemColon)
l.gotColon = true
case r == '(':
l.emit(itemLeftParen)
l.emit(ItemLeftParen)
l.parenDepth++
return lexStatements
case r == ')':
l.emit(itemRightParen)
l.emit(ItemRightParen)
l.parenDepth--
if l.parenDepth < 0 {
return l.errorf("unexpected right parenthesis %q", r)
}
return lexStatements
case r == '{':
l.emit(itemLeftBrace)
l.emit(ItemLeftBrace)
l.braceOpen = true
return lexInsideBraces(l)
case r == '[':
@ -549,14 +549,14 @@ func lexStatements(l *lexer) stateFn {
return l.errorf("unexpected left bracket %q", r)
}
l.gotColon = false
l.emit(itemLeftBracket)
l.emit(ItemLeftBracket)
l.bracketOpen = true
return lexDuration
case r == ']':
if !l.bracketOpen {
return l.errorf("unexpected right bracket %q", r)
}
l.emit(itemRightBracket)
l.emit(ItemRightBracket)
l.bracketOpen = false
default:
@ -581,7 +581,7 @@ func lexInsideBraces(l *lexer) stateFn {
l.backup()
return lexIdentifier
case r == ',':
l.emit(itemComma)
l.emit(ItemComma)
case r == '"' || r == '\'':
l.stringOpen = r
return lexString
@ -590,24 +590,24 @@ func lexInsideBraces(l *lexer) stateFn {
return lexRawString
case r == '=':
if l.next() == '~' {
l.emit(itemEQLRegex)
l.emit(ItemEQLRegex)
break
}
l.backup()
l.emit(itemEQL)
l.emit(ItemEQL)
case r == '!':
switch nr := l.next(); {
case nr == '~':
l.emit(itemNEQRegex)
l.emit(ItemNEQRegex)
case nr == '=':
l.emit(itemNEQ)
l.emit(ItemNEQ)
default:
return l.errorf("unexpected character after '!' inside braces: %q", nr)
}
case r == '{':
return l.errorf("unexpected left brace %q", r)
case r == '}':
l.emit(itemRightBrace)
l.emit(ItemRightBrace)
l.braceOpen = false
if l.seriesDesc {
@ -626,16 +626,16 @@ func lexValueSequence(l *lexer) stateFn {
case r == eof:
return lexStatements
case isSpace(r):
l.emit(itemSpace)
l.emit(ItemSpace)
lexSpace(l)
case r == '+':
l.emit(itemADD)
l.emit(ItemADD)
case r == '-':
l.emit(itemSUB)
l.emit(ItemSUB)
case r == 'x':
l.emit(itemTimes)
l.emit(ItemTimes)
case r == '_':
l.emit(itemBlank)
l.emit(ItemBlank)
case isDigit(r) || (r == '.' && isDigit(l.peek())):
l.backup()
lexNumber(l)
@ -730,7 +730,7 @@ Loop:
break Loop
}
}
l.emit(itemString)
l.emit(ItemString)
return lexStatements
}
@ -747,7 +747,7 @@ Loop:
break Loop
}
}
l.emit(itemString)
l.emit(ItemString)
return lexStatements
}
@ -767,7 +767,7 @@ func lexLineComment(l *lexer) stateFn {
r = l.next()
}
l.backup()
l.emit(itemComment)
l.emit(ItemComment)
return lexStatements
}
@ -781,7 +781,7 @@ func lexDuration(l *lexer) stateFn {
return l.errorf("bad duration syntax: %q", l.input[l.start:l.pos])
}
l.backup()
l.emit(itemDuration)
l.emit(ItemDuration)
return lexStatements
}
return l.errorf("bad duration syntax: %q", l.input[l.start:l.pos])
@ -792,14 +792,14 @@ func lexNumber(l *lexer) stateFn {
if !l.scanNumber() {
return l.errorf("bad number syntax: %q", l.input[l.start:l.pos])
}
l.emit(itemNumber)
l.emit(ItemNumber)
return lexStatements
}
// lexNumberOrDuration scans a number or a duration item.
func lexNumberOrDuration(l *lexer) stateFn {
if l.scanNumber() {
l.emit(itemNumber)
l.emit(ItemNumber)
return lexStatements
}
// Next two chars must be a valid unit and a non-alphanumeric.
@ -808,7 +808,7 @@ func lexNumberOrDuration(l *lexer) stateFn {
return l.errorf("bad number or duration syntax: %q", l.input[l.start:l.pos])
}
l.backup()
l.emit(itemDuration)
l.emit(ItemDuration)
return lexStatements
}
return l.errorf("bad number or duration syntax: %q", l.input[l.start:l.pos])
@ -845,7 +845,7 @@ func lexIdentifier(l *lexer) stateFn {
// absorb
}
l.backup()
l.emit(itemIdentifier)
l.emit(ItemIdentifier)
return lexStatements
}
@ -864,9 +864,9 @@ Loop:
if kw, ok := key[strings.ToLower(word)]; ok {
l.emit(kw)
} else if !strings.Contains(word, ":") {
l.emit(itemIdentifier)
l.emit(ItemIdentifier)
} else {
l.emit(itemMetricIdentifier)
l.emit(ItemMetricIdentifier)
}
break Loop
}

View file

@ -35,19 +35,19 @@ var tests = []struct {
tests: []testCase{
{
input: ",",
expected: []item{{itemComma, 0, ","}},
expected: []item{{ItemComma, 0, ","}},
}, {
input: "()",
expected: []item{{itemLeftParen, 0, `(`}, {itemRightParen, 1, `)`}},
expected: []item{{ItemLeftParen, 0, `(`}, {ItemRightParen, 1, `)`}},
}, {
input: "{}",
expected: []item{{itemLeftBrace, 0, `{`}, {itemRightBrace, 1, `}`}},
expected: []item{{ItemLeftBrace, 0, `{`}, {ItemRightBrace, 1, `}`}},
}, {
input: "[5m]",
expected: []item{
{itemLeftBracket, 0, `[`},
{itemDuration, 1, `5m`},
{itemRightBracket, 3, `]`},
{ItemLeftBracket, 0, `[`},
{ItemDuration, 1, `5m`},
{ItemRightBracket, 3, `]`},
},
}, {
input: "\r\n\r",
@ -60,55 +60,55 @@ var tests = []struct {
tests: []testCase{
{
input: "1",
expected: []item{{itemNumber, 0, "1"}},
expected: []item{{ItemNumber, 0, "1"}},
}, {
input: "4.23",
expected: []item{{itemNumber, 0, "4.23"}},
expected: []item{{ItemNumber, 0, "4.23"}},
}, {
input: ".3",
expected: []item{{itemNumber, 0, ".3"}},
expected: []item{{ItemNumber, 0, ".3"}},
}, {
input: "5.",
expected: []item{{itemNumber, 0, "5."}},
expected: []item{{ItemNumber, 0, "5."}},
}, {
input: "NaN",
expected: []item{{itemNumber, 0, "NaN"}},
expected: []item{{ItemNumber, 0, "NaN"}},
}, {
input: "nAN",
expected: []item{{itemNumber, 0, "nAN"}},
expected: []item{{ItemNumber, 0, "nAN"}},
}, {
input: "NaN 123",
expected: []item{{itemNumber, 0, "NaN"}, {itemNumber, 4, "123"}},
expected: []item{{ItemNumber, 0, "NaN"}, {ItemNumber, 4, "123"}},
}, {
input: "NaN123",
expected: []item{{itemIdentifier, 0, "NaN123"}},
expected: []item{{ItemIdentifier, 0, "NaN123"}},
}, {
input: "iNf",
expected: []item{{itemNumber, 0, "iNf"}},
expected: []item{{ItemNumber, 0, "iNf"}},
}, {
input: "Inf",
expected: []item{{itemNumber, 0, "Inf"}},
expected: []item{{ItemNumber, 0, "Inf"}},
}, {
input: "+Inf",
expected: []item{{itemADD, 0, "+"}, {itemNumber, 1, "Inf"}},
expected: []item{{ItemADD, 0, "+"}, {ItemNumber, 1, "Inf"}},
}, {
input: "+Inf 123",
expected: []item{{itemADD, 0, "+"}, {itemNumber, 1, "Inf"}, {itemNumber, 5, "123"}},
expected: []item{{ItemADD, 0, "+"}, {ItemNumber, 1, "Inf"}, {ItemNumber, 5, "123"}},
}, {
input: "-Inf",
expected: []item{{itemSUB, 0, "-"}, {itemNumber, 1, "Inf"}},
expected: []item{{ItemSUB, 0, "-"}, {ItemNumber, 1, "Inf"}},
}, {
input: "Infoo",
expected: []item{{itemIdentifier, 0, "Infoo"}},
expected: []item{{ItemIdentifier, 0, "Infoo"}},
}, {
input: "-Infoo",
expected: []item{{itemSUB, 0, "-"}, {itemIdentifier, 1, "Infoo"}},
expected: []item{{ItemSUB, 0, "-"}, {ItemIdentifier, 1, "Infoo"}},
}, {
input: "-Inf 123",
expected: []item{{itemSUB, 0, "-"}, {itemNumber, 1, "Inf"}, {itemNumber, 5, "123"}},
expected: []item{{ItemSUB, 0, "-"}, {ItemNumber, 1, "Inf"}, {ItemNumber, 5, "123"}},
}, {
input: "0x123",
expected: []item{{itemNumber, 0, "0x123"}},
expected: []item{{ItemNumber, 0, "0x123"}},
},
},
},
@ -117,22 +117,22 @@ var tests = []struct {
tests: []testCase{
{
input: "\"test\\tsequence\"",
expected: []item{{itemString, 0, `"test\tsequence"`}},
expected: []item{{ItemString, 0, `"test\tsequence"`}},
},
{
input: "\"test\\\\.expression\"",
expected: []item{{itemString, 0, `"test\\.expression"`}},
expected: []item{{ItemString, 0, `"test\\.expression"`}},
},
{
input: "\"test\\.expression\"",
expected: []item{
{itemError, 0, "unknown escape sequence U+002E '.'"},
{itemString, 0, `"test\.expression"`},
{ItemError, 0, "unknown escape sequence U+002E '.'"},
{ItemString, 0, `"test\.expression"`},
},
},
{
input: "`test\\.expression`",
expected: []item{{itemString, 0, "`test\\.expression`"}},
expected: []item{{ItemString, 0, "`test\\.expression`"}},
},
{
// See https://github.com/prometheus/prometheus/issues/939.
@ -146,19 +146,19 @@ var tests = []struct {
tests: []testCase{
{
input: "5s",
expected: []item{{itemDuration, 0, "5s"}},
expected: []item{{ItemDuration, 0, "5s"}},
}, {
input: "123m",
expected: []item{{itemDuration, 0, "123m"}},
expected: []item{{ItemDuration, 0, "123m"}},
}, {
input: "1h",
expected: []item{{itemDuration, 0, "1h"}},
expected: []item{{ItemDuration, 0, "1h"}},
}, {
input: "3w",
expected: []item{{itemDuration, 0, "3w"}},
expected: []item{{ItemDuration, 0, "3w"}},
}, {
input: "1y",
expected: []item{{itemDuration, 0, "1y"}},
expected: []item{{ItemDuration, 0, "1y"}},
},
},
},
@ -167,16 +167,16 @@ var tests = []struct {
tests: []testCase{
{
input: "abc",
expected: []item{{itemIdentifier, 0, "abc"}},
expected: []item{{ItemIdentifier, 0, "abc"}},
}, {
input: "a:bc",
expected: []item{{itemMetricIdentifier, 0, "a:bc"}},
expected: []item{{ItemMetricIdentifier, 0, "a:bc"}},
}, {
input: "abc d",
expected: []item{{itemIdentifier, 0, "abc"}, {itemIdentifier, 4, "d"}},
expected: []item{{ItemIdentifier, 0, "abc"}, {ItemIdentifier, 4, "d"}},
}, {
input: ":bc",
expected: []item{{itemMetricIdentifier, 0, ":bc"}},
expected: []item{{ItemMetricIdentifier, 0, ":bc"}},
}, {
input: "0a:bc",
fail: true,
@ -188,13 +188,13 @@ var tests = []struct {
tests: []testCase{
{
input: "# some comment",
expected: []item{{itemComment, 0, "# some comment"}},
expected: []item{{ItemComment, 0, "# some comment"}},
}, {
input: "5 # 1+1\n5",
expected: []item{
{itemNumber, 0, "5"},
{itemComment, 2, "# 1+1"},
{itemNumber, 8, "5"},
{ItemNumber, 0, "5"},
{ItemComment, 2, "# 1+1"},
{ItemNumber, 8, "5"},
},
},
},
@ -204,56 +204,56 @@ var tests = []struct {
tests: []testCase{
{
input: `=`,
expected: []item{{itemAssign, 0, `=`}},
expected: []item{{ItemAssign, 0, `=`}},
}, {
// Inside braces equality is a single '=' character.
input: `{=}`,
expected: []item{{itemLeftBrace, 0, `{`}, {itemEQL, 1, `=`}, {itemRightBrace, 2, `}`}},
expected: []item{{ItemLeftBrace, 0, `{`}, {ItemEQL, 1, `=`}, {ItemRightBrace, 2, `}`}},
}, {
input: `==`,
expected: []item{{itemEQL, 0, `==`}},
expected: []item{{ItemEQL, 0, `==`}},
}, {
input: `!=`,
expected: []item{{itemNEQ, 0, `!=`}},
expected: []item{{ItemNEQ, 0, `!=`}},
}, {
input: `<`,
expected: []item{{itemLSS, 0, `<`}},
expected: []item{{ItemLSS, 0, `<`}},
}, {
input: `>`,
expected: []item{{itemGTR, 0, `>`}},
expected: []item{{ItemGTR, 0, `>`}},
}, {
input: `>=`,
expected: []item{{itemGTE, 0, `>=`}},
expected: []item{{ItemGTE, 0, `>=`}},
}, {
input: `<=`,
expected: []item{{itemLTE, 0, `<=`}},
expected: []item{{ItemLTE, 0, `<=`}},
}, {
input: `+`,
expected: []item{{itemADD, 0, `+`}},
expected: []item{{ItemADD, 0, `+`}},
}, {
input: `-`,
expected: []item{{itemSUB, 0, `-`}},
expected: []item{{ItemSUB, 0, `-`}},
}, {
input: `*`,
expected: []item{{itemMUL, 0, `*`}},
expected: []item{{ItemMUL, 0, `*`}},
}, {
input: `/`,
expected: []item{{itemDIV, 0, `/`}},
expected: []item{{ItemDIV, 0, `/`}},
}, {
input: `^`,
expected: []item{{itemPOW, 0, `^`}},
expected: []item{{ItemPOW, 0, `^`}},
}, {
input: `%`,
expected: []item{{itemMOD, 0, `%`}},
expected: []item{{ItemMOD, 0, `%`}},
}, {
input: `AND`,
expected: []item{{itemLAND, 0, `AND`}},
expected: []item{{ItemLAND, 0, `AND`}},
}, {
input: `or`,
expected: []item{{itemLOR, 0, `or`}},
expected: []item{{ItemLOR, 0, `or`}},
}, {
input: `unless`,
expected: []item{{itemLUnless, 0, `unless`}},
expected: []item{{ItemLUnless, 0, `unless`}},
},
},
},
@ -262,25 +262,25 @@ var tests = []struct {
tests: []testCase{
{
input: `sum`,
expected: []item{{itemSum, 0, `sum`}},
expected: []item{{ItemSum, 0, `sum`}},
}, {
input: `AVG`,
expected: []item{{itemAvg, 0, `AVG`}},
expected: []item{{ItemAvg, 0, `AVG`}},
}, {
input: `MAX`,
expected: []item{{itemMax, 0, `MAX`}},
expected: []item{{ItemMax, 0, `MAX`}},
}, {
input: `min`,
expected: []item{{itemMin, 0, `min`}},
expected: []item{{ItemMin, 0, `min`}},
}, {
input: `count`,
expected: []item{{itemCount, 0, `count`}},
expected: []item{{ItemCount, 0, `count`}},
}, {
input: `stdvar`,
expected: []item{{itemStdvar, 0, `stdvar`}},
expected: []item{{ItemStdvar, 0, `stdvar`}},
}, {
input: `stddev`,
expected: []item{{itemStddev, 0, `stddev`}},
expected: []item{{ItemStddev, 0, `stddev`}},
},
},
},
@ -289,28 +289,28 @@ var tests = []struct {
tests: []testCase{
{
input: "offset",
expected: []item{{itemOffset, 0, "offset"}},
expected: []item{{ItemOffset, 0, "offset"}},
}, {
input: "by",
expected: []item{{itemBy, 0, "by"}},
expected: []item{{ItemBy, 0, "by"}},
}, {
input: "without",
expected: []item{{itemWithout, 0, "without"}},
expected: []item{{ItemWithout, 0, "without"}},
}, {
input: "on",
expected: []item{{itemOn, 0, "on"}},
expected: []item{{ItemOn, 0, "on"}},
}, {
input: "ignoring",
expected: []item{{itemIgnoring, 0, "ignoring"}},
expected: []item{{ItemIgnoring, 0, "ignoring"}},
}, {
input: "group_left",
expected: []item{{itemGroupLeft, 0, "group_left"}},
expected: []item{{ItemGroupLeft, 0, "group_left"}},
}, {
input: "group_right",
expected: []item{{itemGroupRight, 0, "group_right"}},
expected: []item{{ItemGroupRight, 0, "group_right"}},
}, {
input: "bool",
expected: []item{{itemBool, 0, "bool"}},
expected: []item{{ItemBool, 0, "bool"}},
},
},
},
@ -329,56 +329,56 @@ var tests = []struct {
}, {
input: `{foo='bar'}`,
expected: []item{
{itemLeftBrace, 0, `{`},
{itemIdentifier, 1, `foo`},
{itemEQL, 4, `=`},
{itemString, 5, `'bar'`},
{itemRightBrace, 10, `}`},
{ItemLeftBrace, 0, `{`},
{ItemIdentifier, 1, `foo`},
{ItemEQL, 4, `=`},
{ItemString, 5, `'bar'`},
{ItemRightBrace, 10, `}`},
},
}, {
input: `{foo="bar"}`,
expected: []item{
{itemLeftBrace, 0, `{`},
{itemIdentifier, 1, `foo`},
{itemEQL, 4, `=`},
{itemString, 5, `"bar"`},
{itemRightBrace, 10, `}`},
{ItemLeftBrace, 0, `{`},
{ItemIdentifier, 1, `foo`},
{ItemEQL, 4, `=`},
{ItemString, 5, `"bar"`},
{ItemRightBrace, 10, `}`},
},
}, {
input: `{foo="bar\"bar"}`,
expected: []item{
{itemLeftBrace, 0, `{`},
{itemIdentifier, 1, `foo`},
{itemEQL, 4, `=`},
{itemString, 5, `"bar\"bar"`},
{itemRightBrace, 15, `}`},
{ItemLeftBrace, 0, `{`},
{ItemIdentifier, 1, `foo`},
{ItemEQL, 4, `=`},
{ItemString, 5, `"bar\"bar"`},
{ItemRightBrace, 15, `}`},
},
}, {
input: `{NaN != "bar" }`,
expected: []item{
{itemLeftBrace, 0, `{`},
{itemIdentifier, 1, `NaN`},
{itemNEQ, 5, `!=`},
{itemString, 8, `"bar"`},
{itemRightBrace, 14, `}`},
{ItemLeftBrace, 0, `{`},
{ItemIdentifier, 1, `NaN`},
{ItemNEQ, 5, `!=`},
{ItemString, 8, `"bar"`},
{ItemRightBrace, 14, `}`},
},
}, {
input: `{alert=~"bar" }`,
expected: []item{
{itemLeftBrace, 0, `{`},
{itemIdentifier, 1, `alert`},
{itemEQLRegex, 6, `=~`},
{itemString, 8, `"bar"`},
{itemRightBrace, 14, `}`},
{ItemLeftBrace, 0, `{`},
{ItemIdentifier, 1, `alert`},
{ItemEQLRegex, 6, `=~`},
{ItemString, 8, `"bar"`},
{ItemRightBrace, 14, `}`},
},
}, {
input: `{on!~"bar"}`,
expected: []item{
{itemLeftBrace, 0, `{`},
{itemIdentifier, 1, `on`},
{itemNEQRegex, 3, `!~`},
{itemString, 5, `"bar"`},
{itemRightBrace, 10, `}`},
{ItemLeftBrace, 0, `{`},
{ItemIdentifier, 1, `on`},
{ItemNEQRegex, 3, `!~`},
{ItemString, 5, `"bar"`},
{ItemRightBrace, 10, `}`},
},
}, {
input: `{alert!#"bar"}`, fail: true,
@ -448,43 +448,43 @@ var tests = []struct {
{
input: `{} _ 1 x .3`,
expected: []item{
{itemLeftBrace, 0, `{`},
{itemRightBrace, 1, `}`},
{itemSpace, 2, ` `},
{itemBlank, 3, `_`},
{itemSpace, 4, ` `},
{itemNumber, 5, `1`},
{itemSpace, 6, ` `},
{itemTimes, 7, `x`},
{itemSpace, 8, ` `},
{itemNumber, 9, `.3`},
{ItemLeftBrace, 0, `{`},
{ItemRightBrace, 1, `}`},
{ItemSpace, 2, ` `},
{ItemBlank, 3, `_`},
{ItemSpace, 4, ` `},
{ItemNumber, 5, `1`},
{ItemSpace, 6, ` `},
{ItemTimes, 7, `x`},
{ItemSpace, 8, ` `},
{ItemNumber, 9, `.3`},
},
seriesDesc: true,
},
{
input: `metric +Inf Inf NaN`,
expected: []item{
{itemIdentifier, 0, `metric`},
{itemSpace, 6, ` `},
{itemADD, 7, `+`},
{itemNumber, 8, `Inf`},
{itemSpace, 11, ` `},
{itemNumber, 12, `Inf`},
{itemSpace, 15, ` `},
{itemNumber, 16, `NaN`},
{ItemIdentifier, 0, `metric`},
{ItemSpace, 6, ` `},
{ItemADD, 7, `+`},
{ItemNumber, 8, `Inf`},
{ItemSpace, 11, ` `},
{ItemNumber, 12, `Inf`},
{ItemSpace, 15, ` `},
{ItemNumber, 16, `NaN`},
},
seriesDesc: true,
},
{
input: `metric 1+1x4`,
expected: []item{
{itemIdentifier, 0, `metric`},
{itemSpace, 6, ` `},
{itemNumber, 7, `1`},
{itemADD, 8, `+`},
{itemNumber, 9, `1`},
{itemTimes, 10, `x`},
{itemNumber, 11, `4`},
{ItemIdentifier, 0, `metric`},
{ItemSpace, 6, ` `},
{ItemNumber, 7, `1`},
{ItemADD, 8, `+`},
{ItemNumber, 9, `1`},
{ItemTimes, 10, `x`},
{ItemNumber, 11, `4`},
},
seriesDesc: true,
},
@ -496,141 +496,141 @@ var tests = []struct {
{
input: `test_name{on!~"bar"}[4m:4s]`,
expected: []item{
{itemIdentifier, 0, `test_name`},
{itemLeftBrace, 9, `{`},
{itemIdentifier, 10, `on`},
{itemNEQRegex, 12, `!~`},
{itemString, 14, `"bar"`},
{itemRightBrace, 19, `}`},
{itemLeftBracket, 20, `[`},
{itemDuration, 21, `4m`},
{itemColon, 23, `:`},
{itemDuration, 24, `4s`},
{itemRightBracket, 26, `]`},
{ItemIdentifier, 0, `test_name`},
{ItemLeftBrace, 9, `{`},
{ItemIdentifier, 10, `on`},
{ItemNEQRegex, 12, `!~`},
{ItemString, 14, `"bar"`},
{ItemRightBrace, 19, `}`},
{ItemLeftBracket, 20, `[`},
{ItemDuration, 21, `4m`},
{ItemColon, 23, `:`},
{ItemDuration, 24, `4s`},
{ItemRightBracket, 26, `]`},
},
},
{
input: `test:name{on!~"bar"}[4m:4s]`,
expected: []item{
{itemMetricIdentifier, 0, `test:name`},
{itemLeftBrace, 9, `{`},
{itemIdentifier, 10, `on`},
{itemNEQRegex, 12, `!~`},
{itemString, 14, `"bar"`},
{itemRightBrace, 19, `}`},
{itemLeftBracket, 20, `[`},
{itemDuration, 21, `4m`},
{itemColon, 23, `:`},
{itemDuration, 24, `4s`},
{itemRightBracket, 26, `]`},
{ItemMetricIdentifier, 0, `test:name`},
{ItemLeftBrace, 9, `{`},
{ItemIdentifier, 10, `on`},
{ItemNEQRegex, 12, `!~`},
{ItemString, 14, `"bar"`},
{ItemRightBrace, 19, `}`},
{ItemLeftBracket, 20, `[`},
{ItemDuration, 21, `4m`},
{ItemColon, 23, `:`},
{ItemDuration, 24, `4s`},
{ItemRightBracket, 26, `]`},
},
}, {
input: `test:name{on!~"b:ar"}[4m:4s]`,
expected: []item{
{itemMetricIdentifier, 0, `test:name`},
{itemLeftBrace, 9, `{`},
{itemIdentifier, 10, `on`},
{itemNEQRegex, 12, `!~`},
{itemString, 14, `"b:ar"`},
{itemRightBrace, 20, `}`},
{itemLeftBracket, 21, `[`},
{itemDuration, 22, `4m`},
{itemColon, 24, `:`},
{itemDuration, 25, `4s`},
{itemRightBracket, 27, `]`},
{ItemMetricIdentifier, 0, `test:name`},
{ItemLeftBrace, 9, `{`},
{ItemIdentifier, 10, `on`},
{ItemNEQRegex, 12, `!~`},
{ItemString, 14, `"b:ar"`},
{ItemRightBrace, 20, `}`},
{ItemLeftBracket, 21, `[`},
{ItemDuration, 22, `4m`},
{ItemColon, 24, `:`},
{ItemDuration, 25, `4s`},
{ItemRightBracket, 27, `]`},
},
}, {
input: `test:name{on!~"b:ar"}[4m:]`,
expected: []item{
{itemMetricIdentifier, 0, `test:name`},
{itemLeftBrace, 9, `{`},
{itemIdentifier, 10, `on`},
{itemNEQRegex, 12, `!~`},
{itemString, 14, `"b:ar"`},
{itemRightBrace, 20, `}`},
{itemLeftBracket, 21, `[`},
{itemDuration, 22, `4m`},
{itemColon, 24, `:`},
{itemRightBracket, 25, `]`},
{ItemMetricIdentifier, 0, `test:name`},
{ItemLeftBrace, 9, `{`},
{ItemIdentifier, 10, `on`},
{ItemNEQRegex, 12, `!~`},
{ItemString, 14, `"b:ar"`},
{ItemRightBrace, 20, `}`},
{ItemLeftBracket, 21, `[`},
{ItemDuration, 22, `4m`},
{ItemColon, 24, `:`},
{ItemRightBracket, 25, `]`},
},
}, { // Nested Subquery.
input: `min_over_time(rate(foo{bar="baz"}[2s])[5m:])[4m:3s]`,
expected: []item{
{itemIdentifier, 0, `min_over_time`},
{itemLeftParen, 13, `(`},
{itemIdentifier, 14, `rate`},
{itemLeftParen, 18, `(`},
{itemIdentifier, 19, `foo`},
{itemLeftBrace, 22, `{`},
{itemIdentifier, 23, `bar`},
{itemEQL, 26, `=`},
{itemString, 27, `"baz"`},
{itemRightBrace, 32, `}`},
{itemLeftBracket, 33, `[`},
{itemDuration, 34, `2s`},
{itemRightBracket, 36, `]`},
{itemRightParen, 37, `)`},
{itemLeftBracket, 38, `[`},
{itemDuration, 39, `5m`},
{itemColon, 41, `:`},
{itemRightBracket, 42, `]`},
{itemRightParen, 43, `)`},
{itemLeftBracket, 44, `[`},
{itemDuration, 45, `4m`},
{itemColon, 47, `:`},
{itemDuration, 48, `3s`},
{itemRightBracket, 50, `]`},
{ItemIdentifier, 0, `min_over_time`},
{ItemLeftParen, 13, `(`},
{ItemIdentifier, 14, `rate`},
{ItemLeftParen, 18, `(`},
{ItemIdentifier, 19, `foo`},
{ItemLeftBrace, 22, `{`},
{ItemIdentifier, 23, `bar`},
{ItemEQL, 26, `=`},
{ItemString, 27, `"baz"`},
{ItemRightBrace, 32, `}`},
{ItemLeftBracket, 33, `[`},
{ItemDuration, 34, `2s`},
{ItemRightBracket, 36, `]`},
{ItemRightParen, 37, `)`},
{ItemLeftBracket, 38, `[`},
{ItemDuration, 39, `5m`},
{ItemColon, 41, `:`},
{ItemRightBracket, 42, `]`},
{ItemRightParen, 43, `)`},
{ItemLeftBracket, 44, `[`},
{ItemDuration, 45, `4m`},
{ItemColon, 47, `:`},
{ItemDuration, 48, `3s`},
{ItemRightBracket, 50, `]`},
},
},
// Subquery with offset.
{
input: `test:name{on!~"b:ar"}[4m:4s] offset 10m`,
expected: []item{
{itemMetricIdentifier, 0, `test:name`},
{itemLeftBrace, 9, `{`},
{itemIdentifier, 10, `on`},
{itemNEQRegex, 12, `!~`},
{itemString, 14, `"b:ar"`},
{itemRightBrace, 20, `}`},
{itemLeftBracket, 21, `[`},
{itemDuration, 22, `4m`},
{itemColon, 24, `:`},
{itemDuration, 25, `4s`},
{itemRightBracket, 27, `]`},
{itemOffset, 29, "offset"},
{itemDuration, 36, "10m"},
{ItemMetricIdentifier, 0, `test:name`},
{ItemLeftBrace, 9, `{`},
{ItemIdentifier, 10, `on`},
{ItemNEQRegex, 12, `!~`},
{ItemString, 14, `"b:ar"`},
{ItemRightBrace, 20, `}`},
{ItemLeftBracket, 21, `[`},
{ItemDuration, 22, `4m`},
{ItemColon, 24, `:`},
{ItemDuration, 25, `4s`},
{ItemRightBracket, 27, `]`},
{ItemOffset, 29, "offset"},
{ItemDuration, 36, "10m"},
},
}, {
input: `min_over_time(rate(foo{bar="baz"}[2s])[5m:] offset 6m)[4m:3s]`,
expected: []item{
{itemIdentifier, 0, `min_over_time`},
{itemLeftParen, 13, `(`},
{itemIdentifier, 14, `rate`},
{itemLeftParen, 18, `(`},
{itemIdentifier, 19, `foo`},
{itemLeftBrace, 22, `{`},
{itemIdentifier, 23, `bar`},
{itemEQL, 26, `=`},
{itemString, 27, `"baz"`},
{itemRightBrace, 32, `}`},
{itemLeftBracket, 33, `[`},
{itemDuration, 34, `2s`},
{itemRightBracket, 36, `]`},
{itemRightParen, 37, `)`},
{itemLeftBracket, 38, `[`},
{itemDuration, 39, `5m`},
{itemColon, 41, `:`},
{itemRightBracket, 42, `]`},
{itemOffset, 44, `offset`},
{itemDuration, 51, `6m`},
{itemRightParen, 53, `)`},
{itemLeftBracket, 54, `[`},
{itemDuration, 55, `4m`},
{itemColon, 57, `:`},
{itemDuration, 58, `3s`},
{itemRightBracket, 60, `]`},
{ItemIdentifier, 0, `min_over_time`},
{ItemLeftParen, 13, `(`},
{ItemIdentifier, 14, `rate`},
{ItemLeftParen, 18, `(`},
{ItemIdentifier, 19, `foo`},
{ItemLeftBrace, 22, `{`},
{ItemIdentifier, 23, `bar`},
{ItemEQL, 26, `=`},
{ItemString, 27, `"baz"`},
{ItemRightBrace, 32, `}`},
{ItemLeftBracket, 33, `[`},
{ItemDuration, 34, `2s`},
{ItemRightBracket, 36, `]`},
{ItemRightParen, 37, `)`},
{ItemLeftBracket, 38, `[`},
{ItemDuration, 39, `5m`},
{ItemColon, 41, `:`},
{ItemRightBracket, 42, `]`},
{ItemOffset, 44, `offset`},
{ItemDuration, 51, `6m`},
{ItemRightParen, 53, `)`},
{ItemLeftBracket, 54, `[`},
{ItemDuration, 55, `4m`},
{ItemColon, 57, `:`},
{ItemDuration, 58, `3s`},
{ItemRightBracket, 60, `]`},
},
},
{
@ -677,18 +677,18 @@ func TestLexer(t *testing.T) {
lastItem := out[len(out)-1]
if test.fail {
if lastItem.typ != itemError {
if lastItem.typ != ItemError {
t.Logf("%d: input %q", i, test.input)
t.Fatalf("expected lexing error but did not fail")
}
continue
}
if lastItem.typ == itemError {
if lastItem.typ == ItemError {
t.Logf("%d: input %q", i, test.input)
t.Fatalf("unexpected lexing error at position %d: %s", lastItem.pos, lastItem)
}
if !reflect.DeepEqual(lastItem, item{itemEOF, Pos(len(test.input)), ""}) {
if !reflect.DeepEqual(lastItem, item{ItemEOF, Pos(len(test.input)), ""}) {
t.Logf("%d: input %q", i, test.input)
t.Fatalf("lexing error: expected output to end with EOF item.\ngot:\n%s", expectedList(out))
}

View file

@ -26,7 +26,6 @@ import (
"github.com/prometheus/common/model"
"github.com/prometheus/prometheus/pkg/labels"
"github.com/prometheus/prometheus/pkg/value"
"github.com/prometheus/prometheus/util/strutil"
)
@ -69,7 +68,7 @@ func ParseMetric(input string) (m labels.Labels, err error) {
defer p.recover(&err)
m = p.metric()
if p.peek().typ != itemEOF {
if p.peek().typ != ItemEOF {
p.errorf("could not parse remaining input %.15q...", p.lex.input[p.lex.lastPos:])
}
return m, nil
@ -82,11 +81,11 @@ func ParseMetricSelector(input string) (m []*labels.Matcher, err error) {
defer p.recover(&err)
name := ""
if t := p.peek().typ; t == itemMetricIdentifier || t == itemIdentifier {
if t := p.peek().typ; t == ItemMetricIdentifier || t == ItemIdentifier {
name = p.next().val
}
vs := p.VectorSelector(name)
if p.peek().typ != itemEOF {
if p.peek().typ != ItemEOF {
p.errorf("could not parse remaining input %.15q...", p.lex.input[p.lex.lastPos:])
}
return vs.LabelMatchers, nil
@ -104,8 +103,8 @@ func newParser(input string) *parser {
func (p *parser) parseExpr() (expr Expr, err error) {
defer p.recover(&err)
for p.peek().typ != itemEOF {
if p.peek().typ == itemComment {
for p.peek().typ != ItemEOF {
if p.peek().typ == ItemComment {
continue
}
if expr != nil {
@ -149,20 +148,20 @@ func (p *parser) parseSeriesDesc() (m labels.Labels, vals []sequenceValue, err e
const ctx = "series values"
for {
for p.peek().typ == itemSpace {
for p.peek().typ == ItemSpace {
p.next()
}
if p.peek().typ == itemEOF {
if p.peek().typ == ItemEOF {
break
}
// Extract blanks.
if p.peek().typ == itemBlank {
if p.peek().typ == ItemBlank {
p.next()
times := uint64(1)
if p.peek().typ == itemTimes {
if p.peek().typ == ItemTimes {
p.next()
times, err = strconv.ParseUint(p.expect(itemNumber, ctx).val, 10, 64)
times, err = strconv.ParseUint(p.expect(ItemNumber, ctx).val, 10, 64)
if err != nil {
p.errorf("invalid repetition in %s: %s", ctx, err)
}
@ -172,7 +171,7 @@ func (p *parser) parseSeriesDesc() (m labels.Labels, vals []sequenceValue, err e
}
// This is to ensure that there is a space between this and the next number.
// This is especially required if the next number is negative.
if t := p.expectOneOf(itemSpace, itemEOF, ctx).typ; t == itemEOF {
if t := p.expectOneOf(ItemSpace, ItemEOF, ctx).typ; t == ItemEOF {
break
}
continue
@ -180,15 +179,15 @@ func (p *parser) parseSeriesDesc() (m labels.Labels, vals []sequenceValue, err e
// Extract values.
sign := 1.0
if t := p.peek().typ; t == itemSUB || t == itemADD {
if p.next().typ == itemSUB {
if t := p.peek().typ; t == ItemSUB || t == ItemADD {
if p.next().typ == ItemSUB {
sign = -1
}
}
var k float64
if t := p.peek().typ; t == itemNumber {
k = sign * p.number(p.expect(itemNumber, ctx).val)
} else if t == itemIdentifier && p.peek().val == "stale" {
if t := p.peek().typ; t == ItemNumber {
k = sign * p.number(p.expect(ItemNumber, ctx).val)
} else if t == ItemIdentifier && p.peek().val == "stale" {
p.next()
k = math.Float64frombits(value.StaleNaN)
} else {
@ -199,24 +198,24 @@ func (p *parser) parseSeriesDesc() (m labels.Labels, vals []sequenceValue, err e
})
// If there are no offset repetitions specified, proceed with the next value.
if t := p.peek(); t.typ == itemSpace {
if t := p.peek(); t.typ == ItemSpace {
// This ensures there is a space between every value.
continue
} else if t.typ == itemEOF {
} else if t.typ == ItemEOF {
break
} else if t.typ != itemADD && t.typ != itemSUB {
} else if t.typ != ItemADD && t.typ != ItemSUB {
p.errorf("expected next value or relative expansion in %s but got %s (value: %s)", ctx, t.desc(), p.peek())
}
// Expand the repeated offsets into values.
sign = 1.0
if p.next().typ == itemSUB {
if p.next().typ == ItemSUB {
sign = -1.0
}
offset := sign * p.number(p.expect(itemNumber, ctx).val)
p.expect(itemTimes, ctx)
offset := sign * p.number(p.expect(ItemNumber, ctx).val)
p.expect(ItemTimes, ctx)
times, err := strconv.ParseUint(p.expect(itemNumber, ctx).val, 10, 64)
times, err := strconv.ParseUint(p.expect(ItemNumber, ctx).val, 10, 64)
if err != nil {
p.errorf("invalid repetition in %s: %s", ctx, err)
}
@ -230,7 +229,7 @@ func (p *parser) parseSeriesDesc() (m labels.Labels, vals []sequenceValue, err e
// This is to ensure that there is a space between this expanding notation
// and the next number. This is especially required if the next number
// is negative.
if t := p.expectOneOf(itemSpace, itemEOF, ctx).typ; t == itemEOF {
if t := p.expectOneOf(ItemSpace, ItemEOF, ctx).typ; t == ItemEOF {
break
}
}
@ -252,12 +251,12 @@ func (p *parser) next() item {
} else {
t := p.lex.nextItem()
// Skip comments.
for t.typ == itemComment {
for t.typ == ItemComment {
t = p.lex.nextItem()
}
p.token[0] = t
}
if p.token[p.peekCount].typ == itemError {
if p.token[p.peekCount].typ == ItemError {
p.errorf("%s", p.token[p.peekCount].val)
}
return p.token[p.peekCount]
@ -272,7 +271,7 @@ func (p *parser) peek() item {
t := p.lex.nextItem()
// Skip comments.
for t.typ == itemComment {
for t.typ == ItemComment {
t = p.lex.nextItem()
}
p.token[0] = t
@ -352,11 +351,11 @@ func (p *parser) expr() Expr {
op := p.peek().typ
if !op.isOperator() {
// Check for subquery.
if op == itemLeftBracket {
if op == ItemLeftBracket {
expr = p.subqueryOrRangeSelector(expr, false)
if s, ok := expr.(*SubqueryExpr); ok {
// Parse optional offset.
if p.peek().typ == itemOffset {
if p.peek().typ == ItemOffset {
offset := p.offset()
s.Offset = offset
}
@ -377,7 +376,7 @@ func (p *parser) expr() Expr {
returnBool := false
// Parse bool modifier.
if p.peek().typ == itemBool {
if p.peek().typ == ItemBool {
if !op.isComparisonOperator() {
p.errorf("bool modifier can only be used on comparison operators")
}
@ -386,22 +385,22 @@ func (p *parser) expr() Expr {
}
// Parse ON/IGNORING clause.
if p.peek().typ == itemOn || p.peek().typ == itemIgnoring {
if p.peek().typ == itemOn {
if p.peek().typ == ItemOn || p.peek().typ == ItemIgnoring {
if p.peek().typ == ItemOn {
vecMatching.On = true
}
p.next()
vecMatching.MatchingLabels = p.labels()
// Parse grouping.
if t := p.peek().typ; t == itemGroupLeft || t == itemGroupRight {
if t := p.peek().typ; t == ItemGroupLeft || t == ItemGroupRight {
p.next()
if t == itemGroupLeft {
if t == ItemGroupLeft {
vecMatching.Card = CardManyToOne
} else {
vecMatching.Card = CardOneToMany
}
if p.peek().typ == itemLeftParen {
if p.peek().typ == ItemLeftParen {
vecMatching.Include = p.labels()
}
}
@ -458,35 +457,35 @@ func (p *parser) balance(lhs Expr, op ItemType, rhs Expr, vecMatching *VectorMat
//
func (p *parser) unaryExpr() Expr {
switch t := p.peek(); t.typ {
case itemADD, itemSUB:
case ItemADD, ItemSUB:
p.next()
e := p.unaryExpr()
// Simplify unary expressions for number literals.
if nl, ok := e.(*NumberLiteral); ok {
if t.typ == itemSUB {
if t.typ == ItemSUB {
nl.Val *= -1
}
return nl
}
return &UnaryExpr{Op: t.typ, Expr: e}
case itemLeftParen:
case ItemLeftParen:
p.next()
e := p.expr()
p.expect(itemRightParen, "paren expression")
p.expect(ItemRightParen, "paren expression")
return &ParenExpr{Expr: e}
}
e := p.primaryExpr()
// Expression might be followed by a range selector.
if p.peek().typ == itemLeftBracket {
if p.peek().typ == ItemLeftBracket {
e = p.subqueryOrRangeSelector(e, true)
}
// Parse optional offset.
if p.peek().typ == itemOffset {
if p.peek().typ == ItemOffset {
offset := p.offset()
switch s := e.(type) {
@ -520,7 +519,7 @@ func (p *parser) subqueryOrRangeSelector(expr Expr, checkRange bool) Expr {
var erange time.Duration
var err error
erangeStr := p.expect(itemDuration, ctx).val
erangeStr := p.expect(ItemDuration, ctx).val
erange, err = parseDuration(erangeStr)
if err != nil {
p.error(err)
@ -528,8 +527,8 @@ func (p *parser) subqueryOrRangeSelector(expr Expr, checkRange bool) Expr {
var itm item
if checkRange {
itm = p.expectOneOf(itemRightBracket, itemColon, ctx)
if itm.typ == itemRightBracket {
itm = p.expectOneOf(ItemRightBracket, ItemColon, ctx)
if itm.typ == ItemRightBracket {
// Range selector.
vs, ok := expr.(*VectorSelector)
if !ok {
@ -542,20 +541,20 @@ func (p *parser) subqueryOrRangeSelector(expr Expr, checkRange bool) Expr {
}
}
} else {
itm = p.expect(itemColon, ctx)
itm = p.expect(ItemColon, ctx)
}
// Subquery.
var estep time.Duration
itm = p.expectOneOf(itemRightBracket, itemDuration, ctx)
if itm.typ == itemDuration {
itm = p.expectOneOf(ItemRightBracket, ItemDuration, ctx)
if itm.typ == ItemDuration {
estepStr := itm.val
estep, err = parseDuration(estepStr)
if err != nil {
p.error(err)
}
p.expect(itemRightBracket, ctx)
p.expect(ItemRightBracket, ctx)
}
return &SubqueryExpr{
@ -584,26 +583,26 @@ func (p *parser) number(val string) float64 {
//
func (p *parser) primaryExpr() Expr {
switch t := p.next(); {
case t.typ == itemNumber:
case t.typ == ItemNumber:
f := p.number(t.val)
return &NumberLiteral{f}
case t.typ == itemString:
case t.typ == ItemString:
return &StringLiteral{p.unquoteString(t.val)}
case t.typ == itemLeftBrace:
case t.typ == ItemLeftBrace:
// Metric selector without metric name.
p.backup()
return p.VectorSelector("")
case t.typ == itemIdentifier:
case t.typ == ItemIdentifier:
// Check for function call.
if p.peek().typ == itemLeftParen {
if p.peek().typ == ItemLeftParen {
return p.call(t.val)
}
fallthrough // Else metric selector.
case t.typ == itemMetricIdentifier:
case t.typ == ItemMetricIdentifier:
return p.VectorSelector(t.val)
case t.typ.isAggregator():
@ -623,10 +622,10 @@ func (p *parser) primaryExpr() Expr {
func (p *parser) labels() []string {
const ctx = "grouping opts"
p.expect(itemLeftParen, ctx)
p.expect(ItemLeftParen, ctx)
labels := []string{}
if p.peek().typ != itemRightParen {
if p.peek().typ != ItemRightParen {
for {
id := p.next()
if !isLabel(id.val) {
@ -634,13 +633,13 @@ func (p *parser) labels() []string {
}
labels = append(labels, id.val)
if p.peek().typ != itemComma {
if p.peek().typ != ItemComma {
break
}
p.next()
}
}
p.expect(itemRightParen, ctx)
p.expect(ItemRightParen, ctx)
return labels
}
@ -662,8 +661,8 @@ func (p *parser) aggrExpr() *AggregateExpr {
modifiersFirst := false
if t := p.peek().typ; t == itemBy || t == itemWithout {
if t == itemWithout {
if t := p.peek().typ; t == ItemBy || t == ItemWithout {
if t == ItemWithout {
without = true
}
p.next()
@ -671,21 +670,21 @@ func (p *parser) aggrExpr() *AggregateExpr {
modifiersFirst = true
}
p.expect(itemLeftParen, ctx)
p.expect(ItemLeftParen, ctx)
var param Expr
if agop.typ.isAggregatorWithParam() {
param = p.expr()
p.expect(itemComma, ctx)
p.expect(ItemComma, ctx)
}
e := p.expr()
p.expect(itemRightParen, ctx)
p.expect(ItemRightParen, ctx)
if !modifiersFirst {
if t := p.peek().typ; t == itemBy || t == itemWithout {
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 {
if t == ItemWithout {
without = true
}
p.next()
@ -714,9 +713,9 @@ func (p *parser) call(name string) *Call {
p.errorf("unknown function with name %q", name)
}
p.expect(itemLeftParen, ctx)
p.expect(ItemLeftParen, ctx)
// Might be call without args.
if p.peek().typ == itemRightParen {
if p.peek().typ == ItemRightParen {
p.next() // Consume.
return &Call{fn, nil}
}
@ -727,14 +726,14 @@ func (p *parser) call(name string) *Call {
args = append(args, e)
// Terminate if no more arguments.
if p.peek().typ != itemComma {
if p.peek().typ != ItemComma {
break
}
p.next()
}
// Call must be closed.
p.expect(itemRightParen, ctx)
p.expect(ItemRightParen, ctx)
return &Call{Func: fn, Args: args}
}
@ -745,7 +744,7 @@ func (p *parser) call(name string) *Call {
//
func (p *parser) labelSet() labels.Labels {
set := []labels.Label{}
for _, lm := range p.labelMatchers(itemEQL) {
for _, lm := range p.labelMatchers(ItemEQL) {
set = append(set, labels.Label{Name: lm.Name, Value: lm.Value})
}
return labels.New(set...)
@ -760,16 +759,16 @@ func (p *parser) labelMatchers(operators ...ItemType) []*labels.Matcher {
matchers := []*labels.Matcher{}
p.expect(itemLeftBrace, ctx)
p.expect(ItemLeftBrace, ctx)
// Check if no matchers are provided.
if p.peek().typ == itemRightBrace {
if p.peek().typ == ItemRightBrace {
p.next()
return matchers
}
for {
label := p.expect(itemIdentifier, ctx)
label := p.expect(ItemIdentifier, ctx)
op := p.next().typ
if !op.isOperator() {
@ -785,18 +784,18 @@ func (p *parser) labelMatchers(operators ...ItemType) []*labels.Matcher {
p.errorf("operator must be one of %q, is %q", operators, op)
}
val := p.unquoteString(p.expect(itemString, ctx).val)
val := p.unquoteString(p.expect(ItemString, ctx).val)
// Map the item to the respective match type.
var matchType labels.MatchType
switch op {
case itemEQL:
case ItemEQL:
matchType = labels.MatchEqual
case itemNEQ:
case ItemNEQ:
matchType = labels.MatchNotEqual
case itemEQLRegex:
case ItemEQLRegex:
matchType = labels.MatchRegexp
case itemNEQRegex:
case ItemNEQRegex:
matchType = labels.MatchNotRegexp
default:
p.errorf("item %q is not a metric match type", op)
@ -809,23 +808,23 @@ func (p *parser) labelMatchers(operators ...ItemType) []*labels.Matcher {
matchers = append(matchers, m)
if p.peek().typ == itemIdentifier {
if p.peek().typ == ItemIdentifier {
p.errorf("missing comma before next identifier %q", p.peek().val)
}
// Terminate list if last matcher.
if p.peek().typ != itemComma {
if p.peek().typ != ItemComma {
break
}
p.next()
// Allow comma after each item in a multi-line listing.
if p.peek().typ == itemRightBrace {
if p.peek().typ == ItemRightBrace {
break
}
}
p.expect(itemRightBrace, ctx)
p.expect(ItemRightBrace, ctx)
return matchers
}
@ -840,14 +839,14 @@ func (p *parser) metric() labels.Labels {
var m labels.Labels
t := p.peek().typ
if t == itemIdentifier || t == itemMetricIdentifier {
if t == ItemIdentifier || t == ItemMetricIdentifier {
name = p.next().val
t = p.peek().typ
}
if t != itemLeftBrace && name == "" {
if t != ItemLeftBrace && name == "" {
p.errorf("missing metric name or metric selector")
}
if t == itemLeftBrace {
if t == ItemLeftBrace {
m = p.labelSet()
}
if name != "" {
@ -865,7 +864,7 @@ func (p *parser) offset() time.Duration {
const ctx = "offset"
p.next()
offi := p.expect(itemDuration, ctx)
offi := p.expect(ItemDuration, ctx)
offset, err := parseDuration(offi.val)
if err != nil {
@ -883,8 +882,8 @@ func (p *parser) offset() time.Duration {
func (p *parser) VectorSelector(name string) *VectorSelector {
var matchers []*labels.Matcher
// Parse label matching if any.
if t := p.peek(); t.typ == itemLeftBrace {
matchers = p.labelMatchers(itemEQL, itemNEQ, itemEQLRegex, itemNEQRegex)
if t := p.peek(); t.typ == ItemLeftBrace {
matchers = p.labelMatchers(ItemEQL, ItemNEQ, ItemEQLRegex, ItemNEQRegex)
}
// Metric name must not be set in the label matchers and before at the same time.
if name != "" {
@ -970,10 +969,10 @@ func (p *parser) checkType(node Node) (typ ValueType) {
p.errorf("aggregation operator expected in aggregation expression but got %q", n.Op)
}
p.expectType(n.Expr, ValueTypeVector, "aggregation expression")
if n.Op == itemTopK || n.Op == itemBottomK || n.Op == itemQuantile {
if n.Op == ItemTopK || n.Op == ItemBottomK || n.Op == ItemQuantile {
p.expectType(n.Param, ValueTypeScalar, "aggregation parameter")
}
if n.Op == itemCountValues {
if n.Op == ItemCountValues {
p.expectType(n.Param, ValueTypeString, "aggregation parameter")
}
@ -1035,7 +1034,7 @@ func (p *parser) checkType(node Node) (typ ValueType) {
p.checkType(n.Expr)
case *UnaryExpr:
if n.Op != itemADD && n.Op != itemSUB {
if n.Op != ItemADD && n.Op != ItemSUB {
p.errorf("only + and - operators allowed for unary expressions")
}
if t := p.checkType(n.Expr); t != ValueTypeScalar && t != ValueTypeVector {

View file

@ -71,77 +71,77 @@ var testExpr = []struct {
expected: &NumberLiteral{-493},
}, {
input: "1 + 1",
expected: &BinaryExpr{itemADD, &NumberLiteral{1}, &NumberLiteral{1}, nil, false},
expected: &BinaryExpr{ItemADD, &NumberLiteral{1}, &NumberLiteral{1}, nil, false},
}, {
input: "1 - 1",
expected: &BinaryExpr{itemSUB, &NumberLiteral{1}, &NumberLiteral{1}, nil, false},
expected: &BinaryExpr{ItemSUB, &NumberLiteral{1}, &NumberLiteral{1}, nil, false},
}, {
input: "1 * 1",
expected: &BinaryExpr{itemMUL, &NumberLiteral{1}, &NumberLiteral{1}, nil, false},
expected: &BinaryExpr{ItemMUL, &NumberLiteral{1}, &NumberLiteral{1}, nil, false},
}, {
input: "1 % 1",
expected: &BinaryExpr{itemMOD, &NumberLiteral{1}, &NumberLiteral{1}, nil, false},
expected: &BinaryExpr{ItemMOD, &NumberLiteral{1}, &NumberLiteral{1}, nil, false},
}, {
input: "1 / 1",
expected: &BinaryExpr{itemDIV, &NumberLiteral{1}, &NumberLiteral{1}, nil, false},
expected: &BinaryExpr{ItemDIV, &NumberLiteral{1}, &NumberLiteral{1}, nil, false},
}, {
input: "1 == bool 1",
expected: &BinaryExpr{itemEQL, &NumberLiteral{1}, &NumberLiteral{1}, nil, true},
expected: &BinaryExpr{ItemEQL, &NumberLiteral{1}, &NumberLiteral{1}, nil, true},
}, {
input: "1 != bool 1",
expected: &BinaryExpr{itemNEQ, &NumberLiteral{1}, &NumberLiteral{1}, nil, true},
expected: &BinaryExpr{ItemNEQ, &NumberLiteral{1}, &NumberLiteral{1}, nil, true},
}, {
input: "1 > bool 1",
expected: &BinaryExpr{itemGTR, &NumberLiteral{1}, &NumberLiteral{1}, nil, true},
expected: &BinaryExpr{ItemGTR, &NumberLiteral{1}, &NumberLiteral{1}, nil, true},
}, {
input: "1 >= bool 1",
expected: &BinaryExpr{itemGTE, &NumberLiteral{1}, &NumberLiteral{1}, nil, true},
expected: &BinaryExpr{ItemGTE, &NumberLiteral{1}, &NumberLiteral{1}, nil, true},
}, {
input: "1 < bool 1",
expected: &BinaryExpr{itemLSS, &NumberLiteral{1}, &NumberLiteral{1}, nil, true},
expected: &BinaryExpr{ItemLSS, &NumberLiteral{1}, &NumberLiteral{1}, nil, true},
}, {
input: "1 <= bool 1",
expected: &BinaryExpr{itemLTE, &NumberLiteral{1}, &NumberLiteral{1}, nil, true},
expected: &BinaryExpr{ItemLTE, &NumberLiteral{1}, &NumberLiteral{1}, nil, true},
}, {
input: "+1 + -2 * 1",
expected: &BinaryExpr{
Op: itemADD,
Op: ItemADD,
LHS: &NumberLiteral{1},
RHS: &BinaryExpr{
Op: itemMUL, LHS: &NumberLiteral{-2}, RHS: &NumberLiteral{1},
Op: ItemMUL, LHS: &NumberLiteral{-2}, RHS: &NumberLiteral{1},
},
},
}, {
input: "1 + 2/(3*1)",
expected: &BinaryExpr{
Op: itemADD,
Op: ItemADD,
LHS: &NumberLiteral{1},
RHS: &BinaryExpr{
Op: itemDIV,
Op: ItemDIV,
LHS: &NumberLiteral{2},
RHS: &ParenExpr{&BinaryExpr{
Op: itemMUL, LHS: &NumberLiteral{3}, RHS: &NumberLiteral{1},
Op: ItemMUL, LHS: &NumberLiteral{3}, RHS: &NumberLiteral{1},
}},
},
},
}, {
input: "1 < bool 2 - 1 * 2",
expected: &BinaryExpr{
Op: itemLSS,
Op: ItemLSS,
ReturnBool: true,
LHS: &NumberLiteral{1},
RHS: &BinaryExpr{
Op: itemSUB,
Op: ItemSUB,
LHS: &NumberLiteral{2},
RHS: &BinaryExpr{
Op: itemMUL, LHS: &NumberLiteral{1}, RHS: &NumberLiteral{2},
Op: ItemMUL, LHS: &NumberLiteral{1}, RHS: &NumberLiteral{2},
},
},
},
}, {
input: "-some_metric",
expected: &UnaryExpr{
Op: itemSUB,
Op: ItemSUB,
Expr: &VectorSelector{
Name: "some_metric",
LabelMatchers: []*labels.Matcher{
@ -152,7 +152,7 @@ var testExpr = []struct {
}, {
input: "+some_metric",
expected: &UnaryExpr{
Op: itemADD,
Op: ItemADD,
Expr: &VectorSelector{
Name: "some_metric",
LabelMatchers: []*labels.Matcher{
@ -261,7 +261,7 @@ var testExpr = []struct {
{
input: "foo * bar",
expected: &BinaryExpr{
Op: itemMUL,
Op: ItemMUL,
LHS: &VectorSelector{
Name: "foo",
LabelMatchers: []*labels.Matcher{
@ -279,7 +279,7 @@ var testExpr = []struct {
}, {
input: "foo == 1",
expected: &BinaryExpr{
Op: itemEQL,
Op: ItemEQL,
LHS: &VectorSelector{
Name: "foo",
LabelMatchers: []*labels.Matcher{
@ -291,7 +291,7 @@ var testExpr = []struct {
}, {
input: "foo == bool 1",
expected: &BinaryExpr{
Op: itemEQL,
Op: ItemEQL,
LHS: &VectorSelector{
Name: "foo",
LabelMatchers: []*labels.Matcher{
@ -304,7 +304,7 @@ var testExpr = []struct {
}, {
input: "2.5 / bar",
expected: &BinaryExpr{
Op: itemDIV,
Op: ItemDIV,
LHS: &NumberLiteral{2.5},
RHS: &VectorSelector{
Name: "bar",
@ -316,7 +316,7 @@ var testExpr = []struct {
}, {
input: "foo and bar",
expected: &BinaryExpr{
Op: itemLAND,
Op: ItemLAND,
LHS: &VectorSelector{
Name: "foo",
LabelMatchers: []*labels.Matcher{
@ -334,7 +334,7 @@ var testExpr = []struct {
}, {
input: "foo or bar",
expected: &BinaryExpr{
Op: itemLOR,
Op: ItemLOR,
LHS: &VectorSelector{
Name: "foo",
LabelMatchers: []*labels.Matcher{
@ -352,7 +352,7 @@ var testExpr = []struct {
}, {
input: "foo unless bar",
expected: &BinaryExpr{
Op: itemLUnless,
Op: ItemLUnless,
LHS: &VectorSelector{
Name: "foo",
LabelMatchers: []*labels.Matcher{
@ -371,9 +371,9 @@ var testExpr = []struct {
// Test and/or precedence and reassigning of operands.
input: "foo + bar or bla and blub",
expected: &BinaryExpr{
Op: itemLOR,
Op: ItemLOR,
LHS: &BinaryExpr{
Op: itemADD,
Op: ItemADD,
LHS: &VectorSelector{
Name: "foo",
LabelMatchers: []*labels.Matcher{
@ -389,7 +389,7 @@ var testExpr = []struct {
VectorMatching: &VectorMatching{Card: CardOneToOne},
},
RHS: &BinaryExpr{
Op: itemLAND,
Op: ItemLAND,
LHS: &VectorSelector{
Name: "bla",
LabelMatchers: []*labels.Matcher{
@ -410,11 +410,11 @@ var testExpr = []struct {
// Test and/or/unless precedence.
input: "foo and bar unless baz or qux",
expected: &BinaryExpr{
Op: itemLOR,
Op: ItemLOR,
LHS: &BinaryExpr{
Op: itemLUnless,
Op: ItemLUnless,
LHS: &BinaryExpr{
Op: itemLAND,
Op: ItemLAND,
LHS: &VectorSelector{
Name: "foo",
LabelMatchers: []*labels.Matcher{
@ -449,7 +449,7 @@ var testExpr = []struct {
// Test precedence and reassigning of operands.
input: "bar + on(foo) bla / on(baz, buz) group_right(test) blub",
expected: &BinaryExpr{
Op: itemADD,
Op: ItemADD,
LHS: &VectorSelector{
Name: "bar",
LabelMatchers: []*labels.Matcher{
@ -457,7 +457,7 @@ var testExpr = []struct {
},
},
RHS: &BinaryExpr{
Op: itemDIV,
Op: ItemDIV,
LHS: &VectorSelector{
Name: "bla",
LabelMatchers: []*labels.Matcher{
@ -486,7 +486,7 @@ var testExpr = []struct {
}, {
input: "foo * on(test,blub) bar",
expected: &BinaryExpr{
Op: itemMUL,
Op: ItemMUL,
LHS: &VectorSelector{
Name: "foo",
LabelMatchers: []*labels.Matcher{
@ -508,7 +508,7 @@ var testExpr = []struct {
}, {
input: "foo * on(test,blub) group_left bar",
expected: &BinaryExpr{
Op: itemMUL,
Op: ItemMUL,
LHS: &VectorSelector{
Name: "foo",
LabelMatchers: []*labels.Matcher{
@ -530,7 +530,7 @@ var testExpr = []struct {
}, {
input: "foo and on(test,blub) bar",
expected: &BinaryExpr{
Op: itemLAND,
Op: ItemLAND,
LHS: &VectorSelector{
Name: "foo",
LabelMatchers: []*labels.Matcher{
@ -552,7 +552,7 @@ var testExpr = []struct {
}, {
input: "foo and on() bar",
expected: &BinaryExpr{
Op: itemLAND,
Op: ItemLAND,
LHS: &VectorSelector{
Name: "foo",
LabelMatchers: []*labels.Matcher{
@ -574,7 +574,7 @@ var testExpr = []struct {
}, {
input: "foo and ignoring(test,blub) bar",
expected: &BinaryExpr{
Op: itemLAND,
Op: ItemLAND,
LHS: &VectorSelector{
Name: "foo",
LabelMatchers: []*labels.Matcher{
@ -595,7 +595,7 @@ var testExpr = []struct {
}, {
input: "foo and ignoring() bar",
expected: &BinaryExpr{
Op: itemLAND,
Op: ItemLAND,
LHS: &VectorSelector{
Name: "foo",
LabelMatchers: []*labels.Matcher{
@ -616,7 +616,7 @@ var testExpr = []struct {
}, {
input: "foo unless on(bar) baz",
expected: &BinaryExpr{
Op: itemLUnless,
Op: ItemLUnless,
LHS: &VectorSelector{
Name: "foo",
LabelMatchers: []*labels.Matcher{
@ -638,7 +638,7 @@ var testExpr = []struct {
}, {
input: "foo / on(test,blub) group_left(bar) bar",
expected: &BinaryExpr{
Op: itemDIV,
Op: ItemDIV,
LHS: &VectorSelector{
Name: "foo",
LabelMatchers: []*labels.Matcher{
@ -661,7 +661,7 @@ var testExpr = []struct {
}, {
input: "foo / ignoring(test,blub) group_left(blub) bar",
expected: &BinaryExpr{
Op: itemDIV,
Op: ItemDIV,
LHS: &VectorSelector{
Name: "foo",
LabelMatchers: []*labels.Matcher{
@ -683,7 +683,7 @@ var testExpr = []struct {
}, {
input: "foo / ignoring(test,blub) group_left(bar) bar",
expected: &BinaryExpr{
Op: itemDIV,
Op: ItemDIV,
LHS: &VectorSelector{
Name: "foo",
LabelMatchers: []*labels.Matcher{
@ -705,7 +705,7 @@ var testExpr = []struct {
}, {
input: "foo - on(test,blub) group_right(bar,foo) bar",
expected: &BinaryExpr{
Op: itemSUB,
Op: ItemSUB,
LHS: &VectorSelector{
Name: "foo",
LabelMatchers: []*labels.Matcher{
@ -728,7 +728,7 @@ var testExpr = []struct {
}, {
input: "foo - ignoring(test,blub) group_right(bar,foo) bar",
expected: &BinaryExpr{
Op: itemSUB,
Op: ItemSUB,
LHS: &VectorSelector{
Name: "foo",
LabelMatchers: []*labels.Matcher{
@ -1057,7 +1057,7 @@ var testExpr = []struct {
{
input: "sum by (foo)(some_metric)",
expected: &AggregateExpr{
Op: itemSum,
Op: ItemSum,
Expr: &VectorSelector{
Name: "some_metric",
LabelMatchers: []*labels.Matcher{
@ -1069,7 +1069,7 @@ var testExpr = []struct {
}, {
input: "avg by (foo)(some_metric)",
expected: &AggregateExpr{
Op: itemAvg,
Op: ItemAvg,
Expr: &VectorSelector{
Name: "some_metric",
LabelMatchers: []*labels.Matcher{
@ -1081,7 +1081,7 @@ var testExpr = []struct {
}, {
input: "max by (foo)(some_metric)",
expected: &AggregateExpr{
Op: itemMax,
Op: ItemMax,
Expr: &VectorSelector{
Name: "some_metric",
LabelMatchers: []*labels.Matcher{
@ -1093,7 +1093,7 @@ var testExpr = []struct {
}, {
input: "sum without (foo) (some_metric)",
expected: &AggregateExpr{
Op: itemSum,
Op: ItemSum,
Without: true,
Expr: &VectorSelector{
Name: "some_metric",
@ -1106,7 +1106,7 @@ var testExpr = []struct {
}, {
input: "sum (some_metric) without (foo)",
expected: &AggregateExpr{
Op: itemSum,
Op: ItemSum,
Without: true,
Expr: &VectorSelector{
Name: "some_metric",
@ -1119,7 +1119,7 @@ var testExpr = []struct {
}, {
input: "stddev(some_metric)",
expected: &AggregateExpr{
Op: itemStddev,
Op: ItemStddev,
Expr: &VectorSelector{
Name: "some_metric",
LabelMatchers: []*labels.Matcher{
@ -1130,7 +1130,7 @@ var testExpr = []struct {
}, {
input: "stdvar by (foo)(some_metric)",
expected: &AggregateExpr{
Op: itemStdvar,
Op: ItemStdvar,
Expr: &VectorSelector{
Name: "some_metric",
LabelMatchers: []*labels.Matcher{
@ -1142,7 +1142,7 @@ var testExpr = []struct {
}, {
input: "sum by ()(some_metric)",
expected: &AggregateExpr{
Op: itemSum,
Op: ItemSum,
Expr: &VectorSelector{
Name: "some_metric",
LabelMatchers: []*labels.Matcher{
@ -1154,7 +1154,7 @@ var testExpr = []struct {
}, {
input: "topk(5, some_metric)",
expected: &AggregateExpr{
Op: itemTopK,
Op: ItemTopK,
Expr: &VectorSelector{
Name: "some_metric",
LabelMatchers: []*labels.Matcher{
@ -1166,7 +1166,7 @@ var testExpr = []struct {
}, {
input: "count_values(\"value\", some_metric)",
expected: &AggregateExpr{
Op: itemCountValues,
Op: ItemCountValues,
Expr: &VectorSelector{
Name: "some_metric",
LabelMatchers: []*labels.Matcher{
@ -1179,7 +1179,7 @@ var testExpr = []struct {
// Test usage of keywords as label names.
input: "sum without(and, by, avg, count, alert, annotations)(some_metric)",
expected: &AggregateExpr{
Op: itemSum,
Op: ItemSum,
Without: true,
Expr: &VectorSelector{
Name: "some_metric",
@ -1494,7 +1494,7 @@ var testExpr = []struct {
input: "sum without(and, by, avg, count, alert, annotations)(some_metric) [30m:10s]",
expected: &SubqueryExpr{
Expr: &AggregateExpr{
Op: itemSum,
Op: ItemSum,
Without: true,
Expr: &VectorSelector{
Name: "some_metric",
@ -1525,7 +1525,7 @@ var testExpr = []struct {
expected: &SubqueryExpr{
Expr: &ParenExpr{
Expr: &BinaryExpr{
Op: itemADD,
Op: ItemADD,
VectorMatching: &VectorMatching{
Card: CardOneToOne,
},
@ -1551,7 +1551,7 @@ var testExpr = []struct {
expected: &SubqueryExpr{
Expr: &ParenExpr{
Expr: &BinaryExpr{
Op: itemADD,
Op: ItemADD,
VectorMatching: &VectorMatching{
Card: CardOneToOne,
},