From b0660c9e5adbc8b68361ad7a24dafe916a38d879 Mon Sep 17 00:00:00 2001 From: Jesse Brault Date: Sun, 15 Mar 2026 15:05:00 -0500 Subject: [PATCH] Parsing and lexing bitwise operators. --- dmc-lib/src/ast/binary_expression.rs | 9 ++++ dmc-lib/src/lexer.rs | 6 +++ dmc-lib/src/parser.rs | 79 +++++++++++++++++++++++++++- dmc-lib/src/token.rs | 3 ++ 4 files changed, 96 insertions(+), 1 deletion(-) diff --git a/dmc-lib/src/ast/binary_expression.rs b/dmc-lib/src/ast/binary_expression.rs index 6d97fcf..5cae321 100644 --- a/dmc-lib/src/ast/binary_expression.rs +++ b/dmc-lib/src/ast/binary_expression.rs @@ -23,6 +23,9 @@ pub enum BinaryOperation { Subtract, LeftShift, RightShift, + BitwiseAnd, + BitwiseXor, + BitwiseOr, } pub struct BinaryExpression { @@ -168,6 +171,9 @@ impl BinaryExpression { } BinaryOperation::LeftShift => todo!(), BinaryOperation::RightShift => todo!(), + BinaryOperation::BitwiseAnd => todo!(), + BinaryOperation::BitwiseXor => todo!(), + BinaryOperation::BitwiseOr => todo!(), } diagnostics_result!(diagnostics) @@ -198,6 +204,9 @@ impl BinaryExpression { } BinaryOperation::LeftShift => todo!(), BinaryOperation::RightShift => todo!(), + BinaryOperation::BitwiseAnd => todo!(), + BinaryOperation::BitwiseXor => todo!(), + BinaryOperation::BitwiseOr => todo!(), }; IrOperation::Binary(ir_binary_operation) } diff --git a/dmc-lib/src/lexer.rs b/dmc-lib/src/lexer.rs index 69e2b2c..0433c3e 100644 --- a/dmc-lib/src/lexer.rs +++ b/dmc-lib/src/lexer.rs @@ -58,6 +58,12 @@ impl<'a> Lexer<'a> { 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::Ampersand) + } else if chunk.starts_with("^") { + Token::new(self.position, self.position + 1, TokenKind::Caret) + } else if chunk.starts_with("|") { + Token::new(self.position, self.position + 1, TokenKind::Bar) } 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 d7724fa..259135a 100644 --- a/dmc-lib/src/parser.rs +++ b/dmc-lib/src/parser.rs @@ -662,7 +662,58 @@ impl<'a> Parser<'a> { } fn expression(&mut self) -> Result> { - self.shift_expression() + self.bitwise_or_expression() + } + + fn bitwise_or_expression(&mut self) -> Result> { + let mut result = self.bitwise_xor_expression()?; + while self.current.is_some() && self.peek_current(TokenKind::Bar) { + self.advance(); // | + let rhs = self.bitwise_xor_expression()?; + let source_range = + SourceRange::new(result.source_range().start(), rhs.source_range().end()); + result = Expression::Binary(BinaryExpression::new( + result, + rhs, + BinaryOperation::BitwiseOr, + source_range, + )); + } + Ok(result) + } + + fn bitwise_xor_expression(&mut self) -> Result> { + let mut result = self.bitwise_and_expression()?; + while self.current.is_some() && self.peek_current(TokenKind::Caret) { + self.advance(); // ^ + let rhs = self.bitwise_and_expression()?; + let source_range = + SourceRange::new(result.source_range().start(), rhs.source_range().end()); + result = Expression::Binary(BinaryExpression::new( + result, + rhs, + BinaryOperation::BitwiseXor, + source_range, + )); + } + Ok(result) + } + + fn bitwise_and_expression(&mut self) -> Result> { + let mut result = self.shift_expression()?; + while self.current.is_some() && self.peek_current(TokenKind::Ampersand) { + self.advance(); // & + let rhs = self.shift_expression()?; + let source_range = + SourceRange::new(result.source_range().start(), rhs.source_range().end()); + result = Expression::Binary(BinaryExpression::new( + result, + rhs, + BinaryOperation::BitwiseAnd, + source_range, + )); + } + Ok(result) } fn shift_expression(&mut self) -> Result> { @@ -1067,6 +1118,32 @@ mod smoke_tests { fn simple_right_shift() { smoke_test("fn main() 4 >> 1 end"); } + + #[test] + fn simple_bitwise_and() { + smoke_test("fn main() 2 & 1 end"); + } + + #[test] + fn simple_bitwise_xor() { + smoke_test("fn main() 1 ^ 2 end"); + } + + #[test] + fn simple_bitwise_or() { + smoke_test("fn main() 1 | 2 end"); + } + + #[test] + fn ops_left_to_right() { + smoke_test( + " + fn main() + 1 | 2 ^ 3 & 4 << 5 >> 7 + 8 - 9 * 10 / 11 % 12 + end + ", + ) + } } #[cfg(test)] diff --git a/dmc-lib/src/token.rs b/dmc-lib/src/token.rs index 4b9855a..5e0084a 100644 --- a/dmc-lib/src/token.rs +++ b/dmc-lib/src/token.rs @@ -47,6 +47,9 @@ pub enum TokenKind { Modulo, LeftShift, RightShift, + Ampersand, + Caret, + Bar, Class, Dot, SelfKw,