From 0886fd197f4a37f8ed4efbf47e687351b362d6c2 Mon Sep 17 00:00:00 2001 From: Stefan Date: Wed, 18 Sep 2024 17:18:21 +0200 Subject: [PATCH] local: fault tolerant parser --- core/expression/src/compiler/compiler.rs | 1 + core/expression/src/compiler/error.rs | 3 + core/expression/src/parser/ast.rs | 125 ++++- core/expression/src/parser/error.rs | 7 +- core/expression/src/parser/parser.rs | 650 ++++++++++++----------- core/expression/src/parser/standard.rs | 70 +-- core/expression/src/parser/unary.rs | 119 +++-- core/expression/tests/isolate.rs | 7 +- core/expression_repl/src/main.rs | 6 +- 9 files changed, 592 insertions(+), 396 deletions(-) diff --git a/core/expression/src/compiler/compiler.rs b/core/expression/src/compiler/compiler.rs index b7503509..8a39867a 100644 --- a/core/expression/src/compiler/compiler.rs +++ b/core/expression/src/compiler/compiler.rs @@ -588,6 +588,7 @@ impl<'arena, 'bytecode_ref> CompilerInner<'arena, 'bytecode_ref> { Ok(self.emit(Opcode::End)) } }, + Node::Error(_) => Err(CompilerError::UnexpectedErrorNode), } } } diff --git a/core/expression/src/compiler/error.rs b/core/expression/src/compiler/error.rs index fffe938f..d3085a74 100644 --- a/core/expression/src/compiler/error.rs +++ b/core/expression/src/compiler/error.rs @@ -10,6 +10,9 @@ pub enum CompilerError { #[error("Argument not found for builtin {builtin} at index {index}")] ArgumentNotFound { builtin: String, index: usize }, + + #[error("Unexpected error node")] + UnexpectedErrorNode, } pub(crate) type CompilerResult = Result; diff --git a/core/expression/src/parser/ast.rs b/core/expression/src/parser/ast.rs index 97b0497e..a52db2bb 100644 --- a/core/expression/src/parser/ast.rs +++ b/core/expression/src/parser/ast.rs @@ -1,7 +1,7 @@ -use rust_decimal::Decimal; - use crate::lexer::Operator; use crate::parser::builtin::BuiltInFunction; +use rust_decimal::Decimal; +use thiserror::Error; #[derive(Debug, PartialEq, Clone)] pub enum Node<'a> { @@ -49,4 +49,125 @@ pub enum Node<'a> { kind: BuiltInFunction, arguments: &'a [&'a Node<'a>], }, + Error(AstNodeError), +} + +impl<'a> Node<'a> { + pub fn walk(&self, mut func: F) + where + F: FnMut(&Self), + { + func(self); + + match self { + Node::Error(_) => {} + Node::Null => {} + Node::Bool(_) => {} + Node::Number(_) => {} + Node::String(_) => {} + Node::Pointer => {} + Node::Identifier(_) => {} + Node::Root => {} + Node::TemplateString(parts) => parts.iter().for_each(|n| func(n)), + Node::Array(parts) => parts.iter().for_each(|n| func(n)), + Node::Object(obj) => obj.iter().for_each(|(k, v)| { + func(k); + func(v); + }), + Node::Closure(closure) => func(closure), + Node::Member { node, property } => { + func(node); + func(property); + } + Node::Slice { node, to, from } => { + func(node); + if let Some(to) = to { + func(to); + } + + if let Some(from) = from { + func(from); + } + } + Node::Interval { right, left, .. } => { + func(right); + func(left); + } + Node::Conditional { + on_true, + condition, + on_false, + } => { + func(condition); + func(on_true); + func(on_false); + } + Node::Unary { node, .. } => { + func(node); + } + Node::Binary { left, right, .. } => { + func(left); + func(right); + } + Node::BuiltIn { arguments, .. } => { + arguments.iter().for_each(|n| func(n)); + } + } + } + + pub fn is_error(&self) -> bool { + match self { + Node::Error(_) => true, + _ => false, + } + } + + pub fn has_error(&self) -> bool { + let mut has_error = false; + self.walk(|n| { + if n.is_error() { + has_error = true + } + }); + + has_error + } +} + +#[derive(Debug, PartialEq, Eq, Clone, Error)] +pub enum AstNodeError { + #[error("Unknown built in: {name} at ({}, {})", span.0, span.1)] + UnknownBuiltIn { name: String, span: (u32, u32) }, + + #[error("Unexpected identifier: {received} at ({}, {}); Expected {expected}.", span.0, span.1)] + UnexpectedIdentifier { + received: String, + expected: String, + span: (u32, u32), + }, + + #[error("Unexpected identifier: {received} at ({}, {}); Expected {expected}.", span.0, span.1)] + UnexpectedToken { + received: String, + expected: String, + span: (u32, u32), + }, + + #[error("Invalid number: {number} at ({}, {})", span.0, span.1)] + InvalidNumber { number: String, span: (u32, u32) }, + + #[error("Invalid boolean: {boolean} at ({}, {})", span.0, span.1)] + InvalidBoolean { boolean: String, span: (u32, u32) }, + + #[error("Invalid property: {property} at ({}, {})", span.0, span.1)] + InvalidProperty { property: String, span: (u32, u32) }, + + #[error("Missing expected token: {expected} at {position}")] + MissingToken { expected: String, position: usize }, + + #[error("{message} at ({}, {})", span.0, span.1)] + Custom { message: String, span: (u32, u32) }, + + #[error("Invalid")] + Invalid, } diff --git a/core/expression/src/parser/error.rs b/core/expression/src/parser/error.rs index 7643002c..ed9b9442 100644 --- a/core/expression/src/parser/error.rs +++ b/core/expression/src/parser/error.rs @@ -1,4 +1,5 @@ use thiserror::Error; +use crate::parser::ast::AstNodeError; #[derive(Debug, PartialEq, Eq, Clone, Error)] pub enum ParserError { @@ -14,10 +15,7 @@ pub enum ParserError { #[error("Unknown built in: {name} at ({}, {})", span.0, span.1)] UnknownBuiltIn { name: String, span: (u32, u32) }, - - #[error("Unsupported built in: {name} at ({}, {})", span.0, span.1)] - UnsupportedBuiltIn { name: String, span: (u32, u32) }, - + #[error("Token out of bounds")] TokenOutOfBounds, @@ -26,3 +24,4 @@ pub enum ParserError { } pub(crate) type ParserResult = Result; +pub(crate) type AstResult = Result; diff --git a/core/expression/src/parser/parser.rs b/core/expression/src/parser/parser.rs index d3ca0500..6bf35e4e 100644 --- a/core/expression/src/parser/parser.rs +++ b/core/expression/src/parser/parser.rs @@ -10,9 +10,9 @@ use crate::lexer::{ Bracket, ComparisonOperator, Identifier, Operator, QuotationMark, TemplateString, Token, TokenKind, }; -use crate::parser::ast::Node; +use crate::parser::ast::{AstNodeError, Node}; use crate::parser::builtin::{Arity, BuiltInFunction}; -use crate::parser::error::{ParserError, ParserResult}; +use crate::parser::error::ParserError; use crate::parser::standard::Standard; use crate::parser::unary::Unary; @@ -22,9 +22,8 @@ pub struct BaseParser; #[derive(Debug)] pub struct Parser<'arena, 'token_ref, Flavor> { tokens: &'token_ref [Token<'arena>], - current: Cell<&'token_ref Token<'arena>>, + current: Cell>>, pub(crate) bump: &'arena Bump, - is_done: Cell, position: Cell, depth: Cell, marker_flavor: PhantomData, @@ -36,7 +35,7 @@ impl<'arena, 'token_ref> Parser<'arena, 'token_ref, BaseParser> { tokens: &'token_ref [Token<'arena>], bump: &'arena Bump, ) -> Result { - let current = tokens.get(0).ok_or(ParserError::TokenOutOfBounds)?; + let current = tokens.get(0); let has_range_operator = tokens .iter() .any(|t| t.kind == TokenKind::Operator(Operator::Range)); @@ -47,7 +46,6 @@ impl<'arena, 'token_ref> Parser<'arena, 'token_ref, BaseParser> { current: Cell::new(current), depth: Cell::new(0), position: Cell::new(0), - is_done: Cell::new(false), has_range_operator, marker_flavor: PhantomData, }) @@ -60,7 +58,6 @@ impl<'arena, 'token_ref> Parser<'arena, 'token_ref, BaseParser> { current: self.current, depth: self.depth, position: self.position, - is_done: self.is_done, has_range_operator: self.has_range_operator, marker_flavor: PhantomData, } @@ -73,7 +70,6 @@ impl<'arena, 'token_ref> Parser<'arena, 'token_ref, BaseParser> { current: self.current, depth: self.depth, position: self.position, - is_done: self.is_done, has_range_operator: self.has_range_operator, marker_flavor: PhantomData, } @@ -81,7 +77,7 @@ impl<'arena, 'token_ref> Parser<'arena, 'token_ref, BaseParser> { } impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> { - pub(crate) fn current(&self) -> &Token<'arena> { + pub(crate) fn current(&self) -> Option<&Token<'arena>> { self.current.get() } @@ -89,14 +85,13 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> { self.position.get() } - fn set_position(&self, position: usize) -> ParserResult<()> { - let Some(token) = self.tokens.get(position) else { - return Err(ParserError::TokenOutOfBounds); - }; + fn set_position(&self, position: usize) -> bool { + let target_token = self.tokens.get(position); self.position.set(position); - self.current.set(token); - Ok(()) + self.current.set(target_token); + + target_token.is_some() } pub(crate) fn depth(&self) -> u8 { @@ -104,88 +99,149 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> { } pub(crate) fn is_done(&self) -> bool { - self.is_done.get() + self.current.get().is_none() } - pub(crate) fn next(&self) -> ParserResult<()> { - self.position.set(self.position.get() + 1); - - if let Some(token) = self.tokens.get(self.position.get()) { - self.current.set(token); - Ok(()) - } else { - if self.is_done.get() { - return Err(ParserError::TokenOutOfBounds); - } - - self.is_done.set(true); - Ok(()) - } + pub(crate) fn node(&self, node: Node<'arena>) -> &'arena Node<'arena> { + self.bump.alloc(node) } - pub(crate) fn expect(&self, kind: TokenKind) -> Result<(), ParserError> { + pub(crate) fn error(&self, error: AstNodeError) -> &'arena Node<'arena> { + self.node(Node::Error(error)) + } + + pub(crate) fn next(&self) { + let new_position = self.position.get() + 1; + + self.position.set(new_position); + self.current.set(self.tokens.get(new_position)); + } + + pub(crate) fn expect(&self, kind: TokenKind) -> Option<&'arena Node<'arena>> { let token = self.current(); - if token.kind != kind { - return Err(ParserError::UnexpectedToken { + if token.is_some_and(|t| t.kind == kind) { + self.next(); + return None; + } + + Some( + self.error(AstNodeError::UnexpectedToken { expected: kind.to_string(), - received: token.kind.to_string(), + received: token + .map(|t| t.kind.to_string()) + .unwrap_or_else(|| "None".to_string()), + span: token.map(|t| t.span).unwrap_or((0, 0)), + }), + ) + } + + pub(crate) fn number(&self) -> &'arena Node<'arena> { + let Some(token) = self.current() else { + return self.error(AstNodeError::MissingToken { + expected: "Number".to_string(), + position: self.position(), + }); + }; + + let Ok(decimal) = Decimal::from_str_exact(token.value) else { + return self.error(AstNodeError::InvalidNumber { + number: token.value.to_string(), + span: token.span, + }); + }; + + self.next(); + self.node(Node::Number(decimal)) + } + + pub(crate) fn bool(&self) -> &'arena Node<'arena> { + let Some(token) = self.current() else { + return self.error(AstNodeError::MissingToken { + expected: "Boolean".to_string(), + position: self.position(), + }); + }; + + let TokenKind::Boolean(boolean) = token.kind else { + return self.error(AstNodeError::InvalidBoolean { + boolean: token.value.to_string(), + span: token.span, + }); + }; + + self.next(); + self.node(Node::Bool(boolean)) + } + + pub(crate) fn null(&self) -> &'arena Node<'arena> { + let Some(token) = self.current() else { + return self.error(AstNodeError::MissingToken { + expected: "Null".to_string(), + position: self.position(), + }); + }; + + if token.kind != TokenKind::Identifier(Identifier::Null) { + return self.error(AstNodeError::UnexpectedIdentifier { + expected: "Null".to_string(), + received: token.value.to_string(), span: token.span, }); } - self.next() + self.next(); + self.node(Node::Null) } - pub(crate) fn number(&self) -> ParserResult>> { - let Ok(decimal) = Decimal::from_str_exact(self.current().value) else { - return Ok(None); + pub(crate) fn simple_string(&self, quote_mark: &QuotationMark) -> &'arena Node<'arena> { + if let Some(error_node) = self.expect(TokenKind::QuotationMark(quote_mark.clone())) { + return error_node; + } + + let string_value = self.current().map(|s| s.value); + + let error_literal = self.expect(TokenKind::Literal); + let error_mark_end = self.expect(TokenKind::QuotationMark(quote_mark.clone())); + + error_literal + .or(error_mark_end) + .or(string_value.map(|s| self.node(Node::String(s)))) + .unwrap_or_else(|| self.error(AstNodeError::Invalid)) + } + + pub(crate) fn template_string(&self, expression_parser: F) -> &'arena Node<'arena> + where + F: Fn() -> &'arena Node<'arena>, + { + if let Some(error_node) = self.expect(TokenKind::QuotationMark(QuotationMark::Backtick)) { + return error_node; + } + + let Some(mut current_token) = self.current() else { + return self.error(AstNodeError::MissingToken { + expected: "Backtick (`)".to_string(), + position: self.position(), + }); }; - self.next()?; - Ok(Some(self.node(Node::Number(decimal)))) - } - - pub(crate) fn simple_string( - &self, - quote_mark: &QuotationMark, - ) -> ParserResult<&'arena Node<'arena>> { - self.expect(TokenKind::QuotationMark(quote_mark.clone()))?; - let string_value = self.current().value; - - self.expect(TokenKind::Literal)?; - self.expect(TokenKind::QuotationMark(quote_mark.clone()))?; - - Ok(self.node(Node::String(string_value))) - } - - pub(crate) fn template_string( - &self, - expression_parser: F, - ) -> ParserResult<&'arena Node<'arena>> - where - F: Fn() -> ParserResult<&'arena Node<'arena>>, - { - self.expect(TokenKind::QuotationMark(QuotationMark::Backtick))?; - - let mut current_token = self.current(); let mut nodes = BumpVec::new_in(self.bump); while TokenKind::QuotationMark(QuotationMark::Backtick) != current_token.kind { match current_token.kind { TokenKind::TemplateString(template) => match template { TemplateString::ExpressionStart => { - self.next()?; - nodes.push(expression_parser()?); + self.next(); + nodes.push(expression_parser()); } TemplateString::ExpressionEnd => { - self.next()?; + self.next(); } }, TokenKind::Literal => { nodes.push(self.node(Node::String(current_token.value))); - self.next()?; + self.next(); } _ => { - return Err(ParserError::UnexpectedToken { + return self.error(AstNodeError::UnexpectedToken { expected: "Valid TemplateString token".to_string(), received: current_token.kind.to_string(), span: current_token.span, @@ -193,170 +249,173 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> { } } - current_token = self.current(); + if let Some(ct) = self.current() { + current_token = ct; + } else { + break; + } } - self.expect(TokenKind::QuotationMark(QuotationMark::Backtick))?; - - Ok(self.node(Node::TemplateString(nodes.into_bump_slice()))) - } - - pub(crate) fn bool(&self) -> ParserResult>> { - let current_token = self.current(); - let TokenKind::Boolean(boolean) = current_token.kind else { - return Ok(None); + if let Some(err) = self.expect(TokenKind::QuotationMark(QuotationMark::Backtick)) { + return err; }; - self.next()?; - Ok(Some(self.node(Node::Bool(boolean)))) + self.node(Node::TemplateString(nodes.into_bump_slice())) } - pub(crate) fn null(&self) -> ParserResult>> { - let current_token = self.current(); - if current_token.kind != TokenKind::Identifier(Identifier::Null) { - return Ok(None); - } - - self.next()?; - Ok(Some(self.node(Node::Null))) - } - - pub(crate) fn node(&self, node: Node<'arena>) -> &'arena Node<'arena> { - self.bump.alloc(node) - } - - // Higher level constructs - pub(crate) fn with_postfix( &self, node: &'arena Node<'arena>, expression_parser: F, - ) -> ParserResult<&'arena Node<'arena>> + ) -> &'arena Node<'arena> where - F: Fn() -> ParserResult<&'arena Node<'arena>>, + F: Fn() -> &'arena Node<'arena>, { - let postfix_token = self.current(); + let Some(postfix_token) = self.current() else { + return node; + }; + let postfix_kind = PostfixKind::from(postfix_token); let processed_token = match postfix_kind { - PostfixKind::Other => return Ok(node), + PostfixKind::Other => return node, PostfixKind::MemberAccess => { - self.next()?; + self.next(); let property_token = self.current(); - self.next()?; + self.next(); - if !is_valid_property(property_token) { - return Err(ParserError::UnexpectedToken { - expected: "valid property".to_string(), - received: postfix_token.kind.to_string(), - span: postfix_token.span, - }); - } + let property = match property_token { + None => self.error(AstNodeError::Invalid), + Some(t) => match is_valid_property(t) { + true => self.node(Node::String(t.value)), + false => self.error(AstNodeError::InvalidProperty { + property: t.value.to_string(), + span: t.span, + }), + }, + }; - let property = self.node(Node::String(property_token.value)); - Ok(self.node(Node::Member { node, property })) + self.node(Node::Member { node, property }) } PostfixKind::PropertyAccess => { - self.next()?; + self.next(); let mut from: Option<&'arena Node<'arena>> = None; let mut to: Option<&'arena Node<'arena>> = None; - let mut c = self.current(); + let Some(mut c) = self.current() else { + return self.error(AstNodeError::Invalid); + }; + if c.kind == TokenKind::Operator(Operator::Slice) { - self.next()?; - c = self.current(); + self.next(); + + let Some(cc) = self.current() else { + return self.error(AstNodeError::Invalid); + }; + c = cc; if c.kind != TokenKind::Bracket(Bracket::RightSquareBracket) { - to = Some(expression_parser()?); + to = Some(expression_parser()); } - self.expect(TokenKind::Bracket(Bracket::RightSquareBracket))?; - Ok(self.node(Node::Slice { node, to, from })) + self.expect(TokenKind::Bracket(Bracket::RightSquareBracket)); + self.node(Node::Slice { node, to, from }) } else { - from = Some(expression_parser()?); - c = self.current(); + from = Some(expression_parser()); + let Some(cc) = self.current() else { + return self.error(AstNodeError::Invalid); + }; + c = cc; if c.kind == TokenKind::Operator(Operator::Slice) { - self.next()?; - c = self.current(); + self.next(); + let Some(cc) = self.current() else { + return self.error(AstNodeError::Invalid); + }; + c = cc; if c.kind != TokenKind::Bracket(Bracket::RightSquareBracket) { - to = Some(expression_parser()?); + to = Some(expression_parser()); } - self.expect(TokenKind::Bracket(Bracket::RightSquareBracket))?; - Ok(self.node(Node::Slice { node, from, to })) + self.expect(TokenKind::Bracket(Bracket::RightSquareBracket)); + self.node(Node::Slice { node, from, to }) } else { // Slice operator [:] was not found, // it should be just an index node. - self.expect(TokenKind::Bracket(Bracket::RightSquareBracket))?; - Ok(self.node(Node::Member { + self.expect(TokenKind::Bracket(Bracket::RightSquareBracket)); + self.node(Node::Member { node, - property: from.ok_or(ParserError::MemoryFailure)?, - })) + property: from.unwrap_or_else(|| self.error(AstNodeError::Invalid)), + }) } } } - }?; + }; self.with_postfix(processed_token, expression_parser) } /// Closure - pub(crate) fn closure(&self, expression_parser: F) -> ParserResult<&'arena Node<'arena>> + pub(crate) fn closure(&self, expression_parser: F) -> &'arena Node<'arena> where - F: Fn() -> ParserResult<&'arena Node<'arena>>, + F: Fn() -> &'arena Node<'arena>, { self.depth.set(self.depth.get() + 1); - let node = expression_parser()?; + let node = expression_parser(); self.depth.set(self.depth.get() - 1); - Ok(self.node(Node::Closure(node))) + self.node(Node::Closure(node)) } /// Identifier expression /// Either or - pub(crate) fn identifier( - &self, - expression_parser: F, - ) -> ParserResult>> + pub(crate) fn identifier(&self, expression_parser: F) -> &'arena Node<'arena> where - F: Fn() -> ParserResult<&'arena Node<'arena>>, + F: Fn() -> &'arena Node<'arena>, { - match &self.current().kind { + let Some(token) = self.current() else { + return self.error(AstNodeError::MissingToken { + expected: "Identifier".to_string(), + position: self.position(), + }); + }; + + match token.kind { TokenKind::Identifier(_) | TokenKind::Literal => { // ok } - _ => return Ok(None), + _ => return self.error(AstNodeError::Invalid), } - let identifier_token = self.current(); - self.next()?; + let Some(identifier_token) = self.current() else { + return self.error(AstNodeError::Invalid); + }; + self.next(); + let current_token = self.current(); - if current_token.kind != TokenKind::Bracket(Bracket::LeftParenthesis) { + if current_token.map(|t| t.kind) != Some(TokenKind::Bracket(Bracket::LeftParenthesis)) { let identifier_node = match identifier_token.kind { TokenKind::Identifier(Identifier::RootReference) => self.node(Node::Root), _ => self.node(Node::Identifier(identifier_token.value)), }; - return self - .with_postfix(identifier_node, expression_parser) - .map(Some); + return self.with_postfix(identifier_node, expression_parser); } // Potentially it might be a built-in expression - let builtin = BuiltInFunction::try_from(identifier_token.value).map_err(|_| { - ParserError::UnknownBuiltIn { + let Ok(builtin) = BuiltInFunction::try_from(identifier_token.value) else { + return self.error(AstNodeError::UnknownBuiltIn { name: identifier_token.value.to_string(), span: identifier_token.span, - } - })?; + }); + }; - self.next()?; + self.next(); let builtin_node = match builtin.arity() { Arity::Single => { - let arg = expression_parser()?; - self.expect(TokenKind::Bracket(Bracket::RightParenthesis))?; + let arg = expression_parser(); + self.expect(TokenKind::Bracket(Bracket::RightParenthesis)); Node::BuiltIn { kind: builtin, @@ -364,10 +423,10 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> { } } Arity::Dual => { - let arg1 = expression_parser()?; - self.expect(TokenKind::Operator(Operator::Comma))?; - let arg2 = expression_parser()?; - self.expect(TokenKind::Bracket(Bracket::RightParenthesis))?; + let arg1 = expression_parser(); + self.expect(TokenKind::Operator(Operator::Comma)); + let arg2 = expression_parser(); + self.expect(TokenKind::Bracket(Bracket::RightParenthesis)); Node::BuiltIn { kind: builtin, @@ -375,10 +434,10 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> { } } Arity::Closure => { - let arg1 = expression_parser()?; - self.expect(TokenKind::Operator(Operator::Comma))?; - let arg2 = self.closure(&expression_parser)?; - self.expect(TokenKind::Bracket(Bracket::RightParenthesis))?; + let arg1 = expression_parser(); + self.expect(TokenKind::Operator(Operator::Comma)); + let arg2 = self.closure(&expression_parser); + self.expect(TokenKind::Bracket(Bracket::RightParenthesis)); Node::BuiltIn { kind: builtin, @@ -388,57 +447,55 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> { }; self.with_postfix(self.node(builtin_node), expression_parser) - .map(Some) } /// Interval node - pub(crate) fn interval( - &self, - expression_parser: F, - ) -> ParserResult>> + pub(crate) fn interval(&self, expression_parser: F) -> Option<&'arena Node<'arena>> where - F: Fn() -> ParserResult<&'arena Node<'arena>>, + F: Fn() -> &'arena Node<'arena>, { // Performance optimisation: skip if expression does not contain an interval for faster evaluation if !self.has_range_operator { - return Ok(None); + return None; } - let TokenKind::Bracket(_) = &self.current().kind else { - return Ok(None); + let TokenKind::Bracket(_) = &self.current()?.kind else { + return None; }; let initial_position = self.position(); - let left_bracket = self.current().value; + let left_bracket = self.current()?.value; - let TokenKind::Bracket(_) = &self.current().kind else { - self.set_position(initial_position)?; - return Ok(None); - }; - self.next()?; - - let Ok(left) = expression_parser() else { - self.set_position(initial_position)?; - return Ok(None); + let TokenKind::Bracket(_) = &self.current()?.kind else { + self.set_position(initial_position); + return None; }; - if let Err(_) = self.expect(TokenKind::Operator(Operator::Range)) { - self.set_position(initial_position)?; - return Ok(None); + self.next(); + let left = expression_parser(); + if left.has_error() { + self.set_position(initial_position); + return None; }; - let Ok(right) = expression_parser() else { - self.set_position(initial_position)?; - return Ok(None); + if let Some(_) = self.expect(TokenKind::Operator(Operator::Range)) { + self.set_position(initial_position); + return None; }; - let right_bracket = self.current().value; - - let TokenKind::Bracket(_) = &self.current().kind else { - self.set_position(initial_position)?; - return Ok(None); + let right = expression_parser(); + if right.has_error() { + self.set_position(initial_position); + return None; }; - self.next()?; + + let right_bracket = self.current()?.value; + let TokenKind::Bracket(_) = &self.current()?.kind else { + self.set_position(initial_position); + return None; + }; + + self.next(); let interval_node = self.node(Node::Interval { left_bracket, @@ -447,131 +504,142 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> { right_bracket, }); - self.with_postfix(interval_node, expression_parser) - .map(Some) + Some(self.with_postfix(interval_node, expression_parser)) } /// Array nodes - pub(crate) fn array( - &self, - expression_parser: F, - ) -> ParserResult>> + pub(crate) fn array(&self, expression_parser: F) -> &'arena Node<'arena> where - F: Fn() -> ParserResult<&'arena Node<'arena>>, + F: Fn() -> &'arena Node<'arena>, { - let current_token = self.current(); + let Some(current_token) = self.current() else { + return self.error(AstNodeError::MissingToken { + expected: "Array".to_string(), + position: self.position(), + }); + }; + if current_token.kind != TokenKind::Bracket(Bracket::LeftSquareBracket) { - return Ok(None); + return self.error(AstNodeError::UnexpectedToken { + expected: TokenKind::Bracket(Bracket::LeftSquareBracket).to_string(), + received: current_token.kind.to_string(), + span: current_token.span, + }); } - self.next()?; + self.next(); let mut nodes = BumpVec::new_in(self.bump); - while !(self.current().kind == TokenKind::Bracket(Bracket::RightSquareBracket)) { + while !(self.current().map(|t| t.kind) + == Some(TokenKind::Bracket(Bracket::RightSquareBracket))) + { if !nodes.is_empty() { - self.expect(TokenKind::Operator(Operator::Comma))?; - if self.current().kind == TokenKind::Bracket(Bracket::RightSquareBracket) { + self.expect(TokenKind::Operator(Operator::Comma)); + if self.current().map(|t| t.kind) + == Some(TokenKind::Bracket(Bracket::RightSquareBracket)) + { break; } } - nodes.push(expression_parser()?); + nodes.push(expression_parser()); } - self.expect(TokenKind::Bracket(Bracket::RightSquareBracket))?; + self.expect(TokenKind::Bracket(Bracket::RightSquareBracket)); let node = Node::Array(nodes.into_bump_slice()); self.with_postfix(self.node(node), expression_parser) - .map(Some) } - pub(crate) fn object(&self, expression_parser: F) -> ParserResult<&'arena Node<'arena>> + pub(crate) fn object(&self, expression_parser: F) -> &'arena Node<'arena> where - F: Fn() -> ParserResult<&'arena Node<'arena>>, + F: Fn() -> &'arena Node<'arena>, { - self.expect(TokenKind::Bracket(Bracket::LeftCurlyBracket))?; + if let Some(err_node) = self.expect(TokenKind::Bracket(Bracket::LeftCurlyBracket)) { + return err_node; + }; let mut key_value_pairs = BumpVec::new_in(self.bump); - if let TokenKind::Bracket(Bracket::RightCurlyBracket) = self.current().kind { - self.next()?; - return Ok(self.node(Node::Object(key_value_pairs.into_bump_slice()))); + if let Some(TokenKind::Bracket(Bracket::RightCurlyBracket)) = self.current().map(|t| t.kind) + { + self.next(); + return self.node(Node::Object(key_value_pairs.into_bump_slice())); } loop { - let key = self.object_key(&expression_parser)?; - self.expect(TokenKind::Operator(Operator::Slice))?; - let value = expression_parser()?; + let key = self.object_key(&expression_parser); + self.expect(TokenKind::Operator(Operator::Slice)); + let value = expression_parser(); key_value_pairs.push((key, value)); - let current_token = self.current(); + let Some(current_token) = self.current() else { + break; + }; + match current_token.kind { TokenKind::Operator(Operator::Comma) => { - self.expect(TokenKind::Operator(Operator::Comma))?; + self.expect(TokenKind::Operator(Operator::Comma)); } TokenKind::Bracket(Bracket::RightCurlyBracket) => break, - _ => { - return Err(ParserError::UnexpectedToken { - expected: "RightCurlyBracket or Comma".to_string(), - received: current_token.kind.to_string(), - span: current_token.span, - }) - } + _ => return self.error(AstNodeError::Invalid), } } - self.expect(TokenKind::Bracket(Bracket::RightCurlyBracket))?; - Ok(self.node(Node::Object(key_value_pairs.into_bump_slice()))) + self.expect(TokenKind::Bracket(Bracket::RightCurlyBracket)); + self.node(Node::Object(key_value_pairs.into_bump_slice())) } - pub(crate) fn object_key(&self, expression_parser: F) -> ParserResult<&'arena Node<'arena>> + pub(crate) fn object_key(&self, expression_parser: F) -> &'arena Node<'arena> where - F: Fn() -> ParserResult<&'arena Node<'arena>>, + F: Fn() -> &'arena Node<'arena>, { - let key_token = self.current(); + let Some(key_token) = self.current() else { + return self.error(AstNodeError::Invalid); + }; let key = match key_token.kind { TokenKind::Identifier(identifier) => { - self.next()?; + self.next(); self.node(Node::String(identifier.into())) } TokenKind::Boolean(boolean) => match boolean { true => { - self.next()?; + self.next(); self.node(Node::String("true")) } false => { - self.next()?; + self.next(); self.node(Node::String("false")) } }, TokenKind::Number => { - self.next()?; + self.next(); self.node(Node::String(key_token.value)) } TokenKind::Literal => { - self.next()?; + self.next(); self.node(Node::String(key_token.value)) } TokenKind::Bracket(bracket) => match bracket { Bracket::LeftSquareBracket => { - self.expect(TokenKind::Bracket(Bracket::LeftSquareBracket))?; - let token = expression_parser()?; - self.expect(TokenKind::Bracket(Bracket::RightSquareBracket))?; + self.expect(TokenKind::Bracket(Bracket::LeftSquareBracket)); + let token = expression_parser(); + self.expect(TokenKind::Bracket(Bracket::RightSquareBracket)); token } _ => { - return Err(ParserError::FailedToParse { + return self.error(AstNodeError::Custom { message: "Operator is not supported as object key".to_string(), span: key_token.span, }) } }, TokenKind::QuotationMark(qm) => match qm { - QuotationMark::SingleQuote => self.simple_string(&QuotationMark::SingleQuote)?, - QuotationMark::DoubleQuote => self.simple_string(&QuotationMark::DoubleQuote)?, + QuotationMark::SingleQuote => self.simple_string(&QuotationMark::SingleQuote), + QuotationMark::DoubleQuote => self.simple_string(&QuotationMark::DoubleQuote), QuotationMark::Backtick => { - return Err(ParserError::FailedToParse { + return self.error(AstNodeError::Custom { message: "TemplateString expression not supported as object key" .to_string(), span: key_token.span, @@ -579,20 +647,20 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> { } }, TokenKind::TemplateString(_) => { - return Err(ParserError::FailedToParse { + return self.error(AstNodeError::Custom { message: "TemplateString expression not supported as object key".to_string(), span: key_token.span, }) } TokenKind::Operator(_) => { - return Err(ParserError::FailedToParse { + return self.error(AstNodeError::Custom { message: "Operator is not supported as object key".to_string(), span: key_token.span, }) } }; - Ok(key) + key } /// Conditional @@ -601,20 +669,22 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> { &self, condition: &'arena Node<'arena>, expression_parser: F, - ) -> ParserResult>> + ) -> Option<&'arena Node<'arena>> where - F: Fn() -> ParserResult<&'arena Node<'arena>>, + F: Fn() -> &'arena Node<'arena>, { - let current_token = self.current(); + let Some(current_token) = self.current() else { + return None; + }; if current_token.kind != TokenKind::Operator(Operator::QuestionMark) { - return Ok(None); + return None; } - self.next()?; + self.next(); - let on_true = expression_parser()?; - self.expect(TokenKind::Operator(Operator::Slice))?; - let on_false = expression_parser()?; + let on_true = expression_parser(); + self.expect(TokenKind::Operator(Operator::Slice)); + let on_false = expression_parser(); let conditional_node = Node::Conditional { condition, @@ -622,44 +692,26 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> { on_false, }; - Ok(Some(self.node(conditional_node))) + Some(self.node(conditional_node)) } /// Literal - number, string, array etc. - pub(crate) fn literal(&self, expression_parser: F) -> ParserResult<&'arena Node<'arena>> + pub(crate) fn literal(&self, expression_parser: F) -> &'arena Node<'arena> where - F: Fn() -> ParserResult<&'arena Node<'arena>>, + F: Fn() -> &'arena Node<'arena>, { - let current_token = self.current(); + let Some(current_token) = self.current() else { + return self.error(AstNodeError::Invalid); + }; + match ¤t_token.kind { TokenKind::Identifier(identifier) => match identifier { - Identifier::Null => self.null()?.ok_or_else(|| ParserError::FailedToParse { - message: "Failed to parse null identifier".to_string(), - span: current_token.span, - }), - _ => { - self.identifier(&expression_parser)? - .ok_or_else(|| ParserError::FailedToParse { - message: "Failed to parse identifier".to_string(), - span: current_token.span, - }) - } + Identifier::Null => self.null(), + _ => self.identifier(&expression_parser), }, - TokenKind::Literal => { - self.identifier(&expression_parser)? - .ok_or_else(|| ParserError::FailedToParse { - message: "Failed to parse literal".to_string(), - span: current_token.span, - }) - } - TokenKind::Boolean(_) => self.bool()?.ok_or_else(|| ParserError::FailedToParse { - message: "Failed to parse boolean".to_string(), - span: current_token.span, - }), - TokenKind::Number => self.number()?.ok_or_else(|| ParserError::FailedToParse { - message: "Failed to parse number".to_string(), - span: current_token.span, - }), + TokenKind::Literal => self.identifier(&expression_parser), + TokenKind::Boolean(_) => self.bool(), + TokenKind::Number => self.number(), TokenKind::QuotationMark(quote_mark) => match quote_mark { QuotationMark::SingleQuote | QuotationMark::DoubleQuote => { self.simple_string(quote_mark) @@ -669,33 +721,23 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> { TokenKind::Bracket(bracket) => match bracket { Bracket::LeftParenthesis | Bracket::RightParenthesis - | Bracket::RightSquareBracket => { - self.interval(&expression_parser)? - .ok_or_else(|| ParserError::FailedToParse { - message: "Failed to parse interval".to_string(), - span: current_token.span, - }) - } + | Bracket::RightSquareBracket => self + .interval(&expression_parser) + .unwrap_or_else(|| self.error(AstNodeError::Invalid)), Bracket::LeftSquareBracket => self .interval(&expression_parser) - .transpose() - .or_else(|| self.array(&expression_parser).transpose()) - .transpose()? - .ok_or_else(|| ParserError::FailedToParse { - message: "Invalid bracket".to_string(), - span: current_token.span, - }), + .unwrap_or_else(|| self.array(&expression_parser)), Bracket::LeftCurlyBracket => self.object(&expression_parser), - Bracket::RightCurlyBracket => Err(ParserError::FailedToParse { + Bracket::RightCurlyBracket => self.error(AstNodeError::Custom { message: "Unexpected RightCurlyBracket token".to_string(), span: current_token.span, }), }, - TokenKind::Operator(_) => Err(ParserError::FailedToParse { + TokenKind::Operator(_) => self.error(AstNodeError::Custom { message: "Unexpected Operator token".to_string(), span: current_token.span, }), - TokenKind::TemplateString(_) => Err(ParserError::FailedToParse { + TokenKind::TemplateString(_) => self.error(AstNodeError::Custom { message: "Unexpected TemplateString token".to_string(), span: current_token.span, }), diff --git a/core/expression/src/parser/standard.rs b/core/expression/src/parser/standard.rs index 183a27bd..c0136a5a 100644 --- a/core/expression/src/parser/standard.rs +++ b/core/expression/src/parser/standard.rs @@ -1,7 +1,7 @@ use crate::lexer::{Bracket, Identifier, TokenKind}; -use crate::parser::ast::Node; +use crate::parser::ast::{AstNodeError, Node}; use crate::parser::constants::{Associativity, BINARY_OPERATORS, UNARY_OPERATORS}; -use crate::parser::error::ParserError::{FailedToParse, UnexpectedToken}; +use crate::parser::error::ParserError; use crate::parser::error::ParserResult; use crate::parser::parser::Parser; @@ -10,21 +10,25 @@ pub struct Standard; impl<'arena, 'token_ref> Parser<'arena, 'token_ref, Standard> { pub fn parse(&self) -> ParserResult<&'arena Node<'arena>> { - let result = self.binary_expression(0)?; + let result = self.binary_expression(0); if !self.is_done() { - let token = self.current(); - return Err(FailedToParse { - message: format!("Unterminated token {}", token.value), - span: token.span, - }); + return match self.current() { + None => Err(ParserError::TokenOutOfBounds), + Some(token) => Err(ParserError::FailedToParse { + message: format!("Unterminated token {}", token.kind), + span: token.span, + }), + }; } - return Ok(result); + Ok(result) } - fn binary_expression(&self, precedence: u8) -> ParserResult<&'arena Node<'arena>> { - let mut node_left = self.unary_expression()?; - let mut token = self.current(); + fn binary_expression(&self, precedence: u8) -> &'arena Node<'arena> { + let mut node_left = self.unary_expression(); + let Some(mut token) = self.current() else { + return node_left; + }; while let TokenKind::Operator(operator) = &token.kind { if self.is_done() { @@ -39,10 +43,10 @@ impl<'arena, 'token_ref> Parser<'arena, 'token_ref, Standard> { break; } - self.next()?; + self.next(); let node_right = match op.associativity { - Associativity::Left => self.binary_expression(op.precedence + 1)?, - _ => self.binary_expression(op.precedence)?, + Associativity::Left => self.binary_expression(op.precedence + 1), + _ => self.binary_expression(op.precedence), }; node_left = self.node(Node::Binary { @@ -50,25 +54,31 @@ impl<'arena, 'token_ref> Parser<'arena, 'token_ref, Standard> { left: node_left, right: node_right, }); - token = self.current(); + + let Some(t) = self.current() else { + break; + }; + token = t; } if precedence == 0 { if let Some(conditional_node) = - self.conditional(node_left, || self.binary_expression(0))? + self.conditional(node_left, || self.binary_expression(0)) { node_left = conditional_node; } } - Ok(node_left) + node_left } - fn unary_expression(&self) -> ParserResult<&'arena Node<'arena>> { - let token = self.current(); + fn unary_expression(&self) -> &'arena Node<'arena> { + let Some(mut token) = self.current() else { + return self.error(AstNodeError::Invalid); + }; if self.depth() > 0 && token.kind == TokenKind::Identifier(Identifier::CallbackReference) { - self.next()?; + self.next(); let node = self.node(Node::Pointer); return self.with_postfix(node, || self.binary_expression(0)); @@ -76,31 +86,31 @@ impl<'arena, 'token_ref> Parser<'arena, 'token_ref, Standard> { if let TokenKind::Operator(operator) = &token.kind { let Some(unary_operator) = UNARY_OPERATORS.get(operator) else { - return Err(UnexpectedToken { + return self.error(AstNodeError::UnexpectedToken { expected: "UnaryOperator".to_string(), received: token.kind.to_string(), span: token.span, }); }; - self.next()?; - let expr = self.binary_expression(unary_operator.precedence)?; + self.next(); + let expr = self.binary_expression(unary_operator.precedence); let node = self.node(Node::Unary { operator: *operator, node: expr, }); - return Ok(node); + return node; } - if let Some(interval_node) = self.interval(|| self.binary_expression(0))? { - return Ok(interval_node); + if let Some(interval_node) = self.interval(|| self.binary_expression(0)) { + return interval_node; } if token.kind == TokenKind::Bracket(Bracket::LeftParenthesis) { - self.next()?; - let expr = self.binary_expression(0)?; - self.expect(TokenKind::Bracket(Bracket::RightParenthesis))?; + self.next(); + let expr = self.binary_expression(0); + self.expect(TokenKind::Bracket(Bracket::RightParenthesis)); return self.with_postfix(expr, || self.binary_expression(0)); } diff --git a/core/expression/src/parser/unary.rs b/core/expression/src/parser/unary.rs index 88059418..c98517f8 100644 --- a/core/expression/src/parser/unary.rs +++ b/core/expression/src/parser/unary.rs @@ -1,8 +1,7 @@ use crate::lexer::{Bracket, ComparisonOperator, Identifier, LogicalOperator, Operator, TokenKind}; -use crate::parser::ast::Node; +use crate::parser::ast::{AstNodeError, Node}; use crate::parser::builtin::BuiltInFunction; use crate::parser::constants::{Associativity, BINARY_OPERATORS, UNARY_OPERATORS}; -use crate::parser::error::ParserError::{FailedToParse, UnexpectedToken}; use crate::parser::error::{ParserError, ParserResult}; use crate::parser::parser::Parser; use crate::parser::unary::UnaryNodeBehaviour::CompareWithReference; @@ -14,35 +13,40 @@ const ROOT_NODE: Node<'static> = Node::Identifier("$"); impl<'arena, 'token_ref> Parser<'arena, 'token_ref, Unary> { pub fn parse(&self) -> ParserResult<&'arena Node<'arena>> { - let result = self.root_expression()?; + let result = self.root_expression(); + println!("{:?}", result); if !self.is_done() { - let token = self.current(); - return Err(FailedToParse { - message: format!("Unterminated token {}", token.value), - span: token.span, - }); + return match self.current() { + None => Err(ParserError::TokenOutOfBounds), + Some(token) => Err(ParserError::FailedToParse { + message: format!("Unterminated token {}", token.kind), + span: token.span, + }), + }; } - return Ok(result); + Ok(result) } - fn root_expression(&self) -> ParserResult<&'arena Node<'arena>> { - let mut left_node = self.expression_pair()?; + fn root_expression(&self) -> &'arena Node<'arena> { + let mut left_node = self.expression_pair(); + while !self.is_done() { - let current_token = self.current(); + let Some(current_token) = self.current() else { + break; + }; + let join_operator = match ¤t_token.kind { TokenKind::Operator(Operator::Logical(LogicalOperator::And)) => { Operator::Logical(LogicalOperator::And) } TokenKind::Operator(Operator::Logical(LogicalOperator::Or)) | TokenKind::Operator(Operator::Comma) => Operator::Logical(LogicalOperator::Or), - _ => { - return Err(ParserError::MemoryFailure); - } + _ => return self.error(AstNodeError::Invalid), }; - self.next()?; - let right_node = self.expression_pair()?; + self.next(); + let right_node = self.expression_pair(); left_node = self.node(Node::Binary { left: left_node, operator: join_operator, @@ -50,23 +54,29 @@ impl<'arena, 'token_ref> Parser<'arena, 'token_ref, Unary> { }); } - Ok(left_node) + left_node } - fn expression_pair(&self) -> ParserResult<&'arena Node<'arena>> { + fn expression_pair(&self) -> &'arena Node<'arena> { let mut left_node = &ROOT_NODE; - let initial_token = self.current(); + let Some(initial_token) = self.current() else { + return left_node; + }; + if let TokenKind::Operator(Operator::Comparison(_)) = &initial_token.kind { // Skips } else { - left_node = self.binary_expression(0)?; + left_node = self.binary_expression(0); } - let current_token = self.current(); + let Some(current_token) = self.current() else { + return left_node; + }; + match ¤t_token.kind { TokenKind::Operator(Operator::Comparison(comparison)) => { - self.next()?; - let right_node = self.binary_expression(0)?; + self.next(); + let right_node = self.binary_expression(0); left_node = self.node(Node::Binary { left: left_node, operator: Operator::Comparison(*comparison), @@ -93,12 +103,14 @@ impl<'arena, 'token_ref> Parser<'arena, 'token_ref, Unary> { } } - Ok(left_node) + left_node } - fn binary_expression(&self, precedence: u8) -> ParserResult<&'arena Node<'arena>> { - let mut node_left = self.unary_expression()?; - let mut token = self.current(); + fn binary_expression(&self, precedence: u8) -> &'arena Node<'arena> { + let mut node_left = self.unary_expression(); + let Some(mut token) = self.current() else { + return node_left; + }; while let TokenKind::Operator(operator) = &token.kind { if self.is_done() { @@ -122,10 +134,10 @@ impl<'arena, 'token_ref> Parser<'arena, 'token_ref, Unary> { break; } - self.next()?; + self.next(); let node_right = match op.associativity { - Associativity::Left => self.binary_expression(op.precedence + 1)?, - _ => self.binary_expression(op.precedence)?, + Associativity::Left => self.binary_expression(op.precedence + 1), + _ => self.binary_expression(op.precedence), }; node_left = self.node(Node::Binary { @@ -133,25 +145,31 @@ impl<'arena, 'token_ref> Parser<'arena, 'token_ref, Unary> { left: node_left, right: node_right, }); - token = self.current(); + + let Some(t) = self.current() else { + break; + }; + token = t; } if precedence == 0 { if let Some(conditional_node) = - self.conditional(node_left, || self.binary_expression(0))? + self.conditional(node_left, || self.binary_expression(0)) { node_left = conditional_node; } } - Ok(node_left) + node_left } - fn unary_expression(&self) -> ParserResult<&'arena Node<'arena>> { - let token = self.current(); + fn unary_expression(&self) -> &'arena Node<'arena> { + let Some(token) = self.current() else { + return self.literal(|| self.binary_expression(0)); + }; if self.depth() > 0 && token.kind == TokenKind::Identifier(Identifier::CallbackReference) { - self.next()?; + self.next(); let node = self.node(Node::Pointer); return self.with_postfix(node, || self.binary_expression(0)); @@ -159,31 +177,31 @@ impl<'arena, 'token_ref> Parser<'arena, 'token_ref, Unary> { if let TokenKind::Operator(operator) = &token.kind { let Some(unary_operator) = UNARY_OPERATORS.get(operator) else { - return Err(UnexpectedToken { + return self.error(AstNodeError::UnexpectedToken { expected: "UnaryOperator".to_string(), received: token.kind.to_string(), span: token.span, }); }; - self.next()?; - let expr = self.binary_expression(unary_operator.precedence)?; + self.next(); + let expr = self.binary_expression(unary_operator.precedence); let node = self.node(Node::Unary { operator: *operator, node: expr, }); - return Ok(node); + return node; } - if let Some(interval_node) = self.interval(|| self.binary_expression(0))? { - return Ok(interval_node); + if let Some(interval_node) = self.interval(|| self.binary_expression(0)) { + return interval_node; } if token.kind == TokenKind::Bracket(Bracket::LeftParenthesis) { - self.next()?; - let expr = self.binary_expression(0)?; - self.expect(TokenKind::Bracket(Bracket::RightParenthesis))?; + self.next(); + let expr = self.binary_expression(0); + self.expect(TokenKind::Bracket(Bracket::RightParenthesis)); return self.with_postfix(expr, || self.binary_expression(0)); } @@ -235,11 +253,11 @@ impl From<&Node<'_>> for UnaryNodeBehaviour { let a = UnaryNodeBehaviour::from(*on_true); let b = UnaryNodeBehaviour::from(*on_false); - return if a == b { + if a == b { a } else { CompareWithReference(Equal) - }; + } } Node::Unary { node, .. } => UnaryNodeBehaviour::from(*node), Node::Binary { @@ -251,11 +269,11 @@ impl From<&Node<'_>> for UnaryNodeBehaviour { let a = UnaryNodeBehaviour::from(*left); let b = UnaryNodeBehaviour::from(*right); - return if a == b { + if a == b { a } else { CompareWithReference(Equal) - }; + } } Operator::Logical(_) => AsBoolean, Operator::Comparison(_) => AsBoolean, @@ -318,6 +336,7 @@ impl From<&Node<'_>> for UnaryNodeBehaviour { BuiltInFunction::One => AsBoolean, BuiltInFunction::Type => CompareWithReference(Equal), }, + Node::Error(_) => AsBoolean, } } } diff --git a/core/expression/tests/isolate.rs b/core/expression/tests/isolate.rs index 452440b8..57ca3e2d 100644 --- a/core/expression/tests/isolate.rs +++ b/core/expression/tests/isolate.rs @@ -780,11 +780,12 @@ fn test_standard_csv() { isolate.set_environment(&input); } - let result = isolate + let maybe_result = isolate .run_standard(expression) - .context(format!("Expression: {expression}")) - .unwrap(); + .context(format!("Expression: {expression}")); + assert!(maybe_result.is_ok(), "{}", maybe_result.unwrap_err()); + let result = maybe_result.unwrap(); assert_eq!( result, output, "Expression {expression}. Expected: {output}, got: {result}" diff --git a/core/expression_repl/src/main.rs b/core/expression_repl/src/main.rs index a291ef6b..3fc082d6 100644 --- a/core/expression_repl/src/main.rs +++ b/core/expression_repl/src/main.rs @@ -49,12 +49,12 @@ fn main() -> Result<()> { let mut isolate = Isolate::new(); isolate.set_environment( - &json!({ "customer": { "firstName": "John", "lastName": "Doe", "age": 20 } }), + &json!({ "customer": { "firstName": "John", "lastName": "Doe", "age": 20 }, "hello": true, "$": 10 }), ); - let result = isolate.run_standard(line.as_str()); + let result = isolate.run_unary(line.as_str()); match result { - Ok(res) => println!("{}", res.pretty_print()), + Ok(res) => println!("{}", res), Err(err) => println!("Error: {}", err.to_string().red()), }; }