func lexInsideBraces(l *lexer) stateFn {
	if strings.HasPrefix(l.input[l.pos:], lineComment) {
		return lexLineComment
	}
	switch r := l.next(); {
	case r == eof:
		return l.errorf("unexpected end of input inside braces")
	case isSpace(r):
		return lexSpace
	case isAlpha(r):
		l.backup()
		return lexIdentifier
	case r == ',':
		l.emit(ItemComma)
	case r == '"' || r == '\'':
		l.stringOpen = r
		return lexString
	case r == '`':
		l.stringOpen = r
		return lexRawString
	case r == '=':
		if l.next() == '~' {
			l.emit(ItemEQLRegex)
			break
		}
		l.backup()
		l.emit(ItemEQL)
	case r == '!':
		switch nr := l.next(); {
		case nr == '~':
			l.emit(ItemNEQRegex)
		case nr == '=':
			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.braceOpen = false
		if l.seriesDesc {
			return lexValueSequence
		}
		return lexStatements
	default:
		return l.errorf("unexpected character inside braces: %q", r)
	}
	return lexInsideBraces
}
lexInsideBraces scans the inside of a vector selector. Keywords are ignored and
scanned as identifiers.
package promql
import (
	"fmt"
	"strings"
	"unicode"
	"unicode/utf8"
)
type item struct {
	typ ItemType  
	pos Pos       
	val string    
}
func (i item) String() string {
	switch {
	case i.typ == ItemEOF:
		return "EOF"
	case i.typ == ItemError:
		return i.val
	case i.typ == ItemIdentifier || i.typ == ItemMetricIdentifier:
		return fmt.Sprintf("%q", i.val)
	case i.typ.isKeyword():
		return fmt.Sprintf("<%s>", i.val)
	case i.typ.isOperator():
		return fmt.Sprintf("<op:%s>", i.val)
	case i.typ.isAggregator():
		return fmt.Sprintf("<aggr:%s>", i.val)
	case len(i.val) > 10:
		return fmt.Sprintf("%.10q...", i.val)
	}
	return fmt.Sprintf("%q", i.val)
}
func (i ItemType) isOperator() bool { return i > operatorsStart && i < operatorsEnd }
func (i ItemType) isAggregator() bool { return i > aggregatorsStart && i < aggregatorsEnd }
func (i ItemType) isAggregatorWithParam() bool {
	return i == ItemTopK || i == ItemBottomK || i == ItemCountValues || i == ItemQuantile
}
func (i ItemType) isKeyword() bool { return i > keywordsStart && i < keywordsEnd }
func (i ItemType) isComparisonOperator() bool {
	switch i {
	case ItemEQL, ItemNEQ, ItemLTE, ItemLSS, ItemGTE, ItemGTR:
		return true
	default:
		return false
	}
}
func (i ItemType) isSetOperator() bool {
	switch i {
	case ItemLAND, ItemLOR, ItemLUnless:
		return true
	}
	return false
}
const LowestPrec = 0  
func (i ItemType) precedence() int {
	switch i {
	case ItemLOR:
		return 1
	case ItemLAND, ItemLUnless:
		return 2
	case ItemEQL, ItemNEQ, ItemLTE, ItemLSS, ItemGTE, ItemGTR:
		return 3
	case ItemADD, ItemSUB:
		return 4
	case ItemMUL, ItemDIV, ItemMOD:
		return 5
	case ItemPOW:
		return 6
	default:
		return LowestPrec
	}
}
func (i ItemType) isRightAssociative() bool {
	switch i {
	case ItemPOW:
		return true
	default:
		return false
	}
}
type ItemType int
const (
	ItemError ItemType = iota  
	ItemEOF
	ItemComment
	ItemIdentifier
	ItemMetricIdentifier
	ItemLeftParen
	ItemRightParen
	ItemLeftBrace
	ItemRightBrace
	ItemLeftBracket
	ItemRightBracket
	ItemComma
	ItemAssign
	ItemColon
	ItemSemicolon
	ItemString
	ItemNumber
	ItemDuration
	ItemBlank
	ItemTimes
	ItemSpace
	operatorsStart
	ItemSUB
	ItemADD
	ItemMUL
	ItemMOD
	ItemDIV
	ItemLAND
	ItemLOR
	ItemLUnless
	ItemEQL
	ItemNEQ
	ItemLTE
	ItemLSS
	ItemGTE
	ItemGTR
	ItemEQLRegex
	ItemNEQRegex
	ItemPOW
	operatorsEnd
	aggregatorsStart
	ItemAvg
	ItemCount
	ItemSum
	ItemMin
	ItemMax
	ItemStddev
	ItemStdvar
	ItemTopK
	ItemBottomK
	ItemCountValues
	ItemQuantile
	aggregatorsEnd
	keywordsStart
	ItemOffset
	ItemBy
	ItemWithout
	ItemOn
	ItemIgnoring
	ItemGroupLeft
	ItemGroupRight
	ItemBool
	keywordsEnd
)
var key = map[string]ItemType{
	"and":    ItemLAND,
	"or":     ItemLOR,
	"unless": ItemLUnless,
	"sum":          ItemSum,
	"avg":          ItemAvg,
	"count":        ItemCount,
	"min":          ItemMin,
	"max":          ItemMax,
	"stddev":       ItemStddev,
	"stdvar":       ItemStdvar,
	"topk":         ItemTopK,
	"bottomk":      ItemBottomK,
	"count_values": ItemCountValues,
	"quantile":     ItemQuantile,
	"offset":      ItemOffset,
	"by":          ItemBy,
	"without":     ItemWithout,
	"on":          ItemOn,
	"ignoring":    ItemIgnoring,
	"group_left":  ItemGroupLeft,
	"group_right": ItemGroupRight,
	"bool":        ItemBool,
}
var itemTypeStr = map[ItemType]string{
	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:      "^",
}
func init() {
	for s, ty := range key {
		itemTypeStr[ty] = s
	}
	key["inf"] = ItemNumber
	key["nan"] = ItemNumber
}
func (i ItemType) String() string {
	if s, ok := itemTypeStr[i]; ok {
		return s
	}
	return fmt.Sprintf("<item %d>", i)
}
func (i item) desc() string {
	if _, ok := itemTypeStr[i.typ]; ok {
		return i.String()
	}
	if i.typ == ItemEOF {
		return i.typ.desc()
	}
	return fmt.Sprintf("%s %s", i.typ.desc(), i)
}
func (i ItemType) desc() string {
	switch i {
	case ItemError:
		return "error"
	case ItemEOF:
		return "end of input"
	case ItemComment:
		return "comment"
	case ItemIdentifier:
		return "identifier"
	case ItemMetricIdentifier:
		return "metric identifier"
	case ItemString:
		return "string"
	case ItemNumber:
		return "number"
	case ItemDuration:
		return "duration"
	}
	return fmt.Sprintf("%q", i)
}
const eof = -1
type stateFn func(*lexer) stateFn
type Pos int
type lexer struct {
	input   string     
	state   stateFn    
	pos     Pos        
	start   Pos        
	width   Pos        
	lastPos Pos        
	items   chan item  
	parenDepth  int   
	braceOpen   bool  
	bracketOpen bool  
	gotColon    bool  
	stringOpen  rune  
	seriesDesc bool
}
func (l *lexer) next() rune {
	if int(l.pos) >= len(l.input) {
		l.width = 0
		return eof
	}
	r, w := utf8.DecodeRuneInString(l.input[l.pos:])
	l.width = Pos(w)
	l.pos += l.width
	return r
}
func (l *lexer) peek() rune {
	r := l.next()
	l.backup()
	return r
}
func (l *lexer) backup() {
	l.pos -= l.width
}
func (l *lexer) emit(t ItemType) {
	l.items <- item{t, l.start, l.input[l.start:l.pos]}
	l.start = l.pos
}
func (l *lexer) ignore() {
	l.start = l.pos
}
func (l *lexer) accept(valid string) bool {
	if strings.ContainsRune(valid, l.next()) {
		return true
	}
	l.backup()
	return false
}
func (l *lexer) acceptRun(valid string) {
	for strings.ContainsRune(valid, l.next()) {
	}
	l.backup()
}
func (l *lexer) lineNumber() int {
	return 1 + strings.Count(l.input[:l.lastPos], "\n")
}
func (l *lexer) linePosition() int {
	lb := strings.LastIndex(l.input[:l.lastPos], "\n")
	if lb == -1 {
		return 1 + int(l.lastPos)
	}
	return 1 + int(l.lastPos) - lb
}
func (l *lexer) errorf(format string, args ...interface{}) stateFn {
	l.items <- item{ItemError, l.start, fmt.Sprintf(format, args...)}
	return nil
}
func (l *lexer) nextItem() item {
	item := <-l.items
	l.lastPos = item.pos
	return item
}
func lex(input string) *lexer {
	l := &lexer{
		input: input,
		items: make(chan item),
	}
	go l.run()
	return l
}
func (l *lexer) run() {
	for l.state = lexStatements; l.state != nil; {
		l.state = l.state(l)
	}
	close(l.items)
}
func (l *lexer) close() {
	for range l.items {
	}
}
const lineComment = "#"
func lexStatements(l *lexer) stateFn {
	if l.braceOpen {
		return lexInsideBraces
	}
	if strings.HasPrefix(l.input[l.pos:], lineComment) {
		return lexLineComment
	}
	switch r := l.next(); {
	case r == eof:
		if l.parenDepth != 0 {
			return l.errorf("unclosed left parenthesis")
		} else if l.bracketOpen {
			return l.errorf("unclosed left bracket")
		}
		l.emit(ItemEOF)
		return nil
	case r == ',':
		l.emit(ItemComma)
	case isSpace(r):
		return lexSpace
	case r == '*':
		l.emit(ItemMUL)
	case r == '/':
		l.emit(ItemDIV)
	case r == '%':
		l.emit(ItemMOD)
	case r == '+':
		l.emit(ItemADD)
	case r == '-':
		l.emit(ItemSUB)
	case r == '^':
		l.emit(ItemPOW)
	case r == '=':
		if t := l.peek(); t == '=' {
			l.next()
			l.emit(ItemEQL)
		} else if t == '~' {
			return l.errorf("unexpected character after '=': %q", t)
		} else {
			l.emit(ItemAssign)
		}
	case r == '!':
		if t := l.next(); t == '=' {
			l.emit(ItemNEQ)
		} else {
			return l.errorf("unexpected character after '!': %q", t)
		}
	case r == '<':
		if t := l.peek(); t == '=' {
			l.next()
			l.emit(ItemLTE)
		} else {
			l.emit(ItemLSS)
		}
	case r == '>':
		if t := l.peek(); t == '=' {
			l.next()
			l.emit(ItemGTE)
		} else {
			l.emit(ItemGTR)
		}
	case isDigit(r) || (r == '.' && isDigit(l.peek())):
		l.backup()
		return lexNumberOrDuration
	case r == '"' || r == '\'':
		l.stringOpen = r
		return lexString
	case r == '`':
		l.stringOpen = r
		return lexRawString
	case isAlpha(r) || r == ':':
		if !l.bracketOpen {
			l.backup()
			return lexKeywordOrIdentifier
		}
		if l.gotColon {
			return l.errorf("unexpected colon %q", r)
		}
		l.emit(ItemColon)
		l.gotColon = true
	case r == '(':
		l.emit(ItemLeftParen)
		l.parenDepth++
		return lexStatements
	case r == ')':
		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.braceOpen = true
		return lexInsideBraces(l)
	case r == '[':
		if l.bracketOpen {
			return l.errorf("unexpected left bracket %q", r)
		}
		l.gotColon = false
		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.bracketOpen = false
	default:
		return l.errorf("unexpected character: %q", r)
	}
	return lexStatements
}