error handling

main
Ziyang Hu 2 years ago
parent fcfff45123
commit fa9066725b

@ -14,3 +14,4 @@ chrono = "0.4"
rocksdb = "0.18.0"
anyhow = "1.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 crate::parser::Parser;
use crate::parser::Rule;
use anyhow::Result;
use lazy_static::lazy_static;
use crate::ast::Expr::Const;
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! {
@ -37,84 +59,86 @@ pub enum Expr<'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 rhs = rhs?;
if let (Const(a), Const(b)) = (lhs, rhs) {
match op.as_rule() {
let rule = op.as_rule();
return match rule {
Rule::op_add => {
match (a, b) {
(Value::Null, _) => return Ok(Const(Value::Null)),
(_, Value::Null) => return Ok(Const(Value::Null)),
(Value::Int(va), Value::Int(vb)) => return Ok(Const(Value::Int(va + vb))),
(Value::Float(va), Value::Int(vb)) => return Ok(Const(Value::Float(va + vb as f64))),
(Value::Int(va), Value::Float(vb)) => return Ok(Const(Value::Float(va as f64 + vb))),
(Value::Float(va), Value::Float(vb)) => return 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::RefString(vb)) => return 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::RefString(vb)) => return Ok(Const(Value::OwnString(Box::new(va.to_string() + &*vb)))),
_ => panic!()
(Value::Null, _) => Ok(Const(Value::Null)),
(_, Value::Null) => Ok(Const(Value::Null)),
(Value::Int(va), Value::Int(vb)) => Ok(Const(Value::Int(va + vb))),
(Value::Float(va), Value::Int(vb)) => Ok(Const(Value::Float(va + vb as f64))),
(Value::Int(va), Value::Float(vb)) => Ok(Const(Value::Float(va as f64 + vb))),
(Value::Float(va), Value::Float(vb)) => Ok(Const(Value::Float(va + vb))),
(Value::OwnString(va), Value::OwnString(vb)) => 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)) => 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)))),
(a, b) => Err(CozoError::InfixTypeMismatch { op: rule, lhs: a.into_owned(), rhs: b.into_owned() })
}
}
Rule::op_sub => {
match (a, b) {
(Value::Null, _) => return Ok(Const(Value::Null)),
(_, Value::Null) => return Ok(Const(Value::Null)),
(Value::Int(va), Value::Int(vb)) => return Ok(Const(Value::Int(va - vb))),
(Value::Float(va), Value::Int(vb)) => return Ok(Const(Value::Float(va - vb as f64))),
(Value::Int(va), Value::Float(vb)) => return Ok(Const(Value::Float(va as f64 - vb))),
(Value::Float(va), Value::Float(vb)) => return Ok(Const(Value::Float(va - vb))),
_ => panic!()
(Value::Null, _) => Ok(Const(Value::Null)),
(_, Value::Null) => Ok(Const(Value::Null)),
(Value::Int(va), Value::Int(vb)) => Ok(Const(Value::Int(va - vb))),
(Value::Float(va), Value::Int(vb)) => Ok(Const(Value::Float(va - vb as f64))),
(Value::Int(va), Value::Float(vb)) => Ok(Const(Value::Float(va as f64 - vb))),
(Value::Float(va), Value::Float(vb)) => Ok(Const(Value::Float(va - vb))),
(a, b) => Err(CozoError::InfixTypeMismatch { op: rule, lhs: a.into_owned(), rhs: b.into_owned() })
}
}
Rule::op_mul => {
match (a, b) {
(Value::Null, _) => return Ok(Const(Value::Null)),
(_, Value::Null) => return Ok(Const(Value::Null)),
(Value::Int(va), Value::Int(vb)) => return Ok(Const(Value::Int(va * vb))),
(Value::Float(va), Value::Int(vb)) => return Ok(Const(Value::Float(va * vb as f64))),
(Value::Int(va), Value::Float(vb)) => return Ok(Const(Value::Float(va as f64 * vb))),
(Value::Float(va), Value::Float(vb)) => return Ok(Const(Value::Float(va * vb))),
_ => panic!()
(Value::Null, _) => Ok(Const(Value::Null)),
(_, Value::Null) => Ok(Const(Value::Null)),
(Value::Int(va), Value::Int(vb)) => Ok(Const(Value::Int(va * vb))),
(Value::Float(va), Value::Int(vb)) => Ok(Const(Value::Float(va * vb as f64))),
(Value::Int(va), Value::Float(vb)) => Ok(Const(Value::Float(va as f64 * vb))),
(Value::Float(va), Value::Float(vb)) => Ok(Const(Value::Float(va * vb))),
(a, b) => Err(CozoError::InfixTypeMismatch { op: rule, lhs: a.into_owned(), rhs: b.into_owned() })
}
}
Rule::op_div => {
match (a, b) {
(Value::Null, _) => return Ok(Const(Value::Null)),
(_, Value::Null) => return Ok(Const(Value::Null)),
(Value::Int(va), Value::Int(vb)) => return 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::Int(va), Value::Float(vb)) => return Ok(Const(Value::Float(va as f64 / vb))),
(Value::Float(va), Value::Float(vb)) => return Ok(Const(Value::Float(va / vb))),
_ => panic!()
(Value::Null, _) => Ok(Const(Value::Null)),
(_, Value::Null) => Ok(Const(Value::Null)),
(Value::Int(va), Value::Int(vb)) => Ok(Const(Value::Float(va as f64 / vb as f64))),
(Value::Float(va), Value::Int(vb)) => Ok(Const(Value::Float(va / vb as f64))),
(Value::Int(va), Value::Float(vb)) => Ok(Const(Value::Float(va as f64 / vb))),
(Value::Float(va), Value::Float(vb)) => Ok(Const(Value::Float(va / vb))),
(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_ne => return Ok(Const(Value::Bool(a != b))),
Rule::op_eq => Ok(Const(Value::Bool(a == b))),
Rule::op_ne => Ok(Const(Value::Bool(a != b))),
Rule::op_or => {
match (a, b) {
(Value::Null, Value::Null) => return Ok(Const(Value::Null)),
(Value::Null, Value::Bool(b)) => return Ok(Const(Value::Bool(b))),
(Value::Bool(b), Value::Null) => return Ok(Const(Value::Bool(b))),
(Value::Bool(a), Value::Bool(b)) => return Ok(Const(Value::Bool(a || b))),
_ => panic!()
(Value::Null, Value::Null) => Ok(Const(Value::Null)),
(Value::Null, Value::Bool(b)) => Ok(Const(Value::Bool(b))),
(Value::Bool(b), Value::Null) => Ok(Const(Value::Bool(b))),
(Value::Bool(a), Value::Bool(b)) => Ok(Const(Value::Bool(a || b))),
(a, b) => Err(CozoError::InfixTypeMismatch { op: rule, lhs: a.into_owned(), rhs: b.into_owned() })
}
},
}
Rule::op_and => {
match (a, b) {
(Value::Null, Value::Null) => return Ok(Const(Value::Null)),
(Value::Null, Value::Bool(_)) => return Ok(Const(Value::Null)),
(Value::Bool(_), Value::Null) => return Ok(Const(Value::Null)),
(Value::Bool(a), Value::Bool(b)) => return Ok(Const(Value::Bool(a && b))),
_ => panic!()
(Value::Null, Value::Null) => Ok(Const(Value::Null)),
(Value::Null, Value::Bool(_)) => Ok(Const(Value::Null)),
(Value::Bool(_), Value::Null) => Ok(Const(Value::Null)),
(Value::Bool(a), Value::Bool(b)) => Ok(Const(Value::Bool(a && b))),
(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]
@ -123,7 +147,7 @@ fn parse_int(s: &str, radix: u32) -> i64 {
}
#[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();
for pair in pairs {
let s = pair.as_str();
@ -138,11 +162,8 @@ fn parse_quoted_string(pairs: Pairs<Rule>) -> Result<String> {
r"\t" => ret.push('\t'),
s if s.starts_with(r"\u") => {
let code = parse_int(s, 16) as u32;
let ch = char::from_u32(code);
match ch {
Some(c) => ret.push(c),
None => panic!()
}
let ch = char::from_u32(code).ok_or(CozoError::InvalidUtfCode)?;
ret.push(ch);
}
s => ret.push_str(s)
}
@ -152,7 +173,7 @@ fn parse_quoted_string(pairs: Pairs<Rule>) -> Result<String> {
#[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();
for pair in pairs {
let s = pair.as_str();
@ -167,11 +188,8 @@ fn parse_s_quoted_string(pairs: Pairs<Rule>) -> Result<String> {
r"\t" => ret.push('\t'),
s if s.starts_with(r"\u") => {
let code = parse_int(s, 16) as u32;
let ch = char::from_u32(code);
match ch {
Some(c) => ret.push(c),
None => panic!()
}
let ch = char::from_u32(code).ok_or(CozoError::InvalidUtfCode)?;
ret.push(ch);
}
s => ret.push_str(s)
}
@ -179,7 +197,7 @@ fn parse_s_quoted_string(pairs: Pairs<Rule>) -> Result<String> {
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() {
Rule::expr => 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)
}
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();
parse_expr(expr_tree)
}

Loading…
Cancel
Save