7 Usage
Data Types
The following data types and constants are used throughout TinyExpr++:
te_parser: The main class for defining an evaluation engine and solving expressions.
te_type: The data type for variables, function parameters, and results. By default this is double, but can be float (when TE_FLOAT is defined) or long double (when TE_LONG_DOUBLE is defined).
If long double is in use, then various bitwise functions (BITNOT(), BITRROTATE()) may be able to support 64-bit integers. This will depend on the compiler used to build the library and can be verified by calling te_parser::supports_64bit() at compile time or SUPPORTS64BIT() in an expression at runtime.
te_parser::supports_64bit() is constexpr’ed and thus can be used in if constexpr() evaluations.
te_variable: A user-defined variable or function that can be embedded into a te_parser. (Refer to custom variables.)
te_expr: The base class for a compiled expression. Classes that derive from this can be bound to custom functions. In turn, this allows for connecting more complex, class-based objects to the parser. (Refer to custom classes.)
te_parser::te_nan: An invalid numeric value. This should be returned from user-defined functions to signal a failed calculation.
te_parser::npos: An invalid position. This is returned from te_parser::get_last_error_position() when no error occurred.
te_usr_noop: A no-op function. When passed to te_parser::set_unknown_symbol_resolver(), will disable unknown symbol resolution. (Refer to ch. 9.)
Functions
The primary interface to TinyExpr++ is the class te_parser. A te_parser is a self-contained parser, which stores its own user-defined variables & functions, separators, and state information.
te_parser provides these functions:
1te_type evaluate(const std::string_view expression);
2te_type get_result();
bool success();
int64_t get_last_error_position();
std::string get_last_error_message();
3set_variables_and_functions(const std::set<te_variable>& vars);
std::set<te_variable>& get_variables_and_functions();
add_variable_or_function(const te_variable& var);
remove_variable_or_function(te_variable::name_type var);
remove_unused_variables_and_functions();
4set_unknown_symbol_resolver(te_usr_variant_type usr);
5get_decimal_separator();
set_decimal_separator();
get_list_separator();
set_list_separator();- 1
-
evaluate()takes an expression and immediately returns the result. If there is a parse error, then it returns NaN (which can be verified by usingstd::isnan()). (success()will also return false.) - 2
-
get_result()can be called anytime afterwards to retrieve the result fromevaluate(). - 3
-
set_variables_and_functions(),get_variables_and_functions(), andadd_variable_or_function()are used to add custom variables and functions to the parser. Likewise,remove_variable_or_function()andremove_unused_variables_and_functions()are used to remove them. - 4
-
set_unknown_symbol_resolver()is used to provide a custom function to resolve unknown symbols in an expression. (Refer to ch. 9 for further details.) - 5
-
get_decimal_separator()/set_decimal_separator()andget_list_separator()/set_list_separator()can be used to parse non-US formatted formulas.
Example:
te_parser tep;
// Returns 10, error position is set to te_parser::npos (i.e., no error).
auto result = tep.evaluate("(5+5)");
// Returns NaN, error position is set to 3.
auto result2 = tep.evaluate("(5+5");You can also provide set_variables_and_functions() a list of constants, bound variables, and function pointers/lambdas. evaluate() will then evaluate expressions using these variables and functions.
Error Handling
TinyExpr++ will throw exceptions when:
- An illegal character is specified in a custom function or variable name.
- An illegal character is provided as a list or decimal separator.
- The same character is provided as both the list and decimal separator.
It is recommended to wrap the following functions in try/catch blocks to handle these exceptions:
compile()evaluate()set_variables_and_functions()add_variable_or_function()set_decimal_separator()set_list_separator()
Syntax and calculation errors are trapped within calls to compile() and evaluate(). Error information can be retrieved afterwards by calling the following:
success(): returns whether the last parse was successful or not.get_last_error_position(): returns the 0-based index of where in the expression the parse failed (useful for syntax errors). If there was no parse error, then this will returnte_parser::npos.get_last_error_message(): returns a more detailed message for some calculation errors (e.g., division by zero).
Example:
#include "tinyexpr.h"
#include <iostream>
te_type x{ 0 }, y{ 0 };
// Store variable names and pointers.
te_parser tep;
tep.set_variables_and_functions({{"x", &x}, {"y", &y}});
// Compile the expression with variables.
auto result = tep.evaluate("sqrt(x^2+y^2)");
if (tep.success())
{
x = 3; y = 4;
// Will use the previously used expression, returns 5.
const auto h1 = tep.evaluate();
x = 5; y = 12;
// Returns 13.
const auto h2 = tep.evaluate();
}
else
{
std::cout << "Parse error at " <<
std::to_string(tep.get_last_error_position()) << "\n";
}Along with positional and message information, the return value of a parse can also indicate failure. When an evaluation fails, the parser will return NaN (i.e., std::numeric_limits<te_type>::quiet_NaN()) as the result. NaN values can be verified using the standard function std::isnan().
Example
The following is a short example demonstrating how to use TinyExpr++.
#include "tinyexpr.h"
#include <iostream>
int main(int argc, char *argv[])
{
te_parser tep;
const char* expression = "sqrt(5^2+7^2+11^2+(8-2)^2)";
const auto res = tep.evaluate(expression);
std::cout << "The expression:\n\t" <<
expression << "\nevaluates to:\n\t" << res << "\n";
return EXIT_SUCCESS;
}