rsql_rs/
macros.rs

1#[macro_export]
2macro_rules! gen_parser_to_node {
3    () => {
4        fn parse_to_node(code: &str) -> crate::ParserResult<Expr> {
5            let res = Self::parse(Rule::expression, &code)?.next().unwrap();
6            let res: crate::ast::expr::Expr = res.try_into()?;
7            Ok(res)
8        }
9    };
10}
11
12#[macro_export]
13macro_rules! gen_parser {
14    ($class_name:ident) => {
15        impl<'i> std::convert::TryFrom<pest::iterators::Pair<'i, Rule>>
16            for crate::ast::comparison::Comparison
17        {
18            type Error = crate::error::ParserError;
19
20            fn try_from(
21                value: pest::iterators::Pair<Rule>,
22            ) -> std::result::Result<Self, Self::Error> {
23                match value.as_rule() {
24                    Rule::comparison => {
25                        let comp_name = value.as_str();
26                        if let Some(&comp) = $class_name::default_comparisons().get(comp_name) {
27                            Ok(comp.clone())
28                        } else {
29                            Err(crate::error::ParserError::InvalidComparison(comp_name.to_string()))
30                        }
31                    },
32                    _ => crate::error::ParserError::invalid_pair_rule()?,
33                }
34            }
35        }
36
37        impl<'i> std::convert::TryFrom<pest::iterators::Pair<'i, Rule>>
38            for crate::ast::constraint::Constraint
39        {
40            type Error = crate::error::ParserError;
41
42            fn try_from(
43                value: pest::iterators::Pair<'i, Rule>,
44            ) -> std::result::Result<Self, Self::Error> {
45                let mut selector_opt: std::option::Option<String> = None;
46                let mut comparison_opt: std::option::Option<Comparison> = None;
47                let mut arguments_opt: std::option::Option<Arguments> = None;
48
49                match value.as_rule() {
50                    Rule::constraint => {
51                        for item in value.into_inner() {
52                            match item.as_rule() {
53                                Rule::selector => selector_opt = Some(item.as_str().to_string()),
54                                Rule::comparison => comparison_opt = item.try_into().ok(),
55                                Rule::argument => arguments_opt = item.try_into().ok(),
56                                _ => {},
57                            }
58                        }
59                        let selector = if let Some(selector) = selector_opt {
60                            selector
61                        } else {
62                            return Err(ParserError::LackOfField {
63                                ty: "Constraint".to_string(),
64                                field: "selector".to_string(),
65                            });
66                        };
67                        let comparison = if let Some(comparison) = comparison_opt {
68                            comparison
69                        } else {
70                            return Err(ParserError::LackOfField {
71                                ty: "Constraint".to_string(),
72                                field: "comparison".to_string(),
73                            });
74                        };
75                        let arguments = if let Some(arguments) = arguments_opt {
76                            arguments
77                        } else {
78                            return Err(ParserError::LackOfField {
79                                ty: "Constraint".to_string(),
80                                field: "arguments".to_string(),
81                            });
82                        };
83
84                        Ok(crate::ast::constraint::Constraint { selector, comparison, arguments })
85                    },
86                    _ => crate::error::ParserError::invalid_pair_rule()?,
87                }
88            }
89        }
90
91        impl<'i> std::convert::TryFrom<pest::iterators::Pair<'i, Rule>> for crate::ast::Operator {
92            type Error = crate::error::ParserError;
93
94            fn try_from(
95                value: pest::iterators::Pair<'i, Rule>,
96            ) -> std::result::Result<Self, Self::Error> {
97                match value.as_rule() {
98                    Rule::operator => match value.into_inner().next() {
99                        Some(pair) if pair.as_rule() == Rule::and_op => {
100                            Ok(crate::ast::Operator::And)
101                        },
102                        Some(pair) if pair.as_rule() == Rule::or_op => Ok(crate::ast::Operator::Or),
103                        _ => ParserError::invalid_pair_rule()?,
104                    },
105                    _ => ParserError::invalid_pair_rule()?,
106                }
107            }
108        }
109
110        impl<'i> std::convert::TryFrom<pest::iterators::Pair<'i, Rule>> for crate::ast::expr::Expr {
111            type Error = crate::error::ParserError;
112
113            fn try_from(
114                value: pest::iterators::Pair<'i, Rule>,
115            ) -> std::result::Result<Self, Self::Error> {
116                let mut op_vec: std::vec::Vec<crate::ast::Operator> = vec![];
117                let mut expr_vec: std::vec::Vec<Expr> = vec![];
118
119                let mut parse_op =
120                    |pair: pest::iterators::Pair<'i, Rule>| -> crate::ParserResult<()> {
121                        match pair.as_rule() {
122                            Rule::operator if vec![";", "and"].contains(&pair.as_str()) => {
123                                op_vec.push(crate::ast::Operator::And)
124                            },
125                            Rule::operator if vec![",", "or"].contains(&pair.as_str()) => {
126                                op_vec.push(crate::ast::Operator::Or)
127                            },
128                            _ => crate::error::ParserError::invalid_pair_rule()?,
129                        }
130                        Ok(())
131                    };
132
133                match value.as_rule() {
134                    Rule::expression => {
135                        for expr_item in value.into_inner() {
136                            match expr_item.as_rule() {
137                                Rule::constraint => {
138                                    expr_vec.push(Expr::Item(expr_item.try_into()?))
139                                },
140                                Rule::group => expr_vec.push(Expr::try_from(expr_item)?),
141                                Rule::operator => parse_op(expr_item)?,
142                                _ => crate::error::ParserError::invalid_pair_rule()?,
143                            }
144                        }
145                    },
146                    Rule::group => {
147                        for group_item in value.into_inner() {
148                            match group_item.as_rule() {
149                                Rule::expression => expr_vec.push(Expr::try_from(group_item)?),
150                                Rule::operator => parse_op(group_item)?,
151                                _ => crate::error::ParserError::invalid_pair_rule()?,
152                            }
153                        }
154                    },
155                    _ => crate::error::ParserError::invalid_pair_rule()?,
156                }
157
158                while let Some(top_op) = op_vec.pop() {
159                    if expr_vec.len() < 2 {
160                        crate::error::ParserError::invalid_pair_rule()?
161                    } else {
162                        let right = expr_vec.pop().unwrap();
163                        let left = expr_vec.pop().unwrap();
164                        expr_vec.push(crate::ast::expr::Expr::Node(
165                            top_op,
166                            Box::new(left),
167                            Box::new(right),
168                        ));
169                    }
170                }
171
172                if op_vec.is_empty() && expr_vec.len() == 1 {
173                    Ok(expr_vec.pop().unwrap())
174                } else {
175                    crate::error::ParserError::invalid_pair_rule()?
176                }
177            }
178        }
179    };
180}