From 76cf35e72e48aecd94379c056fbd5da6a560f6b0 Mon Sep 17 00:00:00 2001 From: SimonFJ20 Date: Thu, 16 Mar 2023 15:37:21 +0100 Subject: [PATCH] add function value --- src/ast.rs | 10 ++++ src/parser.rs | 124 ++++++++++++++++++++++++++++++++++++++++---------- test.chl | 12 ----- 3 files changed, 111 insertions(+), 35 deletions(-) delete mode 100644 test.chl diff --git a/src/ast.rs b/src/ast.rs index 13b35d5..3102b6f 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -24,6 +24,10 @@ pub enum Expr { truthy: Box>, falsy: Option>>, }, + FunctionValue { + parameters: Vec>, + body: Box>, + }, Member { subject: Box>, @@ -70,6 +74,11 @@ pub enum Expr { condition: Box>, body: Box>, }, + For { + subject: Node, + value: Box>, + body: Box>, + }, Return(Option>>), Function { name: String, @@ -116,6 +125,7 @@ pub enum BinaryType { GT, GTE, In, + NotIn, Equal, Inequal, And, diff --git a/src/parser.rs b/src/parser.rs index 24593a9..deb8264 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -58,10 +58,12 @@ where } match self.current().token_type { TokenType::Fn => self.parse_function(), - TokenType::Return => self.parse_function(), - TokenType::While => self.parse_function(), - TokenType::Break => self.parse_function(), - TokenType::Continue => self.parse_function(), + TokenType::Return => self.parse_return(), + TokenType::For => self.parse_for(), + TokenType::While => self.parse_while(), + TokenType::Break => self.parse_break(), + TokenType::Continue => self.parse_continue(), + TokenType::Let => self.parse_let(), _ => self.parse_assign(), } } @@ -73,10 +75,39 @@ where } let name = self.token_string(self.current()); self.step(); + let (parameters, body) = match self.parse_function_details() { + Ok(v) => v, + Err(e) => return e, + }; + self.node(Expr::Function { + name, + parameters, + body: Box::new(body), + }) + } + + fn parse_function_details(&mut self) -> Result<(Vec>, Node), Node> { if self.done() || !self.current_is(TokenType::LParen) { - return self.error("expected '('"); + return Err(self.error("expected '('")); } self.step(); + let mut parameters = self.parse_function_parameters(); + if self.done() || !self.current_is(TokenType::RParen) { + return Err(self.error("expected ')'")); + } + self.step(); + let body = if !self.done() && self.current_is(TokenType::LBrace) { + self.parse_block() + } else if !self.done() && self.current_is(TokenType::EqualLessThan) { + self.step(); + self.parse_expr() + } else { + return Err(self.error("expected '{'")); + }; + Ok((parameters, body)) + } + + fn parse_function_parameters(&mut self) -> Vec> { let mut parameters = Vec::>::new(); if !self.done() && !self.current_is(TokenType::RParen) { if self.current_is(TokenType::DotDotDot) { @@ -100,19 +131,7 @@ where } } } - if self.done() || !self.current_is(TokenType::RParen) { - return self.error("expected ')'"); - } - self.step(); - if self.done() || !self.current_is(TokenType::LBrace) { - return self.error("expected '{'"); - } - let body = self.parse_block(); - self.node(Expr::Function { - name, - parameters, - body: Box::new(body), - }) + parameters } fn parse_parameter(&mut self) -> Node { @@ -139,6 +158,25 @@ where } } + fn parse_for(&mut self) -> Node { + self.step(); + let subject = self.parse_parameter(); + if self.done() || !self.current_is(TokenType::In) { + return self.error("expected 'in'"); + } + self.step(); + let value = self.parse_expr(); + if self.done() || !self.current_is(TokenType::LBrace) { + return self.error("expected '{'"); + } + let body = self.parse_block(); + self.node(Expr::For { + subject, + value: Box::new(value), + body: Box::new(body), + }) + } + fn parse_while(&mut self) -> Node { self.step(); let condition = self.parse_expr(); @@ -357,6 +395,18 @@ where left: Box::new(left), right: Box::new(right), }); + } else if self.current_is(TokenType::Not) { + self.step(); + if self.done() || !self.current_is(TokenType::In) { + return self.error("expected 'in'"); + } + self.step(); + let right = self.parse_prec_range(); + left = self.node(Expr::Binary { + binary_type: BinaryType::NotIn, + left: Box::new(left), + right: Box::new(right), + }); } else { break; } @@ -585,9 +635,10 @@ where TokenType::True => self.step_and_node(Expr::Bool(true)), TokenType::LParen => self.parse_unit_group_or_tuple(), TokenType::LBrace => self.parse_block(), - TokenType::Underscore => todo!(), + TokenType::Underscore => self.parse_object(), TokenType::LBracket => self.parse_array(), TokenType::If => self.parse_if(), + TokenType::Fn => self.parse_function_value(), TokenType::MalformedString => self.error("malformed string"), other => self.node(Expr::Error(format!("expected value, got {:?}", other))), } @@ -605,8 +656,19 @@ where self.step(); if !self.done() && !self.current_is(TokenType::LParen) { let first_value = self.parse_expr(); - if !self.done() && !self.current_is(TokenType::LParen) { - todo!() + if !self.done() && !self.current_is(TokenType::RParen) { + let mut values = vec![first_value]; + while !self.done() && self.current_is(TokenType::Comma) { + self.step(); + if self.done() || self.current_is(TokenType::RParen) { + break; + } + values.push(self.parse_expr()); + } + if self.done() || !self.current_is(TokenType::RParen) { + return self.error("expected ')'"); + } + self.step_and_node(Expr::Tuple(values)) } else { self.step_and(first_value) } @@ -616,6 +678,10 @@ where } fn parse_object(&mut self) -> Node { + self.step(); + if self.done() || !self.current_is(TokenType::LBrace) { + return self.error("expected '{' of object literal"); + } self.step(); let mut values = Vec::>::new(); if !self.done() && !self.current_is(TokenType::RBracket) { @@ -709,11 +775,23 @@ where } falsy = Some(self.parse_block()); } - return self.node(Expr::If { + self.node(Expr::If { condition: Box::new(condition), truthy: Box::new(truthy), falsy: falsy.map(Box::new), - }); + }) + } + + fn parse_function_value(&mut self) -> Node { + self.step(); + let (parameters, body) = match self.parse_function_details() { + Ok(v) => v, + Err(e) => return e, + }; + self.node(Expr::FunctionValue { + parameters, + body: Box::new(body), + }) } fn token_string(&self, token: &Token) -> String { diff --git a/test.chl b/test.chl deleted file mode 100644 index 70febb1..0000000 --- a/test.chl +++ /dev/null @@ -1,12 +0,0 @@ -let a = 5; - -if 1 == 0 and true { - return true; -} - -// safadkjasda - -/* -sdasd -*/ -