package logql import ( "errors" "strings" "text/scanner" "github.com/prometheus/prometheus/pkg/labels" ) func init() { // Improve the error messages coming out of yacc. exprErrorVerbose = true // uncomment when you need to understand yacc rule tree. // exprDebug = 3 for str, tok := range tokens { exprToknames[tok-exprPrivate+1] = str } } // ParseExpr parses a string and returns an Expr. func ParseExpr(input string) (expr Expr, err error) { defer func() { r := recover() if r != nil { var ok bool if err, ok = r.(error); ok { if IsParseError(err) { return } err = newParseError(err.Error(), 0, 0) } } }() l := lexer{ parser: exprNewParser().(*exprParserImpl), } l.Init(strings.NewReader(input)) l.Scanner.Error = func(_ *scanner.Scanner, msg string) { l.Error(msg) } e := l.parser.Parse(&l) if e != 0 || len(l.errs) > 0 { return nil, l.errs[0] } return l.expr, nil } // ParseMatchers parses a string and returns labels matchers, if the expression contains // anything else it will return an error. func ParseMatchers(input string) ([]*labels.Matcher, error) { expr, err := ParseExpr(input) if err != nil { return nil, err } matcherExpr, ok := expr.(*matchersExpr) if !ok { return nil, errors.New("only label matchers is supported") } return matcherExpr.matchers, nil } // ParseSampleExpr parses a string and returns the sampleExpr func ParseSampleExpr(input string) (SampleExpr, error) { expr, err := ParseExpr(input) if err != nil { return nil, err } sampleExpr, ok := expr.(SampleExpr) if !ok { return nil, errors.New("only sample expression supported") } return sampleExpr, nil } // ParseLogSelector parses a log selector expression `{app="foo"} |= "filter"` func ParseLogSelector(input string) (LogSelectorExpr, error) { expr, err := ParseExpr(input) if err != nil { return nil, err } logSelector, ok := expr.(LogSelectorExpr) if !ok { return nil, errors.New("only log selector is supported") } return logSelector, nil }