improve error handling and ast

This commit is contained in:
Stefan
2024-09-22 13:03:12 +02:00
parent 7a717df4b9
commit dec4da9472
9 changed files with 269 additions and 111 deletions
+9 -9
View File
@@ -150,18 +150,18 @@ impl<'a> DecisionTableHandler<'a> {
if let Some(description) = rule.get("_description") {
expressions.insert("_description".to_string(), description.clone());
}
for input in &content.inputs {
let rule_value = rule.get(input.id.as_str())?;
let mut input_identifier = input.id.clone();
if let Some(input_field) = &input.field {
input_identifier = format!("{input_field}[{input_identifier}]");
let Some(input_field) = &input.field else {
continue;
};
if let Some(reference) = self.isolate.get_reference(input_field.as_str()) {
reference_map.insert(input_field.clone(), reference);
}
if let Some(reference) = self.isolate.get_reference(input_identifier.as_str()) {
reference_map.insert(input_identifier.clone(), reference);
}
let input_identifier = format!("{input_field}[{}]", &input.id);
expressions.insert(input_identifier, rule_value.clone());
}
+2 -1
View File
@@ -132,6 +132,7 @@ impl<'arena, 'bytecode_ref> CompilerInner<'arena, 'bytecode_ref> {
}
Node::Identifier(v) => Ok(self.emit(Opcode::FetchEnv(v))),
Node::Closure(v) => self.compile_node(v),
Node::Parenthesized(v) => self.compile_node(v),
Node::Member { node, property } => {
self.compile_node(node)?;
self.compile_node(property)?;
@@ -588,7 +589,7 @@ impl<'arena, 'bytecode_ref> CompilerInner<'arena, 'bytecode_ref> {
Ok(self.emit(Opcode::End))
}
},
Node::Error(_) => Err(CompilerError::UnexpectedErrorNode),
Node::Error { .. } => Err(CompilerError::UnexpectedErrorNode),
}
}
}
+4 -1
View File
@@ -63,7 +63,10 @@ impl<'arena> IntelliSense<'arena> {
let typ = type_data.get_type(node);
r.push(IntelliSenseToken {
span: metadata.get(&addr).map(|s| s.span).unwrap_or_default(),
span: node
.span()
.or_else(|| metadata.get(&addr).map(|s| s.span))
.unwrap_or_default(),
node_kind: node.into(),
error: typ.map(|t| t.error.clone()).flatten(),
kind: typ
@@ -229,11 +229,11 @@ impl TypesProvider {
match operator {
Operator::Arithmetic(arith) => match arith {
ArithmeticOperator::Add => match (left_type.kind.as_ref(), right_type.kind.as_ref()) {
ArithmeticOperator::Add => match (left_type.omit_const(), right_type.omit_const()) {
(VariableType::Number, VariableType::Number) => V(VariableType::Number),
(VariableType::String, VariableType::String) => V(VariableType::String),
(VariableType::Any, _) => V(VariableType::Any),
(_, VariableType::Any) => V(VariableType::Any),
(VariableType::Any, VariableType::Number | VariableType::String) => V(VariableType::Any),
(VariableType::Number | VariableType::String, VariableType::Any) => V(VariableType::Any),
_ => Error(format!(
"Operator `{operator}` cannot be applied to types `{left_type}` and `{right_type}`."
)),
@@ -242,10 +242,8 @@ impl TypesProvider {
| ArithmeticOperator::Multiply
| ArithmeticOperator::Divide
| ArithmeticOperator::Modulus
| ArithmeticOperator::Power => match (left_type.kind.as_ref(), &right_type.kind.as_ref()) {
(VariableType::Number, VariableType::Number) => V(VariableType::Number),
(VariableType::Any, _) => V(VariableType::Number),
(_, VariableType::Any) => V(VariableType::Number),
| ArithmeticOperator::Power => match (left_type.omit_const(), right_type.omit_const()) {
(VariableType::Number | VariableType::Any, VariableType::Number | VariableType::Any) => V(VariableType::Number),
_ => Error(format!(
"Operator `{operator}` cannot be applied to types `{left_type}` and `{right_type}`."
)),
@@ -253,10 +251,8 @@ impl TypesProvider {
},
Operator::Logical(l) => match l {
LogicalOperator::And | LogicalOperator::Or | LogicalOperator::Not => {
match (left_type.kind.as_ref(), &right_type.kind.as_ref()) {
(VariableType::Bool, VariableType::Bool) => V(VariableType::Bool),
(VariableType::Any, _) => V(VariableType::Bool),
(_, VariableType::Any) => V(VariableType::Bool),
match (left_type.omit_const(), right_type.omit_const()) {
(VariableType::Bool | VariableType::Any, VariableType::Bool | VariableType::Any) => V(VariableType::Bool),
_ => Error(format!(
"Operator `{operator}` cannot be applied to types `{left_type}` and `{right_type}`."
)),
@@ -270,10 +266,8 @@ impl TypesProvider {
ComparisonOperator::LessThan
| ComparisonOperator::GreaterThan
| ComparisonOperator::LessThanOrEqual
| ComparisonOperator::GreaterThanOrEqual => match (left_type.kind.as_ref(), right_type.kind.as_ref()) {
(VariableType::Number, VariableType::Number) => V(VariableType::Bool),
(VariableType::Any, _) => V(VariableType::Bool),
(_, VariableType::Any) => V(VariableType::Bool),
| ComparisonOperator::GreaterThanOrEqual => match (left_type.omit_const(), right_type.omit_const()) {
(VariableType::Number | VariableType::Any, VariableType::Number | VariableType::Any) => V(VariableType::Bool),
_ => Error(format!(
"Operator `{operator}` cannot be applied to types `{left_type}` and `{right_type}`."
)),
@@ -694,7 +688,20 @@ impl TypesProvider {
}
}
Node::Closure(c) => self.determine(c, scope.clone(), false),
Node::Error(_) => V(VariableType::Any),
Node::Parenthesized(c) => self.determine(c, scope.clone(), false),
Node::Error { node, error } => match node {
None => TypeInfo {
kind: Rc::new(VariableType::Any),
error: Some(error.to_string()),
},
Some(n) => {
let typ = self.determine(n, scope.clone(), false);
TypeInfo {
kind: typ.kind,
error: Some(error.to_string()),
}
}
},
};
self.set_type(node, node_type.clone());
+33 -9
View File
@@ -17,6 +17,7 @@ pub enum Node<'a> {
Object(&'a [(&'a Node<'a>, &'a Node<'a>)]),
Identifier(&'a str),
Closure(&'a Node<'a>),
Parenthesized(&'a Node<'a>),
Root,
Member {
node: &'a Node<'a>,
@@ -51,7 +52,10 @@ pub enum Node<'a> {
kind: BuiltInFunction,
arguments: &'a [&'a Node<'a>],
},
Error(AstNodeError),
Error {
node: Option<&'a Node<'a>>,
error: AstNodeError,
},
}
impl<'a> Node<'a> {
@@ -64,7 +68,6 @@ impl<'a> Node<'a> {
};
match self {
Node::Error(_) => {}
Node::Null => {}
Node::Bool(_) => {}
Node::Number(_) => {}
@@ -72,6 +75,11 @@ impl<'a> Node<'a> {
Node::Pointer => {}
Node::Identifier(_) => {}
Node::Root => {}
Node::Error { node, .. } => {
if let Some(n) = node {
n.walk(func.clone())
}
}
Node::TemplateString(parts) => parts.iter().for_each(|n| n.walk(func.clone())),
Node::Array(parts) => parts.iter().for_each(|n| n.walk(func.clone())),
Node::Object(obj) => obj.iter().for_each(|(k, v)| {
@@ -79,6 +87,7 @@ impl<'a> Node<'a> {
v.walk(func.clone());
}),
Node::Closure(closure) => closure.walk(func.clone()),
Node::Parenthesized(c) => c.walk(func.clone()),
Node::Member { node, property } => {
node.walk(func.clone());
property.walk(func.clone());
@@ -120,19 +129,37 @@ impl<'a> Node<'a> {
}
pub fn first_error(&self) -> Option<AstNodeError> {
let error = Cell::new(None);
let error_cell = Cell::new(None);
self.walk(|n| {
if let Node::Error(err) = n {
error.set(Some(err.clone()))
if let Node::Error { error, .. } = n {
error_cell.set(Some(error.clone()))
}
});
error.into_inner()
error_cell.into_inner()
}
pub fn has_error(&self) -> bool {
self.first_error().is_some()
}
pub(crate) fn span(&self) -> Option<(u32, u32)> {
match self {
Node::Error { error, .. } => match error {
AstNodeError::UnknownBuiltIn { span, .. } => Some(span.clone()),
AstNodeError::UnexpectedIdentifier { span, .. } => Some(span.clone()),
AstNodeError::UnexpectedToken { span, .. } => Some(span.clone()),
AstNodeError::InvalidNumber { span, .. } => Some(span.clone()),
AstNodeError::InvalidBoolean { span, .. } => Some(span.clone()),
AstNodeError::InvalidProperty { span, .. } => Some(span.clone()),
AstNodeError::MissingToken { position, .. } => {
Some((*position as u32, *position as u32))
}
AstNodeError::Custom { span, .. } => Some(span.clone()),
},
_ => None,
}
}
}
#[derive(Debug, PartialEq, Eq, Clone, Error)]
@@ -168,7 +195,4 @@ pub enum AstNodeError {
#[error("{message} at ({}, {})", span.0, span.1)]
Custom { message: String, span: (u32, u32) },
#[error("Invalid")]
Invalid,
}
+160 -64
View File
@@ -19,6 +19,14 @@ use crate::parser::standard::Standard;
use crate::parser::unary::Unary;
use crate::parser::NodeMetadata;
macro_rules! expect {
($self:ident, $token:expr) => {
if let Some(error_node) = $self.expect($token) {
return error_node;
}
};
}
#[derive(Debug)]
pub struct BaseParser;
@@ -90,16 +98,6 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
self
}
fn get_metadata(&self, node: &'arena Node<'arena>) -> Option<NodeMetadata> {
let Some(node_metadata) = &self.node_metadata else {
return None;
};
let nm = node_metadata.borrow();
let address = node as *const Node as usize;
nm.get(&address).cloned()
}
pub(crate) fn current(&self) -> Option<&Token<'arena>> {
self.current.get()
}
@@ -115,6 +113,7 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
}
}
#[allow(dead_code)]
fn token_end(&self) -> u32 {
match self.current() {
None => self.tokens.last().map(|t| t.span.1).unwrap_or_default(),
@@ -122,7 +121,7 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
}
}
fn prev_token_end(&self) -> u32 {
pub(crate) fn prev_token_end(&self) -> u32 {
match self.tokens.get(self.position() - 1) {
None => self.token_start(),
Some(t) => t.span.1,
@@ -172,8 +171,23 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
}
pub(crate) fn error(&self, error: AstNodeError) -> &'arena Node<'arena> {
// TODO
self.node(Node::Error(error), |_| NodeMetadata { span: (0, 0) })
self.node(Node::Error { error, node: None }, |_| NodeMetadata {
span: (self.prev_token_end(), self.prev_token_end()),
})
}
pub(crate) fn error_with_node(
&self,
error: AstNodeError,
node: &'arena Node<'arena>,
) -> &'arena Node<'arena> {
self.node(
Node::Error {
error,
node: Some(node),
},
|_| NodeMetadata { span: (0, 0) },
)
}
pub(crate) fn next(&self) {
@@ -260,10 +274,7 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
}
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;
}
expect!(self, TokenKind::QuotationMark(quote_mark.clone()));
let string_value = self.current();
let error_literal = self.expect(TokenKind::Literal);
@@ -273,16 +284,24 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
.or(error_mark_end)
.or(string_value
.map(|t| self.node(Node::String(t.value), |_| NodeMetadata { span: t.span })))
.unwrap_or_else(|| self.error(AstNodeError::Invalid))
.unwrap_or_else(|| {
self.error(AstNodeError::Custom {
message: format!(
"Failed to parse string `{}`",
string_value.map(|s| s.value).unwrap_or_default()
),
span: string_value
.map(|s| s.span)
.unwrap_or((self.prev_token_end(), self.prev_token_end())),
})
})
}
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;
}
expect!(self, TokenKind::QuotationMark(QuotationMark::Backtick));
let Some(mut current_token) = self.current() else {
return self.error(AstNodeError::MissingToken {
@@ -330,10 +349,7 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
}
}
if let Some(err) = self.expect(TokenKind::QuotationMark(QuotationMark::Backtick)) {
return err;
};
expect!(self, TokenKind::QuotationMark(QuotationMark::Backtick));
self.node(Node::TemplateString(nodes.into_bump_slice()), |_| {
NodeMetadata { span }
})
@@ -351,7 +367,6 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
return node;
};
let start_token = postfix_token;
let postfix_kind = PostfixKind::from(postfix_token);
let processed_token = match postfix_kind {
@@ -362,13 +377,22 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
self.next();
let property = match property_token {
None => self.error(AstNodeError::Invalid),
None => self.error_with_node(
AstNodeError::Custom {
message: "Expected a property".to_string(),
span: (self.prev_token_end(), self.prev_token_end()),
},
node,
),
Some(t) => match is_valid_property(t) {
true => self.node(Node::String(t.value), |_| NodeMetadata { span: t.span }),
false => self.error(AstNodeError::InvalidProperty {
property: t.value.to_string(),
span: t.span,
}),
false => self.error_with_node(
AstNodeError::InvalidProperty {
property: t.value.to_string(),
span: t.span,
},
node,
),
},
};
@@ -382,14 +406,26 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
let mut to: Option<&'arena Node<'arena>> = None;
let Some(mut c) = self.current() else {
return self.error(AstNodeError::Invalid);
return self.error_with_node(
AstNodeError::Custom {
message: "Expected a property".to_string(),
span: (self.prev_token_end(), self.prev_token_end()),
},
node,
);
};
if c.kind == TokenKind::Operator(Operator::Slice) {
self.next();
let Some(cc) = self.current() else {
return self.error(AstNodeError::Invalid);
return self.error_with_node(
AstNodeError::Custom {
message: "Unexpected token".to_string(),
span: (self.prev_token_end(), self.prev_token_end()),
},
node,
);
};
c = cc;
@@ -397,7 +433,7 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
to = Some(expression_parser());
}
self.expect(TokenKind::Bracket(Bracket::RightSquareBracket));
expect!(self, TokenKind::Bracket(Bracket::RightSquareBracket));
self.node(Node::Slice { node, to, from }, |h| NodeMetadata {
span: (
h.metadata(node).map(|m| m.span.0).unwrap_or_default(),
@@ -405,16 +441,39 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
),
})
} else {
from = Some(expression_parser());
let from_node = expression_parser();
from = Some(from_node);
let Some(cc) = self.current() else {
return self.error(AstNodeError::Invalid);
return self.error_with_node(
AstNodeError::Custom {
message: "Unexpected token".to_string(),
span: (self.prev_token_end(), self.prev_token_end()),
},
self.node(
Node::Member {
node,
property: from_node,
},
|h| NodeMetadata {
span: h.span(node, from_node).unwrap_or_default(),
},
),
);
};
c = cc;
if c.kind == TokenKind::Operator(Operator::Slice) {
self.next();
let Some(cc) = self.current() else {
return self.error(AstNodeError::Invalid);
return self.error_with_node(
AstNodeError::Custom {
message: "Invalid slice syntax".to_string(),
span: (self.prev_token_end(), self.prev_token_end()),
},
self.node(Node::Slice { node, from, to }, |h| NodeMetadata {
span: h.span(node, from_node).unwrap_or_default(),
}),
);
};
c = cc;
@@ -422,21 +481,35 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
to = Some(expression_parser());
}
self.expect(TokenKind::Bracket(Bracket::RightSquareBracket));
self.node(Node::Slice { node, from, to }, |_| NodeMetadata {
span: (start_token.span.0, self.prev_token_end()),
expect!(self, TokenKind::Bracket(Bracket::RightSquareBracket));
self.node(Node::Slice { node, from, to }, |h| NodeMetadata {
span: (
h.metadata(node).map(|m| m.span.0).unwrap_or_default(),
self.prev_token_end(),
),
})
} else {
// Slice operator [:] was not found,
// it should be just an index node.
self.expect(TokenKind::Bracket(Bracket::RightSquareBracket));
expect!(self, TokenKind::Bracket(Bracket::RightSquareBracket));
self.node(
Node::Member {
node,
property: from.unwrap_or_else(|| self.error(AstNodeError::Invalid)),
property: from.unwrap_or_else(|| {
return self.error_with_node(
AstNodeError::Custom {
message: "Invalid index property".to_string(),
span: (self.prev_token_end(), self.prev_token_end()),
},
node,
);
}),
},
|_| NodeMetadata {
span: (start_token.span.0, self.prev_token_end()),
|h| NodeMetadata {
span: (
h.metadata(node).map(|m| m.span.0).unwrap_or_default(),
self.prev_token_end(),
),
},
)
}
@@ -481,14 +554,18 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
// ok
}
_ => {
return self.node(Node::Error(AstNodeError::Invalid), |_| NodeMetadata {
return self.error(AstNodeError::Custom {
message: format!("Expected an `identifier`, received `{}`.", token.kind),
span: token.span,
})
});
}
}
let Some(identifier_token) = self.current() else {
return self.error(AstNodeError::Invalid);
return self.error(AstNodeError::Custom {
message: "Expected an `identifier`.".to_string(),
span: (self.prev_token_end(), self.prev_token_end()),
});
};
self.next();
@@ -540,6 +617,7 @@ 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));
@@ -648,7 +726,7 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
== Some(TokenKind::Bracket(Bracket::RightSquareBracket)))
{
if !nodes.is_empty() {
self.expect(TokenKind::Operator(Operator::Comma));
expect!(self, TokenKind::Operator(Operator::Comma));
if self.current().map(|t| t.kind)
== Some(TokenKind::Bracket(Bracket::RightSquareBracket))
{
@@ -659,7 +737,8 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
nodes.push(expression_parser());
}
self.expect(TokenKind::Bracket(Bracket::RightSquareBracket));
expect!(self, TokenKind::Bracket(Bracket::RightSquareBracket));
let node = Node::Array(nodes.into_bump_slice());
self.with_postfix(
@@ -675,9 +754,7 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
F: Fn() -> &'arena Node<'arena>,
{
let span_start = self.token_start();
if let Some(err_node) = self.expect(TokenKind::Bracket(Bracket::LeftCurlyBracket)) {
return err_node;
};
expect!(self, TokenKind::Bracket(Bracket::LeftCurlyBracket));
let mut key_value_pairs = BumpVec::new_in(self.bump);
if let Some(TokenKind::Bracket(Bracket::RightCurlyBracket)) = self.current().map(|t| t.kind)
@@ -692,7 +769,7 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
loop {
let key = self.object_key(&expression_parser);
self.expect(TokenKind::Operator(Operator::Slice));
expect!(self, TokenKind::Operator(Operator::Slice));
let value = expression_parser();
key_value_pairs.push((key, value));
@@ -703,14 +780,19 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
match current_token.kind {
TokenKind::Operator(Operator::Comma) => {
self.expect(TokenKind::Operator(Operator::Comma));
expect!(self, TokenKind::Operator(Operator::Comma));
}
TokenKind::Bracket(Bracket::RightCurlyBracket) => break,
_ => return self.error(AstNodeError::Invalid),
_ => {
return self.error(AstNodeError::Custom {
message: "Invalid object syntax".to_string(),
span: current_token.span,
})
}
}
}
self.expect(TokenKind::Bracket(Bracket::RightCurlyBracket));
expect!(self, TokenKind::Bracket(Bracket::RightCurlyBracket));
self.node(Node::Object(key_value_pairs.into_bump_slice()), |_| {
NodeMetadata {
span: (span_start, self.prev_token_end()),
@@ -723,7 +805,10 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
F: Fn() -> &'arena Node<'arena>,
{
let Some(key_token) = self.current() else {
return self.error(AstNodeError::Invalid);
return self.error(AstNodeError::Custom {
message: "Expected an object key".to_string(),
span: (self.prev_token_end(), self.prev_token_end()),
});
};
let key = match key_token.kind {
@@ -761,9 +846,9 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
}
TokenKind::Bracket(bracket) => match bracket {
Bracket::LeftSquareBracket => {
self.expect(TokenKind::Bracket(Bracket::LeftSquareBracket));
expect!(self, TokenKind::Bracket(Bracket::LeftSquareBracket));
let token = expression_parser();
self.expect(TokenKind::Bracket(Bracket::RightSquareBracket));
expect!(self, TokenKind::Bracket(Bracket::RightSquareBracket));
token
}
@@ -822,7 +907,10 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
self.next();
let on_true = expression_parser();
self.expect(TokenKind::Operator(Operator::Slice));
if let Some(error_node) = self.expect(TokenKind::Operator(Operator::Slice)) {
return Some(error_node);
}
let on_false = expression_parser();
let conditional_node = Node::Conditional {
@@ -842,7 +930,10 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
F: Fn() -> &'arena Node<'arena>,
{
let Some(current_token) = self.current() else {
return self.error(AstNodeError::Invalid);
return self.error(AstNodeError::Custom {
message: "Expected a literal".to_string(),
span: (self.prev_token_end(), self.prev_token_end()),
});
};
match &current_token.kind {
@@ -862,9 +953,14 @@ 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)
.unwrap_or_else(|| self.error(AstNodeError::Invalid)),
| Bracket::RightSquareBracket => {
self.interval(&expression_parser).unwrap_or_else(|| {
self.error(AstNodeError::Custom {
message: "Invalid syntax".to_string(),
span: (self.prev_token_end(), self.prev_token_end()),
})
})
}
Bracket::LeftSquareBracket => self
.interval(&expression_parser)
.unwrap_or_else(|| self.array(&expression_parser)),
+15 -3
View File
@@ -74,7 +74,10 @@ impl<'arena, 'token_ref> Parser<'arena, 'token_ref, Standard> {
fn unary_expression(&self) -> &'arena Node<'arena> {
let Some(token) = self.current() else {
return self.error(AstNodeError::Invalid);
return self.error(AstNodeError::Custom {
message: "Unexpected end of unary expression".to_string(),
span: (self.prev_token_end(), self.prev_token_end()),
});
};
if self.depth() > 0 && token.kind == TokenKind::Identifier(Identifier::CallbackReference) {
@@ -116,9 +119,18 @@ impl<'arena, 'token_ref> Parser<'arena, 'token_ref, Standard> {
}
if token.kind == TokenKind::Bracket(Bracket::LeftParenthesis) {
let p_start = self.current().map(|s| s.span.0);
self.next();
let expr = self.binary_expression(0);
self.expect(TokenKind::Bracket(Bracket::RightParenthesis));
let binary_node = self.binary_expression(0);
if let Some(error_node) = self.expect(TokenKind::Bracket(Bracket::RightParenthesis)) {
return error_node;
};
let expr = self.node(Node::Parenthesized(binary_node), |_| NodeMetadata {
span: (p_start.unwrap_or_default(), self.prev_token_end()),
});
return self.with_postfix(expr, || self.binary_expression(0));
}
+19 -4
View File
@@ -36,7 +36,12 @@ impl<'arena, 'token_ref> Parser<'arena, 'token_ref, Unary> {
}
TokenKind::Operator(Operator::Logical(LogicalOperator::Or))
| TokenKind::Operator(Operator::Comma) => Operator::Logical(LogicalOperator::Or),
_ => return self.error(AstNodeError::Invalid),
_ => {
return self.error(AstNodeError::Custom {
message: format!("Invalid join operator `{}`", current_token.kind),
span: current_token.span,
})
}
};
self.next();
@@ -208,9 +213,18 @@ impl<'arena, 'token_ref> Parser<'arena, 'token_ref, Unary> {
}
if token.kind == TokenKind::Bracket(Bracket::LeftParenthesis) {
let p_start = self.current().map(|s| s.span.0);
self.next();
let expr = self.binary_expression(0);
self.expect(TokenKind::Bracket(Bracket::RightParenthesis));
let binary_node = self.binary_expression(0);
if let Some(error_node) = self.expect(TokenKind::Bracket(Bracket::RightParenthesis)) {
return error_node;
};
let expr = self.node(Node::Parenthesized(binary_node), |_| NodeMetadata {
span: (p_start.unwrap_or_default(), self.prev_token_end()),
});
return self.with_postfix(expr, || self.binary_expression(0));
}
@@ -269,6 +283,7 @@ impl From<&Node<'_>> for UnaryNodeBehaviour {
}
}
Node::Unary { node, .. } => UnaryNodeBehaviour::from(*node),
Node::Parenthesized(n) => UnaryNodeBehaviour::from(*n),
Node::Binary {
left,
operator,
@@ -345,7 +360,7 @@ impl From<&Node<'_>> for UnaryNodeBehaviour {
BuiltInFunction::One => AsBoolean,
BuiltInFunction::Type => CompareWithReference(Equal),
},
Node::Error(_) => AsBoolean,
Node::Error { .. } => AsBoolean,
}
}
}
+4 -4
View File
@@ -86,11 +86,11 @@ fn standard_test() {
StandardTest {
src: "(1 - 2) * 3",
result: &Node::Binary {
left: &Node::Binary {
left: &Node::Parenthesized(&Node::Binary {
left: &Node::Number(D1),
operator: Operator::Arithmetic(ArithmeticOperator::Subtract),
right: &Node::Number(D2),
},
}),
operator: Operator::Arithmetic(ArithmeticOperator::Multiply),
right: &Node::Number(D3),
},
@@ -123,11 +123,11 @@ fn standard_test() {
src: "(a or b) and c",
result: &Node::Binary {
operator: Operator::Logical(LogicalOperator::And),
left: &Node::Binary {
left: &Node::Parenthesized(&Node::Binary {
left: &Node::Identifier("a"),
right: &Node::Identifier("b"),
operator: Operator::Logical(LogicalOperator::Or),
},
}),
right: &Node::Identifier("c"),
},
},