Cesar Rodas 10 сар өмнө
parent
commit
ac9b5b35e8

+ 19 - 0
utxo/src/filter_expr/mod.rs

@@ -27,6 +27,25 @@ pub enum Error {
 
     #[error("Math overflow")]
     Overflow,
+
+    #[error("Unexpected rule: {0:?}")]
+    UnexpectedRule(Rule),
+
+    #[error("Parsing error: {0:?}")]
+    ParsingError(#[from] pest::error::Error<Rule>),
+
+    #[error("Internal parsing error: Missing next rule")]
+    MissingNextRule,
+
+    #[error("Error parsing number: {0}")]
+    ParseIntError(#[from] ParseIntError),
+
+    #[error("Invalid order: {0}")]
+    InvalidOrder(String),
 }
 
+use std::num::ParseIntError;
+
+use parser::Rule;
+
 pub use self::program::Program;

+ 50 - 30
utxo/src/filter_expr/parser.rs

@@ -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,
-    }
+    })
 }

+ 3 - 5
utxo/src/filter_expr/value.rs

@@ -1,12 +1,10 @@
-use std::ops::Add;
-
 use crate::{
-    payment::PaymentTo, AccountId, Amount, Asset, PaymentFrom, RevId, Status, Tag, TxId, Type,
+    filter_expr::Error, payment::PaymentTo, AccountId, Amount, Asset, PaymentFrom, RevId, Status,
+    Tag, TxId, Type,
 };
 use chrono::{DateTime, Utc};
 use num::CheckedAdd;
-
-use super::Error;
+use std::ops::Add;
 
 #[derive(Clone, Debug, PartialEq, PartialOrd)]
 pub enum Value {