diff --git a/src/interpreter.rs b/src/interpreter.rs index 72ef37c..9e05216 100644 --- a/src/interpreter.rs +++ b/src/interpreter.rs @@ -526,6 +526,7 @@ impl Interpreter { Operator::Multiply => Ok(Value::Int(left * right)), Operator::Divide => Ok(Value::Int(left / right)), Operator::Equals => Ok(Value::Bool(left == right)), + Operator::Modulo => Ok(Value::Int(left % right)), }, _ => Err(Error::new_runtime( "Binary operation on non-numeric values".to_string(), diff --git a/src/lexer.rs b/src/lexer.rs index f3bbc55..10f50f8 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -56,8 +56,12 @@ pub enum TokenKind { Minus, Asterisk, Slash, + Percent, PlusEquals, MinusEquals, + StarEquals, + SlashEquals, + PercentEquals, Colon, Dot, DblDot, @@ -178,7 +182,14 @@ impl Lexer { self.create_token(TokenKind::Minus) } } - Some('*') => self.create_token(TokenKind::Asterisk), + Some('*') => { + if self.peek_char() == Some('=') { + self.read_char(); + self.create_token(TokenKind::StarEquals) + } else { + self.create_token(TokenKind::Asterisk) + } + } Some(':') => self.create_token(TokenKind::Colon), Some('/') => { if self.peek_char() == Some('/') { @@ -199,10 +210,21 @@ impl Lexer { self.read_char(); } return self.next_token(); + } else if self.peek_char() == Some('=') { + self.read_char(); + self.create_token(TokenKind::SlashEquals) } else { return self.create_token(TokenKind::Slash); } } + Some('%') => { + if self.peek_char() == Some('=') { + self.read_char(); + self.create_token(TokenKind::PercentEquals) + } else { + self.create_token(TokenKind::Percent) + } + } Some('.') => { let start = self.position; if self.peek_char() == Some('.') { @@ -1003,4 +1025,58 @@ mod tests { assert_eq!(kind, expected); } } + + #[test] + fn test_lex_times_equals() { + let code = "x *= 10;"; + let mut lexer = Lexer::new(code); + let expected_tokens = vec![ + TokenKind::Identifier("x".to_string()), + TokenKind::StarEquals, + TokenKind::Int(10), + TokenKind::Semicolon, + TokenKind::Eof, + ]; + + for expected in expected_tokens { + let kind = lexer.next_token().kind; + assert_eq!(kind, expected); + } + } + + #[test] + fn test_lex_divide_equals() { + let code = "x /= 10;"; + let mut lexer = Lexer::new(code); + let expected_tokens = vec![ + TokenKind::Identifier("x".to_string()), + TokenKind::SlashEquals, + TokenKind::Int(10), + TokenKind::Semicolon, + TokenKind::Eof, + ]; + + for expected in expected_tokens { + let kind = lexer.next_token().kind; + assert_eq!(kind, expected); + } + } + + #[test] + fn test_lex_mod_equals() { + let code = "x %= 10;"; + let mut lexer = Lexer::new(code); + let expected_tokens = vec![ + TokenKind::Identifier("x".to_string()), + TokenKind::PercentEquals, + TokenKind::Int(10), + TokenKind::Semicolon, + TokenKind::Eof, + ]; + + for expected in expected_tokens { + let kind = lexer.next_token().kind; + assert_eq!(kind, expected); + } + } } diff --git a/src/parser.rs b/src/parser.rs index 1443fdc..84e3230 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -286,6 +286,7 @@ pub enum Operator { Multiply, Divide, Equals, + Modulo, } pub struct Parser { @@ -828,10 +829,17 @@ impl Parser { loop { match self.current_token().kind { - TokenKind::PlusEquals | TokenKind::MinusEquals => { + TokenKind::PlusEquals + | TokenKind::MinusEquals + | TokenKind::StarEquals + | TokenKind::SlashEquals + | TokenKind::PercentEquals => { let op = match self.current_token().kind { TokenKind::PlusEquals => Operator::Plus, TokenKind::MinusEquals => Operator::Minus, + TokenKind::StarEquals => Operator::Multiply, + TokenKind::SlashEquals => Operator::Divide, + TokenKind::PercentEquals => Operator::Modulo, _ => unreachable!(), }; self.advance(); diff --git a/tests/scripts/opers.hk b/tests/scripts/opers.hk new file mode 100644 index 0000000..a9038b6 --- /dev/null +++ b/tests/scripts/opers.hk @@ -0,0 +1,20 @@ +let a = 1; +a += 8; +println(a); + +a -= 3; +println(a); + +a *= 2; +println(a); + +a /= 2; +println(a); + +a %= 2; +println(a); + +a += 1; + +a %= 2; +println(a); diff --git a/tests/scripts/opers.hk.err b/tests/scripts/opers.hk.err new file mode 100644 index 0000000..e69de29 diff --git a/tests/scripts/opers.hk.out b/tests/scripts/opers.hk.out new file mode 100644 index 0000000..0638fa8 --- /dev/null +++ b/tests/scripts/opers.hk.out @@ -0,0 +1,6 @@ +9 +6 +12 +6 +0 +1