local: fault tolerant parser

This commit is contained in:
Stefan
2024-09-18 17:18:41 +02:00
parent 35265f76a2
commit 0886fd197f
9 changed files with 592 additions and 396 deletions
+1
View File
@@ -588,6 +588,7 @@ impl<'arena, 'bytecode_ref> CompilerInner<'arena, 'bytecode_ref> {
Ok(self.emit(Opcode::End))
}
},
Node::Error(_) => Err(CompilerError::UnexpectedErrorNode),
}
}
}
+3
View File
@@ -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<T> = Result<T, CompilerError>;
+123 -2
View File
@@ -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<F>(&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,
}
+3 -4
View File
@@ -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<T> = Result<T, ParserError>;
pub(crate) type AstResult<T> = Result<T, AstNodeError>;
+346 -304
View File
@@ -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<Option<&'token_ref Token<'arena>>>,
pub(crate) bump: &'arena Bump,
is_done: Cell<bool>,
position: Cell<usize>,
depth: Cell<u8>,
marker_flavor: PhantomData<Flavor>,
@@ -36,7 +35,7 @@ impl<'arena, 'token_ref> Parser<'arena, 'token_ref, BaseParser> {
tokens: &'token_ref [Token<'arena>],
bump: &'arena Bump,
) -> Result<Self, ParserError> {
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<Option<&'arena Node<'arena>>> {
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<F>(&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<F>(
&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<Option<&'arena Node<'arena>>> {
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<Option<&'arena Node<'arena>>> {
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<F>(
&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<F>(&self, expression_parser: F) -> ParserResult<&'arena Node<'arena>>
pub(crate) fn closure<F>(&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 <Identifier> or <Identifier Expression>
pub(crate) fn identifier<F>(
&self,
expression_parser: F,
) -> ParserResult<Option<&'arena Node<'arena>>>
pub(crate) fn identifier<F>(&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<F>(
&self,
expression_parser: F,
) -> ParserResult<Option<&'arena Node<'arena>>>
pub(crate) fn interval<F>(&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<F>(
&self,
expression_parser: F,
) -> ParserResult<Option<&'arena Node<'arena>>>
pub(crate) fn array<F>(&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<F>(&self, expression_parser: F) -> ParserResult<&'arena Node<'arena>>
pub(crate) fn object<F>(&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<F>(&self, expression_parser: F) -> ParserResult<&'arena Node<'arena>>
pub(crate) fn object_key<F>(&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>>>
) -> 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<F>(&self, expression_parser: F) -> ParserResult<&'arena Node<'arena>>
pub(crate) fn literal<F>(&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 &current_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,
}),
+40 -30
View File
@@ -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));
}
+69 -50
View File
@@ -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 &current_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 &current_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,
}
}
}
+4 -3
View File
@@ -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}"
+3 -3
View File
@@ -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()),
};
}