eqrs 0.1.1

Zero-dependency math expression evaluator with variables
Documentation
pub mod operator;
pub mod token;

use token::{Token, TokenParseError};

#[derive(Debug, PartialEq)]
pub enum TokenizeError {
    TokenParseError(TokenParseError),
}

pub fn tokenize(str: &str) -> Result<Vec<Token>, TokenizeError> {
    let mut vec = vec![];
    let chars: Vec<char> = str.chars().collect();

    let mut i = 0;
    while i < str.len() {
        let c = chars[i];
        
        if c.is_whitespace() {
            i += 1;
            continue;
        } else if c.is_ascii_digit() || c == '.' {
            let mut j = i;
            loop {
                j += 1;
                if j == str.len() || !chars[j].is_ascii_digit() && chars[j] != '.' {
                    break;
                }
            }
            vec.push(Token::Num(
                chars[i..j]
                    .iter()
                    .collect::<String>()
                    .parse()
                    .expect("parse should work with all digits"),
            ));
            i = j - 1;
        } else {
            match Token::parse(&c) {
                Ok(tk) => vec.push(tk),
                Err(e) => return Err(TokenizeError::TokenParseError(e)),
            }
        }

        i += 1;
    }

    Ok(vec)
}

#[cfg(test)]
mod tests {
    use super::*;
    use operator::Op;

    #[test]
    fn tokenize_1() {
        assert_eq!(
            tokenize("2 + 2"),
            Ok(vec![Token::Num(2.0), Token::Op(Op::Add), Token::Num(2.0)])
        );
    }

    #[test]
    fn tokenize_2() {
        assert_eq!(
            tokenize("2 + 2 * 9 - 8"),
            Ok(vec![
                Token::Num(2.0),
                Token::Op(Op::Add),
                Token::Num(2.0),
                Token::Op(Op::Mul),
                Token::Num(9.0),
                Token::Op(Op::Sub),
                Token::Num(8.0)
            ])
        );
    }

    #[test]
    fn tokenize_3() {
        assert_eq!(
            tokenize("x(7xy + 6) * 3y^2"),
            Ok(vec![
                Token::Var('x'),
                Token::ParL,
                Token::Num(7.0),
                Token::Var('x'),
                Token::Var('y'),
                Token::Op(Op::Add),
                Token::Num(6.0),
                Token::ParR,
                Token::Op(Op::Mul),
                Token::Num(3.0),
                Token::Var('y'),
                Token::Op(Op::Pow),
                Token::Num(2.0)
            ])
        );
    }

    #[test]
    fn tokenize_4() {
        assert_eq!(
            tokenize("x + &"),
            Err(TokenizeError::TokenParseError(
                TokenParseError::IsPunctuation
            ))
        );
    }
}