expr_solver/lib.rs
1pub mod ast;
2pub mod interpreter;
3pub mod lexer;
4pub mod parser;
5pub mod token;
6pub mod utils;
7
8use interpreter::Interpreter;
9use lexer::Lexer;
10use parser::Parser;
11
12/// Takes mathematical expression as string, resolves it.
13/// # Arguments
14/// * input_string
15/// # Returns
16/// Result enum with solved value or incase of an error, error string.
17/// # Examples
18/// ```
19/// use expr_solver::resolve;
20///
21/// // simple binary expression.
22/// assert_eq!(resolve("2+2".to_string()), Ok(4.0));
23/// assert_eq!(resolve("3!".to_string()), Ok(6.0));
24///
25/// // follows precendence, 2 + (2 * 2) and NOT (2 + 2) * 2
26/// assert_eq!(resolve("2+2*2".to_string()), Ok(6.0));
27///
28/// // unary expression.
29/// assert_eq!(resolve("-2".to_string()), Ok(-2.0));
30///
31/// // even chain them. -(-2)
32/// assert_eq!(resolve("--2".to_string()), Ok(2.0));
33///
34/// // binary and unary in one expression.
35/// assert_eq!(resolve("2+-2".to_string()), Ok(0.0));
36///
37/// // gives syntax error.
38/// assert!(matches!(resolve("2&2".to_string()), Err(String)));
39/// ```
40pub fn resolve(input_string: String) -> Result<f64, String> {
41 log::debug!("[expr-resolve] input_string={}", &input_string);
42
43 // create a new lexer
44 // and parse input string into tokens.
45 let mut lexer = Lexer::new(&input_string);
46 lexer.scan();
47
48 if lexer.has_errors {
49 log::debug!(
50 "[expr-resolve] Found lexical errors in expression : {}",
51 &input_string
52 );
53 return Err("Found lexical error(s) in the expression.".to_string());
54 }
55
56 // create a new parser
57 let mut parser = Parser::new(&mut lexer);
58 // and parse tokens into AST.
59 let ast = parser.parse();
60
61 // if the ast is correct.
62 match ast {
63 Ok(ast) => {
64 // we walk the ast with our interpreter.
65 Interpreter::walk_ast(&ast)
66 }
67 // otherwise we return the error we got from the parser.
68 Err(err) => Err(err),
69 }
70}