diff --git a/dmc-lib/src/ast/binary_expression.rs b/dmc-lib/src/ast/binary_expression.rs index 7dbd881..6d97fcf 100644 --- a/dmc-lib/src/ast/binary_expression.rs +++ b/dmc-lib/src/ast/binary_expression.rs @@ -18,8 +18,11 @@ use std::rc::Rc; pub enum BinaryOperation { Multiply, Divide, + Modulo, Add, Subtract, + LeftShift, + RightShift, } pub struct BinaryExpression { @@ -137,6 +140,9 @@ impl BinaryExpression { BinaryOperation::Divide => { todo!() } + BinaryOperation::Modulo => { + todo!() + } BinaryOperation::Add => { handle_diagnostic!( self.check_op( @@ -160,6 +166,8 @@ impl BinaryExpression { diagnostics ) } + BinaryOperation::LeftShift => todo!(), + BinaryOperation::RightShift => todo!(), } diagnostics_result!(diagnostics) @@ -183,10 +191,13 @@ impl BinaryExpression { IrBinaryOperation::new(lhs, rhs, IrBinaryOperator::Multiply) } BinaryOperation::Divide => IrBinaryOperation::new(lhs, rhs, IrBinaryOperator::Divide), + BinaryOperation::Modulo => todo!(), BinaryOperation::Add => IrBinaryOperation::new(lhs, rhs, IrBinaryOperator::Add), BinaryOperation::Subtract => { IrBinaryOperation::new(lhs, rhs, IrBinaryOperator::Subtract) } + BinaryOperation::LeftShift => todo!(), + BinaryOperation::RightShift => todo!(), }; IrOperation::Binary(ir_binary_operation) } diff --git a/dmc-lib/src/lexer.rs b/dmc-lib/src/lexer.rs index 70781b3..69e2b2c 100644 --- a/dmc-lib/src/lexer.rs +++ b/dmc-lib/src/lexer.rs @@ -46,8 +46,18 @@ impl<'a> Lexer<'a> { self.position + 1, TokenKind::RightParentheses, ) + } else if chunk.starts_with("*") { + Token::new(self.position, self.position + 1, TokenKind::Star) + } else if chunk.starts_with("/") { + Token::new(self.position, self.position + 1, TokenKind::Slash) + } else if chunk.starts_with("%") { + Token::new(self.position, self.position + 1, TokenKind::Modulo) } else if chunk.starts_with("+") { Token::new(self.position, self.position + 1, TokenKind::Plus) + } else if chunk.starts_with("<<") { + Token::new(self.position, self.position + 2, TokenKind::LeftShift) + } else if chunk.starts_with(">>") { + Token::new(self.position, self.position + 2, TokenKind::RightShift) } else if chunk.starts_with("=") { Token::new(self.position, self.position + 1, TokenKind::Equals) } else if chunk.starts_with(",") { diff --git a/dmc-lib/src/parser.rs b/dmc-lib/src/parser.rs index 914d366..d7724fa 100644 --- a/dmc-lib/src/parser.rs +++ b/dmc-lib/src/parser.rs @@ -662,17 +662,52 @@ impl<'a> Parser<'a> { } fn expression(&mut self) -> Result> { - self.additive_expression() + self.shift_expression() + } + + fn shift_expression(&mut self) -> Result> { + let mut result = self.additive_expression()?; + while self.current.is_some() { + let current = self.get_current(); + match current.kind() { + TokenKind::LeftShift => { + self.advance(); // left shift + let rhs = self.additive_expression()?; + let source_range = + SourceRange::new(result.source_range().start(), rhs.source_range().end()); + result = Expression::Binary(BinaryExpression::new( + result, + rhs, + BinaryOperation::LeftShift, + source_range, + )); + } + TokenKind::RightShift => { + self.advance(); // right shift + let rhs = self.additive_expression()?; + let source_range = + SourceRange::new(result.source_range().start(), rhs.source_range().end()); + result = Expression::Binary(BinaryExpression::new( + result, + rhs, + BinaryOperation::RightShift, + source_range, + )); + } + _ => break, + } + } + Ok(result) } fn additive_expression(&mut self) -> Result> { - let mut result = self.prefix_expression()?; + let mut result = self.multiplicative_expression()?; while self.current.is_some() { let current = self.get_current(); match current.kind() { TokenKind::Plus => { self.advance(); // plus - let rhs = self.prefix_expression()?; + let rhs = self.multiplicative_expression()?; let source_range = SourceRange::new(result.source_range().start(), rhs.source_range().end()); result = Expression::Binary(BinaryExpression::new( @@ -684,7 +719,7 @@ impl<'a> Parser<'a> { } TokenKind::Minus => { self.advance(); // minus - let rhs = self.prefix_expression()?; + let rhs = self.multiplicative_expression()?; let source_range = SourceRange::new(result.source_range().start(), rhs.source_range().end()); result = Expression::Binary(BinaryExpression::new( @@ -700,6 +735,53 @@ impl<'a> Parser<'a> { Ok(result) } + fn multiplicative_expression(&mut self) -> Result> { + let mut result = self.prefix_expression()?; + while self.current.is_some() { + let current = self.get_current(); + match current.kind() { + TokenKind::Star => { + self.advance(); // multiply + let rhs = self.prefix_expression()?; + let source_range = + SourceRange::new(result.source_range().start(), rhs.source_range().end()); + result = Expression::Binary(BinaryExpression::new( + result, + rhs, + BinaryOperation::Multiply, + source_range, + )); + } + TokenKind::Slash => { + self.advance(); // slash + let rhs = self.prefix_expression()?; + let source_range = + SourceRange::new(result.source_range().start(), rhs.source_range().end()); + result = Expression::Binary(BinaryExpression::new( + result, + rhs, + BinaryOperation::Divide, + source_range, + )) + } + TokenKind::Modulo => { + self.advance(); // modulo + let rhs = self.prefix_expression()?; + let source_range = + SourceRange::new(result.source_range().start(), rhs.source_range().end()); + result = Expression::Binary(BinaryExpression::new( + result, + rhs, + BinaryOperation::Modulo, + source_range, + )); + } + _ => break, + } + } + Ok(result) + } + fn prefix_expression(&mut self) -> Result> { // first, collect all consecutive operators let mut operator_tokens = vec![]; @@ -960,6 +1042,31 @@ mod smoke_tests { ", ); } + + #[test] + fn simple_multiply() { + smoke_test("fn main() 1 * 2 end"); + } + + #[test] + fn simple_divide() { + smoke_test("fn main() 1 / 2 end"); + } + + #[test] + fn simple_modulo() { + smoke_test("fn main() 1 % 2 end"); + } + + #[test] + fn simple_left_shift() { + smoke_test("fn main() 2 << 1 end"); + } + + #[test] + fn simple_right_shift() { + smoke_test("fn main() 4 >> 1 end"); + } } #[cfg(test)] diff --git a/dmc-lib/src/token.rs b/dmc-lib/src/token.rs index 2c0117c..4b9855a 100644 --- a/dmc-lib/src/token.rs +++ b/dmc-lib/src/token.rs @@ -42,6 +42,11 @@ pub enum TokenKind { RightArrow, Plus, Minus, + Star, + Slash, + Modulo, + LeftShift, + RightShift, Class, Dot, SelfKw,