|
@@ -1,8 +1,7 @@
|
|
|
-use std::str::FromStr;
|
|
|
-
|
|
|
-// src/main.rs
|
|
|
-use pest::{error::Error, Parser, Span};
|
|
|
+use super::Error;
|
|
|
+use pest::{Parser, Span};
|
|
|
use pest_derive::Parser;
|
|
|
+use std::str::FromStr;
|
|
|
|
|
|
#[derive(Parser)]
|
|
|
#[grammar = "src/filter_expr/expr.pest"] // relative path to your .pest file
|
|
@@ -32,13 +31,13 @@ pub enum Order {
|
|
|
}
|
|
|
|
|
|
impl FromStr for Order {
|
|
|
- type Err = ();
|
|
|
+ type Err = Error;
|
|
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
|
match s {
|
|
|
"asc" => Ok(Order::Ascending),
|
|
|
"desc" => Ok(Order::Descending),
|
|
|
- _ => Err(()),
|
|
|
+ s => Err(Error::InvalidOrder(s.to_owned())),
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -133,8 +132,8 @@ fn unescape(string: &str) -> Option<String> {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-fn parse_expr(pair: pest::iterators::Pair<Rule>) -> Expr {
|
|
|
- match pair.as_rule() {
|
|
|
+fn parse_expr(pair: pest::iterators::Pair<Rule>) -> Result<Expr, Error> {
|
|
|
+ Ok(match pair.as_rule() {
|
|
|
Rule::logical_expr
|
|
|
| Rule::logical_term
|
|
|
| Rule::comparison
|
|
@@ -148,12 +147,12 @@ fn parse_expr(pair: pest::iterators::Pair<Rule>) -> Expr {
|
|
|
let (first_expr, next) = if let Some(first_expr) = last_expr {
|
|
|
(first_expr, Some(first))
|
|
|
} else {
|
|
|
- (parse_expr(first), inner.next())
|
|
|
+ (parse_expr(first)?, inner.next())
|
|
|
};
|
|
|
last_expr = Some(if let Some(op_pair) = next {
|
|
|
let op = op_pair.as_str().into();
|
|
|
- let second = inner.next().unwrap();
|
|
|
- let second_expr = parse_expr(second);
|
|
|
+ let second = inner.next().ok_or(Error::MissingNextRule)?;
|
|
|
+ let second_expr = parse_expr(second)?;
|
|
|
Expr::Op {
|
|
|
op,
|
|
|
left: Box::new(first_expr),
|
|
@@ -164,7 +163,7 @@ fn parse_expr(pair: pest::iterators::Pair<Rule>) -> Expr {
|
|
|
});
|
|
|
}
|
|
|
|
|
|
- last_expr.unwrap()
|
|
|
+ last_expr.ok_or(Error::MissingNextRule)?
|
|
|
}
|
|
|
Rule::string => {
|
|
|
let mut inner = pair.into_inner();
|
|
@@ -180,26 +179,33 @@ fn parse_expr(pair: pest::iterators::Pair<Rule>) -> Expr {
|
|
|
}
|
|
|
Rule::not_expr => {
|
|
|
let mut inner = pair.into_inner();
|
|
|
- Expr::Not(Box::new(parse_expr(inner.next().unwrap())))
|
|
|
+ Expr::Not(Box::new(
|
|
|
+ inner
|
|
|
+ .next()
|
|
|
+ .map(parse_expr)
|
|
|
+ .ok_or(Error::MissingNextRule)??,
|
|
|
+ ))
|
|
|
}
|
|
|
Rule::variable => {
|
|
|
let mut inner = pair.into_inner();
|
|
|
- let mut first = vec![inner.next().unwrap().as_str().to_owned()];
|
|
|
- while let Some(Expr::Ident(ident)) = inner.next().map(parse_expr) {
|
|
|
+ let mut first = vec![inner
|
|
|
+ .next()
|
|
|
+ .ok_or(Error::MissingNextRule)?
|
|
|
+ .as_str()
|
|
|
+ .to_owned()];
|
|
|
+ while let Some(Ok(Expr::Ident(ident))) = inner.next().map(parse_expr) {
|
|
|
first.push(ident);
|
|
|
}
|
|
|
Expr::Variable(first)
|
|
|
}
|
|
|
- Rule::number => Expr::Number(pair.as_str().parse().unwrap()),
|
|
|
+ Rule::number => Expr::Number(pair.as_str().parse()?),
|
|
|
Rule::ident => Expr::Ident(pair.as_str().to_owned()),
|
|
|
- x => {
|
|
|
- panic!("Unexpected rule: {:?} {:?}", x, pair);
|
|
|
- }
|
|
|
- }
|
|
|
+ rule => return Err(Error::UnexpectedRule(rule)),
|
|
|
+ })
|
|
|
}
|
|
|
|
|
|
-pub fn parse_query(query: &str) -> Query {
|
|
|
- let pairs = QueryParser::parse(Rule::query, query).expect("parsing");
|
|
|
+pub fn parse_query(query: &str) -> Result<Query, Error> {
|
|
|
+ let pairs = QueryParser::parse(Rule::query, query)?;
|
|
|
|
|
|
let mut where_clause = None;
|
|
|
let mut limit_clause = None;
|
|
@@ -211,31 +217,45 @@ pub fn parse_query(query: &str) -> Query {
|
|
|
break;
|
|
|
}
|
|
|
Rule::where_clause => {
|
|
|
- where_clause = Some(parse_expr(pair.into_inner().next().unwrap()));
|
|
|
+ where_clause = Some(
|
|
|
+ pair.into_inner()
|
|
|
+ .next()
|
|
|
+ .map(parse_expr)
|
|
|
+ .ok_or(Error::MissingNextRule)??,
|
|
|
+ );
|
|
|
}
|
|
|
Rule::limit_clause => {
|
|
|
- limit_clause = Some(match parse_expr(pair.into_inner().next().unwrap()) {
|
|
|
- Expr::Number(v) => v,
|
|
|
+ limit_clause = match pair
|
|
|
+ .into_inner()
|
|
|
+ .next()
|
|
|
+ .map(parse_expr)
|
|
|
+ .ok_or(Error::MissingNextRule)??
|
|
|
+ {
|
|
|
+ Expr::Number(v) => Some(v),
|
|
|
_ => unreachable!(),
|
|
|
- });
|
|
|
+ };
|
|
|
}
|
|
|
Rule::order_by_clause => {
|
|
|
let mut iter = pair.into_inner();
|
|
|
- let expr = parse_expr(iter.next().unwrap());
|
|
|
+ let expr = iter
|
|
|
+ .next()
|
|
|
+ .map(parse_expr)
|
|
|
+ .ok_or(Error::MissingNextRule)??;
|
|
|
let order = if let Some(order_by_text) = iter.next() {
|
|
|
- order_by_text.as_str().to_lowercase().parse().unwrap()
|
|
|
+ order_by_text.as_str().to_lowercase().parse()?
|
|
|
} else {
|
|
|
Order::Ascending
|
|
|
};
|
|
|
+
|
|
|
order_by_clause = Some((expr, order));
|
|
|
}
|
|
|
_ => unreachable!(),
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- Query {
|
|
|
+ Ok(Query {
|
|
|
where_clause,
|
|
|
limit_clause,
|
|
|
order_by_clause,
|
|
|
- }
|
|
|
+ })
|
|
|
}
|