From 861d2a21d298e2b1eb4c697f152ec04cc9b7a6f2 Mon Sep 17 00:00:00 2001 From: Benjamin Bolte Date: Wed, 30 Oct 2024 15:00:06 -0700 Subject: [PATCH] surface more errors --- klang/src/parser/expressions.rs | 216 ++++++++++++++++++-------------- klang/src/parser/functions.rs | 2 +- klang/src/parser/literals.rs | 28 +++-- klang/src/parser/statements.rs | 69 +++++----- 4 files changed, 180 insertions(+), 135 deletions(-) diff --git a/klang/src/parser/expressions.rs b/klang/src/parser/expressions.rs index 02d1c6c..d118e9b 100644 --- a/klang/src/parser/expressions.rs +++ b/klang/src/parser/expressions.rs @@ -1,8 +1,11 @@ use super::ast::*; +use super::errors::ParseError; use super::literals::{parse_identifier, parse_literal}; use super::parser::Rule; -pub(crate) fn parse_expression(pair: pest::iterators::Pair) -> Expression { +pub(crate) fn parse_expression( + pair: pest::iterators::Pair, +) -> Result { match pair.as_rule() { Rule::expression => parse_expression(pair.into_inner().next().unwrap()), Rule::conditional => parse_conditional(pair), @@ -16,88 +19,97 @@ pub(crate) fn parse_expression(pair: pest::iterators::Pair) -> Expression Rule::postfix => parse_postfix(pair), Rule::primary => parse_primary(pair), // _ => panic!("Unknown expression type: {:?}", pair.as_rule()), - _ => Expression { expr: None }, + _ => Ok(Expression { expr: None }), } } -fn parse_conditional(pair: pest::iterators::Pair) -> Expression { - let mut parts = pair.into_inner(); +fn parse_conditional(pair: pest::iterators::Pair) -> Result { + let mut parts = pair.clone().into_inner(); match parts.len() { 1 => parse_expression(parts.next().unwrap()), 3 => { - let condition = parse_expression(parts.next().unwrap()); - let if_true = parse_expression(parts.next().unwrap()); - let if_false = parse_expression(parts.next().unwrap()); + let condition = parse_expression(parts.next().unwrap())?; + let if_true = parse_expression(parts.next().unwrap())?; + let if_false = parse_expression(parts.next().unwrap())?; - Expression { + Ok(Expression { expr: Some(expression::Expr::Conditional(Box::new(ConditionalExpr { condition: Some(Box::new(condition)), then_expr: Some(Box::new(if_true)), else_expr: Some(Box::new(if_false)), }))), - } + }) } - _ => panic!( - "Unexpected number of parts in conditional: {:?}", - parts.len() - ), + _ => Err(ParseError::from_pair( + format!( + "Unexpected number of parts in conditional: {:?}", + parts.len() + ), + pair, + )), } } -fn parse_logical_or(pair: pest::iterators::Pair) -> Expression { - let mut parts = pair.into_inner(); +fn parse_logical_or(pair: pest::iterators::Pair) -> Result { + let mut parts = pair.clone().into_inner(); match parts.len() { 1 => parse_expression(parts.next().unwrap()), 2 => { - let left = parse_expression(parts.next().unwrap()); - let right = parse_expression(parts.next().unwrap()); + let left = parse_expression(parts.next().unwrap())?; + let right = parse_expression(parts.next().unwrap())?; - Expression { + Ok(Expression { expr: Some(expression::Expr::Binary(Box::new(BinaryExpr { operator: BinaryOperator::Or.into(), left: Some(Box::new(left)), right: Some(Box::new(right)), }))), - } + }) } - _ => panic!( - "Unexpected number of parts in logical or: {:?}", - parts.len() - ), + _ => Err(ParseError::from_pair( + format!( + "Unexpected number of parts in logical or: {:?}", + parts.len() + ), + pair, + )), } } -fn parse_logical_and(pair: pest::iterators::Pair) -> Expression { - let mut parts = pair.into_inner(); +fn parse_logical_and(pair: pest::iterators::Pair) -> Result { + let mut parts = pair.clone().into_inner(); match parts.len() { 1 => parse_expression(parts.next().unwrap()), 2 => { - let left = parse_expression(parts.next().unwrap()); - let right = parse_expression(parts.next().unwrap()); + let left = parse_expression(parts.next().unwrap())?; + let right = parse_expression(parts.next().unwrap())?; - Expression { + Ok(Expression { expr: Some(expression::Expr::Binary(Box::new(BinaryExpr { operator: BinaryOperator::And.into(), left: Some(Box::new(left)), right: Some(Box::new(right)), }))), - } + }) } - _ => panic!( - "Unexpected number of parts in logical and: {:?}", - parts.len() - ), + _ => Err(ParseError::from_pair( + format!( + "Unexpected number of parts in logical and: {:?}", + parts.len() + ), + pair, + )), } } -fn parse_equality(pair: pest::iterators::Pair) -> Expression { - let mut parts = pair.into_inner(); +fn parse_equality(pair: pest::iterators::Pair) -> Result { + let mut parts = pair.clone().into_inner(); match parts.len() { 1 => parse_expression(parts.next().unwrap()), 3 => { - let left = parse_expression(parts.next().unwrap()); + let left = parse_expression(parts.next().unwrap())?; let operator = parts.next().unwrap(); - let right = parse_expression(parts.next().unwrap()); + let right = parse_expression(parts.next().unwrap())?; let operator = match operator.as_str() { "==" => BinaryOperator::Eq, @@ -105,26 +117,29 @@ fn parse_equality(pair: pest::iterators::Pair) -> Expression { _ => panic!("Unknown equality operator: {:?}", operator), }; - Expression { + Ok(Expression { expr: Some(expression::Expr::Binary(Box::new(BinaryExpr { operator: operator.into(), left: Some(Box::new(left)), right: Some(Box::new(right)), }))), - } + }) } - _ => panic!("Unexpected number of parts in equality: {:?}", parts.len()), + _ => Err(ParseError::from_pair( + format!("Unexpected number of parts in equality: {:?}", parts.len()), + pair, + )), } } -fn parse_comparison(pair: pest::iterators::Pair) -> Expression { - let mut parts = pair.into_inner(); +fn parse_comparison(pair: pest::iterators::Pair) -> Result { + let mut parts = pair.clone().into_inner(); match parts.len() { 1 => parse_expression(parts.next().unwrap()), 3 => { - let left = parse_expression(parts.next().unwrap()); + let left = parse_expression(parts.next().unwrap())?; let operator = parts.next().unwrap(); - let right = parse_expression(parts.next().unwrap()); + let right = parse_expression(parts.next().unwrap())?; let operator = match operator.as_str() { "<" => BinaryOperator::Lt, @@ -134,29 +149,32 @@ fn parse_comparison(pair: pest::iterators::Pair) -> Expression { _ => panic!("Unknown comparison operator: {:?}", operator), }; - Expression { + Ok(Expression { expr: Some(expression::Expr::Binary(Box::new(BinaryExpr { operator: operator.into(), left: Some(Box::new(left)), right: Some(Box::new(right)), }))), - } + }) } - _ => panic!( - "Unexpected number of parts in comparison: {:?}", - parts.len() - ), + _ => Err(ParseError::from_pair( + format!( + "Unexpected number of parts in comparison: {:?}", + parts.len() + ), + pair, + )), } } -fn parse_additive(pair: pest::iterators::Pair) -> Expression { - let mut parts = pair.into_inner(); +fn parse_additive(pair: pest::iterators::Pair) -> Result { + let mut parts = pair.clone().into_inner(); match parts.len() { 1 => parse_expression(parts.next().unwrap()), 3 => { - let left = parse_expression(parts.next().unwrap()); + let left = parse_expression(parts.next().unwrap())?; let operator = parts.next().unwrap(); - let right = parse_expression(parts.next().unwrap()); + let right = parse_expression(parts.next().unwrap())?; let operator = match operator.as_str() { "+" => BinaryOperator::Add, @@ -164,26 +182,29 @@ fn parse_additive(pair: pest::iterators::Pair) -> Expression { _ => panic!("Unknown additive operator: {:?}", operator), }; - Expression { + Ok(Expression { expr: Some(expression::Expr::Binary(Box::new(BinaryExpr { operator: operator.into(), left: Some(Box::new(left)), right: Some(Box::new(right)), }))), - } + }) } - _ => panic!("Unexpected number of parts in additive: {:?}", parts.len()), + _ => Err(ParseError::from_pair( + format!("Unexpected number of parts in additive: {:?}", parts.len()), + pair, + )), } } -fn parse_multiplicative(pair: pest::iterators::Pair) -> Expression { - let mut parts = pair.into_inner(); +fn parse_multiplicative(pair: pest::iterators::Pair) -> Result { + let mut parts = pair.clone().into_inner(); match parts.len() { 1 => parse_expression(parts.next().unwrap()), 3 => { - let left = parse_expression(parts.next().unwrap()); + let left = parse_expression(parts.next().unwrap())?; let operator = parts.next().unwrap(); - let right = parse_expression(parts.next().unwrap()); + let right = parse_expression(parts.next().unwrap())?; let operator = match operator.as_str() { "*" => BinaryOperator::Mul, @@ -191,28 +212,31 @@ fn parse_multiplicative(pair: pest::iterators::Pair) -> Expression { _ => panic!("Unknown multiplicative operator: {:?}", operator), }; - Expression { + Ok(Expression { expr: Some(expression::Expr::Binary(Box::new(BinaryExpr { operator: operator.into(), left: Some(Box::new(left)), right: Some(Box::new(right)), }))), - } + }) } - _ => panic!( - "Unexpected number of parts in multiplicative: {:?}", - parts.len() - ), + _ => Err(ParseError::from_pair( + format!( + "Unexpected number of parts in multiplicative: {:?}", + parts.len() + ), + pair, + )), } } -fn parse_unary(pair: pest::iterators::Pair) -> Expression { - let mut parts = pair.into_inner(); +fn parse_unary(pair: pest::iterators::Pair) -> Result { + let mut parts = pair.clone().into_inner(); match parts.len() { 1 => parse_expression(parts.next().unwrap()), 2 => { let operator = parts.next().unwrap(); - let operand = parse_expression(parts.next().unwrap()); + let operand = parse_expression(parts.next().unwrap())?; let operator = match operator.as_str() { "!" => UnaryOperator::Not, @@ -220,52 +244,58 @@ fn parse_unary(pair: pest::iterators::Pair) -> Expression { _ => panic!("Unknown unary operator: {:?}", operator), }; - Expression { + Ok(Expression { expr: Some(expression::Expr::Unary(Box::new(UnaryExpr { operator: operator.into(), operand: Some(Box::new(operand)), }))), - } + }) } - _ => panic!("Unexpected number of parts in unary: {:?}", parts.len()), + _ => Err(ParseError::from_pair( + format!("Unexpected number of parts in unary: {:?}", parts.len()), + pair, + )), } } -fn parse_postfix(pair: pest::iterators::Pair) -> Expression { - let mut parts = pair.into_inner(); +fn parse_postfix(pair: pest::iterators::Pair) -> Result { + let mut parts = pair.clone().into_inner(); match parts.len() { 1 => parse_expression(parts.next().unwrap()), 2 => { - let operand = parse_expression(parts.next().unwrap()); - let argument_list = parse_argument_list(parts.next().unwrap()); + let operand = parse_expression(parts.next().unwrap())?; + let argument_list = parse_argument_list(parts.next().unwrap())?; - Expression { + Ok(Expression { expr: Some(expression::Expr::FunctionCall(Box::new(FunctionCallExpr { function: Some(Box::new(operand)), arguments: argument_list, }))), - } + }) } - _ => panic!("Unexpected number of parts in postfix: {:?}", parts.len()), + _ => Err(ParseError::from_pair( + format!("Unexpected number of parts in postfix: {:?}", parts.len()), + pair, + )), } } -fn parse_argument_list(pair: pest::iterators::Pair) -> Vec { - pair.into_inner() - .map(|p| { - let mut parts = p.into_inner(); - let identifier = parts.next().unwrap(); - let expression = parse_expression(parts.next().unwrap()); +fn parse_argument_list(pair: pest::iterators::Pair) -> Result, ParseError> { + let mut arguments = Vec::new(); + for p in pair.into_inner() { + let mut parts = p.into_inner(); + let identifier = parts.next().unwrap(); + let expression = parse_expression(parts.next().unwrap())?; - Argument { - name: identifier.as_str().to_string(), - value: Some(expression), - } - }) - .collect() + arguments.push(Argument { + name: identifier.as_str().to_string(), + value: Some(expression), + }); + } + Ok(arguments) } -fn parse_primary(pair: pest::iterators::Pair) -> Expression { +fn parse_primary(pair: pest::iterators::Pair) -> Result { let parts = pair.into_inner(); match parts.len() { 1 => { diff --git a/klang/src/parser/functions.rs b/klang/src/parser/functions.rs index 6d7d3b0..7a2a5bd 100644 --- a/klang/src/parser/functions.rs +++ b/klang/src/parser/functions.rs @@ -15,7 +15,7 @@ pub(crate) fn parse_function_def(function_def: Pair) -> Result name = part.as_str().to_string(), Rule::parameter_list => parameters = parse_parameters(part)?, Rule::doc_string => doc_string = parse_doc_string(part)?, - Rule::block => body = Some(parse_block(part)), + Rule::block => body = Some(parse_block(part)?), _ => { return Err(ParseError::from_pair( format!("Unknown rule: {:?}", part.as_rule()), diff --git a/klang/src/parser/literals.rs b/klang/src/parser/literals.rs index 78bc4e4..b157b51 100644 --- a/klang/src/parser/literals.rs +++ b/klang/src/parser/literals.rs @@ -1,16 +1,17 @@ use super::ast::*; +use super::errors::ParseError; use super::parser::Rule; -pub(crate) fn parse_literal(pair: pest::iterators::Pair) -> Expression { +pub(crate) fn parse_literal(pair: pest::iterators::Pair) -> Result { let inner_pair = pair.into_inner().next().unwrap(); match inner_pair.as_rule() { Rule::string => { let value = inner_pair.as_str()[1..inner_pair.as_str().len() - 1].to_string(); - Expression { + Ok(Expression { expr: Some(expression::Expr::Literal(LiteralExpr { value: Some(literal_expr::Value::StringLiteral(StringLiteral { value })), })), - } + }) } Rule::number => { let s = inner_pair.as_str(); @@ -27,23 +28,26 @@ pub(crate) fn parse_literal(pair: pest::iterators::Pair) -> Expression { convert_to_standard_units(value, unit) }; - Expression { + Ok(Expression { expr: Some(expression::Expr::Literal(LiteralExpr { value: Some(literal_expr::Value::NumberLiteral(NumberLiteral { value })), })), - } + }) } Rule::boolean => { let value = inner_pair.as_str() == "true"; - Expression { + Ok(Expression { expr: Some(expression::Expr::Literal(LiteralExpr { value: Some(literal_expr::Value::BooleanLiteral(BooleanLiteral { value, })), })), - } + }) } - _ => panic!("Unknown literal type: {:?}", inner_pair), + _ => Err(ParseError::from_pair( + format!("Unknown literal type: {:?}", inner_pair), + inner_pair, + )), } } @@ -71,10 +75,12 @@ fn convert_to_standard_units(value: f64, unit: &str) -> f64 { } } -pub(crate) fn parse_identifier(pair: pest::iterators::Pair) -> Expression { - Expression { +pub(crate) fn parse_identifier( + pair: pest::iterators::Pair, +) -> Result { + Ok(Expression { expr: Some(expression::Expr::Identifier(Identifier { name: pair.as_str().to_string(), })), - } + }) } diff --git a/klang/src/parser/statements.rs b/klang/src/parser/statements.rs index 5ad07fa..bfa03ab 100644 --- a/klang/src/parser/statements.rs +++ b/klang/src/parser/statements.rs @@ -1,8 +1,10 @@ use super::ast::*; +use super::errors::ParseError; +use super::expressions::parse_expression; use super::parser::Rule; use pest::iterators::Pair; -pub fn parse_block(pair: Pair) -> Block { +pub fn parse_block(pair: Pair) -> Result { let statements = pair .into_inner() .filter_map(|p| { @@ -12,13 +14,12 @@ pub fn parse_block(pair: Pair) -> Block { None } }) - .filter(|s| s.stmt.is_some()) - .collect(); + .collect::, _>>()?; - Block { statements } + Ok(Block { statements }) } -pub fn parse_statement(pair: Pair) -> Statement { +pub fn parse_statement(pair: Pair) -> Result { let inner = pair.into_inner().next().unwrap(); match inner.as_rule() { Rule::assignment_stmt => parse_assignment_statement(inner), @@ -27,15 +28,18 @@ pub fn parse_statement(pair: Pair) -> Statement { Rule::break_stmt => parse_break_statement(inner), Rule::return_stmt => parse_return_statement(inner), Rule::empty_stmt => parse_empty_statement(inner), - _ => panic!("Unknown statement type: {:?}", inner.as_rule()), + _ => Err(ParseError::from_pair( + format!("Unknown statement type: {:?}", inner.as_rule()), + inner, + )), } } -fn parse_assignment_statement(pair: Pair) -> Statement { - let mut inner = pair.into_inner(); +fn parse_assignment_statement(pair: Pair) -> Result { + let mut inner = pair.clone().into_inner(); let identifier = inner.next().unwrap().as_str().to_string(); let operator = inner.next().unwrap().as_str().to_string(); - let expression = super::expressions::parse_expression(inner.next().unwrap()); + let expression = parse_expression(inner.next().unwrap())?; let parsed_operator = match operator.as_str() { "=" => None, @@ -43,10 +47,15 @@ fn parse_assignment_statement(pair: Pair) -> Statement { "-=" => Some(BinaryOperator::Sub), "*=" => Some(BinaryOperator::Mul), "/=" => Some(BinaryOperator::Div), - _ => panic!("Unknown assignment operator: {:?}", operator), + _ => { + return Err(ParseError::from_pair( + format!("Unknown assignment operator: {:?}", operator), + pair, + )) + } }; - match parsed_operator { + Ok(match parsed_operator { Some(op) => Statement { stmt: Some(statement::Stmt::Assignment(AssignmentStmt { identifier: identifier.clone(), @@ -65,44 +74,44 @@ fn parse_assignment_statement(pair: Pair) -> Statement { }, None => Statement { stmt: Some(statement::Stmt::Assignment(AssignmentStmt { - identifier: identifier, + identifier, expression: Some(expression), })), }, - } + }) } -fn parse_expression_statement(pair: Pair) -> Statement { - let expression = super::expressions::parse_expression(pair.into_inner().next().unwrap()); - Statement { +fn parse_expression_statement(pair: Pair) -> Result { + let expression = parse_expression(pair.into_inner().next().unwrap())?; + Ok(Statement { stmt: Some(statement::Stmt::Expression(ExpressionStmt { expression: Some(expression), })), - } + }) } -fn parse_loop_statement(pair: Pair) -> Statement { - let block = parse_block(pair.into_inner().next().unwrap()); - Statement { +fn parse_loop_statement(pair: Pair) -> Result { + let block = parse_block(pair.into_inner().next().unwrap())?; + Ok(Statement { stmt: Some(statement::Stmt::Loop(LoopStmt { body: Some(block) })), - } + }) } -fn parse_break_statement(_pair: Pair) -> Statement { - Statement { +fn parse_break_statement(_pair: Pair) -> Result { + Ok(Statement { stmt: Some(statement::Stmt::Break(BreakStmt {})), - } + }) } -fn parse_return_statement(pair: Pair) -> Statement { - let expression = super::expressions::parse_expression(pair.into_inner().next().unwrap()); - Statement { +fn parse_return_statement(pair: Pair) -> Result { + let expression = parse_expression(pair.into_inner().next().unwrap())?; + Ok(Statement { stmt: Some(statement::Stmt::Return(ReturnStmt { expression: Some(expression), })), - } + }) } -fn parse_empty_statement(_pair: Pair) -> Statement { - Statement { stmt: None } +fn parse_empty_statement(_pair: Pair) -> Result { + Ok(Statement { stmt: None }) }