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 }