Library Usage

        use expression_parser::{Environment, ExpressionFile};

        let input = r#"
        a = 1 + 1;
        a + 5        
        "#;

        // ofcourse handle this better in you code
        let parsed_expression = ExpressionFile::parse(input).unwrap();

        // you can now decide what to do with the expression

        // we will just evaluate it here with default variables.

        let mut vars = Environment::default();
        let output = ExpressionFile::eval(parsed_expression, &mut vars).unwrap();
        assert_eq!(output, 7.into());

Add extra variables you can use in your code:

        use expression_parser::{Env, Environment, ExpressionFile};

        let input = r#"
        5 * DATA     
        "#;

        let parsed_expression = ExpressionFile::parse(input).unwrap();

        let mut env = Environment::default();
        env.variables_mut().insert("DATA", 1234.into());

        let output = ExpressionFile::eval(parsed_expression, &mut env).unwrap();
        assert_eq!(output, 6170.into());

Define your own functions in Rust like:

        use expression_parser::{
            Closure, Env, Environment, Error, ExpressionFile, ExpressionValue,
        };
        use std::sync::Arc;

        let mut env = Environment::default();

        // a `Closure` struct is just a container for holding the function.
        // `new` takes a list of the arguments used (only for debugging purposes)
        // and an `Arc` with a `Box`ed function with two arguments.
        // the first is a list containing all the arguments given by the user. These need to be validated yourself.
        // the second argument is a `Environment` struct that has methods to access variables outside the function and side effects.
        // the return value is a `Result<ExpressionValue, Error>`
        let closure = Closure::new(
            vec!["x".to_string(), "y".to_string()],
            Arc::new(Box::new(|vars, _| {
                /// validate the arguments or return an error
                fn validate_number(x: Option<&ExpressionValue>) -> Result<f64, Error> {
                    x.ok_or(Error::new_static("missing arguments"))?
                        .as_number()
                        .ok_or(Error::new_static("argument not a number"))
                }

                let x = validate_number(vars.get(0))?;
                let y = validate_number(vars.get(1))?;
                let result = x * y;

                // the `into` casts the rust value into a `ExpressionValue` enum
                Ok(result.into())
            })),
        );
        env.variables_mut().insert("external_func", closure.into());

        let script = r#"
        external_func.(6, 2)
        "#;

        let parsed = ExpressionFile::parse(script).unwrap();
        let result = ExpressionFile::eval(parsed, &mut env);
        assert_eq!(result, Ok(12.into()))
        use expression_parser::{Closure, Env, Environment, Error, Expression, ExpressionFile};
        use std::sync::Arc;

        let closure = Closure::new(
            vec!["map".to_string(), "key".to_string()],
            Arc::new(Box::new(|vars, context| {
                let map = vars
                    .get(0)
                    .ok_or(Error::new_static("expect a map as the first argument"))?
                    // probably do something more smart than just clone
                    .clone()
                    .as_map()
                    .ok_or(Error::new_static("expect a map as the first argument"))?;
                let key = vars
                    .get(1)
                    .ok_or(Error::new_static("expect a key as the second argument"))?
                    .as_string()
                    .ok_or(Error::new_static("expect a key as the second argument"))?;

                // get access to the underlying HashMap
                let result = map.0.get(&key).ok_or(Error::new_static("key not found"))?;

                // the result is an expression, these can include variables ect.
                // We can just match on the value or eval the Expression with the current context.
                let result = Expression::eval(result.clone(), &mut Box::new(context))?;

                Ok(result)
            })),
        );

        let mut env = Environment::default();
        env.variables_mut().insert("map_get", closure.into());

        let script = r#"
        map_get.(
            {"test": "some_value"},
            "test"
        )
        "#;

        let result = ExpressionFile::run(script, &mut env);
        assert_eq!(result, Ok("some_value".into()));

        let script = r#"
        text = "some_variable";
        map_get.(
            {"test": text},
            "test"
        )
        "#;

        let result = ExpressionFile::run(script, &mut env);
        assert_eq!(result, Ok("some_variable".into()));

Use your own variables:

        use expression_parser::{Environment, ExpressionFile, ExpressionValue};
        use std::collections::HashMap;

        // if you like python keywords better than the names I picked
        let mut my_variables = HashMap::new();
        my_variables.insert(String::from("True"), ExpressionValue::Bool(true));
        my_variables.insert(String::from("False"), ExpressionValue::Bool(false));
        my_variables.insert(String::from("None"), ExpressionValue::Null);

        // `Environment::builder` lets you configure your environment yourself.
        let mut env = Environment::builder()
            .with_variables(Box::new(my_variables))
            .build();

        let input = r#"
            a = True and True;
            b = False or True;
            c = None or True;
            all(a, b, c)
        "#;

        let parsed_expression = ExpressionFile::parse(input).unwrap();

        let output = ExpressionFile::eval(parsed_expression, &mut env).unwrap();
        assert_eq!(output, true.into());

Or extend the default variables:

        use expression_parser::{Environment, ExpressionFile, VariableMap, Variables};

        // `Variables::default` returns a `VariableMap` with all the default variables
        let mut my_variables = Variables::default();
        // so this allready exists in the variables.
        assert!(my_variables.insert("true", true.into()).is_some());
        my_variables.insert("DATA", vec![1, 5, 1].into());
        my_variables.insert("SOME", true.into());

        // `Environment::builder` lets you configure your environment yourself.
        let mut env = Environment::builder()
            .with_variables(Box::new(my_variables))
            .build();

        let input = r#"
            // returns DATA because SOME is true 
            if(SOME, DATA, error("data not found"))
        "#;

        let parsed_expression = ExpressionFile::parse(input).unwrap();

        let output = ExpressionFile::eval(parsed_expression, &mut env).unwrap();
        assert_eq!(output, vec![1, 5, 1].into());