use crate::lexer::Token; use crate::tile::Operator; use std::fmt; use std::iter::Peekable; #[derive(Debug, Clone, PartialEq, Eq)] pub enum Expression { Digit(u64), Parentheses(Box), Binary(Operator, Box, Box), } impl fmt::Display for Expression { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Expression::Digit(value) => write!(f, "{value}"), Expression::Parentheses(expr) => write!(f, "({expr})"), Expression::Binary(operator, left, right) => { write!(f, "{left} {operator} {right}") } } } } pub type Expressions = Vec; pub fn parse(tokens: &[Token]) -> Result { let mut tokens = tokens.iter().peekable(); let mut expressions = Vec::new(); while tokens.peek().is_some() { expressions.push(parse_expression(&mut tokens)?); tokens.next(); } Ok(expressions) } fn parse_expression<'a>( tokens: &mut Peekable>, ) -> Result { let mut left = parse_term(tokens)?; while let Some(Token::Operator(operator)) = tokens.peek() { let operator = *operator; tokens.next(); let right = parse_term(tokens)?; left = Expression::Binary(operator, Box::new(left), Box::new(right)); } Ok(left) } fn parse_term<'a>( tokens: &mut Peekable>, ) -> Result { let mut left = parse_factor(tokens)?; while let Some(Token::Operator(operator)) = tokens.peek() { let operator = *operator; tokens.next(); let right = parse_factor(tokens)?; left = Expression::Binary(operator, Box::new(left), Box::new(right)); } Ok(left) } fn parse_factor<'a>( tokens: &mut Peekable>, ) -> Result { match tokens.next() { Some(Token::NumberLiteral(value)) => Ok(Expression::Digit(*value)), Some(Token::LeftParen) => { let expression = parse_expression(tokens)?; if let Some(Token::RightParen) = tokens.next() { Ok(Expression::Parentheses(Box::new(expression))) } else { Err(()) } } _ => Err(()), } } #[cfg(test)] mod tests { use super::*; #[test] fn test_parse() { let tokens = vec![ Token::NumberLiteral(1), Token::Operator(Operator::Add), Token::NumberLiteral(2), Token::Operator(Operator::Multiply), Token::NumberLiteral(3), ]; let expression = parse(&tokens).unwrap(); assert_eq!( expression, vec![Expression::Binary( Operator::Multiply, Box::new(Expression::Binary( Operator::Add, Box::new(Expression::Digit(1)), Box::new(Expression::Digit(2)), )), Box::new(Expression::Digit(3)), )], ); } #[test] fn test_parse_parentheses() { let tokens = vec![ Token::LeftParen, Token::NumberLiteral(1), Token::Operator(Operator::Add), Token::NumberLiteral(2), Token::RightParen, Token::Operator(Operator::Multiply), Token::NumberLiteral(3), ]; let expression = parse(&tokens).unwrap(); assert_eq!( expression, vec![Expression::Binary( Operator::Multiply, Box::new(Expression::Parentheses(Box::new(Expression::Binary( Operator::Add, Box::new(Expression::Digit(1)), Box::new(Expression::Digit(2)), )))), Box::new(Expression::Digit(3)), )], ); } #[test] fn test_parse_equals() { let tokens = vec![ Token::NumberLiteral(1), Token::Equals, Token::NumberLiteral(2), Token::Equals, Token::NumberLiteral(3), ]; let expression = parse(&tokens).unwrap(); assert_eq!( expression, vec![ Expression::Digit(1), Expression::Digit(2), Expression::Digit(3), ], ); } }