parseFilter parses the filter directive to produce a QueryFilter / parse tree.
(it *lex.ItemIterator)
| 2432 | |
| 2433 | // parseFilter parses the filter directive to produce a QueryFilter / parse tree. |
| 2434 | func parseFilter(it *lex.ItemIterator) (*FilterTree, error) { |
| 2435 | it.Next() |
| 2436 | item := it.Item() |
| 2437 | if item.Typ != itemLeftRound { |
| 2438 | return nil, item.Errorf("Expected ( after filter directive") |
| 2439 | } |
| 2440 | |
| 2441 | // opStack is used to collect the operators in right order. |
| 2442 | opStack := new(filterTreeStack) |
| 2443 | opStack.push(&FilterTree{Op: "("}) // Push ( onto operator stack. |
| 2444 | // valueStack is used to collect the values. |
| 2445 | valueStack := new(filterTreeStack) |
| 2446 | |
| 2447 | loop: |
| 2448 | for it.Next() { |
| 2449 | item := it.Item() |
| 2450 | lval := strings.ToLower(item.Val) |
| 2451 | switch { |
| 2452 | case lval == "and" || lval == "or" || lval == "not": // Handle operators. |
| 2453 | op := lval |
| 2454 | opPred := filterOpPrecedence[op] |
| 2455 | x.AssertTruef(opPred > 0, "Expected opPred > 0: %d", opPred) |
| 2456 | // Evaluate the stack until we see an operator with strictly lower pred. |
| 2457 | for !opStack.empty() { |
| 2458 | topOp := opStack.peek() |
| 2459 | if filterOpPrecedence[topOp.Op] < opPred { |
| 2460 | break |
| 2461 | } |
| 2462 | err := evalStack(opStack, valueStack) |
| 2463 | if err != nil { |
| 2464 | return nil, err |
| 2465 | } |
| 2466 | } |
| 2467 | opStack.push(&FilterTree{Op: op}) // Push current operator. |
| 2468 | case item.Typ == itemName: // Value. |
| 2469 | it.Prev() |
| 2470 | f, err := parseFunction(it, nil) |
| 2471 | if err != nil { |
| 2472 | return nil, err |
| 2473 | } |
| 2474 | leaf := &FilterTree{Func: f} |
| 2475 | valueStack.push(leaf) |
| 2476 | case item.Typ == itemLeftRound: // Just push to op stack. |
| 2477 | opStack.push(&FilterTree{Op: "("}) |
| 2478 | |
| 2479 | case item.Typ == itemRightRound: // Pop op stack until we see a (. |
| 2480 | for !opStack.empty() { |
| 2481 | topOp := opStack.peek() |
| 2482 | if topOp.Op == "(" { |
| 2483 | break |
| 2484 | } |
| 2485 | err := evalStack(opStack, valueStack) |
| 2486 | if err != nil { |
| 2487 | return nil, err |
| 2488 | } |
| 2489 | } |
| 2490 | _, err := opStack.pop() // Pop away the (. |
| 2491 | if err != nil { |