bosun.org@v0.0.0-20210513094433-e25bc3e69a1f/cmd/bosun/expr/parse/parse.go (about)

     1  // Copyright 2011 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Package parse builds parse trees for expressions as defined by expr. Clients
     6  // should use that package to construct expressions rather than this one, which
     7  // provides shared internal data structures not intended for general use.
     8  package parse // import "bosun.org/cmd/bosun/expr/parse"
     9  
    10  import (
    11  	"fmt"
    12  	"runtime"
    13  	"sort"
    14  	"strconv"
    15  	"strings"
    16  
    17  	"bosun.org/models"
    18  )
    19  
    20  // Tree is the representation of a single parsed expression.
    21  type Tree struct {
    22  	Text string // text parsed to create the expression.
    23  	Root Node   // top-level root of the tree, returns a number.
    24  
    25  	funcs   []map[string]Func
    26  	mapExpr bool
    27  
    28  	// Parsing only; cleared after parse.
    29  	lex       *lexer
    30  	token     [1]item // one-token lookahead for parser.
    31  	peekCount int
    32  }
    33  
    34  type Func struct {
    35  	Args          []models.FuncType
    36  	Return        models.FuncType
    37  	Tags          func([]Node) (Tags, error)
    38  	F             interface{}
    39  	VArgs         bool
    40  	VArgsPos      int
    41  	VArgsOmit     bool
    42  	MapFunc       bool // Func is only valid in map expressions
    43  	PrefixEnabled bool
    44  	PrefixKey     bool
    45  	VariantReturn bool
    46  	Check         func(*Tree, *FuncNode) error
    47  }
    48  
    49  type Tags map[string]struct{}
    50  
    51  func (t Tags) String() string {
    52  	var keys []string
    53  	for k := range t {
    54  		keys = append(keys, k)
    55  	}
    56  	sort.Strings(keys)
    57  	return strings.Join(keys, ",")
    58  }
    59  
    60  func (t Tags) Equal(o Tags) bool {
    61  	if len(t) != len(o) {
    62  		return false
    63  	}
    64  	for k := range t {
    65  		if _, present := o[k]; !present {
    66  			return false
    67  		}
    68  	}
    69  	return true
    70  }
    71  
    72  // Subset returns true if o is a subset of t.
    73  func (t Tags) Subset(o Tags) bool {
    74  	for k := range t {
    75  		if _, ok := o[k]; !ok {
    76  			return false
    77  		}
    78  	}
    79  	return true
    80  }
    81  
    82  // Intersection returns Tags common to both tagsets.
    83  func (t Tags) Intersection(o Tags) Tags {
    84  	result := Tags{}
    85  	for k := range t {
    86  		if _, ok := o[k]; ok {
    87  			result[k] = struct{}{}
    88  		}
    89  	}
    90  	return result
    91  }
    92  
    93  // Parse returns a Tree, created by parsing the expression described in the
    94  // argument string. If an error is encountered, parsing stops and an empty Tree
    95  // is returned with the error.
    96  func Parse(text string, funcs ...map[string]Func) (t *Tree, err error) {
    97  	t = New()
    98  	t.Text = text
    99  	err = t.Parse(text, funcs...)
   100  	return
   101  }
   102  
   103  func ParseSub(text string, funcs ...map[string]Func) (t *Tree, err error) {
   104  	t = New()
   105  	t.mapExpr = true
   106  	t.Text = text
   107  	err = t.Parse(text, funcs...)
   108  	return
   109  }
   110  
   111  // next returns the next token.
   112  func (t *Tree) next() item {
   113  	if t.peekCount > 0 {
   114  		t.peekCount--
   115  	} else {
   116  		t.token[0] = t.lex.nextItem()
   117  	}
   118  	return t.token[t.peekCount]
   119  }
   120  
   121  // backup backs the input stream up one token.
   122  func (t *Tree) backup() {
   123  	t.peekCount++
   124  }
   125  
   126  // peek returns but does not consume the next token.
   127  func (t *Tree) peek() item {
   128  	if t.peekCount > 0 {
   129  		return t.token[t.peekCount-1]
   130  	}
   131  	t.peekCount = 1
   132  	t.token[0] = t.lex.nextItem()
   133  	return t.token[0]
   134  }
   135  
   136  // Parsing.
   137  
   138  // New allocates a new parse tree with the given name.
   139  func New(funcs ...map[string]Func) *Tree {
   140  	return &Tree{
   141  		funcs: funcs,
   142  	}
   143  }
   144  
   145  // errorf formats the error and terminates processing.
   146  func (t *Tree) errorf(format string, args ...interface{}) {
   147  	t.Root = nil
   148  	format = fmt.Sprintf("expr: %s", format)
   149  	panic(fmt.Errorf(format, args...))
   150  }
   151  
   152  // error terminates processing.
   153  func (t *Tree) error(err error) {
   154  	t.errorf("%s", err)
   155  }
   156  
   157  // expect consumes the next token and guarantees it has the required type.
   158  func (t *Tree) expect(expected itemType, context string) item {
   159  	token := t.next()
   160  	if token.typ != expected {
   161  		t.unexpected(token, context)
   162  	}
   163  	return token
   164  }
   165  
   166  // expectOneOf consumes the next token and guarantees it has one of the required types.
   167  func (t *Tree) expectOneOf(expected1, expected2 itemType, context string) item {
   168  	token := t.next()
   169  	if token.typ != expected1 && token.typ != expected2 {
   170  		t.unexpected(token, context)
   171  	}
   172  	return token
   173  }
   174  
   175  // unexpected complains about the token and terminates processing.
   176  func (t *Tree) unexpected(token item, context string) {
   177  	t.errorf("unexpected %s in %s", token, context)
   178  }
   179  
   180  // recover is the handler that turns panics into returns from the top level of Parse.
   181  func (t *Tree) recover(errp *error) {
   182  	e := recover()
   183  	if e != nil {
   184  		if _, ok := e.(runtime.Error); ok {
   185  			panic(e)
   186  		}
   187  		if t != nil {
   188  			t.stopParse()
   189  		}
   190  		*errp = e.(error)
   191  	}
   192  	return
   193  }
   194  
   195  // startParse initializes the parser, using the lexer.
   196  func (t *Tree) startParse(funcs []map[string]Func, lex *lexer) {
   197  	t.Root = nil
   198  	t.lex = lex
   199  	t.funcs = funcs
   200  	for _, funcMap := range funcs {
   201  		for name, f := range funcMap {
   202  			if f.VariantReturn {
   203  				if f.Tags == nil {
   204  					panic(fmt.Errorf("%v: expected Tags definition: got nil", name))
   205  				}
   206  				continue
   207  			}
   208  			switch f.Return {
   209  			case models.TypeSeriesSet, models.TypeNumberSet:
   210  				if f.Tags == nil {
   211  					panic(fmt.Errorf("%v: expected Tags definition: got nil", name))
   212  				}
   213  			default:
   214  				if f.Tags != nil {
   215  					panic(fmt.Errorf("%v: unexpected Tags definition: expected nil", name))
   216  				}
   217  			}
   218  		}
   219  	}
   220  }
   221  
   222  // stopParse terminates parsing.
   223  func (t *Tree) stopParse() {
   224  	t.lex = nil
   225  }
   226  
   227  // Parse parses the expression definition string to construct a representation
   228  // of the expression for execution.
   229  func (t *Tree) Parse(text string, funcs ...map[string]Func) (err error) {
   230  	defer t.recover(&err)
   231  	t.startParse(funcs, lex(text))
   232  	t.Text = text
   233  	t.parse()
   234  	t.stopParse()
   235  	return nil
   236  }
   237  
   238  // parse is the top-level parser for an expression.
   239  // It runs to EOF.
   240  func (t *Tree) parse() {
   241  	t.Root = t.O()
   242  	t.expect(itemEOF, "root input")
   243  	if err := t.Root.Check(t); err != nil {
   244  		t.error(err)
   245  	}
   246  }
   247  
   248  /* Grammar:
   249  O -> A {"||" A}
   250  A -> C {"&&" C}
   251  C -> P {( "==" | "!=" | ">" | ">=" | "<" | "<=") P}
   252  P -> M {( "+" | "-" ) M}
   253  M -> E {( "*" | "/" ) F}
   254  E -> F {( "**" ) F}
   255  F -> v | "(" O ")" | "!" O | "-" O
   256  v -> number | func(..)
   257  Func -> optPrefix name "(" param {"," param} ")"
   258  param -> number | "string" | subExpr | [query]
   259  optPrefix -> [ prefix ]
   260  */
   261  
   262  // expr:
   263  func (t *Tree) O() Node {
   264  	n := t.A()
   265  	for {
   266  		switch t.peek().typ {
   267  		case itemOr:
   268  			n = newBinary(t.next(), n, t.A())
   269  		default:
   270  			return n
   271  		}
   272  	}
   273  }
   274  
   275  func (t *Tree) A() Node {
   276  	n := t.C()
   277  	for {
   278  		switch t.peek().typ {
   279  		case itemAnd:
   280  			n = newBinary(t.next(), n, t.C())
   281  		default:
   282  			return n
   283  		}
   284  	}
   285  }
   286  
   287  func (t *Tree) C() Node {
   288  	n := t.P()
   289  	for {
   290  		switch t.peek().typ {
   291  		case itemEq, itemNotEq, itemGreater, itemGreaterEq, itemLess, itemLessEq:
   292  			n = newBinary(t.next(), n, t.P())
   293  		default:
   294  			return n
   295  		}
   296  	}
   297  }
   298  
   299  func (t *Tree) P() Node {
   300  	n := t.M()
   301  	for {
   302  		switch t.peek().typ {
   303  		case itemPlus, itemMinus:
   304  			n = newBinary(t.next(), n, t.M())
   305  		default:
   306  			return n
   307  		}
   308  	}
   309  }
   310  
   311  func (t *Tree) M() Node {
   312  	n := t.E()
   313  	for {
   314  		switch t.peek().typ {
   315  		case itemMult, itemDiv, itemMod:
   316  			n = newBinary(t.next(), n, t.E())
   317  		default:
   318  			return n
   319  		}
   320  	}
   321  }
   322  
   323  func (t *Tree) E() Node {
   324  	n := t.F()
   325  	for {
   326  		switch t.peek().typ {
   327  		case itemPow:
   328  			n = newBinary(t.next(), n, t.F())
   329  		default:
   330  			return n
   331  		}
   332  	}
   333  }
   334  
   335  func (t *Tree) F() Node {
   336  	switch token := t.peek(); token.typ {
   337  	case itemNumber, itemFunc:
   338  		return t.v()
   339  	case itemNot, itemMinus:
   340  		return newUnary(t.next(), t.F())
   341  	case itemPrefix:
   342  		token := t.next()
   343  		return newPrefix(token.val, token.pos, t.F())
   344  	case itemLeftParen:
   345  		t.next()
   346  		n := t.O()
   347  		t.expect(itemRightParen, "input: F()")
   348  		return n
   349  	default:
   350  		t.unexpected(token, "input: F()")
   351  	}
   352  	return nil
   353  }
   354  
   355  func (t *Tree) v() Node {
   356  	switch token := t.next(); token.typ {
   357  	case itemNumber:
   358  		n, err := newNumber(token.pos, token.val)
   359  		if err != nil {
   360  			t.error(err)
   361  		}
   362  		return n
   363  	case itemFunc:
   364  		t.backup()
   365  		return t.Func()
   366  	default:
   367  		t.unexpected(token, "input: v()")
   368  	}
   369  	return nil
   370  }
   371  
   372  func (t *Tree) Func() (f *FuncNode) {
   373  	token := t.next()
   374  	funcv, ok := t.GetFunction(token.val)
   375  	if !ok {
   376  		t.errorf("non existent function %s", token.val)
   377  	}
   378  	f = newFunc(token.pos, token.val, funcv)
   379  	t.expect(itemLeftParen, "func")
   380  	for {
   381  		switch token = t.next(); token.typ {
   382  		default:
   383  			t.backup()
   384  			node := t.O()
   385  			f.append(node)
   386  			if len(f.Args) == 1 && f.F.VariantReturn {
   387  				f.F.Return = node.Return()
   388  			}
   389  		case itemTripleQuotedString:
   390  			f.append(newString(token.pos, token.val, token.val[3:len(token.val)-3]))
   391  		case itemString:
   392  			s, err := strconv.Unquote(token.val)
   393  			if err != nil {
   394  				t.errorf("Unquoting error: %s", err)
   395  			}
   396  			f.append(newString(token.pos, token.val, s))
   397  		case itemRightParen:
   398  			return
   399  		case itemExpr:
   400  			t.expect(itemLeftParen, "v() expect left paran in itemExpr")
   401  			start := t.lex.lastPos
   402  			leftCount := 1
   403  		TOKENS:
   404  			for {
   405  				switch token = t.next(); token.typ {
   406  				case itemLeftParen:
   407  					leftCount++
   408  				case itemFunc:
   409  				case itemRightParen:
   410  					leftCount--
   411  					if leftCount == 0 {
   412  						t.expect(itemRightParen, "v() expect right paren in itemExpr")
   413  						t.backup()
   414  						break TOKENS
   415  					}
   416  				case itemEOF:
   417  					t.unexpected(token, "input: v()")
   418  				default:
   419  					// continue
   420  				}
   421  			}
   422  			n, err := newExprNode(t.lex.input[start:t.lex.lastPos], t.lex.lastPos)
   423  			if err != nil {
   424  				t.error(err)
   425  			}
   426  			n.Tree, err = ParseSub(n.Text, t.funcs...)
   427  			if err != nil {
   428  				t.error(err)
   429  			}
   430  			f.append(n)
   431  		}
   432  		switch token = t.next(); token.typ {
   433  		case itemComma:
   434  			// continue
   435  		case itemRightParen:
   436  			return
   437  		default:
   438  			t.unexpected(token, "func")
   439  		}
   440  	}
   441  }
   442  
   443  func (t *Tree) GetFunction(name string) (v Func, ok bool) {
   444  	for _, funcMap := range t.funcs {
   445  		if funcMap == nil {
   446  			continue
   447  		}
   448  		if v, ok = funcMap[name]; ok {
   449  			return
   450  		}
   451  	}
   452  	return
   453  }
   454  
   455  func (t *Tree) SetFunction(name string, F interface{}) error {
   456  	for i, funcMap := range t.funcs {
   457  		if funcMap == nil {
   458  			continue
   459  		}
   460  		if v, ok := funcMap[name]; ok {
   461  			v.F = F
   462  			t.funcs[i][name] = v
   463  			return nil
   464  		}
   465  	}
   466  	return fmt.Errorf("can not set function, function %v not found", name)
   467  }
   468  
   469  func (t *Tree) String() string {
   470  	return t.Root.String()
   471  }