fastn_resolved/evalexpr/mod.rs
1//!
2//! ## Quickstart
3//!
4//! Add `evalexpr` as dependency to your `Cargo.toml`:
5//!
6//! ```toml
7//! [dependencies]
8//! evalexpr = "<desired version>"
9//! ```
10//!
11//! Then you can use `evalexpr` to **evaluate expressions** like this:
12//!
13//! ```rust
14//! use fastn_resolved::evalexpr::*;
15//!
16//! assert_eq!(eval("1 + 2 + 3"), Ok(Value::from(6)));
17//! // `eval` returns a variant of the `Value` enum,
18//! // while `eval_[type]` returns the respective type directly.
19//! // Both can be used interchangeably.
20//! assert_eq!(eval_int("1 + 2 + 3"), Ok(6));
21//! assert_eq!(eval("1 - 2 * 3"), Ok(Value::from(-5)));
22//! assert_eq!(eval("1.0 + 2 * 3"), Ok(Value::from(7.0)));
23//! assert_eq!(eval("true && 4 > 2"), Ok(Value::from(true)));
24//! ```
25//!
26//! You can **chain** expressions and **assign** to variables like this:
27//!
28//! ```rust
29//! use fastn_resolved::evalexpr::*;
30//!
31//! let mut context = HashMapContext::new();
32//! // Assign 5 to a like this
33//! assert_eq!(eval_empty_with_context_mut("a = 5", &mut context), Ok(EMPTY_VALUE));
34//! // The HashMapContext is type safe, so this will fail now
35//! assert_eq!(eval_empty_with_context_mut("a = 5.0", &mut context),
36//! Err(EvalexprError::expected_int(Value::from(5.0))));
37//! // We can check which value the context stores for a like this
38//! assert_eq!(context.get_value("a"), Some(&Value::from(5)));
39//! // And use the value in another expression like this
40//! assert_eq!(eval_int_with_context_mut("a = a + 2; a", &mut context), Ok(7));
41//! // It is also possible to save a bit of typing by using an operator-assignment operator
42//! assert_eq!(eval_int_with_context_mut("a += 2; a", &mut context), Ok(9));
43//! ```
44//!
45//! And you can use **variables** and **functions** in expressions like this:
46//!
47//! ```rust
48//! use fastn_resolved::evalexpr::*;
49//!
50//! let context = fastn_resolved::context_map! {
51//! "five" => 5,
52//! "twelve" => 12,
53//! "f" => Function::new(|argument| {
54//! if let Ok(int) = argument.as_int() {
55//! Ok(Value::Int(int / 2))
56//! } else if let Ok(float) = argument.as_float() {
57//! Ok(Value::Float(float / 2.0))
58//! } else {
59//! Err(EvalexprError::expected_number(argument.clone()))
60//! }
61//! }),
62//! "avg" => Function::new(|argument| {
63//! let arguments = argument.as_tuple()?;
64//!
65//! if let (Value::Int(a), Value::Int(b)) = (&arguments[0], &arguments[1]) {
66//! Ok(Value::Int((a + b) / 2))
67//! } else {
68//! Ok(Value::Float((arguments[0].as_number()? + arguments[1].as_number()?) / 2.0))
69//! }
70//! })
71//! }.unwrap(); // Do proper error handling here
72//!
73//! assert_eq!(eval_with_context("five + 8 > f(twelve)", &context), Ok(Value::from(true)));
74//! // `eval_with_context` returns a variant of the `Value` enum,
75//! // while `eval_[type]_with_context` returns the respective type directly.
76//! // Both can be used interchangeably.
77//! assert_eq!(eval_boolean_with_context("five + 8 > f(twelve)", &context), Ok(true));
78//! assert_eq!(eval_with_context("avg(2, 4) == 3", &context), Ok(Value::from(true)));
79//! ```
80//!
81//! You can also **precompile** expressions like this:
82//!
83//! ```rust
84//! use fastn_resolved::evalexpr::*;
85//!
86//! let precompiled = build_operator_tree("a * b - c > 5").unwrap(); // Do proper error handling here
87//!
88//! let mut context = fastn_resolved::context_map! {
89//! "a" => 6,
90//! "b" => 2,
91//! "c" => 3
92//! }.unwrap(); // Do proper error handling here
93//! assert_eq!(precompiled.eval_with_context(&context), Ok(Value::from(true)));
94//!
95//! context.set_value("c".into(), 8.into()).unwrap(); // Do proper error handling here
96//! assert_eq!(precompiled.eval_with_context(&context), Ok(Value::from(false)));
97//! // `Node::eval_with_context` returns a variant of the `Value` enum,
98//! // while `Node::eval_[type]_with_context` returns the respective type directly.
99//! // Both can be used interchangeably.
100//! assert_eq!(precompiled.eval_boolean_with_context(&context), Ok(false));
101//! ```
102//!
103//! ## Features
104//!
105//! ### Operators
106//!
107//! This crate offers a set of binary and unary operators for building expressions.
108//! Operators have a precedence to determine their order of evaluation, where operators of higher precedence are evaluated first.
109//! The precedence should resemble that of most common programming languages, especially Rust.
110//! Variables and values have a precedence of 200, and function literals have 190.
111//!
112//! Supported binary operators:
113//!
114//! | Operator | Precedence | Description |
115//! |----------|------------|-------------|
116//! | ^ | 120 | Exponentiation |
117//! | * | 100 | Product |
118//! | / | 100 | Division (integer if both arguments are integers, otherwise float) |
119//! | % | 100 | Modulo (integer if both arguments are integers, otherwise float) |
120//! | + | 95 | Sum or String Concatenation |
121//! | - | 95 | Difference |
122//! | < | 80 | Lower than |
123//! | \> | 80 | Greater than |
124//! | <= | 80 | Lower than or equal |
125//! | \>= | 80 | Greater than or equal |
126//! | == | 80 | Equal |
127//! | != | 80 | Not equal |
128//! | && | 75 | Logical and |
129//! | || | 70 | Logical or |
130//! | = | 50 | Assignment |
131//! | += | 50 | Sum-Assignment or String-Concatenation-Assignment |
132//! | -= | 50 | Difference-Assignment |
133//! | *= | 50 | Product-Assignment |
134//! | /= | 50 | Division-Assignment |
135//! | %= | 50 | Modulo-Assignment |
136//! | ^= | 50 | Exponentiation-Assignment |
137//! | &&= | 50 | Logical-And-Assignment |
138//! | ||= | 50 | Logical-Or-Assignment |
139//! | , | 40 | Aggregation |
140//! | ; | 0 | Expression Chaining |
141//!
142//! Supported unary operators:
143//!
144//! | Operator | Precedence | Description |
145//! |----------|------------|-------------|
146//! | - | 110 | Negation |
147//! | ! | 110 | Logical not |
148//!
149//! Operators that take numbers as arguments can either take integers or floating point numbers.
150//! If one of the arguments is a floating point number, all others are converted to floating point numbers as well, and the resulting value is a floating point number as well.
151//! Otherwise, the result is an integer.
152//! An exception to this is the exponentiation operator that always returns a floating point number.
153//! Example:
154//!
155//! ```rust
156//! use fastn_resolved::evalexpr::*;
157//!
158//! assert_eq!(eval("1 / 2"), Ok(Value::from(0)));
159//! assert_eq!(eval("1.0 / 2"), Ok(Value::from(0.5)));
160//! assert_eq!(eval("2^2"), Ok(Value::from(4.0)));
161//! ```
162//!
163//! #### The Aggregation Operator
164//!
165//! The aggregation operator aggregates a set of values into a tuple.
166//! A tuple can contain arbitrary values, it is not restricted to a single type.
167//! The operator is n-ary, so it supports creating tuples longer than length two.
168//! Example:
169//!
170//! ```rust
171//! use fastn_resolved::evalexpr::*;
172//!
173//! assert_eq!(eval("1, \"b\", 3"),
174//! Ok(Value::from(vec![Value::from(1), Value::from("b"), Value::from(3)])));
175//! ```
176//!
177//! To create nested tuples, use parentheses:
178//!
179//! ```rust
180//! use fastn_resolved::evalexpr::*;
181//!
182//! assert_eq!(eval("1, 2, (true, \"b\")"), Ok(Value::from(vec![
183//! Value::from(1),
184//! Value::from(2),
185//! Value::from(vec![
186//! Value::from(true),
187//! Value::from("b")
188//! ])
189//! ])));
190//! ```
191//!
192//! #### The Assignment Operator
193//!
194//! This crate features the assignment operator, that allows expressions to store their result in a variable in the expression context.
195//! If an expression uses the assignment operator, it must be evaluated with a mutable context.
196//!
197//! Note that assignments are type safe when using the `HashMapContext`.
198//! That means that if an identifier is assigned a value of a type once, it cannot be assigned a value of another type.
199//!
200//! ```rust
201//! use fastn_resolved::evalexpr::*;
202//!
203//! let mut context = HashMapContext::new();
204//! assert_eq!(eval_with_context("a = 5", &context), Err(EvalexprError::ContextNotMutable));
205//! assert_eq!(eval_empty_with_context_mut("a = 5", &mut context), Ok(EMPTY_VALUE));
206//! assert_eq!(eval_empty_with_context_mut("a = 5.0", &mut context),
207//! Err(EvalexprError::expected_int(5.0.into())));
208//! assert_eq!(eval_int_with_context("a", &context), Ok(5));
209//! assert_eq!(context.get_value("a"), Some(5.into()).as_ref());
210//! ```
211//!
212//! For each binary operator, there exists an equivalent operator-assignment operator.
213//! Here are some examples:
214//!
215//! ```rust
216//! use fastn_resolved::evalexpr::*;
217//!
218//! assert_eq!(eval_int("a = 2; a *= 2; a += 2; a"), Ok(6));
219//! assert_eq!(eval_float("a = 2.2; a /= 2.0 / 4 + 1; a"), Ok(2.2 / (2.0 / 4.0 + 1.0)));
220//! assert_eq!(eval_string("a = \"abc\"; a += \"def\"; a"), Ok("abcdef".to_string()));
221//! assert_eq!(eval_boolean("a = true; a &&= false; a"), Ok(false));
222//! ```
223//!
224//! #### The Expression Chaining Operator
225//!
226//! The expression chaining operator works as one would expect from programming languages that use the semicolon to end statements, like `Rust`, `C` or `Java`.
227//! It has the special feature that it returns the value of the last expression in the expression chain.
228//! If the last expression is terminated by a semicolon as well, then `Value::Empty` is returned.
229//! Expression chaining is useful together with assignment to create small scripts.
230//!
231//! ```rust
232//! use fastn_resolved::evalexpr::*;
233//!
234//! let mut context = HashMapContext::new();
235//! assert_eq!(eval("1;2;3;4;"), Ok(Value::Empty));
236//! assert_eq!(eval("1;2;3;4"), Ok(4.into()));
237//!
238//! // Initialization of variables via script
239//! assert_eq!(eval_empty_with_context_mut("hp = 1; max_hp = 5; heal_amount = 3;", &mut context),
240//! Ok(EMPTY_VALUE));
241//! // Precompile healing script
242//! let healing_script = build_operator_tree("hp = min(hp + heal_amount, max_hp); hp").unwrap(); // Do proper error handling here
243//! // Execute precompiled healing script
244//! assert_eq!(healing_script.eval_int_with_context_mut(&mut context), Ok(4));
245//! assert_eq!(healing_script.eval_int_with_context_mut(&mut context), Ok(5));
246//! ```
247//!
248//! ### Contexts
249//!
250//! An expression evaluator that just evaluates expressions would be useful already, but this crate can do more.
251//! It allows using [*variables*](#variables), [*assignments*](#the-assignment-operator), [*statement chaining*](#the-expression-chaining-operator) and [*user-defined functions*](#user-defined-functions) within an expression.
252//! When assigning to variables, the assignment is stored in a context.
253//! When the variable is read later on, it is read from the context.
254//! Contexts can be preserved between multiple calls to eval by creating them yourself.
255//! Here is a simple example to show the difference between preserving and not preserving context between evaluations:
256//!
257//! ```rust
258//! use fastn_resolved::evalexpr::*;
259//!
260//! assert_eq!(eval("a = 5;"), Ok(Value::from(())));
261//! // The context is not preserved between eval calls
262//! assert_eq!(eval("a"), Err(EvalexprError::VariableIdentifierNotFound("a".to_string())));
263//!
264//! let mut context = HashMapContext::new();
265//! assert_eq!(eval_with_context_mut("a = 5;", &mut context), Ok(Value::from(())));
266//! // Assignments require mutable contexts
267//! assert_eq!(eval_with_context("a = 6", &context), Err(EvalexprError::ContextNotMutable));
268//! // The HashMapContext is type safe
269//! assert_eq!(eval_with_context_mut("a = 5.5", &mut context),
270//! Err(EvalexprError::ExpectedInt { actual: Value::from(5.5) }));
271//! // Reading a variable does not require a mutable context
272//! assert_eq!(eval_with_context("a", &context), Ok(Value::from(5)));
273//!
274//! ```
275//!
276//! Note that the assignment is forgotten between the two calls to eval in the first example.
277//! In the second part, the assignment is correctly preserved.
278//! Note as well that to assign to a variable, the context needs to be passed as a mutable reference.
279//! When passed as an immutable reference, an error is returned.
280//!
281//! Also, the `HashMapContext` is type safe.
282//! This means that assigning to `a` again with a different type yields an error.
283//! Type unsafe contexts may be implemented if requested.
284//! For reading `a`, it is enough to pass an immutable reference.
285//!
286//! Contexts can also be manipulated in code.
287//! Take a look at the following example:
288//!
289//! ```rust
290//! use fastn_resolved::evalexpr::*;
291//!
292//! let mut context = HashMapContext::new();
293//! // We can set variables in code like this...
294//! context.set_value("a".into(), 5.into());
295//! // ...and read from them in expressions
296//! assert_eq!(eval_int_with_context("a", &context), Ok(5));
297//! // We can write or overwrite variables in expressions...
298//! assert_eq!(eval_with_context_mut("a = 10; b = 1.0;", &mut context), Ok(().into()));
299//! // ...and read the value in code like this
300//! assert_eq!(context.get_value("a"), Some(&Value::from(10)));
301//! assert_eq!(context.get_value("b"), Some(&Value::from(1.0)));
302//! ```
303//!
304//! Contexts are also required for user-defined functions.
305//! Those can be passed one by one with the `set_function` method, but it might be more convenient to use the `context_map!` macro instead:
306//!
307//! ```rust
308//! use fastn_resolved::evalexpr::*;
309//!
310//! let context = fastn_resolved::context_map!{
311//! "f" => Function::new(|args| Ok(Value::from(args.as_int()? + 5))),
312//! }.unwrap_or_else(|error| panic!("Error creating context: {}", error));
313//! assert_eq!(eval_int_with_context("f 5", &context), Ok(10));
314//! ```
315//!
316//! For more information about user-defined functions, refer to the respective [section](#user-defined-functions).
317//!
318//! ### Builtin Functions
319//!
320//! This crate offers a set of builtin functions.
321//!
322//! | Identifier | Argument Amount | Argument Types | Description |
323//! |----------------------|-----------------|------------------------|-------------|
324//! | `min` | >= 1 | Numeric | Returns the minimum of the arguments |
325//! | `max` | >= 1 | Numeric | Returns the maximum of the arguments |
326//! | `len` | 1 | String/Tuple | Returns the character length of a string, or the amount of elements in a tuple (not recursively) |
327//! | `floor` | 1 | Numeric | Returns the largest integer less than or equal to a number |
328//! | `round` | 1 | Numeric | Returns the nearest integer to a number. Rounds half-way cases away from 0.0 |
329//! | `ceil` | 1 | Numeric | Returns the smallest integer greater than or equal to a number |
330//! | `if` | 3 | Boolean, Any, Any | If the first argument is true, returns the second argument, otherwise, returns the third |
331//! | `typeof` | 1 | Any | returns "string", "float", "int", "boolean", "tuple", or "empty" depending on the type of the argument |
332//! | `math::is_nan` | 1 | Numeric | Returns true if the argument is the floating-point value NaN, false if it is another floating-point value, and throws an error if it is not a number |
333//! | `math::is_finite` | 1 | Numeric | Returns true if the argument is a finite floating-point number, false otherwise |
334//! | `math::is_infinite` | 1 | Numeric | Returns true if the argument is an infinite floating-point number, false otherwise |
335//! | `math::is_normal` | 1 | Numeric | Returns true if the argument is a floating-point number that is neither zero, infinite, [subnormal](https://en.wikipedia.org/wiki/Subnormal_number), or NaN, false otherwise |
336//! | `math::ln` | 1 | Numeric | Returns the natural logarithm of the number |
337//! | `math::log` | 2 | Numeric, Numeric | Returns the logarithm of the number with respect to an arbitrary base |
338//! | `math::log2` | 1 | Numeric | Returns the base 2 logarithm of the number |
339//! | `math::log10` | 1 | Numeric | Returns the base 10 logarithm of the number |
340//! | `math::exp` | 1 | Numeric | Returns `e^(number)`, (the exponential function) |
341//! | `math::exp2` | 1 | Numeric | Returns `2^(number)` |
342//! | `math::pow` | 2 | Numeric, Numeric | Raises a number to the power of the other number |
343//! | `math::cos` | 1 | Numeric | Computes the cosine of a number (in radians) |
344//! | `math::acos` | 1 | Numeric | Computes the arccosine of a number. The return value is in radians in the range [0, pi] or NaN if the number is outside the range [-1, 1] |
345//! | `math::cosh` | 1 | Numeric | Hyperbolic cosine function |
346//! | `math::acosh` | 1 | Numeric | Inverse hyperbolic cosine function |
347//! | `math::sin` | 1 | Numeric | Computes the sine of a number (in radians) |
348//! | `math::asin` | 1 | Numeric | Computes the arcsine of a number. The return value is in radians in the range [-pi/2, pi/2] or NaN if the number is outside the range [-1, 1] |
349//! | `math::sinh` | 1 | Numeric | Hyperbolic sine function |
350//! | `math::asinh` | 1 | Numeric | Inverse hyperbolic sine function |
351//! | `math::tan` | 1 | Numeric | Computes the tangent of a number (in radians) |
352//! | `math::atan` | 1 | Numeric | Computes the arctangent of a number. The return value is in radians in the range [-pi/2, pi/2] |
353//! | `math::atan2` | 2 | Numeric, Numeric | Computes the four quadrant arctangent in radians |
354//! | `math::tanh` | 1 | Numeric | Hyperbolic tangent function |
355//! | `math::atanh` | 1 | Numeric | Inverse hyperbolic tangent function. |
356//! | `math::sqrt` | 1 | Numeric | Returns the square root of a number. Returns NaN for a negative number |
357//! | `math::cbrt` | 1 | Numeric | Returns the cube root of a number |
358//! | `math::hypot` | 2 | Numeric | Calculates the length of the hypotenuse of a right-angle triangle given legs of length given by the two arguments |
359//! | `str::regex_matches` | 2 | String, String | Returns true if the first argument matches the regex in the second argument (Requires `regex_support` feature flag) |
360//! | `str::regex_replace` | 3 | String, String, String | Returns the first argument with all matches of the regex in the second argument replaced by the third argument (Requires `regex_support` feature flag) |
361//! | `str::to_lowercase` | 1 | String | Returns the lower-case version of the string |
362//! | `str::to_uppercase` | 1 | String | Returns the upper-case version of the string |
363//! | `str::trim` | 1 | String | Strips whitespace from the start and the end of the string |
364//! | `str::from` | >= 0 | Any | Returns passed value as string |
365//! | `bitand` | 2 | Int | Computes the bitwise and of the given integers |
366//! | `bitor` | 2 | Int | Computes the bitwise or of the given integers |
367//! | `bitxor` | 2 | Int | Computes the bitwise xor of the given integers |
368//! | `bitnot` | 1 | Int | Computes the bitwise not of the given integer |
369//! | `shl` | 2 | Int | Computes the given integer bitwise shifted left by the other given integer |
370//! | `shr` | 2 | Int | Computes the given integer bitwise shifted right by the other given integer |
371//! | `random` | 0 | Empty | Return a random float between 0 and 1. Requires the `rand` feature flag. |
372//!
373//! The `min` and `max` functions can deal with a mixture of integer and floating point arguments.
374//! If the maximum or minimum is an integer, then an integer is returned.
375//! Otherwise, a float is returned.
376//!
377//! The regex functions require the feature flag `regex_support`.
378//!
379//! ### Values
380//!
381//! Operators take values as arguments and produce values as results.
382//! Values can be booleans, integer or floating point numbers, strings, tuples or the empty type.
383//! Values are denoted as displayed in the following table.
384//!
385//! | Value type | Example |
386//! |------------|---------|
387//! | `Value::String` | `"abc"`, `""`, `"a\"b\\c"` |
388//! | `Value::Boolean` | `true`, `false` |
389//! | `Value::Int` | `3`, `-9`, `0`, `135412` |
390//! | `Value::Float` | `3.`, `.35`, `1.00`, `0.5`, `123.554`, `23e4`, `-2e-3`, `3.54e+2` |
391//! | `Value::Tuple` | `(3, 55.0, false, ())`, `(1, 2)` |
392//! | `Value::Empty` | `()` |
393//!
394//! Integers are internally represented as `i64`, and floating point numbers are represented as `f64`.
395//! Tuples are represented as `Vec<Value>` and empty values are not stored, but represented by Rust's unit type `()` where necessary.
396//!
397//! There exist type aliases for some of the types.
398//! They include `IntType`, `FloatType`, `TupleType` and `EmptyType`.
399//!
400//! Values can be constructed either directly or using the `From` trait.
401//! They can be decomposed using the `Value::as_[type]` methods.
402//! The type of a value can be checked using the `Value::is_[type]` methods.
403//!
404//! **Examples for constructing a value:**
405//!
406//! | Code | Result |
407//! |------|--------|
408//! | `Value::from(4)` | `Value::Int(4)` |
409//! | `Value::from(4.4)` | `Value::Float(4.4)` |
410//! | `Value::from(true)` | `Value::Boolean(true)` |
411//! | `Value::from(vec![Value::from(3)])` | `Value::Tuple(vec![Value::Int(3)])` |
412//!
413//! **Examples for deconstructing a value:**
414//!
415//! | Code | Result |
416//! |------|--------|
417//! | `Value::from(4).as_int()` | `Ok(4)` |
418//! | `Value::from(4.4).as_float()` | `Ok(4.4)` |
419//! | `Value::from(true).as_int()` | `Err(Error::ExpectedInt {actual: Value::Boolean(true)})` |
420//!
421//! Values have a precedence of 200.
422//!
423//! ### Variables
424//!
425//! This crate allows to compile parameterizable formulas by using variables.
426//! A variable is a literal in the formula, that does not contain whitespace or can be parsed as value.
427//! For working with variables, a [context](#contexts) is required.
428//! It stores the mappings from variables to their values.
429//!
430//! Variables do not have fixed types in the expression itself, but are typed by the context.
431//! Once a variable is assigned a value of a specific type, it cannot be assigned a value of another type.
432//! This might change in the future and can be changed by using a type-unsafe context (not provided by this crate as of now).
433//!
434//! Here are some examples and counter-examples on expressions that are interpreted as variables:
435//!
436//! | Expression | Variable? | Explanation |
437//! |------------|--------|-------------|
438//! | `a` | yes | |
439//! | `abc` | yes | |
440//! | `a<b` | no | Expression is interpreted as variable `a`, operator `<` and variable `b` |
441//! | `a b` | no | Expression is interpreted as function `a` applied to argument `b` |
442//! | `123` | no | Expression is interpreted as `Value::Int` |
443//! | `true` | no | Expression is interpreted as `Value::Bool` |
444//! | `.34` | no | Expression is interpreted as `Value::Float` |
445//!
446//! Variables have a precedence of 200.
447//!
448//! ### User-Defined Functions
449//!
450//! This crate allows to define arbitrary functions to be used in parsed expressions.
451//! A function is defined as a `Function` instance, wrapping an `fn(&Value) -> EvalexprResult<Value>`.
452//! The definition needs to be included in the [`Context`](#contexts) that is used for evaluation.
453//! As of now, functions cannot be defined within the expression, but that might change in the future.
454//!
455//! The function gets passed what ever value is directly behind it, be it a tuple or a single values.
456//! If there is no value behind a function, it is interpreted as a variable instead.
457//! More specifically, a function needs to be followed by either an opening brace `(`, another literal, or a value.
458//! While not including special support for multi-valued functions, they can be realized by requiring a single tuple argument.
459//!
460//! Be aware that functions need to verify the types of values that are passed to them.
461//! The `error` module contains some shortcuts for verification, and error types for passing a wrong value type.
462//! Also, most numeric functions need to distinguish between being called with integers or floating point numbers, and act accordingly.
463//!
464//! Here are some examples and counter-examples on expressions that are interpreted as function calls:
465//!
466//! | Expression | Function? | Explanation |
467//! |------------|--------|-------------|
468//! | `a v` | yes | |
469//! | `x 5.5` | yes | |
470//! | `a (3, true)` | yes | |
471//! | `a b 4` | yes | Call `a` with the result of calling `b` with `4` |
472//! | `5 b` | no | Error, value cannot be followed by a literal |
473//! | `12 3` | no | Error, value cannot be followed by a value |
474//! | `a 5 6` | no | Error, function call cannot be followed by a value |
475//!
476//! Functions have a precedence of 190.
477//!
478//! ### [Serde](https://serde.rs)
479//!
480//! To use this crate with serde, the `serde_support` feature flag has to be set.
481//! This can be done like this in the `Cargo.toml`:
482//!
483//! ```toml
484//! [dependencies]
485//! evalexpr = {version = "7", features = ["serde_support"]}
486//! ```
487//!
488//! This crate implements `serde::de::Deserialize` for its type `Node` that represents a parsed expression tree.
489//! The implementation expects a [serde `string`](https://serde.rs/data-model.html) as input.
490//! Example parsing with [ron format](docs.rs/ron):
491//!
492//! ```rust
493//! # #[cfg(feature = "serde_support")] {
494//! extern crate ron;
495//! use fastn_resolved::evalexpr::*;
496//!
497//! let mut context = fastn_resolved::context_map!{
498//! "five" => 5
499//! }.unwrap(); // Do proper error handling here
500//!
501//! // In ron format, strings are surrounded by "
502//! let serialized_free = "\"five * five\"";
503//! match ron::de::from_str::<ExprNode>(serialized_free) {
504//! Ok(free) => assert_eq!(free.eval_with_context(&context), Ok(Value::from(25))),
505//! Err(error) => {
506//! () // Handle error
507//! }
508//! }
509//! # }
510//! ```
511//!
512//! With `serde`, expressions can be integrated into arbitrarily complex data.
513//!
514//! The crate also implements `Serialize` and `Deserialize` for the `HashMapContext`,
515//! but note that only the variables get (de)serialized, not the functions.
516//!
517//! ## License
518//!
519//! This crate is primarily distributed under the terms of the MIT license.
520//! See [LICENSE](LICENSE) for details.
521//!
522
523#![deny(missing_docs)]
524#![forbid(unsafe_code)]
525
526pub use fastn_resolved::evalexpr::{
527 context::{
528 Context, ContextWithMutableFunctions, ContextWithMutableVariables, EmptyContext,
529 HashMapContext, IterateVariablesContext,
530 },
531 error::{EvalexprError, EvalexprResult},
532 function::Function,
533 interface::*,
534 operator::Operator,
535 token::PartialToken,
536 tree::ExprNode,
537 value::{value_type::ValueType, EmptyType, FloatType, IntType, TupleType, Value, EMPTY_VALUE},
538};
539
540mod context;
541pub mod error;
542mod function;
543mod interface;
544mod operator;
545mod token;
546mod tree;
547mod value;
548
549// Exports