From 6a6547b9c7d5d539fe3d2a5335c622fb16d0cf67 Mon Sep 17 00:00:00 2001 From: Garrit Franke <32395585+garritfra@users.noreply.github.com> Date: Sat, 13 Feb 2021 14:46:35 +0100 Subject: [PATCH] feat: assignment operators (#10) * feat: assignment operators * docs: use assignment operators Co-authored-by: Garrit Franke --- docs/concepts/control-flow.md | 2 +- examples/bubblesort.sb | 4 ++-- lib/stdio.sb | 2 +- src/generator/js.rs | 4 ++++ src/lexer/mod.rs | 36 ++++++++++++++++++++++++++++++++--- src/parser/node_type.rs | 8 ++++++++ src/parser/rules.rs | 4 ++++ src/parser/tests.rs | 2 +- tests/operator_assignments.sb | 8 ++++++++ 9 files changed, 62 insertions(+), 8 deletions(-) create mode 100644 tests/operator_assignments.sb diff --git a/docs/concepts/control-flow.md b/docs/concepts/control-flow.md index 7a4a306..369c5cc 100644 --- a/docs/concepts/control-flow.md +++ b/docs/concepts/control-flow.md @@ -113,7 +113,7 @@ fn main() { while index < 5 { println("the value is: " + a[index]) - index = index + 1 + index += 1 } } ``` diff --git a/examples/bubblesort.sb b/examples/bubblesort.sb index f800bf9..902b893 100644 --- a/examples/bubblesort.sb +++ b/examples/bubblesort.sb @@ -14,10 +14,10 @@ fn main() { arr[d+1] = swap } - d = d + 1 + d += 1 } - c = c + 1 + c += 1 } println(arr) diff --git a/lib/stdio.sb b/lib/stdio.sb index cf46fd5..e5cb55f 100644 --- a/lib/stdio.sb +++ b/lib/stdio.sb @@ -13,7 +13,7 @@ fn println(msg: string) { fn len(arr: int[]): int { let c: int = 0 while arr[c] { - c = c + 1 + c += 1 } return c diff --git a/src/generator/js.rs b/src/generator/js.rs index 8649982..822c7b5 100644 --- a/src/generator/js.rs +++ b/src/generator/js.rs @@ -242,6 +242,10 @@ fn generate_bin_op(left: Expression, op: BinOp, right: Expression) -> String { BinOp::NotEqual => "!==", BinOp::Or => "||", BinOp::Subtraction => "-", + BinOp::AddAssign => "+=", + BinOp::SubtractAssign => "-=", + BinOp::MultiplyAssign => "*=", + BinOp::DivideAssign => "/=", }; format!( "({l} {op} {r})", diff --git a/src/lexer/mod.rs b/src/lexer/mod.rs index af2d8bf..3f79e42 100644 --- a/src/lexer/mod.rs +++ b/src/lexer/mod.rs @@ -94,6 +94,14 @@ pub enum TokenKind { And, /// "||" Or, + /// "+=" + PlusEqual, + /// "-=" + MinusEqual, + /// "*=" + StarEqual, + /// "/=" + SlashEqual, /// "(" BraceOpen, /// ")" @@ -193,15 +201,37 @@ impl Cursor<'_> { c if is_whitespace(c) => self.whitespace(), '0'..='9' => self.number(), '"' | '\'' => self.string(), - '+' => Plus, - '-' => Minus, - '*' => Star, + '+' => match self.first() { + '=' => { + self.bump(); + PlusEqual + } + _ => Plus, + }, + '-' => match self.first() { + '=' => { + self.bump(); + MinusEqual + } + _ => Minus, + }, + '*' => match self.first() { + '=' => { + self.bump(); + StarEqual + } + _ => Star, + }, '%' => Percent, '/' => match self.first() { '/' => { self.bump(); self.comment() } + '=' => { + self.bump(); + SlashEqual + } _ => Slash, }, '=' => match self.first() { diff --git a/src/parser/node_type.rs b/src/parser/node_type.rs index 12e2263..405a159 100644 --- a/src/parser/node_type.rs +++ b/src/parser/node_type.rs @@ -146,6 +146,10 @@ pub enum BinOp { NotEqual, And, Or, + AddAssign, + SubtractAssign, + MultiplyAssign, + DivideAssign, } impl TryFrom for BinOp { @@ -165,6 +169,10 @@ impl TryFrom for BinOp { TokenKind::NotEqual => Ok(BinOp::NotEqual), TokenKind::And => Ok(BinOp::And), TokenKind::Or => Ok(BinOp::Or), + TokenKind::PlusEqual => Ok(BinOp::AddAssign), + TokenKind::MinusEqual => Ok(BinOp::SubtractAssign), + TokenKind::StarEqual => Ok(BinOp::MultiplyAssign), + TokenKind::SlashEqual => Ok(BinOp::DivideAssign), other => Err(format!("Token {:?} cannot be converted into a BinOp", other).into()), } } diff --git a/src/parser/rules.rs b/src/parser/rules.rs index 218c951..8fa5488 100644 --- a/src/parser/rules.rs +++ b/src/parser/rules.rs @@ -152,6 +152,10 @@ impl Parser { TokenKind::Assign => self.parse_assignent(Some(expr)), _ => Ok(Statement::Exp(expr)), } + } else if let Ok(_) = BinOp::try_from(self.peek()?.kind) { + let expr = Expression::Variable(ident.into()); + let state = Statement::Exp(self.parse_bin_op(Some(expr))?); + Ok(state) } else { let state = Statement::Exp(Expression::Variable(ident.into())); Ok(state) diff --git a/src/parser/tests.rs b/src/parser/tests.rs index 210b96b..5159f84 100644 --- a/src/parser/tests.rs +++ b/src/parser/tests.rs @@ -463,7 +463,7 @@ fn test_array_access_in_loop() { while i < 5 { println(x[i]) - i = i + 1 + i += 1 } } "; diff --git a/tests/operator_assignments.sb b/tests/operator_assignments.sb new file mode 100644 index 0000000..3d3a7dd --- /dev/null +++ b/tests/operator_assignments.sb @@ -0,0 +1,8 @@ +fn main() { + let x = 10 + x += 1 + x -= 2 + x *= 2 + x /= 2 + println(x) +} \ No newline at end of file