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}