(gq *GraphQuery, it *lex.ItemIterator, again bool)
| 157 | } |
| 158 | |
| 159 | func parseMathFunc(gq *GraphQuery, it *lex.ItemIterator, again bool) (*MathTree, bool, error) { |
| 160 | if !again { |
| 161 | it.Next() |
| 162 | item := it.Item() |
| 163 | if item.Typ != itemLeftRound { |
| 164 | return nil, false, errors.Errorf("Expected ( after math") |
| 165 | } |
| 166 | } |
| 167 | |
| 168 | // opStack is used to collect the operators in right order. |
| 169 | opStack := new(mathTreeStack) |
| 170 | opStack.push(&MathTree{Fn: "("}) // Push ( onto operator stack. |
| 171 | // valueStack is used to collect the values. |
| 172 | valueStack := new(mathTreeStack) |
| 173 | |
| 174 | loop: |
| 175 | for it.Next() { |
| 176 | item := it.Item() |
| 177 | lval := strings.ToLower(item.Val) |
| 178 | switch { |
| 179 | case isMathFunc(lval): |
| 180 | op := lval |
| 181 | it.Prev() |
| 182 | lastItem := it.Item() |
| 183 | it.Next() |
| 184 | if op == "-" && |
| 185 | (lastItem.Val == "(" || lastItem.Val == "," || isBinaryMath(lastItem.Val)) { |
| 186 | op = "u-" // This is a unary - |
| 187 | } |
| 188 | opPred := mathOpPrecedence[op] |
| 189 | x.AssertTruef(opPred > 0, "Expected opPred > 0 for %v: %d", op, opPred) |
| 190 | // Evaluate the stack until we see an operator with strictly lower pred. |
| 191 | for !opStack.empty() { |
| 192 | topOp := opStack.peek() |
| 193 | if mathOpPrecedence[topOp.Fn] < opPred { |
| 194 | break |
| 195 | } |
| 196 | err := evalMathStack(opStack, valueStack) |
| 197 | if err != nil { |
| 198 | return nil, false, err |
| 199 | } |
| 200 | } |
| 201 | opStack.push(&MathTree{Fn: op}) // Push current operator. |
| 202 | peekIt, err := it.Peek(1) |
| 203 | if err != nil { |
| 204 | return nil, false, err |
| 205 | } |
| 206 | if peekIt[0].Typ == itemLeftRound { |
| 207 | again := false |
| 208 | var child *MathTree |
| 209 | for { |
| 210 | child, again, err = parseMathFunc(gq, it, again) |
| 211 | if err != nil { |
| 212 | return nil, false, err |
| 213 | } |
| 214 | valueStack.push(child) |
| 215 | if !again { |
| 216 | break |
no test coverage detected