cmkl/spring-2025/sen-109/00020/eval/src/parsemath/parser.rs

276 lines
8.3 KiB
Rust

/// This program reads tokens returned by Tokenizer and converts them into AST.
// Standard lib
use std::fmt;
// Internal modules
use super::ast::Node;
use super::token::{OperPrec, Token};
use super::tokenizer::Tokenizer;
//Structs and constants
// Parser struct
pub struct Parser<'a> {
tokenizer: Tokenizer<'a>,
current_token: Token,
}
// Public methods of Parser
impl<'a> Parser<'a> {
// Create a new instance of Parser
pub fn new(expr: &'a str) -> Result<Self, ParseError> {
let mut lexer = Tokenizer::new(expr);
let cur_token = match lexer.next() {
Some(token) => token,
None => return Err(ParseError::InvalidOperator("Invalid character".into())),
};
Ok(Parser {
tokenizer: lexer,
current_token: cur_token,
})
}
// Take an arithmetic expression as input and return an AST
pub fn parse(&mut self) -> Result<Node, ParseError> {
let ast = self.generate_ast(OperPrec::DefaultZero);
match ast {
Ok(ast) => Ok(ast),
Err(e) => Err(e),
}
}
}
// Private methods of Parser
impl<'a> Parser<'a> {
// Retrieve the next token from arithmetic expression and set it to current_token field in Parser struct
fn get_next_token(&mut self) -> Result<(), ParseError> {
let next_token = match self.tokenizer.next() {
Some(token) => token,
None => return Err(ParseError::InvalidOperator("Invalid character".into())),
};
self.current_token = next_token;
Ok(())
}
// Main workhorse method that is called recursively
fn generate_ast(&mut self, oper_prec: OperPrec) -> Result<Node, ParseError> {
let mut left_expr = self.parse_number()?;
while oper_prec < self.current_token.get_oper_prec() {
if self.current_token == Token::EOF {
break;
}
let right_expr = self.convert_token_to_node(left_expr.clone())?;
left_expr = right_expr;
}
Ok(left_expr)
}
// Construct AST node for numbers, taking into account negative prefixes while handling parenthesis
fn parse_number(&mut self) -> Result<Node, ParseError> {
let token = self.current_token.clone();
match token {
Token::Subtract => {
self.get_next_token()?;
let expr = self.generate_ast(OperPrec::Negative)?;
Ok(Node::Negative(Box::new(expr)))
}
Token::Num(i) => {
self.get_next_token()?;
Ok(Node::Number(i))
}
Token::LeftParen => {
self.get_next_token()?;
let expr = self.generate_ast(OperPrec::DefaultZero)?;
let _ = self.check_paren(Token::RightParen);
if self.current_token == Token::LeftParen
{
let right = self.generate_ast(OperPrec::MulDiv)?;
return Ok(Node::Multiply(Box::new(expr), Box::new(right)));
}
Ok(expr)
}
_ => Err(ParseError::UnableToParse("Unable to parse".to_string())),
}
}
// Check for balancing parenthesis
fn check_paren(&mut self, expected: Token) -> Result<(), ParseError> {
if expected == self.current_token {
self.get_next_token()?;
Ok(())
} else {
Err(ParseError::InvalidOperator(format!(
"Expected {:?}, got {:?}",
expected, self.current_token
)))
}
}
// Construct Operator AST nodes
fn convert_token_to_node(&mut self, left_expr: Node) -> Result<Node, ParseError>
{
match self.current_token
{
Token::And =>
{
self.get_next_token()?;
let right_expr = self.generate_ast(OperPrec::AndOr)?;
Ok(Node::And(Box::new(left_expr), Box::new(right_expr)))
},
Token::Or =>
{
self.get_next_token()?;
let right_expr = self.generate_ast(OperPrec::AndOr)?;
Ok(Node::Or(Box::new(left_expr), Box::new(right_expr)))
},
Token::Add =>
{
self.get_next_token()?;
//Get right-side expression
let right_expr = self.generate_ast(OperPrec::AddSub)?;
Ok(Node::Add(Box::new(left_expr), Box::new(right_expr)))
}
Token::Subtract =>
{
self.get_next_token()?;
let right_expr = self.generate_ast(OperPrec::AddSub)?;
Ok(Node::Subtract(Box::new(left_expr), Box::new(right_expr)))
}
Token::Multiply =>
{
self.get_next_token()?;
let right_expr = self.generate_ast(OperPrec::MulDiv)?;
Ok(Node::Multiply(Box::new(left_expr), Box::new(right_expr)))
}
Token::Divide =>
{
self.get_next_token()?;
let right_expr = self.generate_ast(OperPrec::MulDiv)?;
Ok(Node::Divide(Box::new(left_expr), Box::new(right_expr)))
}
Token::Caret =>
{
self.get_next_token()?;
let right_expr = self.generate_ast(OperPrec::Power)?;
Ok(Node::Caret(Box::new(left_expr), Box::new(right_expr)))
}
_ => Err(ParseError::InvalidOperator(format!(
"Please enter valid operator {:?}",
self.current_token
))),
}
}
}
// Custom error handler for Parser
#[derive(Debug)]
pub enum ParseError {
UnableToParse(String),
InvalidOperator(String),
}
impl fmt::Display for ParseError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match &self {
ParseError::UnableToParse(e) => write!(f, "Error in evaluating {}", e),
ParseError::InvalidOperator(e) => write!(f, "Error in evaluating {}", e),
}
}
}
// Handle error thrown from AST module
impl From<Box<dyn std::error::Error>> for ParseError {
fn from(_evalerr: Box<dyn std::error::Error>) -> Self {
ParseError::UnableToParse("Unable to parse".into())
}
}
// Unit tests
#[cfg(test)]
mod tests {
use super::*;
use crate::parsemath::ast::Node::{And, Or, Add, Subtract, Multiply, Divide, Number, Caret};
// Original Tests
#[test]
fn test_addition()
{
let mut parser = Parser::new("1+2").unwrap();
let expected = Add(Box::new(Number(1.0)), Box::new(Number(2.0)));
assert_eq!(parser.parse().unwrap(), expected);
}
#[test]
fn test_bitwise_or()
{
let mut parser = Parser::new("6|2").unwrap();
let expected = Or(Box::new(Number(6.0)), Box::new(Number(2.0)));
assert_eq!(parser.parse().unwrap(), expected);
}
// New Tests
#[test]
fn test_subtract()
{
let mut parser = Parser::new("60-32").unwrap();
let expected = Subtract(Box::new(Number(60.0)), Box::new(Number(32.0)));
assert_eq!(parser.parse().unwrap(), expected);
}
#[test]
fn test_mutiply()
{
let mut parser = Parser::new("7*2").unwrap();
let expected = Multiply(Box::new(Number(7.0)), Box::new(Number(2.0)));
assert_eq!(parser.parse().unwrap(), expected);
}
#[test]
fn test_divide()
{
let mut parser = Parser::new("95/10").unwrap();
let expected = Divide(Box::new(Number(95.0)), Box::new(Number(10.0)));
assert_eq!(parser.parse().unwrap(), expected);
}
#[test]
fn test_bitwise_and()
{
let mut parser = Parser::new("50&32").unwrap();
let expected = And(Box::new(Number(50.0)), Box::new(Number(32.0)));
assert_eq!(parser.parse().unwrap(), expected);
}
#[test]
fn test_caret()
{
let mut parser = Parser::new("4^5").unwrap();
let expected = Caret(Box::new(Number(4.0)), Box::new(Number(5.0)));
assert_eq!(parser.parse().unwrap(), expected);
}
#[test]
fn test_parenthesis()
{
let mut parser = Parser::new("(2 + 3").unwrap();
let expected = Caret(Box::new(Number(2.0)), Box::new(Number(3.0)));
assert_eq!(parser.parse().unwrap(), expected);
}
}