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 { reader: Peekable>, } impl Lexer { pub fn new(reader: R) -> Lexer { Lexer { reader: reader.bytes().peekable() } } } impl Iterator for Lexer { type Item = Token; fn next(&mut self) -> Option { 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 } } }