use crate::math::{ lexer::Token, types::{Expression, Operator}, }; pub fn from(tokens: Vec) -> Parser { Parser::new(tokens) } pub struct Parser { tokens: Vec, position: usize, } impl Parser { pub fn new(tokens: Vec) -> Self { Self { tokens, position: 0, } } pub fn parse(&mut self) -> Expression { self.parse_additive() } fn parse_additive(&mut self) -> Expression { let mut left = self.parse_multiplicative(); while let Some(token) = self.tokens.get(self.position) { match token { Token::Operator(Operator::Add) => { self.position += 1; let right = self.parse_multiplicative(); left = Expression::Operation(Operator::Add, Box::new(left), Box::new(right)); } Token::Operator(Operator::Subtract) => { self.position += 1; let right = self.parse_multiplicative(); left = Expression::Operation(Operator::Subtract, Box::new(left), Box::new(right)); } _ => break, } } left } fn parse_multiplicative(&mut self) -> Expression { let mut left = self.parse_exponential(); while let Some(token) = self.tokens.get(self.position) { match token { Token::Operator(Operator::Multiply) => { self.position += 1; let right = self.parse_exponential(); left = Expression::Operation(Operator::Multiply, Box::new(left), Box::new(right)); } Token::Operator(Operator::Divide) => { self.position += 1; let right = self.parse_exponential(); left = Expression::Fraction(Box::new(left), Box::new(right)); } Token::Operator(Operator::Modulo) => { self.position += 1; let right = self.parse_exponential(); left = Expression::Operation(Operator::Modulo, Box::new(left), Box::new(right)); } Token::OpenParen => { let right = self.parse_group(); left = Expression::Operation(Operator::Multiply, Box::new(left), Box::new(right)); } Token::Identifier(_) => { let right = self.parse_primary(); left = Expression::Operation(Operator::Multiply, Box::new(left), Box::new(right)); } _ => break, } } left } fn parse_exponential(&mut self) -> Expression { let mut left = self.parse_group(); while let Some(token) = self.tokens.get(self.position) { match token { Token::Operator(Operator::Power) => { self.position += 1; let right = self.parse_group(); left = Expression::Operation(Operator::Power, Box::new(left), Box::new(right)); } _ => break, } } left } fn parse_group(&mut self) -> Expression { match self.tokens.get(self.position).expect("expected token!") { Token::OpenParen => { self.position += 1; let expression = self.parse_additive(); self.position += 1; expression } _ => self.parse_primary(), } } fn parse_primary(&mut self) -> Expression { let token = self .tokens .get(self.position) .cloned() .expect("expected token!"); match token { Token::Number(num) => { self.position += 1; Expression::Number(num) } Token::Identifier(identifier) => { let is_function = matches!(self.tokens.get(self.position + 1), Some(Token::OpenParen)); if is_function { self.position += 2; let params = self.parse_function_params(); Expression::Function(identifier, params) } else { self.position += 1; Expression::Variable(identifier) } } _ => { panic!("unexpected token! {:?}", token); } } } fn parse_function_params(&mut self) -> Vec { let mut params: Vec = Vec::new(); while let Some(token) = self.tokens.get(self.position) { match token { Token::Comma => { self.position += 1; } Token::CloseParen => { self.position += 1; break; } _ => { let expression = self.parse_additive(); params.push(expression); } } } params } }