ParseExpr parses an expression. binOpPrcdncLb: binary operator precedence lower bound. Any binary operator with a lower precedence than that will cause ParseExpr to stop. This is used for parsing binary operators following a unary operator.
(binOpPrcdncLb int)
| 304 | // Any binary operator with a lower precedence than that will cause ParseExpr to stop. |
| 305 | // This is used for parsing binary operators following a unary operator. |
| 306 | func (p *Parser) ParseExpr(binOpPrcdncLb int) (Expr, error) { |
| 307 | var err error |
| 308 | // Dummy root node. |
| 309 | root := &BinaryExpr{} |
| 310 | |
| 311 | // Parse a non-binary expression type to start. |
| 312 | // This variable will always be the root of the expression tree. |
| 313 | root.RHS, err = p.parseUnaryExpr(false) |
| 314 | if err != nil { |
| 315 | return nil, err |
| 316 | } |
| 317 | |
| 318 | // Loop over operations and unary exprs and build a tree based on precendence. |
| 319 | for { |
| 320 | // If the next token is NOT an operator then return the expression. |
| 321 | op, pos, lit := p.scanIgnoreWhitespace() |
| 322 | if op == NOT { |
| 323 | op, pos, lit = p.scanIgnoreWhitespace() |
| 324 | if op == IN { |
| 325 | op = NOT_IN |
| 326 | } else { |
| 327 | return nil, newParseError(tokstr(op, lit), []string{"IN"}, pos) |
| 328 | } |
| 329 | } |
| 330 | if !op.isBinaryOperator() || op.Precedence() < binOpPrcdncLb { |
| 331 | p.unscan() |
| 332 | return rewriteIsExpr(root.RHS) |
| 333 | } |
| 334 | |
| 335 | // Otherwise parse the next expression. |
| 336 | var rhs Expr |
| 337 | if rhs, err = p.parseUnaryExpr(op == IN || op == NOT_IN); err != nil { |
| 338 | return nil, err |
| 339 | } |
| 340 | |
| 341 | // Find the right spot in the tree to add the new expression by |
| 342 | // descending the RHS of the expression tree until we reach the last |
| 343 | // BinaryExpr or a BinaryExpr whose RHS has an operator with |
| 344 | // precedence >= the operator being added. |
| 345 | for node := root; ; { |
| 346 | r, ok := node.RHS.(*BinaryExpr) |
| 347 | if !ok || r.Op.Precedence() >= op.Precedence() { |
| 348 | // Add the new expression here and break. |
| 349 | node.RHS = &BinaryExpr{LHS: node.RHS, RHS: rhs, Op: op} |
| 350 | break |
| 351 | } |
| 352 | node = r |
| 353 | } |
| 354 | } |
| 355 | } |
| 356 | |
| 357 | // parseUnaryExpr parses an non-binary expression. |
| 358 | // TODO: shz@ revisit inclusion parameter when open sourcing |