use core::{iter::Peekable, marker::PhantomData};
use calc_common::Character;
use crate::{Evaluator, Operator};
#[derive(Debug)]
pub enum Token<I> {
Operator(Operator),
Number(I),
OpenParenthesis(),
ClosingParenthesis(),
}
pub struct Lexer<E, I>
where
I: Iterator<Item = Character>,
E: Evaluator,
{
iter: Peekable<I>,
phantomdata: PhantomData<E>,
}
impl<I: Iterator<Item = Character>, E: Evaluator> Lexer<E, I> {
pub fn new(iter: I) -> Self {
Self {
iter: iter.peekable(),
phantomdata: PhantomData,
}
}
}
impl<I: Iterator<Item = Character>, E: Evaluator> Iterator for Lexer<E, I> {
type Item = Token<E::Item>;
fn next(&mut self) -> Option<Token<E::Item>> {
let mut num = E::zero();
let mut num_created = false;
loop {
let next_char = self.iter.peek().copied();
let token = match next_char {
Some(Character::OpenParen) => Some(Token::OpenParenthesis()),
Some(Character::CloseParen) => Some(Token::ClosingParenthesis()),
Some(Character::Plus) => Some(Token::Operator(Operator::Add)),
Some(Character::Minus) => Some(Token::Operator(Operator::Subtract)),
Some(Character::Multiply) => Some(Token::Operator(Operator::Multiply)),
Some(Character::Slash) => Some(Token::Operator(Operator::Divide)),
Some(Character::Caret) => Some(Token::Operator(Operator::Exponentiate)),
Some(Character::Dot) => unimplemented!(),
Some(
digit @ (Character::Zero
| Character::One
| Character::Two
| Character::Three
| Character::Four
| Character::Five
| Character::Six
| Character::Seven
| Character::Eight
| Character::Nine),
) => {
let num_delta = digit as u8;
num = E::add_digit(num, num_delta);
num_created = true;
self.iter.next();
continue;
}
Some(
character @ (Character::A
| Character::B
| Character::C
| Character::D
| Character::E
| Character::F
| Character::G
| Character::H
| Character::I
| Character::J
| Character::K
| Character::L
| Character::M
| Character::N
| Character::O
| Character::P
| Character::Q
| Character::R
| Character::S
| Character::T
| Character::U
| Character::V
| Character::W
| Character::X
| Character::Y
| Character::Z),
) => {
let _ = character;
todo!()
}
None => None,
};
if !num_created {
self.iter.next();
return token;
}
return Some(Token::Number(num));
}
}
}