Improve documentation

This commit is contained in:
Sebastian Schmidt 2019-08-30 09:39:25 +03:00
parent 4571f3a578
commit b8d7344cc5
2 changed files with 90 additions and 78 deletions

View File

@ -164,6 +164,11 @@ Supported unary operators:
| - | 110 | Negation | | - | 110 | Negation |
| ! | 110 | Logical not | | ! | 110 | Logical not |
Operators that take numbers as arguments can either take integers or floating point numbers.
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.
Otherwise, the result is an integer.
An exception to this is the exponentiation operator that always returns a floating point number.
#### The Aggregation Operator #### The Aggregation Operator
The aggregation operator aggregates a set of values into a tuple. The aggregation operator aggregates a set of values into a tuple.
@ -321,8 +326,8 @@ This crate offers a set of builtin functions.
| `min` | >= 1 | Numeric | Returns the minimum of the arguments | | `min` | >= 1 | Numeric | Returns the minimum of the arguments |
| `max` | >= 1 | Numeric | Returns the maximum of the arguments | | `max` | >= 1 | Numeric | Returns the maximum of the arguments |
| `len` | 1 | String/Tuple | Returns the character length of a string, or the amount of elements in a tuple (not recursively) | | `len` | 1 | String/Tuple | Returns the character length of a string, or the amount of elements in a tuple (not recursively) |
| `str::regex_matches` | 2 | String, String | Returns true if the first argument matches the regex in the second argument | | `str::regex_matches` | 2 | String, String | Returns true if the first argument matches the regex in the second argument (Requires `regex_support` feature flag) |
| `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 | | `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) |
| `str::to_lowercase` | 1 | String | Returns the lower-case version of the string | | `str::to_lowercase` | 1 | String | Returns the lower-case version of the string |
| `str::to_uppercase` | 1 | String | Returns the upper-case version of the string | | `str::to_uppercase` | 1 | String | Returns the upper-case version of the string |
| `str::trim` | 1 | String | Strips whitespace from the start and the end of the string | | `str::trim` | 1 | String | Strips whitespace from the start and the end of the string |
@ -375,53 +380,22 @@ The type of a value can be checked using the `Value::is_[type]` methods.
| `Value::from(4.4).as_float()` | `Ok(4.4)` | | `Value::from(4.4).as_float()` | `Ok(4.4)` |
| `Value::from(true).as_int()` | `Err(Error::ExpectedInt {actual: Value::Boolean(true)})` | | `Value::from(true).as_int()` | `Err(Error::ExpectedInt {actual: Value::Boolean(true)})` |
Operators that take numbers as arguments can either take integers or floating point numbers.
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.
Otherwise, the result is an integer.
An exception to this is the exponentiation operator that always returns a floating point number.
Values have a precedence of 200. Values have a precedence of 200.
### Variables ### Variables
This crate allows to compile parameterizable formulas by using variables. This crate allows to compile parameterizable formulas by using variables.
A variable is a literal in the formula, that does not contain whitespace or can be parsed as value. A variable is a literal in the formula, that does not contain whitespace or can be parsed as value.
The user needs to provide bindings to the variables for evaluation. For working with variables, a [context](#contexts) is required.
This is done with the `Context` trait. It stores the mappings from variables to their values.
Two structs implementing this trait are predefined.
There is `EmptyContext`, that returns `None` for each request, and `HashMapContext`, that stores mappings from literals to variables in a hash map.
Variables do not have fixed types in the expression itself, but are typed by the context. Variables do not have fixed types in the expression itself, but are typed by the context.
The `Context` trait contains a function that takes a string literal and returns a `Value` enum. Once a variable is assigned a value of a specific type, it cannot be assigned a value of another type.
The variant of this enum decides the type on evaluation. This might change in the future and can be changed by using a type-unsafe context (not provided by this crate as of now).
Variables have a precedence of 200. Here are some examples and counter-examples on expressions that are interpreted as variables:
### User-Defined Functions | Expression | Variable? | Explanation |
This crate also allows to define arbitrary functions to be used in parsed expressions.
A function is defined as a `Function` instance.
It contains two properties, the `argument_amount` and the `function`.
The `function` is a boxed `Fn(&[Value]) -> EvalexprResult<Value, Error>`.
The `argument_amount` determines the length of the slice that is passed to `function` if it is `Some(_)`, otherwise the function is defined to take an arbitrary amount of arguments.
It is verified on execution by the crate and does not need to be verified by the `function`.
Functions with no arguments are not allowed.
Use variables instead.
Be aware that functions need to verify the types of values that are passed to them.
The `error` module contains some shortcuts for verification, and error types for passing a wrong value type.
Also, most numeric functions need to differentiate between being called with integers or floating point numbers, and act accordingly.
Functions are identified by literals, like variables as well.
A literal identifies a function, if it is followed by an opening brace `(`, another literal, or a value.
Same as variables, function bindings are provided by the user via a `Context`.
Functions have a precedence of 190.
### Examplary variables and functions in expressions:
| Expression | Valid? | Explanation |
|------------|--------|-------------| |------------|--------|-------------|
| `a` | yes | | | `a` | yes | |
| `abc` | yes | | | `abc` | yes | |
@ -431,6 +405,38 @@ Functions have a precedence of 190.
| `true` | no | Expression is interpreted as `Value::Bool` | | `true` | no | Expression is interpreted as `Value::Bool` |
| `.34` | no | Expression is interpreted as `Value::Float` | | `.34` | no | Expression is interpreted as `Value::Float` |
Variables have a precedence of 200.
### User-Defined Functions
This crate also allows to define arbitrary functions to be used in parsed expressions.
A function is defined as a `Function` instance, wrapping a boxed `Fn(&[Value]) -> EvalexprResult<Value, Error>`.
The definition needs to be included in the [`Context`](#contexts) that is used for evaluation.
As of now, functions cannot be defined within the expression, but that might change in the future.
The function gets passed what ever value is directly behind it, be it a tuple or a single values.
If there is no value behind a function, it is interpreted as a variable instead.
More specifically, a function needs to be followed by either an opening brace `(`, another literal, or a value.
While not including special support for multi-valued functions, they can be realized by requiring a single tuple argument.
Be aware that functions need to verify the types of values that are passed to them.
The `error` module contains some shortcuts for verification, and error types for passing a wrong value type.
Also, most numeric functions need to differentiate between being called with integers or floating point numbers, and act accordingly.
Here are some examples and counter-examples on expressions that are interpreted as function calls:
| Expression | Variable? | Explanation |
|------------|--------|-------------|
| `a v` | yes | |
| `x 5.5` | yes | |
| `a (3, true)` | yes | |
| `a b 4` | yes | Call `a` with the result of calling `b` with `4` |
| `5 b` | no | Error, value cannot be followed by a literal |
| `12 3` | no | Error, value cannot be followed by a value |
| `a 5 6` | no | Error, function call cannot be followed by a value |
Functions have a precedence of 190.
### [Serde](https://serde.rs) ### [Serde](https://serde.rs)
To use this crate with serde, the `serde_support` feature flag has to be set. To use this crate with serde, the `serde_support` feature flag has to be set.

View File

@ -151,6 +151,11 @@
//! | - | 110 | Negation | //! | - | 110 | Negation |
//! | ! | 110 | Logical not | //! | ! | 110 | Logical not |
//! //!
//! Operators that take numbers as arguments can either take integers or floating point numbers.
//! 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.
//! Otherwise, the result is an integer.
//! An exception to this is the exponentiation operator that always returns a floating point number.
//!
//! #### The Aggregation Operator //! #### The Aggregation Operator
//! //!
//! The aggregation operator aggregates a set of values into a tuple. //! The aggregation operator aggregates a set of values into a tuple.
@ -308,8 +313,8 @@
//! | `min` | >= 1 | Numeric | Returns the minimum of the arguments | //! | `min` | >= 1 | Numeric | Returns the minimum of the arguments |
//! | `max` | >= 1 | Numeric | Returns the maximum of the arguments | //! | `max` | >= 1 | Numeric | Returns the maximum of the arguments |
//! | `len` | 1 | String/Tuple | Returns the character length of a string, or the amount of elements in a tuple (not recursively) | //! | `len` | 1 | String/Tuple | Returns the character length of a string, or the amount of elements in a tuple (not recursively) |
//! | `str::regex_matches` | 2 | String, String | Returns true if the first argument matches the regex in the second argument | //! | `str::regex_matches` | 2 | String, String | Returns true if the first argument matches the regex in the second argument (Requires `regex_support` feature flag) |
//! | `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 | //! | `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) |
//! | `str::to_lowercase` | 1 | String | Returns the lower-case version of the string | //! | `str::to_lowercase` | 1 | String | Returns the lower-case version of the string |
//! | `str::to_uppercase` | 1 | String | Returns the upper-case version of the string | //! | `str::to_uppercase` | 1 | String | Returns the upper-case version of the string |
//! | `str::trim` | 1 | String | Strips whitespace from the start and the end of the string | //! | `str::trim` | 1 | String | Strips whitespace from the start and the end of the string |
@ -362,53 +367,22 @@
//! | `Value::from(4.4).as_float()` | `Ok(4.4)` | //! | `Value::from(4.4).as_float()` | `Ok(4.4)` |
//! | `Value::from(true).as_int()` | `Err(Error::ExpectedInt {actual: Value::Boolean(true)})` | //! | `Value::from(true).as_int()` | `Err(Error::ExpectedInt {actual: Value::Boolean(true)})` |
//! //!
//! Operators that take numbers as arguments can either take integers or floating point numbers.
//! 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.
//! Otherwise, the result is an integer.
//! An exception to this is the exponentiation operator that always returns a floating point number.
//!
//! Values have a precedence of 200. //! Values have a precedence of 200.
//! //!
//! ### Variables //! ### Variables
//! //!
//! This crate allows to compile parameterizable formulas by using variables. //! This crate allows to compile parameterizable formulas by using variables.
//! A variable is a literal in the formula, that does not contain whitespace or can be parsed as value. //! A variable is a literal in the formula, that does not contain whitespace or can be parsed as value.
//! The user needs to provide bindings to the variables for evaluation. //! For working with variables, a [context](#contexts) is required.
//! This is done with the `Context` trait. //! It stores the mappings from variables to their values.
//! Two structs implementing this trait are predefined.
//! There is `EmptyContext`, that returns `None` for each request, and `HashMapContext`, that stores mappings from literals to variables in a hash map.
//! //!
//! Variables do not have fixed types in the expression itself, but are typed by the context. //! Variables do not have fixed types in the expression itself, but are typed by the context.
//! The `Context` trait contains a function that takes a string literal and returns a `Value` enum. //! Once a variable is assigned a value of a specific type, it cannot be assigned a value of another type.
//! The variant of this enum decides the type on evaluation. //! This might change in the future and can be changed by using a type-unsafe context (not provided by this crate as of now).
//! //!
//! Variables have a precedence of 200. //! Here are some examples and counter-examples on expressions that are interpreted as variables:
//! //!
//! ### User-Defined Functions //! | Expression | Variable? | Explanation |
//!
//! This crate also allows to define arbitrary functions to be used in parsed expressions.
//! A function is defined as a `Function` instance.
//! It contains two properties, the `argument_amount` and the `function`.
//! The `function` is a boxed `Fn(&[Value]) -> EvalexprResult<Value, Error>`.
//! The `argument_amount` determines the length of the slice that is passed to `function` if it is `Some(_)`, otherwise the function is defined to take an arbitrary amount of arguments.
//! It is verified on execution by the crate and does not need to be verified by the `function`.
//!
//! Functions with no arguments are not allowed.
//! Use variables instead.
//!
//! Be aware that functions need to verify the types of values that are passed to them.
//! The `error` module contains some shortcuts for verification, and error types for passing a wrong value type.
//! Also, most numeric functions need to differentiate between being called with integers or floating point numbers, and act accordingly.
//!
//! Functions are identified by literals, like variables as well.
//! A literal identifies a function, if it is followed by an opening brace `(`, another literal, or a value.
//!
//! Same as variables, function bindings are provided by the user via a `Context`.
//! Functions have a precedence of 190.
//!
//! ### Examplary variables and functions in expressions:
//!
//! | Expression | Valid? | Explanation |
//! |------------|--------|-------------| //! |------------|--------|-------------|
//! | `a` | yes | | //! | `a` | yes | |
//! | `abc` | yes | | //! | `abc` | yes | |
@ -418,6 +392,38 @@
//! | `true` | no | Expression is interpreted as `Value::Bool` | //! | `true` | no | Expression is interpreted as `Value::Bool` |
//! | `.34` | no | Expression is interpreted as `Value::Float` | //! | `.34` | no | Expression is interpreted as `Value::Float` |
//! //!
//! Variables have a precedence of 200.
//!
//! ### User-Defined Functions
//!
//! This crate also allows to define arbitrary functions to be used in parsed expressions.
//! A function is defined as a `Function` instance, wrapping a boxed `Fn(&[Value]) -> EvalexprResult<Value, Error>`.
//! The definition needs to be included in the [`Context`](#contexts) that is used for evaluation.
//! As of now, functions cannot be defined within the expression, but that might change in the future.
//!
//! The function gets passed what ever value is directly behind it, be it a tuple or a single values.
//! If there is no value behind a function, it is interpreted as a variable instead.
//! More specifically, a function needs to be followed by either an opening brace `(`, another literal, or a value.
//! While not including special support for multi-valued functions, they can be realized by requiring a single tuple argument.
//!
//! Be aware that functions need to verify the types of values that are passed to them.
//! The `error` module contains some shortcuts for verification, and error types for passing a wrong value type.
//! Also, most numeric functions need to differentiate between being called with integers or floating point numbers, and act accordingly.
//!
//! Here are some examples and counter-examples on expressions that are interpreted as function calls:
//!
//! | Expression | Variable? | Explanation |
//! |------------|--------|-------------|
//! | `a v` | yes | |
//! | `x 5.5` | yes | |
//! | `a (3, true)` | yes | |
//! | `a b 4` | yes | Call `a` with the result of calling `b` with `4` |
//! | `5 b` | no | Error, value cannot be followed by a literal |
//! | `12 3` | no | Error, value cannot be followed by a value |
//! | `a 5 6` | no | Error, function call cannot be followed by a value |
//!
//! Functions have a precedence of 190.
//!
//! ### [Serde](https://serde.rs) //! ### [Serde](https://serde.rs)
//! //!
//! To use this crate with serde, the `serde_support` feature flag has to be set. //! To use this crate with serde, the `serde_support` feature flag has to be set.