(
context: &mut ParserContext,
env: &mut Environment,
tokens: &[Token],
position: &mut usize,
)
| 16 | use crate::token::TokenKind; |
| 17 | |
| 18 | pub(crate) fn parse_like_expression( |
| 19 | context: &mut ParserContext, |
| 20 | env: &mut Environment, |
| 21 | tokens: &[Token], |
| 22 | position: &mut usize, |
| 23 | ) -> Result<Box<dyn Expr>, Box<Diagnostic>> { |
| 24 | let lhs = parse_glob_expression(context, env, tokens, position)?; |
| 25 | |
| 26 | // Check for `LIKE` or `NOT LIKE` |
| 27 | // <expr> LIKE <expr> AND <expr> |
| 28 | // <expr> NOT LIKE <expr> AND <expr> |
| 29 | if is_current_token(tokens, position, TokenKind::Like) |
| 30 | || (is_current_token(tokens, position, TokenKind::Not) |
| 31 | && is_next_token(tokens, position, TokenKind::Like)) |
| 32 | { |
| 33 | let has_not_keyword = is_current_token(tokens, position, TokenKind::Not); |
| 34 | let operator_location = if has_not_keyword { |
| 35 | // Consume `NOT` and `LIKE` keyword |
| 36 | *position += 2; |
| 37 | let mut not_location = tokens[*position - 2].location; |
| 38 | let between_location = tokens[*position - 1].location; |
| 39 | not_location.expand_until(between_location); |
| 40 | not_location |
| 41 | } else { |
| 42 | // Consume `LIKE` keyword |
| 43 | *position += 1; |
| 44 | tokens[*position - 1].location |
| 45 | }; |
| 46 | |
| 47 | let pattern = parse_glob_expression(context, env, tokens, position)?; |
| 48 | |
| 49 | let lhs_type = lhs.expr_type(); |
| 50 | let rhs_type = pattern.expr_type(); |
| 51 | |
| 52 | // Can perform this operator between LHS and RHS |
| 53 | let expected_rhs_types = lhs_type.can_perform_like_op_with(); |
| 54 | if expected_rhs_types.contains(&rhs_type) { |
| 55 | let expr = Box::new(LikeExpr { |
| 56 | input: lhs, |
| 57 | pattern, |
| 58 | }); |
| 59 | |
| 60 | return Ok(apply_not_keyword_if_exists(expr, has_not_keyword)); |
| 61 | } |
| 62 | |
| 63 | // Check if RHS expr can be implicit casted to Expected LHS type to make this |
| 64 | // Expression valid |
| 65 | for expected_type in expected_rhs_types.iter() { |
| 66 | if !expected_type.has_implicit_cast_from(&pattern) { |
| 67 | continue; |
| 68 | } |
| 69 | |
| 70 | let casting = Box::new(CastExpr { |
| 71 | value: pattern, |
| 72 | result_type: expected_type.clone(), |
| 73 | }); |
| 74 | |
| 75 | let expr = Box::new(LikeExpr { |
no test coverage detected
searching dependent graphs…