qail_core/parser/grammar/
special_funcs.rs1use super::base::parse_identifier;
9use super::expressions::parse_expression;
10use crate::ast::*;
11use nom::{
12 IResult, Parser,
13 bytes::complete::tag_no_case,
14 character::complete::{char, multispace0, multispace1},
15 combinator::opt,
16 sequence::preceded,
17};
18
19pub fn parse_special_function(input: &str) -> IResult<&str, Expr> {
22 if let Ok(result) = parse_substring(input) {
24 return Ok(result);
25 }
26 if let Ok(result) = parse_extract(input) {
28 return Ok(result);
29 }
30 Err(nom::Err::Error(nom::error::Error::new(
32 input,
33 nom::error::ErrorKind::Tag,
34 )))
35}
36
37pub fn parse_substring(input: &str) -> IResult<&str, Expr> {
39 let (input, _) = tag_no_case("substring").parse(input)?;
40 let (input, _) = multispace0(input)?;
41 let (input, _) = char('(').parse(input)?;
42 let (input, _) = multispace0(input)?;
43
44 let (input, string_expr) = parse_expression(input)?;
46 let (input, _) = multispace1(input)?;
47
48 let (input, _) = tag_no_case("from").parse(input)?;
50 let (input, _) = multispace1(input)?;
51
52 let (input, from_expr) = parse_expression(input)?;
54 let (input, _) = multispace0(input)?;
55
56 let (input, for_expr) = opt(preceded(
58 (tag_no_case("for"), multispace1),
59 parse_expression,
60 ))
61 .parse(input)?;
62
63 let (input, _) = multispace0(input)?;
64 let (input, _) = char(')').parse(input)?;
65
66 let mut args = vec![
67 (None, Box::new(string_expr)),
68 (Some("FROM".to_string()), Box::new(from_expr)),
69 ];
70 if let Some(len_expr) = for_expr {
71 args.push((Some("FOR".to_string()), Box::new(len_expr)));
72 }
73
74 Ok((
75 input,
76 Expr::SpecialFunction {
77 name: "SUBSTRING".to_string(),
78 args,
79 alias: None,
80 },
81 ))
82}
83
84pub fn parse_extract(input: &str) -> IResult<&str, Expr> {
86 let (input, _) = tag_no_case("extract").parse(input)?;
87 let (input, _) = multispace0(input)?;
88 let (input, _) = char('(').parse(input)?;
89 let (input, _) = multispace0(input)?;
90
91 let (input, field) = parse_identifier(input)?;
93 let (input, _) = multispace1(input)?;
94
95 let (input, _) = tag_no_case("from").parse(input)?;
97 let (input, _) = multispace1(input)?;
98
99 let (input, date_expr) = parse_expression(input)?;
101 let (input, _) = multispace0(input)?;
102 let (input, _) = char(')').parse(input)?;
103
104 Ok((
105 input,
106 Expr::SpecialFunction {
107 name: "EXTRACT".to_string(),
108 args: vec![
109 (None, Box::new(Expr::Named(field.to_string()))),
110 (Some("FROM".to_string()), Box::new(date_expr)),
111 ],
112 alias: None,
113 },
114 ))
115}