// SPDX-License-Identifier: AGPL-3.0-or-later //! Lexer implementation using logos. 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) -> (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)), }