rsc 3.0.0

A fast calculator for solving scientific and algebraic math equations in strings.
Documentation
RSC, the Calculator for Rust Code
=================================
![](https://img.shields.io/crates/l/rsc.svg) ![](https://img.shields.io/badge/status-stable-blue.svg)

**New**: crate updated to 3.0, read the [Changelog](CHANGELOG.md).

**RSC is a handwritten scientific calculator for interpreting equations inside strings.** RSC is designed to do a single
thing very well, enabling anyone to extend it with more features.

RSC intends to beat Wirth's Law. **Therefore, RSC will not receive many additions.** It will still receive updates with
relation to efficiency.

## Library
```rust
use rsc::{tokenize, parse, Interpreter};

// Maybe you write a wrapper function
fn evaluate(input: &str, interpreter: &mut Interpreter<f64>) -> Result<f64, ()> {
    // You have to call each function in the pipeline, but this gives you the most
    // control over error handling and performance.
    match tokenize(input) { // Step 1: splits input into symbols, words, and numbers
        Ok(tokens) => match parse(&tokens) { // Step 2: builds an Expr using tokens
            Ok(expr) => match interpreter.eval(&expr) { // Step 3: interprets the Expr
                Ok(result) => println!("{}", result),
                Err(interpret_error) => eprintln!("{:?}", interpret_error),
            },
            Err(parse_error) => eprintln!("{:?}", parse_error),
        },
        Err(tokenize_error) => eprintln!("{:?}", tokenize_error),
    }
}

fn main() {
    // Constructs an f64 interpreter with included variables
    let mut interpreter = Interpreter::default();
    
    evaluate("5^2", &mut interpreter); // prints "25"
    evaluate("x = 3", &mut interpreter); // prints "3"
    evaluate("x(3) + 1", &mut interpreter); // prints "10"
}
```

Variables are stored in the `Interpreter`:
```rust
use rsc::{tokenize, parse, Interpreter, Variant, InterpretError};

// assume you still had your evaluate function above

fn main() {
    // Create a completely empty interpreter for f64 calculations
    let mut i = Interpreter::<f64>::new();
    
    // Create some variables
    i.set_var(String::from("pi"), Variant::Num(std::f64::consts::PI));
    i.set_var(String::from("double"), Variant::Function(|name, args| {
        if args.len() < 1 {
            Err(InterpretError::TooFewArgs(name, 1))
        } else if args.len() > 1 {
            Err(InterpretError::TooManyArgs(name, 1))
        } else {
            Ok(args[0] * 2) // get the only argument and double it
        }
    }));
    
    evaluate("double(pi)", &mut i); // prints "6.283185307179586"
}
```

Because it can be redundant checking that functions received the correct number of arguments (if you wish to do so at all),
I made a helper function called `ensure_arg_count`. The above function redefined:

```rust
use rsc::ensure_arg_count;

i.set_var(String::from("double"), Variant::Function(|name, args| {
    // return Err if args are not within the min and max count
    ensure_arg_count(1, 1, args.len(), name)?;
    Ok(args[0] * 2)
}));
```

## Executable
### First you might need to build RSC as an executable
```shell
cargo build --release --features=executable
```
The `executable` feature is required to tell the crate to bring in certain dependencies only for the executable version, for colors in the terminal and argument parsing.

### Usage
```shell
RSC interactive expression interpreter.
Try "help" for commands and examples.
>sqrt(15+3)
:4.242640687119285
>:square root
>sqrt(15, 3)
Function "sqrt" received more than the maximum 1 argument.
> |-5|
:5
>abs(-5)
:5
>sqrt(4)(2)
        ^ UnexpectedToken(Token { value: Symbol(LP), span: 7..8 })
>(sqrt(4))(2)
:4
>x = 1.24
:1.24
>x(4)
:4.96
>vars
factorial(..)
sqrt(..)
abs(..)
x = 1.24
e = 2.718281828459045
pi = 3.141592653589793
tau = 6.283185307179586
```

Expressions can be passed to rsc directly:
```shell
$ rsc "12/sqrt(128)"
1.0606601717798212
```

There are various flags you can pass. Try:
```shell
rsc -tev
```

```shell
$ rsc -h
rsc 3.0.0
A scientific calculator for the terminal.

USAGE:
    rsc [FLAGS] [expr]

FLAGS:
    -e, --expr        Prints the expression tree
    -h, --help        Prints help information
        --no-color    Prevents colored text
    -t, --tokens      Prints the tokens
    -v, --vars        Prints variable map
    -V, --version     Prints version information

ARGS:
    <expr>
```

## Notes About Performance
 * The lexer is iterative and can easily be optimized.
 * The parser is an LL(2) recursive-descent parser, and that's the simplest, most brute-force parsing solution I came up with. It's easy to understand and maintain, but not the most efficient. The parser is currently the slowest of the 3 phases.
 * The `Interpreter::eval` function uses recursion for simplicity. Removing the recursion could prevent unnecessary pushing and popping of the frame pointer, and enable better caching, providing better performance.
 * Performance improvement PRs are very much welcomed and probably easy!

## Stability
RSC will not have any major changes to its syntax. It will remain consistent for a long time. It is up to forkers to make different flavors of RSC. It will also forever keep the same open-source permissions.

## License
RSC is MIT licensed. RSC will always remain free to modify and use without attribution.