mirror of
https://github.com/gorules/zen.git
synced 2026-10-04 00:02:18 +00:00
fix: unary closure expression (#301)
This commit is contained in:
@@ -313,7 +313,7 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
|
||||
|
||||
pub(crate) fn template_string<F>(&self, expression_parser: F) -> &'arena Node<'arena>
|
||||
where
|
||||
F: Fn() -> &'arena Node<'arena>,
|
||||
F: Fn(ParserContext) -> &'arena Node<'arena>,
|
||||
{
|
||||
expect!(self, TokenKind::QuotationMark(QuotationMark::Backtick));
|
||||
|
||||
@@ -332,7 +332,7 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
|
||||
TokenKind::TemplateString(template) => match template {
|
||||
TemplateString::ExpressionStart => {
|
||||
self.next();
|
||||
nodes.push(expression_parser());
|
||||
nodes.push(expression_parser(ParserContext::Global));
|
||||
}
|
||||
TemplateString::ExpressionEnd => {
|
||||
self.next();
|
||||
@@ -375,7 +375,7 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
|
||||
expression_parser: F,
|
||||
) -> &'arena Node<'arena>
|
||||
where
|
||||
F: Fn() -> &'arena Node<'arena>,
|
||||
F: Fn(ParserContext) -> &'arena Node<'arena>,
|
||||
{
|
||||
let Some(postfix_token) = self.current() else {
|
||||
return node;
|
||||
@@ -444,7 +444,7 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
|
||||
c = cc;
|
||||
|
||||
if c.kind != TokenKind::Bracket(Bracket::RightSquareBracket) {
|
||||
to = Some(expression_parser());
|
||||
to = Some(expression_parser(ParserContext::Global));
|
||||
}
|
||||
|
||||
expect!(self, TokenKind::Bracket(Bracket::RightSquareBracket));
|
||||
@@ -455,7 +455,7 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
|
||||
),
|
||||
})
|
||||
} else {
|
||||
let from_node = expression_parser();
|
||||
let from_node = expression_parser(ParserContext::Global);
|
||||
from = Some(from_node);
|
||||
let Some(cc) = self.current() else {
|
||||
return self.error_with_node(
|
||||
@@ -492,7 +492,7 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
|
||||
c = cc;
|
||||
|
||||
if c.kind != TokenKind::Bracket(Bracket::RightSquareBracket) {
|
||||
to = Some(expression_parser());
|
||||
to = Some(expression_parser(ParserContext::Global));
|
||||
}
|
||||
|
||||
expect!(self, TokenKind::Bracket(Bracket::RightSquareBracket));
|
||||
@@ -537,12 +537,12 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
|
||||
/// Closure
|
||||
pub(crate) fn closure<F>(&self, expression_parser: F) -> &'arena Node<'arena>
|
||||
where
|
||||
F: Fn() -> &'arena Node<'arena>,
|
||||
F: Fn(ParserContext) -> &'arena Node<'arena>,
|
||||
{
|
||||
let start = self.token_start();
|
||||
|
||||
self.depth.set(self.depth.get() + 1);
|
||||
let node = expression_parser();
|
||||
let node = expression_parser(ParserContext::Closure);
|
||||
self.depth.set(self.depth.get() - 1);
|
||||
|
||||
self.node(Node::Closure(node), |_| NodeMetadata {
|
||||
@@ -554,7 +554,7 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
|
||||
/// Either <Identifier> or <Identifier Expression>
|
||||
pub(crate) fn identifier<F>(&self, expression_parser: F) -> &'arena Node<'arena>
|
||||
where
|
||||
F: Fn() -> &'arena Node<'arena>,
|
||||
F: Fn(ParserContext) -> &'arena Node<'arena>,
|
||||
{
|
||||
let Some(token) = self.current() else {
|
||||
return self.error(AstNodeError::MissingToken {
|
||||
@@ -610,7 +610,7 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
|
||||
self.next();
|
||||
let builtin_node = match builtin.arity() {
|
||||
Arity::Single => {
|
||||
let arg = expression_parser();
|
||||
let arg = expression_parser(ParserContext::Global);
|
||||
self.expect(TokenKind::Bracket(Bracket::RightParenthesis));
|
||||
|
||||
Node::BuiltIn {
|
||||
@@ -619,9 +619,9 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
|
||||
}
|
||||
}
|
||||
Arity::Dual => {
|
||||
let arg1 = expression_parser();
|
||||
let arg1 = expression_parser(ParserContext::Global);
|
||||
self.expect(TokenKind::Operator(Operator::Comma));
|
||||
let arg2 = expression_parser();
|
||||
let arg2 = expression_parser(ParserContext::Global);
|
||||
self.expect(TokenKind::Bracket(Bracket::RightParenthesis));
|
||||
|
||||
Node::BuiltIn {
|
||||
@@ -630,7 +630,7 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
|
||||
}
|
||||
}
|
||||
Arity::Closure => {
|
||||
let arg1 = expression_parser();
|
||||
let arg1 = expression_parser(ParserContext::Global);
|
||||
|
||||
self.expect(TokenKind::Operator(Operator::Comma));
|
||||
let arg2 = self.closure(&expression_parser);
|
||||
@@ -654,7 +654,7 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
|
||||
/// Interval node
|
||||
pub(crate) fn interval<F>(&self, expression_parser: F) -> Option<&'arena Node<'arena>>
|
||||
where
|
||||
F: Fn() -> &'arena Node<'arena>,
|
||||
F: Fn(ParserContext) -> &'arena Node<'arena>,
|
||||
{
|
||||
// Performance optimisation: skip if expression does not contain an interval for faster evaluation
|
||||
if !self.has_range_operator {
|
||||
@@ -674,7 +674,7 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
|
||||
};
|
||||
|
||||
self.next();
|
||||
let left = expression_parser();
|
||||
let left = expression_parser(ParserContext::Global);
|
||||
if left.has_error() {
|
||||
self.set_position(initial_position);
|
||||
return None;
|
||||
@@ -685,7 +685,7 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
|
||||
return None;
|
||||
};
|
||||
|
||||
let right = expression_parser();
|
||||
let right = expression_parser(ParserContext::Global);
|
||||
if right.has_error() {
|
||||
self.set_position(initial_position);
|
||||
return None;
|
||||
@@ -717,7 +717,7 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
|
||||
/// Array nodes
|
||||
pub(crate) fn array<F>(&self, expression_parser: F) -> &'arena Node<'arena>
|
||||
where
|
||||
F: Fn() -> &'arena Node<'arena>,
|
||||
F: Fn(ParserContext) -> &'arena Node<'arena>,
|
||||
{
|
||||
let Some(current_token) = self.current() else {
|
||||
return self.error(AstNodeError::MissingToken {
|
||||
@@ -748,7 +748,7 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
|
||||
}
|
||||
}
|
||||
|
||||
nodes.push(expression_parser());
|
||||
nodes.push(expression_parser(ParserContext::Global));
|
||||
}
|
||||
|
||||
expect!(self, TokenKind::Bracket(Bracket::RightSquareBracket));
|
||||
@@ -765,7 +765,7 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
|
||||
|
||||
pub(crate) fn object<F>(&self, expression_parser: F) -> &'arena Node<'arena>
|
||||
where
|
||||
F: Fn() -> &'arena Node<'arena>,
|
||||
F: Fn(ParserContext) -> &'arena Node<'arena>,
|
||||
{
|
||||
let span_start = self.token_start();
|
||||
expect!(self, TokenKind::Bracket(Bracket::LeftCurlyBracket));
|
||||
@@ -784,7 +784,7 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
|
||||
loop {
|
||||
let key = self.object_key(&expression_parser);
|
||||
expect!(self, TokenKind::Operator(Operator::Slice));
|
||||
let value = expression_parser();
|
||||
let value = expression_parser(ParserContext::Global);
|
||||
|
||||
key_value_pairs.push((key, value));
|
||||
|
||||
@@ -816,7 +816,7 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
|
||||
|
||||
pub(crate) fn object_key<F>(&self, expression_parser: F) -> &'arena Node<'arena>
|
||||
where
|
||||
F: Fn() -> &'arena Node<'arena>,
|
||||
F: Fn(ParserContext) -> &'arena Node<'arena>,
|
||||
{
|
||||
let Some(key_token) = self.current() else {
|
||||
return self.error(AstNodeError::Custom {
|
||||
@@ -861,7 +861,7 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
|
||||
TokenKind::Bracket(bracket) => match bracket {
|
||||
Bracket::LeftSquareBracket => {
|
||||
expect!(self, TokenKind::Bracket(Bracket::LeftSquareBracket));
|
||||
let token = expression_parser();
|
||||
let token = expression_parser(ParserContext::Global);
|
||||
expect!(self, TokenKind::Bracket(Bracket::RightSquareBracket));
|
||||
|
||||
token
|
||||
@@ -914,7 +914,7 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
|
||||
expression_parser: F,
|
||||
) -> Option<&'arena Node<'arena>>
|
||||
where
|
||||
F: Fn() -> &'arena Node<'arena>,
|
||||
F: Fn(ParserContext) -> &'arena Node<'arena>,
|
||||
{
|
||||
let Some(current_token) = self.current() else {
|
||||
return None;
|
||||
@@ -925,12 +925,12 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
|
||||
|
||||
self.next();
|
||||
|
||||
let on_true = expression_parser();
|
||||
let on_true = expression_parser(ParserContext::Global);
|
||||
if let Some(error_node) = self.expect(TokenKind::Operator(Operator::Slice)) {
|
||||
return Some(error_node);
|
||||
}
|
||||
|
||||
let on_false = expression_parser();
|
||||
let on_false = expression_parser(ParserContext::Global);
|
||||
|
||||
let conditional_node = Node::Conditional {
|
||||
condition,
|
||||
@@ -946,7 +946,7 @@ impl<'arena, 'token_ref, Flavor> Parser<'arena, 'token_ref, Flavor> {
|
||||
/// Literal - number, string, array etc.
|
||||
pub(crate) fn literal<F>(&self, expression_parser: F) -> &'arena Node<'arena>
|
||||
where
|
||||
F: Fn() -> &'arena Node<'arena>,
|
||||
F: Fn(ParserContext) -> &'arena Node<'arena>,
|
||||
{
|
||||
let Some(current_token) = self.current() else {
|
||||
return self.error(AstNodeError::Custom {
|
||||
@@ -1053,3 +1053,9 @@ impl<'a, 'arena> MetadataHelper<'a, 'arena> {
|
||||
n as *const Node as usize
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub(crate) enum ParserContext {
|
||||
Global,
|
||||
Closure,
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ impl<'arena, 'token_ref> Parser<'arena, 'token_ref, Standard> {
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -84,7 +84,7 @@ impl<'arena, 'token_ref> Parser<'arena, 'token_ref, Standard> {
|
||||
self.next();
|
||||
|
||||
let node = self.node(Node::Pointer, |_| NodeMetadata { span: token.span });
|
||||
return self.with_postfix(node, || self.binary_expression(0));
|
||||
return self.with_postfix(node, |_| self.binary_expression(0));
|
||||
}
|
||||
|
||||
if let TokenKind::Operator(operator) = &token.kind {
|
||||
@@ -114,7 +114,7 @@ impl<'arena, 'token_ref> Parser<'arena, 'token_ref, Standard> {
|
||||
return node;
|
||||
}
|
||||
|
||||
if let Some(interval_node) = self.interval(|| self.binary_expression(0)) {
|
||||
if let Some(interval_node) = self.interval(|_| self.binary_expression(0)) {
|
||||
return interval_node;
|
||||
}
|
||||
|
||||
@@ -131,9 +131,9 @@ impl<'arena, 'token_ref> Parser<'arena, 'token_ref, Standard> {
|
||||
span: (p_start.unwrap_or_default(), self.prev_token_end()),
|
||||
});
|
||||
|
||||
return self.with_postfix(expr, || self.binary_expression(0));
|
||||
return self.with_postfix(expr, |_| self.binary_expression(0));
|
||||
}
|
||||
|
||||
self.literal(|| self.binary_expression(0))
|
||||
self.literal(|_| self.binary_expression(0))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ use crate::lexer::{Bracket, ComparisonOperator, Identifier, LogicalOperator, Ope
|
||||
use crate::parser::ast::{AstNodeError, Node};
|
||||
use crate::parser::builtin::BuiltInFunction;
|
||||
use crate::parser::constants::{Associativity, BINARY_OPERATORS, UNARY_OPERATORS};
|
||||
use crate::parser::parser::Parser;
|
||||
use crate::parser::parser::{Parser, ParserContext};
|
||||
use crate::parser::unary::UnaryNodeBehaviour::CompareWithReference;
|
||||
use crate::parser::{NodeMetadata, ParserResult};
|
||||
|
||||
@@ -70,13 +70,13 @@ impl<'arena, 'token_ref> Parser<'arena, 'token_ref, Unary> {
|
||||
if let Some(TokenKind::Operator(Operator::Comparison(_))) = self.current_kind() {
|
||||
// Skips
|
||||
} else {
|
||||
left_node = self.binary_expression(0);
|
||||
left_node = self.binary_expression(0, ParserContext::Global);
|
||||
}
|
||||
|
||||
match self.current_kind() {
|
||||
Some(TokenKind::Operator(Operator::Comparison(comparison))) => {
|
||||
self.next();
|
||||
let right_node = self.binary_expression(0);
|
||||
let right_node = self.binary_expression(0, ParserContext::Global);
|
||||
left_node = self.node(
|
||||
Node::Binary {
|
||||
left: left_node,
|
||||
@@ -130,7 +130,7 @@ impl<'arena, 'token_ref> Parser<'arena, 'token_ref, Unary> {
|
||||
left_node
|
||||
}
|
||||
|
||||
fn binary_expression(&self, precedence: u8) -> &'arena Node<'arena> {
|
||||
fn binary_expression(&self, precedence: u8, ctx: ParserContext) -> &'arena Node<'arena> {
|
||||
let mut node_left = self.unary_expression();
|
||||
let Some(mut token) = self.current() else {
|
||||
return node_left;
|
||||
@@ -141,12 +141,14 @@ impl<'arena, 'token_ref> Parser<'arena, 'token_ref, Unary> {
|
||||
break;
|
||||
}
|
||||
|
||||
if matches!(
|
||||
operator,
|
||||
Operator::Comma
|
||||
| Operator::Logical(LogicalOperator::And)
|
||||
| Operator::Logical(LogicalOperator::Or)
|
||||
) {
|
||||
if ctx == ParserContext::Global
|
||||
&& matches!(
|
||||
operator,
|
||||
Operator::Comma
|
||||
| Operator::Logical(LogicalOperator::And)
|
||||
| Operator::Logical(LogicalOperator::Or)
|
||||
)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -160,8 +162,10 @@ impl<'arena, 'token_ref> Parser<'arena, 'token_ref, Unary> {
|
||||
|
||||
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, ParserContext::Global)
|
||||
}
|
||||
_ => self.binary_expression(op.precedence, ParserContext::Global),
|
||||
};
|
||||
|
||||
node_left = self.node(
|
||||
@@ -183,7 +187,7 @@ impl<'arena, 'token_ref> Parser<'arena, 'token_ref, Unary> {
|
||||
|
||||
if precedence == 0 {
|
||||
if let Some(conditional_node) =
|
||||
self.conditional(node_left, || self.binary_expression(0))
|
||||
self.conditional(node_left, |c| self.binary_expression(0, c))
|
||||
{
|
||||
node_left = conditional_node;
|
||||
}
|
||||
@@ -194,14 +198,14 @@ impl<'arena, 'token_ref> Parser<'arena, 'token_ref, Unary> {
|
||||
|
||||
fn unary_expression(&self) -> &'arena Node<'arena> {
|
||||
let Some(token) = self.current() else {
|
||||
return self.literal(|| self.binary_expression(0));
|
||||
return self.literal(|c| self.binary_expression(0, c));
|
||||
};
|
||||
|
||||
if self.depth() > 0 && token.kind == TokenKind::Identifier(Identifier::CallbackReference) {
|
||||
self.next();
|
||||
|
||||
let node = self.node(Node::Pointer, |_| NodeMetadata { span: token.span });
|
||||
return self.with_postfix(node, || self.binary_expression(0));
|
||||
return self.with_postfix(node, |c| self.binary_expression(0, c));
|
||||
}
|
||||
|
||||
if let TokenKind::Operator(operator) = &token.kind {
|
||||
@@ -214,7 +218,7 @@ impl<'arena, 'token_ref> Parser<'arena, 'token_ref, Unary> {
|
||||
};
|
||||
|
||||
self.next();
|
||||
let expr = self.binary_expression(unary_operator.precedence);
|
||||
let expr = self.binary_expression(unary_operator.precedence, ParserContext::Global);
|
||||
let node = self.node(
|
||||
Node::Unary {
|
||||
operator: *operator,
|
||||
@@ -231,7 +235,7 @@ impl<'arena, 'token_ref> Parser<'arena, 'token_ref, Unary> {
|
||||
return node;
|
||||
}
|
||||
|
||||
if let Some(interval_node) = self.interval(|| self.binary_expression(0)) {
|
||||
if let Some(interval_node) = self.interval(|c| self.binary_expression(0, c)) {
|
||||
return interval_node;
|
||||
}
|
||||
|
||||
@@ -239,7 +243,7 @@ impl<'arena, 'token_ref> Parser<'arena, 'token_ref, Unary> {
|
||||
let p_start = self.current().map(|s| s.span.0);
|
||||
|
||||
self.next();
|
||||
let binary_node = self.binary_expression(0);
|
||||
let binary_node = self.binary_expression(0, ParserContext::Global);
|
||||
if let Some(error_node) = self.expect(TokenKind::Bracket(Bracket::RightParenthesis)) {
|
||||
return error_node;
|
||||
};
|
||||
@@ -248,10 +252,10 @@ impl<'arena, 'token_ref> Parser<'arena, 'token_ref, Unary> {
|
||||
span: (p_start.unwrap_or_default(), self.prev_token_end()),
|
||||
});
|
||||
|
||||
return self.with_postfix(expr, || self.binary_expression(0));
|
||||
return self.with_postfix(expr, |c| self.binary_expression(0, c));
|
||||
}
|
||||
|
||||
self.literal(|| self.binary_expression(0))
|
||||
self.literal(|c| self.binary_expression(0, c))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -64,6 +64,7 @@ rand(100) >= 0 and rand(100) <= 100; { "$": true }; true
|
||||
sum([1, 2, 3, 4, 5]) / len([1, 2, 3, 4, 5]); { "$": 3 }; true
|
||||
median([4, 2, 7, 5, 3]); { "$": 4 }; true
|
||||
mode([1, 2, 2, 3, 3, 3, 4, 4, 4, 4]); { "$": 4 }; true
|
||||
some($, # > 10 and # < 20); { "$": [1, 2, 3, 15] }; true
|
||||
|
||||
# String expressions
|
||||
'GB','US';{$: 'US'};true
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 4 and column 8.
|
Reference in New Issue
Block a user