parseExpression parses an expression with OR operators (lowest precedence)
()
| 33 | |
| 34 | // parseExpression parses an expression with OR operators (lowest precedence) |
| 35 | func (p *Parser) parseExpression() (ast.Expression, error) { |
| 36 | // Check context if available |
| 37 | if p.ctx != nil { |
| 38 | if err := p.ctx.Err(); err != nil { |
| 39 | // Context cancellation is not a syntax error, wrap it directly |
| 40 | return nil, fmt.Errorf("parsing cancelled: %w", err) |
| 41 | } |
| 42 | } |
| 43 | |
| 44 | // Check recursion depth to prevent stack overflow |
| 45 | p.depth++ |
| 46 | defer func() { p.depth-- }() |
| 47 | |
| 48 | if p.depth > MaxRecursionDepth { |
| 49 | return nil, goerrors.RecursionDepthLimitError( |
| 50 | p.depth, |
| 51 | MaxRecursionDepth, |
| 52 | p.currentLocation(), |
| 53 | "", |
| 54 | ) |
| 55 | } |
| 56 | |
| 57 | // Start by parsing AND expressions (higher precedence) |
| 58 | left, err := p.parseAndExpression() |
| 59 | if err != nil { |
| 60 | return nil, err |
| 61 | } |
| 62 | |
| 63 | // Handle OR operators (lowest precedence, left-associative) |
| 64 | for p.isType(models.TokenTypeOr) { |
| 65 | opPos := p.currentLocation() |
| 66 | operator := p.currentToken.Token.Value |
| 67 | p.advance() // Consume OR |
| 68 | |
| 69 | right, err := p.parseAndExpression() |
| 70 | if err != nil { |
| 71 | return nil, err |
| 72 | } |
| 73 | |
| 74 | left = &ast.BinaryExpression{ |
| 75 | Left: left, |
| 76 | Operator: operator, |
| 77 | Right: right, |
| 78 | Pos: opPos, |
| 79 | } |
| 80 | } |
| 81 | |
| 82 | return left, nil |
| 83 | } |
| 84 | |
| 85 | // parseAndExpression parses an expression with AND operators (middle precedence) |
| 86 | func (p *Parser) parseAndExpression() (ast.Expression, error) { |
no test coverage detected