mathrc 0.2.1

Rust Mathematics Library
Documentation
use crate::parser::tokenizer::TOKEN;

#[derive(Debug)]
pub enum Expr {
    Number(f64),
    BinaryOp { op: Operation, left: Box<Expr>, right: Box<Expr> },
}

#[derive(Debug)]
pub enum Operation {
    ADD,
    SUB,
    MUL,
    DIV,
}

pub struct Parser {
    tokens: Vec<TOKEN>,
    pos: usize,
}

impl Parser {
    pub fn new(tokens: Vec<TOKEN>) -> Self {
        Self { tokens, pos: 0 }
    }

    fn peek(&self) -> Option<&TOKEN> {
        self.tokens.get(self.pos)
    }

    fn consume(&mut self) -> Option<&TOKEN> {
        let t = self.tokens.get(self.pos);
        self.pos += 1;
        t
    }

    pub fn parse(&mut self) -> Option<Expr> {
        self.parse_additive()
    }

    fn parse_additive(&mut self) -> Option<Expr> {
        let mut left = self.parse_multiplicative()?;

        while let Some(op) = self.peek() {
            let op = match op {
                TOKEN::PLUS => Operation::ADD,
                TOKEN::MINUS => Operation::SUB,
                _ => break,
            };
            self.consume();
            let right = self.parse_multiplicative()?;
            left = Expr::BinaryOp { op, left: Box::new(left), right: Box::new(right) };
        }

        Some(left)
    }

    fn parse_multiplicative(&mut self) -> Option<Expr> {
        let mut left = self.parse_primary()?;

        while let Some(op) = self.peek() {
            let op = match op {
                TOKEN::MULTIPLE => Operation::MUL,
                TOKEN::DIVIDE => Operation::DIV,
                _ => break,
            };
            self.consume();
            let right = self.parse_primary()?;
            left = Expr::BinaryOp { op, left: Box::new(left), right: Box::new(right) };
        }

        Some(left)
    }

    fn parse_primary(&mut self) -> Option<Expr> {
        match self.peek() {
            Some(TOKEN::NUMBERS(_)) => {
                if let Some(TOKEN::NUMBERS(n)) = self.consume() {
                    return Some(Expr::Number(*n));
                }
                None
            }
            Some(TOKEN::LPAREN) => {
                self.consume();
                let expr = self.parse()?;
                if self.consume() != Some(&TOKEN::RPAREN) {
                    return None;
                }
                Some(expr)
            }
            _ => None
        }
    }
}