error handling

main
Ziyang Hu 2 years ago
parent fcfff45123
commit fa9066725b

@ -13,4 +13,5 @@ uuid = "0.8"
chrono = "0.4" chrono = "0.4"
rocksdb = "0.18.0" rocksdb = "0.18.0"
anyhow = "1.0" anyhow = "1.0"
lazy_static = "1.4.0" lazy_static = "1.4.0"
thiserror = "1.0.30"

@ -3,10 +3,32 @@ use pest::Parser as PestParser;
use pest::prec_climber::{Assoc, PrecClimber, Operator}; use pest::prec_climber::{Assoc, PrecClimber, Operator};
use crate::parser::Parser; use crate::parser::Parser;
use crate::parser::Rule; use crate::parser::Rule;
use anyhow::Result;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use crate::ast::Expr::Const; use crate::ast::Expr::Const;
use crate::value::Value; use crate::value::Value;
use thiserror::Error;
#[derive(Error, Debug)]
pub enum CozoError {
#[error("Invalid UTF code")]
InvalidUtfCode,
#[error("Type mismatch")]
InfixTypeMismatch {
op: Rule,
lhs: Value<'static>,
rhs: Value<'static>,
},
#[error(transparent)]
ParseInt(#[from] std::num::ParseIntError),
#[error(transparent)]
ParseFloat(#[from] std::num::ParseFloatError),
#[error(transparent)]
Parse(#[from] pest::error::Error<Rule>),
}
lazy_static! { lazy_static! {
@ -37,84 +59,86 @@ pub enum Expr<'a> {
Const(Value<'a>), Const(Value<'a>),
} }
fn parse_expr_infix<'a>(lhs: Result<Expr<'a>>, op: Pair<Rule>, rhs: Result<Expr<'a>>) -> Result<Expr<'a>> { fn parse_expr_infix<'a>(lhs: Result<Expr<'a>, CozoError>, op: Pair<Rule>, rhs: Result<Expr<'a>, CozoError>) -> Result<Expr<'a>, CozoError> {
let lhs = lhs?; let lhs = lhs?;
let rhs = rhs?; let rhs = rhs?;
if let (Const(a), Const(b)) = (lhs, rhs) { if let (Const(a), Const(b)) = (lhs, rhs) {
match op.as_rule() { let rule = op.as_rule();
return match rule {
Rule::op_add => { Rule::op_add => {
match (a, b) { match (a, b) {
(Value::Null, _) => return Ok(Const(Value::Null)), (Value::Null, _) => Ok(Const(Value::Null)),
(_, Value::Null) => return Ok(Const(Value::Null)), (_, Value::Null) => Ok(Const(Value::Null)),
(Value::Int(va), Value::Int(vb)) => return Ok(Const(Value::Int(va + vb))), (Value::Int(va), Value::Int(vb)) => Ok(Const(Value::Int(va + vb))),
(Value::Float(va), Value::Int(vb)) => return Ok(Const(Value::Float(va + vb as f64))), (Value::Float(va), Value::Int(vb)) => Ok(Const(Value::Float(va + vb as f64))),
(Value::Int(va), Value::Float(vb)) => return Ok(Const(Value::Float(va as f64 + vb))), (Value::Int(va), Value::Float(vb)) => Ok(Const(Value::Float(va as f64 + vb))),
(Value::Float(va), Value::Float(vb)) => return Ok(Const(Value::Float(va + vb))), (Value::Float(va), Value::Float(vb)) => Ok(Const(Value::Float(va + vb))),
(Value::OwnString(va), Value::OwnString(vb)) => return Ok(Const(Value::OwnString(Box::new(*va + &*vb)))), (Value::OwnString(va), Value::OwnString(vb)) => Ok(Const(Value::OwnString(Box::new(*va + &*vb)))),
(Value::OwnString(va), Value::RefString(vb)) => return Ok(Const(Value::OwnString(Box::new(*va + &*vb)))), (Value::OwnString(va), Value::RefString(vb)) => Ok(Const(Value::OwnString(Box::new(*va + &*vb)))),
(Value::RefString(va), Value::OwnString(vb)) => return Ok(Const(Value::OwnString(Box::new(va.to_string() + &*vb)))), (Value::RefString(va), Value::OwnString(vb)) => Ok(Const(Value::OwnString(Box::new(va.to_string() + &*vb)))),
(Value::RefString(va), Value::RefString(vb)) => return Ok(Const(Value::OwnString(Box::new(va.to_string() + &*vb)))), (Value::RefString(va), Value::RefString(vb)) => Ok(Const(Value::OwnString(Box::new(va.to_string() + &*vb)))),
_ => panic!() (a, b) => Err(CozoError::InfixTypeMismatch { op: rule, lhs: a.into_owned(), rhs: b.into_owned() })
} }
} }
Rule::op_sub => { Rule::op_sub => {
match (a, b) { match (a, b) {
(Value::Null, _) => return Ok(Const(Value::Null)), (Value::Null, _) => Ok(Const(Value::Null)),
(_, Value::Null) => return Ok(Const(Value::Null)), (_, Value::Null) => Ok(Const(Value::Null)),
(Value::Int(va), Value::Int(vb)) => return Ok(Const(Value::Int(va - vb))), (Value::Int(va), Value::Int(vb)) => Ok(Const(Value::Int(va - vb))),
(Value::Float(va), Value::Int(vb)) => return Ok(Const(Value::Float(va - vb as f64))), (Value::Float(va), Value::Int(vb)) => Ok(Const(Value::Float(va - vb as f64))),
(Value::Int(va), Value::Float(vb)) => return Ok(Const(Value::Float(va as f64 - vb))), (Value::Int(va), Value::Float(vb)) => Ok(Const(Value::Float(va as f64 - vb))),
(Value::Float(va), Value::Float(vb)) => return Ok(Const(Value::Float(va - vb))), (Value::Float(va), Value::Float(vb)) => Ok(Const(Value::Float(va - vb))),
_ => panic!() (a, b) => Err(CozoError::InfixTypeMismatch { op: rule, lhs: a.into_owned(), rhs: b.into_owned() })
} }
} }
Rule::op_mul => { Rule::op_mul => {
match (a, b) { match (a, b) {
(Value::Null, _) => return Ok(Const(Value::Null)), (Value::Null, _) => Ok(Const(Value::Null)),
(_, Value::Null) => return Ok(Const(Value::Null)), (_, Value::Null) => Ok(Const(Value::Null)),
(Value::Int(va), Value::Int(vb)) => return Ok(Const(Value::Int(va * vb))), (Value::Int(va), Value::Int(vb)) => Ok(Const(Value::Int(va * vb))),
(Value::Float(va), Value::Int(vb)) => return Ok(Const(Value::Float(va * vb as f64))), (Value::Float(va), Value::Int(vb)) => Ok(Const(Value::Float(va * vb as f64))),
(Value::Int(va), Value::Float(vb)) => return Ok(Const(Value::Float(va as f64 * vb))), (Value::Int(va), Value::Float(vb)) => Ok(Const(Value::Float(va as f64 * vb))),
(Value::Float(va), Value::Float(vb)) => return Ok(Const(Value::Float(va * vb))), (Value::Float(va), Value::Float(vb)) => Ok(Const(Value::Float(va * vb))),
_ => panic!() (a, b) => Err(CozoError::InfixTypeMismatch { op: rule, lhs: a.into_owned(), rhs: b.into_owned() })
} }
} }
Rule::op_div => { Rule::op_div => {
match (a, b) { match (a, b) {
(Value::Null, _) => return Ok(Const(Value::Null)), (Value::Null, _) => Ok(Const(Value::Null)),
(_, Value::Null) => return Ok(Const(Value::Null)), (_, Value::Null) => Ok(Const(Value::Null)),
(Value::Int(va), Value::Int(vb)) => return Ok(Const(Value::Float(va as f64 / vb as f64))), (Value::Int(va), Value::Int(vb)) => Ok(Const(Value::Float(va as f64 / vb as f64))),
(Value::Float(va), Value::Int(vb)) => return Ok(Const(Value::Float(va / vb as f64))), (Value::Float(va), Value::Int(vb)) => Ok(Const(Value::Float(va / vb as f64))),
(Value::Int(va), Value::Float(vb)) => return Ok(Const(Value::Float(va as f64 / vb))), (Value::Int(va), Value::Float(vb)) => Ok(Const(Value::Float(va as f64 / vb))),
(Value::Float(va), Value::Float(vb)) => return Ok(Const(Value::Float(va / vb))), (Value::Float(va), Value::Float(vb)) => Ok(Const(Value::Float(va / vb))),
_ => panic!() (a, b) => Err(CozoError::InfixTypeMismatch { op: rule, lhs: a.into_owned(), rhs: b.into_owned() })
} }
} }
Rule::op_eq => return Ok(Const(Value::Bool(a == b))), Rule::op_eq => Ok(Const(Value::Bool(a == b))),
Rule::op_ne => return Ok(Const(Value::Bool(a != b))), Rule::op_ne => Ok(Const(Value::Bool(a != b))),
Rule::op_or => { Rule::op_or => {
match (a, b) { match (a, b) {
(Value::Null, Value::Null) => return Ok(Const(Value::Null)), (Value::Null, Value::Null) => Ok(Const(Value::Null)),
(Value::Null, Value::Bool(b)) => return Ok(Const(Value::Bool(b))), (Value::Null, Value::Bool(b)) => Ok(Const(Value::Bool(b))),
(Value::Bool(b), Value::Null) => return Ok(Const(Value::Bool(b))), (Value::Bool(b), Value::Null) => Ok(Const(Value::Bool(b))),
(Value::Bool(a), Value::Bool(b)) => return Ok(Const(Value::Bool(a || b))), (Value::Bool(a), Value::Bool(b)) => Ok(Const(Value::Bool(a || b))),
_ => panic!() (a, b) => Err(CozoError::InfixTypeMismatch { op: rule, lhs: a.into_owned(), rhs: b.into_owned() })
} }
}, }
Rule::op_and => { Rule::op_and => {
match (a, b) { match (a, b) {
(Value::Null, Value::Null) => return Ok(Const(Value::Null)), (Value::Null, Value::Null) => Ok(Const(Value::Null)),
(Value::Null, Value::Bool(_)) => return Ok(Const(Value::Null)), (Value::Null, Value::Bool(_)) => Ok(Const(Value::Null)),
(Value::Bool(_), Value::Null) => return Ok(Const(Value::Null)), (Value::Bool(_), Value::Null) => Ok(Const(Value::Null)),
(Value::Bool(a), Value::Bool(b)) => return Ok(Const(Value::Bool(a && b))), (Value::Bool(a), Value::Bool(b)) => Ok(Const(Value::Bool(a && b))),
_ => panic!() (a, b) => Err(CozoError::InfixTypeMismatch { op: rule, lhs: a.into_owned(), rhs: b.into_owned() })
} }
}, }
Rule::op_coalesce => return Ok(if a == Value::Null { Const(b) } else { Const(a) }), Rule::op_coalesce => Ok(if a == Value::Null { Const(b) } else { Const(a) }),
_ => {} _ => { unimplemented!() }
} };
} else {
unimplemented!()
} }
unimplemented!()
} }
#[inline] #[inline]
@ -123,7 +147,7 @@ fn parse_int(s: &str, radix: u32) -> i64 {
} }
#[inline] #[inline]
fn parse_quoted_string(pairs: Pairs<Rule>) -> Result<String> { fn parse_quoted_string(pairs: Pairs<Rule>) -> Result<String, CozoError> {
let mut ret = String::new(); let mut ret = String::new();
for pair in pairs { for pair in pairs {
let s = pair.as_str(); let s = pair.as_str();
@ -138,11 +162,8 @@ fn parse_quoted_string(pairs: Pairs<Rule>) -> Result<String> {
r"\t" => ret.push('\t'), r"\t" => ret.push('\t'),
s if s.starts_with(r"\u") => { s if s.starts_with(r"\u") => {
let code = parse_int(s, 16) as u32; let code = parse_int(s, 16) as u32;
let ch = char::from_u32(code); let ch = char::from_u32(code).ok_or(CozoError::InvalidUtfCode)?;
match ch { ret.push(ch);
Some(c) => ret.push(c),
None => panic!()
}
} }
s => ret.push_str(s) s => ret.push_str(s)
} }
@ -152,7 +173,7 @@ fn parse_quoted_string(pairs: Pairs<Rule>) -> Result<String> {
#[inline] #[inline]
fn parse_s_quoted_string(pairs: Pairs<Rule>) -> Result<String> { fn parse_s_quoted_string(pairs: Pairs<Rule>) -> Result<String, CozoError> {
let mut ret = String::new(); let mut ret = String::new();
for pair in pairs { for pair in pairs {
let s = pair.as_str(); let s = pair.as_str();
@ -167,11 +188,8 @@ fn parse_s_quoted_string(pairs: Pairs<Rule>) -> Result<String> {
r"\t" => ret.push('\t'), r"\t" => ret.push('\t'),
s if s.starts_with(r"\u") => { s if s.starts_with(r"\u") => {
let code = parse_int(s, 16) as u32; let code = parse_int(s, 16) as u32;
let ch = char::from_u32(code); let ch = char::from_u32(code).ok_or(CozoError::InvalidUtfCode)?;
match ch { ret.push(ch);
Some(c) => ret.push(c),
None => panic!()
}
} }
s => ret.push_str(s) s => ret.push_str(s)
} }
@ -179,7 +197,7 @@ fn parse_s_quoted_string(pairs: Pairs<Rule>) -> Result<String> {
Ok(ret) Ok(ret)
} }
fn parse_expr_primary(pair: Pair<Rule>) -> Result<Expr> { fn parse_expr_primary(pair: Pair<Rule>) -> Result<Expr, CozoError> {
match pair.as_rule() { match pair.as_rule() {
Rule::expr => parse_expr_primary(pair.into_inner().next().unwrap()), Rule::expr => parse_expr_primary(pair.into_inner().next().unwrap()),
Rule::term => parse_expr_primary(pair.into_inner().next().unwrap()), Rule::term => parse_expr_primary(pair.into_inner().next().unwrap()),
@ -200,11 +218,11 @@ fn parse_expr_primary(pair: Pair<Rule>) -> Result<Expr> {
} }
} }
fn parse_expr(pair: Pair<Rule>) -> Result<Expr> { fn parse_expr(pair: Pair<Rule>) -> Result<Expr, CozoError> {
PREC_CLIMBER.climb(pair.into_inner(), parse_expr_primary, parse_expr_infix) PREC_CLIMBER.climb(pair.into_inner(), parse_expr_primary, parse_expr_infix)
} }
pub fn parse_expr_from_str(inp: &str) -> Result<Expr> { pub fn parse_expr_from_str(inp: &str) -> Result<Expr, CozoError> {
let expr_tree = Parser::parse(Rule::expr, inp)?.next().unwrap(); let expr_tree = Parser::parse(Rule::expr, inp)?.next().unwrap();
parse_expr(expr_tree) parse_expr(expr_tree)
} }

Loading…
Cancel
Save