rsql_rs/parser/
rsql.rs

1use crate::ast::comparison;
2use crate::ast::comparison::Comparison;
3use crate::ast::constraint::Arguments;
4use crate::ast::expr::Expr;
5use crate::error::ParserError;
6
7use crate::parser::Parser;
8use crate::ParserResult;
9use pest::iterators::Pair;
10use pest::Parser as PestParser;
11use std::collections::{HashMap, HashSet};
12use std::convert::{TryFrom, TryInto};
13use std::iter::FromIterator;
14
15lazy_static! {
16    pub(crate) static ref DEFAULT_COMPS_MAP: HashMap<&'static str, &'static Comparison> = {
17        let tuple_vec: HashSet<&'static Comparison> = HashSet::from_iter(vec![
18            &comparison::EQUAL as &'static Comparison,
19            &comparison::NOT_EQUAL as &'static Comparison,
20            &comparison::GREATER_THAN as &'static Comparison,
21            &comparison::GREATER_THAN_OR_EQUAL as &'static Comparison,
22            &comparison::LESS_THAN as &'static Comparison,
23            &comparison::LESS_THAN_OR_EQUAL as &'static Comparison,
24            &comparison::IN as &'static Comparison,
25            &comparison::OUT as &'static Comparison,
26        ]);
27        let tuple_vec: Vec<(&'static str, &'static Comparison)> = tuple_vec
28            .iter()
29            .flat_map(|&comp| comp.symbols.iter().map(move |sym| (sym.as_str(), comp)))
30            .collect();
31        tuple_vec.into_iter().collect()
32    };
33}
34
35#[derive(Parser)]
36#[grammar = "rsql.pest"]
37pub struct RsqlParser;
38gen_parser!(RsqlParser);
39
40impl Parser for RsqlParser {
41    type R = Rule;
42
43    gen_parser_to_node!();
44
45    fn default_comparisons() -> &'static HashMap<&'static str, &'static Comparison> {
46        &DEFAULT_COMPS_MAP as &'static HashMap<&'static str, &'static Comparison>
47    }
48}
49
50impl<'i> TryFrom<Pair<'i, Rule>> for Arguments {
51    type Error = ParserError;
52
53    fn try_from(value: Pair<'i, Rule>) -> Result<Self, Self::Error> {
54        match value.as_rule() {
55            Rule::argument => {
56                let mut args = vec![];
57                for arg_item in value.into_inner() {
58                    let item_rules = arg_item.as_rule();
59                    let args_inner = arg_item.into_inner();
60                    match item_rules {
61                        Rule::value => {
62                            for arg_inner in args_inner {
63                                match arg_inner.as_rule() {
64                                    Rule::unreserved_str => {
65                                        for unreserved_inner in arg_inner.into_inner() {
66                                            if unreserved_inner.as_rule() == Rule::unreserved_inner
67                                            {
68                                                args.push(unreserved_inner.as_str().to_string());
69                                            }
70                                        }
71                                    },
72                                    Rule::double_quoted => {
73                                        for double_inner in arg_inner.into_inner() {
74                                            if double_inner.as_rule() == Rule::double_quoted_inner {
75                                                args.push(double_inner.as_str().to_string());
76                                            }
77                                        }
78                                    },
79                                    Rule::single_quoted => {
80                                        for single_inner in arg_inner.into_inner() {
81                                            if single_inner.as_rule() == Rule::single_quoted_inner {
82                                                args.push(single_inner.as_str().to_string());
83                                            }
84                                        }
85                                    },
86                                    _ => ParserError::invalid_pair_rule()?,
87                                }
88                            }
89                        },
90                        _ => ParserError::invalid_pair_rule()?,
91                    }
92                }
93
94                Ok(Arguments(args))
95            },
96            _ => ParserError::invalid_pair_rule()?,
97        }
98    }
99}
100
101#[cfg(test)]
102mod tests {
103    use crate::parser::rsql::*;
104    use crate::parser::Parser;
105    use crate::ParserResult;
106
107    #[test]
108    fn default_rsql_map_test() -> ParserResult<()> {
109        let _ = env_logger::builder().is_test(true).try_init();
110        let _ = RsqlParser::default_comparisons();
111        Ok(())
112    }
113}