use core::fmt::Display;
use crate::lexer::token::{Token, TokenKind};
use crate::Result;
pub struct Parser<'a> {
tokens: &'a [Token],
current: usize,
src: &'a str,
}
impl<'a> Parser<'a> {
pub fn new(src: &'a str, tokens: &'a [Token]) -> Self {
Self {
tokens,
current: 0,
src,
}
}
}
impl<'a> Iterator for Parser<'a> {
type Item = Result<Expression>;
fn next(&mut self) -> Option<Self::Item> {
if self.current >= self.tokens.len() {
None
} else {
Some(self.expr())
}
}
}
#[derive(Debug)]
pub enum ArithmeticOp {
Add, Sub, Mul, Div, Mod
}
impl From<TokenKind> for ArithmeticOp {
fn from(value: TokenKind) -> Self {
match value {
TokenKind::Slash => ArithmeticOp::Div,
TokenKind::Mul => ArithmeticOp::Mul,
TokenKind::Mod => ArithmeticOp::Mod,
TokenKind::Minus => ArithmeticOp::Sub,
TokenKind::Plus => ArithmeticOp::Add,
_ => unreachable!("Can't with {value:?}")
}
}
}
#[derive(Debug)]
pub enum Expression {
Arithmetic {
left: Box<Expression>,
op: ArithmeticOp,
right: Box<Expression>,
},
Num(f64),
}
impl Expression {
pub fn calc(&self) -> f64 {
match self {
Expression::Arithmetic { left, op, right } => {
match op {
ArithmeticOp::Add => left.calc() + right.calc(),
ArithmeticOp::Sub => left.calc() - right.calc(),
ArithmeticOp::Mul => left.calc() * right.calc(),
ArithmeticOp::Div => left.calc() / right.calc(),
ArithmeticOp::Mod => left.calc() % right.calc(),
}
}
Expression::Num(n) => *n,
}
}
}
impl Display for Expression {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.calc())
}
}
impl<'a> Parser<'a> {
pub fn expr(&mut self) -> Result<Expression> {
self.sum_sub()
}
fn sum_sub(&mut self) -> Result<Expression> {
let mut left = self.factor()?;
while self.matches(&[TokenKind::Plus, TokenKind::Minus]) {
let op = self.previous().unwrap().kind;
let right = Box::new(self.sum_sub()?);
left = Expression::Arithmetic {
left: Box::new(left),
op: ArithmeticOp::from(op),
right
};
}
Ok(left)
}
fn factor(&mut self) -> Result<Expression> {
let mut left = self.literal()?;
while self.matches(&[TokenKind::Mul, TokenKind::Slash, TokenKind::Mod]) {
let op = self.previous().unwrap().kind;
let right = Box::new(self.factor()?);
left = Expression::Arithmetic {
left: Box::new(left),
op: ArithmeticOp::from(op),
right
};
}
Ok(left)
}
fn literal(&mut self) -> Result<Expression> {
let t = self.next()?;
match t.kind {
TokenKind::Number => {
let span = t.span.slice(self.src);
let num = span.parse::<f64>().unwrap();
Ok(Expression::Num(num))
},
TokenKind::LParen => {
let e = self.expr()?;
assert!( self.next()?.kind == TokenKind::RParen );
Ok(e)
},
_ => Err(format!("Unexpected token {:?}", t.kind).into())
}
}
fn next(&mut self) -> Result<Token> {
if self.current >= self.tokens.len() {
Err("Expected token".into())
} else {
self.current += 1;
Ok(self.tokens[self.current - 1])
}
}
fn previous(&mut self) -> Result<Token> {
if self.current > 0 {
Ok(self.tokens[self.current - 1])
} else {
Err("No previous token".into())
}
}
fn peek(&mut self) -> Result<Token> {
if self.current >= self.tokens.len() {
Err("Expected token".into())
} else {
Ok(self.tokens[self.current])
}
}
fn advance(&mut self) {
self.current += 1;
}
fn matches(&mut self, kinds: &[TokenKind]) -> bool {
if self.peek().is_ok_and(|t| {
kinds.contains(&t.kind)
}) {
self.advance();
true
} else {
false
}
}
}