partiql/parser/
expressions.rs

1use collect_mac::collect;
2use indexmap::IndexMap as Map;
3
4use nom::branch::alt;
5use nom::bytes::complete::{tag, tag_no_case};
6use nom::character::complete::alphanumeric1;
7use nom::character::complete::char;
8use nom::character::complete::multispace0;
9use nom::combinator::map;
10use nom::combinator::opt;
11use nom::multi::separated_list1;
12use nom::sequence::delimited;
13use nom::sequence::preceded;
14use nom::sequence::tuple;
15use nom::IResult;
16
17pub use crate::parser;
18pub use crate::parser::elements;
19pub use crate::parser::elements::string_allowed_in_field;
20pub use crate::parser::whitespace;
21use crate::pqlir_parser;
22pub use crate::sql::clause;
23use crate::sql::Expr;
24use crate::sql::Field;
25use crate::sql::Selector;
26use crate::sql::SelectorNode;
27use crate::value::PqlValue;
28
29pub fn pqlvalue_as_field(input: &str) -> IResult<&str, Field> {
30    let (input, (value, alias)) = tuple((
31        pqlir_parser::root,
32        opt(preceded(
33            opt(preceded(multispace0, tag_no_case("AS"))),
34            preceded(multispace0, alphanumeric1),
35        )),
36    ))(input)?;
37
38    let field = Field {
39        expr: Expr::Value(value),
40        alias: alias.map(String::from),
41    };
42    Ok((input, field))
43}
44
45pub fn parse_field(input: &str) -> IResult<&str, Field> {
46    alt((expr_as_field, pqlvalue_as_field, selector_as_field))(input)
47}
48
49/// ```
50/// use std::str::FromStr;
51/// use partiql::parser;
52/// use partiql::value::PqlValue;
53/// fn main() -> anyhow::Result<()> {
54///   let value = parser::expressions::pqlvalue_with_alias_to_pql_value(r#"[1,2,3] AS arr"#)?.1;
55///   let expected = PqlValue::from_str(r#"{ "arr" : [1,2,3] }"#)?;
56///   assert_eq!(value, expected);
57///   Ok(())
58/// }
59/// ```
60pub fn pqlvalue_with_alias_to_pql_value(input: &str) -> IResult<&str, PqlValue> {
61    let (input, field) = pqlvalue_as_field(input)?;
62    let value = match field {
63        Field {
64            expr: Expr::Value(value),
65            alias: Some(alias),
66        } => PqlValue::Object(collect! {
67            as Map::<String , PqlValue>:
68            alias.to_string() => value
69        }),
70        _ => todo!(),
71    };
72    Ok((input, value))
73}
74
75pub fn selector_as_field(input: &str) -> IResult<&str, Field> {
76    let (input, (selector, alias)) = tuple((
77        parse_selector,
78        opt(preceded(
79            opt(preceded(multispace0, tag_no_case("AS"))),
80            preceded(multispace0, alphanumeric1),
81        )),
82    ))(input)?;
83
84    let field = Field {
85        expr: Expr::Selector(selector),
86        alias: alias.map(String::from),
87    };
88    Ok((input, field))
89}
90
91pub fn projection(input: &str) -> IResult<&str, (Selector, Option<String>)> {
92    let (input, (selector, opt_alias)) = tuple((
93        parse_selector,
94        opt(preceded(
95            opt(preceded(multispace0, tag_no_case("AS"))),
96            preceded(multispace0, alphanumeric1),
97        )),
98    ))(input)?;
99    Ok((input, (selector, opt_alias.map(String::from))))
100}
101
102pub fn expr_as_field(input: &str) -> IResult<&str, Field> {
103    // The math::parse must be placed after the parse_path_as_expr to prevent the inf keyword from being parsed.
104    let (input, (expr, alias)) = tuple((
105        alt((
106            parse_star_as_expr,
107            parser::math::parse,
108            parser::elements::float_number,
109            parser::func::count,
110        )),
111        opt(preceded(
112            opt(preceded(multispace0, tag_no_case("AS"))),
113            preceded(multispace0, alphanumeric1),
114        )),
115    ))(input)?;
116
117    let field = Field {
118        expr,
119        alias: alias.map(String::from),
120    };
121    Ok((input, field))
122}
123
124pub fn parse_expr(input: &str) -> IResult<&str, Expr> {
125    // The math::parse must be placed after the parse_path_as_expr to prevent the inf keyword from being parsed.
126    alt((
127        parse_star_as_expr,
128        parser::math::parse,
129        parser::elements::float_number,
130        parser::func::count,
131    ))(input)
132}
133
134pub fn parse_star_as_expr(input: &str) -> IResult<&str, Expr> {
135    map(tag("*"), |_| Expr::Star)(input)
136}
137
138pub fn parse_sql_as_expr(_input: &str) -> IResult<&str, Expr> {
139    todo!()
140    // map(parse_field, |sql| Expr::Sql(sql))(input)
141}
142
143pub fn parse_alias_in_from_clause(input: &str) -> IResult<&str, String> {
144    let (input, (_, alias)) = tuple((
145        opt(preceded(whitespace, tag_no_case("AS"))),
146        preceded(whitespace, string_allowed_in_field),
147    ))(input)?;
148    Ok((input, alias))
149}
150
151pub fn parse_selector(input: &str) -> IResult<&str, Selector> {
152    pub fn selecotrnode_with_index<'a>(input: &str) -> IResult<&str, Vec<SelectorNode>> {
153        let (input, (s, opt_i)) = tuple((
154            string_allowed_in_field,
155            opt(delimited(char('['), elements::integer, char(']'))),
156        ))(input)?;
157
158        let mut nodes = vec![];
159        nodes.push(SelectorNode::String(s));
160        if let Some(i) = opt_i {
161            nodes.push(SelectorNode::Number(i as i64));
162        };
163
164        Ok((input, nodes))
165    }
166
167    let (input, (opt_dot, vec_nodes)) = tuple((
168        opt(char('.')),
169        separated_list1(char('.'), selecotrnode_with_index),
170    ))(input)?;
171
172    let mut nodes = vec![];
173    if let Some(_dot) = opt_dot {
174        nodes.push(SelectorNode::default())
175    }
176    let mut nodes2 = vec_nodes.into_iter().flatten().collect::<Vec<_>>();
177    nodes.append(&mut nodes2);
178    let res = Selector::from(nodes.as_slice());
179    Ok((input, res))
180}
181
182pub fn parse_path_as_expr<'a>(input: &'a str) -> IResult<&'a str, Expr> {
183    map(parse_selector, |selector| Expr::Selector(selector))(input)
184}
185
186#[cfg(test)]
187mod tests {
188    use super::parse_selector;
189    use crate::parser;
190    use crate::sql::Selector;
191    use crate::sql::SelectorNode;
192    use crate::value::PqlValue;
193    use std::str::FromStr;
194
195    #[test]
196    fn selector_xyz() -> anyhow::Result<()> {
197        let (_, selector) = parse_selector("x.y.z")?;
198
199        let expected = Selector::from(
200            vec![
201                SelectorNode::from("x"),
202                SelectorNode::from("y"),
203                SelectorNode::from("z"),
204            ]
205            .as_slice(),
206        );
207
208        assert_eq!(selector, expected);
209        Ok(())
210    }
211
212    #[test]
213    fn selector_xy2z() -> anyhow::Result<()> {
214        let (_, selector) = parse_selector("x.y[2].z")?;
215
216        let expected = Selector::from(
217            vec![
218                SelectorNode::from("x"),
219                SelectorNode::from("y"),
220                SelectorNode::from(2),
221                SelectorNode::from("z"),
222            ]
223            .as_slice(),
224        );
225
226        assert_eq!(selector, expected);
227        Ok(())
228    }
229
230    #[test]
231    fn alias_pql_vlaue_to_pql_value() -> anyhow::Result<()> {
232        let value = parser::expressions::pqlvalue_with_alias_to_pql_value(r#"[1,2,3] AS arr"#)?.1;
233        let expected = PqlValue::from_str(r#"{ "arr" : [1,2,3] }"#)?;
234        assert_eq!(value, expected);
235        Ok(())
236    }
237}