Files
adventofcode24/day-03-rust/src/lexer.rs
2024-12-04 20:57:28 +01:00

61 lines
1.8 KiB
Rust

use std::io::{Bytes, Read};
use std::iter::Peekable;
pub type Number = i32;
#[derive(PartialEq, Debug)]
pub enum Token {
Identifier(String),
Number(Number),
Operator(u8),
}
pub struct Lexer<R: Read> {
reader: Peekable<Bytes<R>>,
}
impl<R: Read> Lexer<R> {
pub fn new(reader: R) -> Lexer<R> {
Lexer { reader: reader.bytes().peekable() }
}
}
impl<R: Read> Iterator for Lexer<R> {
type Item = Token;
fn next(&mut self) -> Option<Token> {
if let Some(Ok(ch)) = self.reader.next() {
match ch {
b'A' ..= b'Z' | b'a' ..= b'z' | b'\'' => {
let mut identifier = String::new();
identifier.push(ch as char);
while let Some(Ok(b'A' ..= b'Z' | b'a' ..= b'z' | b'\'')) = self.reader.peek() {
identifier.push(self.reader.next().unwrap().unwrap() as char);
}
Some(Token::Identifier(identifier))
}
b'0' ..= b'9' | b'-' => {
let negative: bool;
let mut number: Number = 0;
if ch == b'-' {
negative = true;
} else {
negative = false;
number = (ch - b'0') as Number;
}
while let Some(Ok(b'0' ..= b'9')) = self.reader.peek() {
number *= 10;
number += (self.reader.next().unwrap().unwrap() - b'0') as Number;
}
if negative {
number *= -1;
}
Some(Token::Number(number))
}
_ => Some(Token::Operator(ch))
}
} else {
None
}
}
}