From 0d213f33e94926433ca884fdf37ed3c7e760f175 Mon Sep 17 00:00:00 2001 From: Garrit Franke Date: Wed, 9 Dec 2020 20:56:04 +0100 Subject: [PATCH] Add variable assignment --- examples/playground.sb | 3 ++- src/generator/js.rs | 7 +++++-- src/parser/node_type.rs | 2 +- src/parser/rules.rs | 17 +++++++++++++++++ src/parser/tests.rs | 14 ++++++++++++++ 5 files changed, 39 insertions(+), 4 deletions(-) diff --git a/examples/playground.sb b/examples/playground.sb index d272666..b355425 100644 --- a/examples/playground.sb +++ b/examples/playground.sb @@ -1,4 +1,5 @@ fn main() { let x = 10 - return x + 10 + x = 5 + return x } diff --git a/src/generator/js.rs b/src/generator/js.rs index d2e6843..7740dee 100644 --- a/src/generator/js.rs +++ b/src/generator/js.rs @@ -72,6 +72,7 @@ fn generate_statement(statement: Statement) -> String { Statement::If(expr, if_state, else_state) => { generate_conditional(expr, *if_state, else_state.map(|x| *x)) } + Statement::Assign(name, state) => generate_assign(name, *state), Statement::Block(_) => generate_block(statement), Statement::While(expr, body) => generate_while_loop(expr, *body), } @@ -84,7 +85,6 @@ fn generate_expression(expr: Expression) -> String { Expression::Char(_) => todo!(), Expression::Bool(b) => b.to_string(), Expression::FunctionCall(name, e) => generate_function_call(name, e), - Expression::Assign(_, _) => todo!(), Expression::Array(els) => generate_array(els), Expression::BinOp(left, op, right) => generate_bin_op(*left, op, *right), } @@ -161,7 +161,6 @@ fn generate_function_call(func: String, args: Vec) -> String { Expression::Bool(v) => v.to_string(), Expression::FunctionCall(n, a) => generate_function_call(n, a), Expression::Str(s) | Expression::Variable(s) => s, - Expression::Assign(_, _) => todo!(), Expression::Array(_) => todo!(), Expression::BinOp(left, op, right) => generate_bin_op(*left, op, *right), }) @@ -200,3 +199,7 @@ fn generate_bin_op(left: Expression, op: BinOp, right: Expression) -> String { r = generate_expression(right) ) } + +fn generate_assign(name: String, expr: Expression) -> String { + format!("{} = {};\n", name, generate_expression(expr)) +} diff --git a/src/parser/node_type.rs b/src/parser/node_type.rs index b483395..e170b4c 100644 --- a/src/parser/node_type.rs +++ b/src/parser/node_type.rs @@ -38,6 +38,7 @@ pub struct Variable { pub enum Statement { Block(Vec), Declare(Variable, Option), + Assign(String, Box), Return(Option), If(Expression, Box, Option>), While(Expression, Box), @@ -53,7 +54,6 @@ pub enum Expression { Array(Vec), FunctionCall(String, Vec), Variable(String), - Assign(String, Box), BinOp(Box, BinOp, Box), } diff --git a/src/parser/rules.rs b/src/parser/rules.rs index 0037257..1230915 100644 --- a/src/parser/rules.rs +++ b/src/parser/rules.rs @@ -97,9 +97,13 @@ impl Parser { TokenKind::Keyword(Keyword::While) => self.parse_while_loop(), TokenKind::Identifier(_) => { let ident = self.match_identifier()?; + if let Ok(_) = self.peek_token(TokenKind::BraceOpen) { let state = self.parse_function_call(Some(ident))?; Ok(Statement::Exp(state)) + } else if let Ok(_) = self.peek_token(TokenKind::Assign) { + let state = self.parse_assignent(Some(ident))?; + Ok(state) } else { let state = Statement::Exp(Expression::Variable(ident.into())); Ok(state) @@ -309,4 +313,17 @@ impl Parser { other => Err(format!("Expected identifier, found {:?}", other)), } } + + fn parse_assignent(&mut self, name: Option) -> Result { + let name = match name { + Some(name) => name, + None => self.match_identifier()?, + }; + + self.match_token(TokenKind::Assign)?; + + let expr = self.parse_expression()?; + + Ok(Statement::Assign(name, Box::new(expr))) + } } diff --git a/src/parser/tests.rs b/src/parser/tests.rs index d3e2107..4b861c9 100644 --- a/src/parser/tests.rs +++ b/src/parser/tests.rs @@ -89,6 +89,20 @@ fn test_parse_variable_declaration() { assert!(tree.is_ok()) } +#[test] +fn test_parse_variable_reassignment() { + let raw = " + fn main() { + let x = 1 + x = x + 1 + return x + } + "; + let tokens = tokenize(raw); + let tree = parse(tokens, Some(raw.to_string())); + assert!(tree.is_ok()) +} + #[test] fn test_parse_variable_declaration_added() { let raw = "