summary refs log tree commit diff
path: root/crates/brainf_lexer/src/lexer.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/brainf_lexer/src/lexer.rs')
-rw-r--r--crates/brainf_lexer/src/lexer.rs75
1 files changed, 75 insertions, 0 deletions
diff --git a/crates/brainf_lexer/src/lexer.rs b/crates/brainf_lexer/src/lexer.rs
new file mode 100644
index 0000000..b95cd87
--- /dev/null
+++ b/crates/brainf_lexer/src/lexer.rs
@@ -0,0 +1,75 @@
+//! Lexer implementation using logos.
+
+#![expect(clippy::indexing_slicing)]
+
+use logos::{Lexer, Logos};
+
+/// List of operator codes for the lexer
+/// Note: Any input symbol that is not in this list is a comment
+
+fn loop_callback(lex: &Lexer<Token>) -> (usize, usize) {
+	let span = lex.span();
+
+	(span.start, span.len())
+}
+
+/// List of Tokens for the lexer
+/// Note: Any input symbol that is not in this list is a comment
+#[derive(Clone, Copy, Debug, Logos, PartialEq, Eq)]
+#[logos(skip r"[^<>+\-.,\[\]]+")]
+pub enum Token {
+	/// `>`
+	///
+	/// Increment the data pointer by one (to point to the next cell to the
+	/// right).
+	#[token(">")]
+	IncrementPointer,
+
+	/// `<`
+	///
+	/// Decrement the data pointer by one (to point to the next cell to the
+	/// left).
+	#[token("<")]
+	DecrementPointer,
+
+	/// `+`
+	///
+	/// Increment the byte at the data pointer by one.
+	#[token("+")]
+	IncrementByte,
+
+	/// `-`
+	///
+	/// Decrement the byte at the data pointer by one.
+	#[token("-")]
+	DecrementByte,
+
+	/// `.`
+	///
+	/// Output the byte at the data pointer.
+	#[token(".")]
+	OutputByte,
+
+	/// `,`
+	///
+	/// Accept one byte of input, storing its value in the byte at the data
+	/// pointer.
+	#[token(",")]
+	InputByte,
+
+	/// `[`
+	///
+	/// If the byte at the data pointer is zero, then instead of moving the
+	/// instruction pointer forward to the next command, jump it forward to the
+	/// command after the matching ] command.
+	#[token("[", loop_callback)]
+	StartLoop((usize, usize)),
+
+	/// `]`
+	///
+	/// If the byte at the data pointer is nonzero, then instead of moving the
+	/// instruction pointer forward to the next command, jump it back to the
+	/// command after the matching [ command.
+	#[token("]", loop_callback)]
+	EndLoop((usize, usize)),
+}