From edd3998244bea7be0c6f85f8e9b883a49184bfdb Mon Sep 17 00:00:00 2001 From: mainak55512 Date: Thu, 17 Oct 2024 09:57:18 +0530 Subject: [PATCH] handled most of the errors properly --- src/main.rs | 6 +-- src/query.rs | 14 ++--- src/query/interpreter.rs | 114 +++++++++++++++++---------------------- src/query/parser.rs | 58 ++++++++++---------- 4 files changed, 91 insertions(+), 101 deletions(-) diff --git a/src/main.rs b/src/main.rs index d09cc89..220052f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,7 +27,7 @@ fn main() -> Result<(), Box> { let cli = Cli::parse(); let content = if let Some(load) = cli.load.as_deref() { - fs::read_to_string(load).map_err(|err| err.to_string())? + fs::read_to_string(load).map_err(|_| "File not found or couldn't read from file")? } else { io::stdin() .lock() @@ -38,7 +38,7 @@ fn main() -> Result<(), Box> { let content = serde_json::from_str::>(&content)?; let query_string = cli.query.as_deref().unwrap_or_default(); - let query = Query::new(query_string); + let query = Query::new(query_string)?; let params = cli.params.unwrap_or_default(); let params = params @@ -66,7 +66,7 @@ fn main() -> Result<(), Box> { // apply the query and params to content. let mut output = Vec::new(); for obj in &content { - if query.eval(obj) { + if query.eval(obj)? { output.push(filter(obj)); } } diff --git a/src/query.rs b/src/query.rs index bcc1b9d..771c247 100644 --- a/src/query.rs +++ b/src/query.rs @@ -12,17 +12,17 @@ pub struct Query { } impl Query { - pub fn new(query: &str) -> Self { + pub fn new(query: &str) -> Result> { let mut tokens = lexer::tokenize(query); - let ast = parser::parse_ast(&mut tokens); - Self { ast } + let ast = parser::parse_ast(&mut tokens)?; + Ok(Self { ast }) } - pub fn eval(&self, obj: &Value) -> bool { - if let RuntimeType::Bool(result) = interpreter::eval_ast_stmt(obj, &self.ast) { - result + pub fn eval(&self, obj: &Value) -> Result> { + if let RuntimeType::Bool(result) = interpreter::eval_ast_stmt(obj, &self.ast)? { + Ok(result) } else { - false + Ok(false) } } } diff --git a/src/query/interpreter.rs b/src/query/interpreter.rs index 5beb0b8..6e578f0 100644 --- a/src/query/interpreter.rs +++ b/src/query/interpreter.rs @@ -8,7 +8,10 @@ pub enum RuntimeType { Bool(bool), } -pub(super) fn eval_ast_stmt(obj: &Value, ast: &ASTNode) -> RuntimeType { +pub(super) fn eval_ast_stmt( + obj: &Value, + ast: &ASTNode, +) -> Result> { let kind = match ast { ASTNode::PrimarySymbol(ast) => ast.kind, ASTNode::BinaryExpr(ast) => ast.kind, @@ -17,29 +20,32 @@ pub(super) fn eval_ast_stmt(obj: &Value, ast: &ASTNode) -> RuntimeType { match kind { LiteralType::LogicalExpr => eval_logical_expr(obj, ast), LiteralType::BinaryExpr => eval_binary_expr(obj, ast), - LiteralType::NumericLiteral => RuntimeType::Element(ast.clone()), - LiteralType::StringLiteral => RuntimeType::Element(ast.clone()), - LiteralType::BinaryOperator => RuntimeType::Bool(false), - LiteralType::NoneType => RuntimeType::Bool(true), + LiteralType::NumericLiteral => Ok(RuntimeType::Element(ast.clone())), + LiteralType::StringLiteral => Ok(RuntimeType::Element(ast.clone())), + LiteralType::BinaryOperator => Ok(RuntimeType::Bool(false)), + LiteralType::NoneType => Ok(RuntimeType::Bool(true)), } } -fn eval_logical_expr(obj: &Value, ast: &ASTNode) -> RuntimeType { +fn eval_logical_expr( + obj: &Value, + ast: &ASTNode, +) -> Result> { if let ASTNode::BinaryExpr(ref ast) = ast { - let lhs = eval_ast_stmt(obj, &ast.left); - let rhs = eval_ast_stmt(obj, &ast.right); - return _eval_logical_expr(lhs, rhs, &ast.operator); + let lhs = eval_ast_stmt(obj, &ast.left)?; + let rhs = eval_ast_stmt(obj, &ast.right)?; + return Ok(_eval_logical_expr(lhs, rhs, &ast.operator)); } - RuntimeType::Bool(false) + Ok(RuntimeType::Bool(false)) } -fn eval_binary_expr(obj: &Value, ast: &ASTNode) -> RuntimeType { +fn eval_binary_expr(obj: &Value, ast: &ASTNode) -> Result> { if let ASTNode::BinaryExpr(ref ast) = ast { - let lhs = eval_ast_stmt(obj, &ast.left); - let rhs = eval_ast_stmt(obj, &ast.right); + let lhs = eval_ast_stmt(obj, &ast.left)?; + let rhs = eval_ast_stmt(obj, &ast.right)?; return _eval_binary_expr(obj, lhs, rhs, &ast.operator); } - RuntimeType::Bool(false) + Ok(RuntimeType::Bool(false)) } fn _eval_binary_expr( @@ -47,7 +53,7 @@ fn _eval_binary_expr( lhs: RuntimeType, rhs: RuntimeType, operator: &str, -) -> RuntimeType { +) -> Result> { let left = if let RuntimeType::Element(ASTNode::PrimarySymbol(val)) = &lhs { &val.symbol } else { @@ -61,66 +67,46 @@ fn _eval_binary_expr( match operator { "=" => match right_node_type { - LiteralType::NumericLiteral => RuntimeType::Bool( - get_value_from_obj(obj, left) - .to_string() - .parse::() - .expect("Not a Number") - == right.parse::().expect("Not a Number"), - ), - _ => RuntimeType::Bool(get_value_from_obj(obj, left) == right), + LiteralType::NumericLiteral => Ok(RuntimeType::Bool( + get_value_from_obj(obj, left).to_string().parse::()? + == right.parse::()?, + )), + _ => Ok(RuntimeType::Bool(get_value_from_obj(obj, left) == right)), }, ">" => match right_node_type { - LiteralType::NumericLiteral => RuntimeType::Bool( - get_value_from_obj(obj, left) - .to_string() - .parse::() - .expect("Not a Number") - > right.parse::().expect("Not a Number"), - ), - _ => RuntimeType::Bool(false), + LiteralType::NumericLiteral => Ok(RuntimeType::Bool( + get_value_from_obj(obj, left).to_string().parse::()? > right.parse::()?, + )), + _ => Ok(RuntimeType::Bool(false)), }, "<" => match right_node_type { - LiteralType::NumericLiteral => RuntimeType::Bool( - get_value_from_obj(obj, left) - .to_string() - .parse::() - .expect("Not a Number") - < right.parse::().expect("Not a Number"), - ), - _ => RuntimeType::Bool(false), + LiteralType::NumericLiteral => Ok(RuntimeType::Bool( + get_value_from_obj(obj, left).to_string().parse::()? < right.parse::()?, + )), + _ => Ok(RuntimeType::Bool(false)), }, ">=" => match right_node_type { - LiteralType::NumericLiteral => RuntimeType::Bool( - get_value_from_obj(obj, left) - .to_string() - .parse::() - .expect("Not a Number") - >= right.parse::().expect("Not a Number"), - ), - _ => RuntimeType::Bool(false), + LiteralType::NumericLiteral => Ok(RuntimeType::Bool( + get_value_from_obj(obj, left).to_string().parse::()? + >= right.parse::()?, + )), + _ => Ok(RuntimeType::Bool(false)), }, "<=" => match right_node_type { - LiteralType::NumericLiteral => RuntimeType::Bool( - get_value_from_obj(obj, left) - .to_string() - .parse::() - .expect("Not a Number") - <= right.parse::().expect("Not a Number"), - ), - _ => RuntimeType::Bool(false), + LiteralType::NumericLiteral => Ok(RuntimeType::Bool( + get_value_from_obj(obj, left).to_string().parse::()? + <= right.parse::()?, + )), + _ => Ok(RuntimeType::Bool(false)), }, "!=" => match right_node_type { - LiteralType::NumericLiteral => RuntimeType::Bool( - get_value_from_obj(obj, left) - .to_string() - .parse::() - .expect("Not a Number") - != right.parse::().expect("Not a Number"), - ), - _ => RuntimeType::Bool(get_value_from_obj(obj, left) != right), + LiteralType::NumericLiteral => Ok(RuntimeType::Bool( + get_value_from_obj(obj, left).to_string().parse::()? + != right.parse::()?, + )), + _ => Ok(RuntimeType::Bool(get_value_from_obj(obj, left) != right)), }, - _ => RuntimeType::Bool(false), + _ => Ok(RuntimeType::Bool(false)), } } diff --git a/src/query/parser.rs b/src/query/parser.rs index e8ee1c9..e23a72d 100644 --- a/src/query/parser.rs +++ b/src/query/parser.rs @@ -33,22 +33,22 @@ pub struct BinaryExpr { pub operator: String, } -pub(super) fn parse_ast(tokens: &mut VecDeque) -> ASTNode { +pub(super) fn parse_ast( + tokens: &mut VecDeque, +) -> Result> { if tokens.is_empty() { - return ASTNode::NoneType; + return Ok(ASTNode::NoneType); } - let mut left = parse_binary_expr(tokens); + let mut left = parse_binary_expr(tokens)?; if !tokens.is_empty() && tokens[0].val != "&&" && tokens[0].val != "||" { - println!("Query is invalid"); - std::process::exit(1); + return Err("Query is invalid".into()); } while !tokens.is_empty() && (tokens[0].val == "&&" || tokens[0].val == "||") { - let operator = tokens.pop_front().expect("Empty operator").val; + let operator = tokens.pop_front().ok_or("Empty operator")?.val; if tokens.is_empty() { - println!("Query is invalid"); - std::process::exit(1); + return Err("Query is invalid".into()); } - let right = parse_binary_expr(tokens); + let right = parse_binary_expr(tokens)?; left = ASTNode::BinaryExpr(Box::new(BinaryExpr { kind: LiteralType::LogicalExpr, left, @@ -56,35 +56,39 @@ pub(super) fn parse_ast(tokens: &mut VecDeque) -> ASTNode { operator, })) } - left + Ok(left) } -fn parse_primary_expr(token_array: &mut VecDeque) -> ASTNode { +fn parse_primary_expr( + token_array: &mut VecDeque, +) -> Result> { let tk = &token_array[0].token_type; match tk { - TokenType::Number => ASTNode::PrimarySymbol(PrimarySymbol { + TokenType::Number => Ok(ASTNode::PrimarySymbol(PrimarySymbol { kind: LiteralType::NumericLiteral, - symbol: token_array.pop_front().expect("NaN").val, - }), - TokenType::String => ASTNode::PrimarySymbol(PrimarySymbol { + symbol: token_array.pop_front().ok_or("Not a Number")?.val, + })), + TokenType::String => Ok(ASTNode::PrimarySymbol(PrimarySymbol { kind: LiteralType::StringLiteral, - symbol: token_array.pop_front().expect("Invalid String").val, - }), - TokenType::Binary => ASTNode::PrimarySymbol(PrimarySymbol { + symbol: token_array.pop_front().ok_or("Invalid String")?.val, + })), + TokenType::Binary => Ok(ASTNode::PrimarySymbol(PrimarySymbol { kind: LiteralType::BinaryOperator, - symbol: token_array.pop_front().expect("Invalid Operator").val, - }), + symbol: token_array.pop_front().ok_or("Invalid Operator")?.val, + })), TokenType::Paren => { token_array.pop_front(); - let value = parse_ast(token_array); + let value = parse_ast(token_array)?; token_array.pop_front(); - value + Ok(value) } } } -fn parse_binary_expr(token_array: &mut VecDeque) -> ASTNode { - let mut left = parse_primary_expr(token_array); +fn parse_binary_expr( + token_array: &mut VecDeque, +) -> Result> { + let mut left = parse_primary_expr(token_array)?; while !token_array.is_empty() && (token_array[0].val == "=" || token_array[0].val == ">=" @@ -93,8 +97,8 @@ fn parse_binary_expr(token_array: &mut VecDeque) -> ASTNode { || token_array[0].val == "<" || token_array[0].val == "!=") { - let operator = token_array.pop_front().expect("Invalid Operator").val; - let right = parse_primary_expr(token_array); + let operator = token_array.pop_front().ok_or("Invalid Operator")?.val; + let right = parse_primary_expr(token_array)?; left = ASTNode::BinaryExpr(Box::new(BinaryExpr { kind: LiteralType::BinaryExpr, left, @@ -102,5 +106,5 @@ fn parse_binary_expr(token_array: &mut VecDeque) -> ASTNode { operator, })) } - left + Ok(left) }