hummingbird
Solving the self-adjoint angular flux transport equation using spectral elements on Cartesian geometry
Loading...
Searching...
No Matches
tinyexpr.h
Go to the documentation of this file.
1// SPDX-License-Identifier: Zlib
2/*
3 * TINYEXPR - Tiny recursive descent parser and evaluation engine in C
4 *
5 * Copyright (c) 2015-2026 Lewis Van Winkle
6 *
7 * http://CodePlea.com
8 *
9 * This software is provided 'as-is', without any express or implied
10 * warranty. In no event will the authors be held liable for any damages
11 * arising from the use of this software.
12 *
13 * Permission is granted to anyone to use this software for any purpose,
14 * including commercial applications, and to alter it and redistribute it
15 * freely, subject to the following restrictions:
16 *
17 * 1. The origin of this software must not be misrepresented; you must not
18 * claim that you wrote the original software. If you use this software
19 * in a product, an acknowledgement in the product documentation would be
20 * appreciated but is not required.
21 * 2. Altered source versions must be plainly marked as such, and must not be
22 * misrepresented as being the original software.
23 * 3. This notice may not be removed or altered from any source distribution.
24 */
25
26/*
27 * TINYEXPR++ - Tiny recursive descent parser and evaluation engine in C++
28 *
29 * Copyright (c) 2020-2026 Blake Madden
30 *
31 * C++ version of the TinyExpr library.
32 *
33 * This software is provided 'as-is', without any express or implied
34 * warranty. In no event will the authors be held liable for any damages
35 * arising from the use of this software.
36 *
37 * Permission is granted to anyone to use this software for any purpose,
38 * including commercial applications, and to alter it and redistribute it
39 * freely, subject to the following restrictions:
40 *
41 * 1. The origin of this software must not be misrepresented; you must not
42 * claim that you wrote the original software. If you use this software
43 * in a product, an acknowledgement in the product documentation would be
44 * appreciated but is not required.
45 * 2. Altered source versions must be plainly marked as such, and must not be
46 * misrepresented as being the original software.
47 * 3. This notice may not be removed or altered from any source distribution.
48 */
49
50#ifndef TINYEXPR_PLUS_PLUS_H
51#define TINYEXPR_PLUS_PLUS_H
52
53#include <algorithm>
54#include <cassert>
55#include <cctype>
56#include <cfloat>
57#include <clocale>
58#include <cmath>
59#include <cstdint>
60#include <cstdio>
61#include <cstdlib>
62#include <cstring>
63#include <ctime>
64#include <functional>
65#include <initializer_list>
66#include <limits>
67#include <random>
68#include <set>
69#include <span>
70#include <stdexcept>
71#include <string>
72#include <string_view>
73#include <utility>
74#include <variant>
75#include <vector>
76#if __has_include(<bit>)
77#include <bit>
78#endif
79// type_traits to get n_args.
80#include <tuple>
81#include <type_traits>
82
87#define TINYEXPR_CPP_COPYRIGHT \
88 "TinyExpr: Copyright (c) 2015-2026 Lewis Van Winkle\n" \
89 "TinyExpr++: Copyright (c) 2020-2026 Blake Madden"
90
91class te_parser;
92
93#if defined(TE_RAND_SEED) && defined(TE_RAND_SEED_TIME)
94#error TE_RAND_SEED and TE_RAND_SEED_TIME compile options cannot be combined. Only one random number generator seeding method can be specified.
95#endif
96
97#if defined(TE_FLOAT) && defined(TE_LONG_DOUBLE)
98#error TE_FLOAT and TE_LONG_DOUBLE compile options cannot be combined. Only one data type can be specified.
99#endif
100
101/// @brief Define this to use @c float instead of @c double for the parser's
102/// data type.
103#ifdef TE_FLOAT
104/// @brief The parameter and return type for parser and its functions.
105using te_type = float;
106#elif defined(TE_LONG_DOUBLE)
107using te_type = long double;
108#else
109/// @brief The parameter and return type for parser and its functions.
110using te_type = double;
111#endif
112
113#if defined(TE_FLOAT) && defined(TE_BITWISE_OPERATORS)
114#error TE_FLOAT and TE_BITWISE_OPERATORS compile options cannot be combined. TE_FLOAT will not support bitwise operations.
115#endif
116
117/// @brief How deeply an expression may nest parentheses and function calls;
118/// anything deeper is a parse error, rather than a possible stack overflow.
119#ifndef TE_MAX_DEPTH
120#define TE_MAX_DEPTH 128
121#endif
122
123class te_expr;
124// clang-format off
125// regular functions
126using te_fun0 = te_type (*)();
151// context functions (where te_variable passes a client's te_expr as the first argument)
152using te_confun0 = te_type (*)(const te_expr*);
153using te_confun1 = te_type (*)(const te_expr*, te_type);
177// clang-format on
178
179/// @brief A function argument, either a number or a string literal.
180/// @note A `std::string_view` points into the parser's copy of the expression.
181/// Do not store it beyond the compiled expression's lifetime.
182using te_arg = std::variant<te_type, std::string_view>;
183
184/// @brief A function taking any number of number-or-string arguments.
185/// @note The parser does not check the argument count for these.
186/// Review `args.size()` and each argument's type, returning
187/// te_parser::te_nan if invalid.
188/// @warning The span is only valid for the duration of the call.
189using te_arg_fun = te_type (*)(std::span<const te_arg>);
190/// @brief Context version of te_arg_fun (te_variable passes a client's te_expr
191/// first).
192/// @warning The span is only valid for the duration of the call.
193using te_arg_confun = te_type (*)(const te_expr*, std::span<const te_arg>);
194
195template <typename FuncType>
197
198// Specialization for function pointers
199template <typename ReturnType, typename... Args>
200struct te_fun_traits<ReturnType (*)(Args...)> {
201 using arg_tuple = std::tuple<Args...>;
202 constexpr static size_t arity = std::tuple_size<arg_tuple>::value;
203};
204
205// Specialization for function types
206template <typename ReturnType, typename... Args>
207struct te_fun_traits<ReturnType(Args...)> {
208 using arg_tuple = std::tuple<Args...>;
209 constexpr static size_t arity = std::tuple_size<arg_tuple>::value;
210};
211
212// Helper variable template for easier access
213template <typename FuncType>
215
216template <typename T>
217constexpr bool te_is_constant_v = std::is_same_v<T, te_type>;
218
219template <typename T>
220constexpr bool te_is_variable_v = std::is_same_v<T, const te_type*>;
221
222template <typename FuncType>
224 constexpr static bool value{false};
225};
226
227// Specialization for function pointers
228template <typename ReturnType, typename... Args>
229struct te_is_closure<ReturnType (*)(const te_expr*, Args...)> {
230 constexpr static bool value{true};
231};
232
233// Specialization for function types
234template <typename ReturnType, typename... Args>
235struct te_is_closure<ReturnType(const te_expr*, Args...)> {
236 constexpr static bool value{true};
237};
238
239// te_arg_confun matches the above specializations, but is not a fixed-arity
240// closure.
241template <>
243 constexpr static bool value{false};
244};
245
246template <typename T>
248
249// A string literal from the formula.
250template <typename T>
251constexpr bool te_is_string_v = std::is_same_v<T, std::string_view>;
252
253template <typename T>
254constexpr bool te_is_arg_function_v = std::is_same_v<T, te_arg_fun>;
255
256template <typename T>
257constexpr bool te_is_arg_closure_v = std::is_same_v<T, te_arg_confun>;
258
259template <typename T>
260constexpr bool te_is_function_v =
263
264// functions for unknown symbol resolution
265using te_usr_noop = std::function<void()>;
266using te_usr_fun0 = std::function<te_type(std::string_view)>;
267using te_usr_fun1 = std::function<te_type(std::string_view, std::string&)>;
268
269using te_usr_variant_type = std::variant<te_usr_noop, te_usr_fun0, te_usr_fun1>;
270
271// do not change the ordering of these, the indices are used to determine
272// the value type of te_variable
273using te_variant_type = std::variant<
274 te_type, const te_type*, // indices 0-1
283 // string literals and the functions that accept them
284 te_arg_fun, te_arg_confun, std::string_view>;
285
286/// @brief A variable's flags, effecting how it is evaluated.
287/// @note This is a bitmask, so flags (TE_PURE and TE_VARIADIC) can be OR'ed.
288/// @internal Note that because this is a bitmask, don't declare it as an enum
289/// class,
290/// just a C-style enum.
292 /// @brief Don't do anything special when evaluating.
294 /// @brief Don't update when simple evaluation is run
295 /// (i.e., only updated when expression is compiled).
296 TE_PURE = (1 << 0),
297 /// @brief Function that can take 1-24 argument (unused arguments are set to
298 /// NaN).
299 TE_VARIADIC = (1 << 1)
300};
301
302/// @private
304 public:
305 [[nodiscard]]
306 bool operator()(const std::string& lhv, const std::string& rhv) const {
307 const auto minStrLen = std::min(lhv.length(), rhv.length());
308 for (size_t i = 0; i < minStrLen; ++i) {
309 const auto lhCh = tolower(lhv[i]);
310 const auto rhCh = tolower(rhv[i]);
311 if (lhCh == rhCh) {
312 continue;
313 }
314 return (lhCh < rhCh);
315 }
316 return (lhv.length() < rhv.length());
317 }
318
319 // We can assume that we are only dealing with a-z, A-Z, 0-9, ., or _,
320 // so use a branchless tolower.
321 [[nodiscard]]
322 constexpr static char tolower(const char chr) noexcept {
323 return chr + (32 * (chr >= 'A' && chr <= 'Z'));
324 }
325};
326
327/// @brief A compiled expression.
328/// @details Can also be an additional object that can be passed to
329/// te_confun0-te_confun24 functions via a te_variable.
330class te_expr {
331 public:
332 te_expr(const te_variable_flags type, const te_variant_type& value) noexcept
333 : m_type(type), m_value(value) {}
334
335 explicit te_expr(const te_variable_flags type) noexcept : m_type(type) {}
336
337 /// @private
338 te_expr() noexcept = default;
339
340 /// @private
341 te_expr(const te_expr&) = delete;
342 /// @private
343 te_expr& operator=(const te_expr&) = delete;
344
345 /// @private
346 virtual ~te_expr() = default;
347
348 /// @brief The type that m_value represents.
350 /// @brief The te_type constant, te_type pointer, or function to bind to.
351 te_variant_type m_value{static_cast<te_type>(0.0)};
352 /// @brief Additional parameters.
353 std::vector<te_expr*> m_parameters{nullptr};
354};
355
356/// @brief Custom variable or function that can be added to a te_parser.
358 public:
359 /// @private
360 using name_type = std::string;
361
362 /// @private
363 [[nodiscard]]
364 bool operator<(const te_variable& that) const {
365 return te_string_less{}(m_name, that.m_name);
366 }
367
368 /// @brief The name as it would appear in a formula.
370 /// @brief The te_type constant, te_type pointer, or function to bind the name
371 /// to.
373 /// @brief The type that m_value represents.
375 /// If @c m_value is a function pointer of type `te_confun0`-`te_confun24`,
376 /// then this is passed to that function when called. This is useful for
377 /// passing an object which manages additional data to your functions.
379};
380
381/// @brief Math formula parser.
383 public:
384 /// @private
385 te_parser() = default;
386
387 /// @private
388 // cppcheck-suppress uninitMemberVar
389 te_parser(const te_parser& that)
396 try {
397 if (!m_expression.empty()) {
398 [[maybe_unused]]
399 const auto retVal = evaluate(m_expression);
400 }
401 } catch (const std::exception& expt) {
402 m_parseSuccess = false;
404 m_lastErrorMessage = expt.what();
405 }
406 }
407
408 /// @private
416
417 // re-run the expression that was copied over
418 reset_state();
419
420 try {
421 if (!m_expression.empty()) {
422 [[maybe_unused]]
423 const auto retVal = evaluate(m_expression);
424 }
425 } catch (const std::exception& expt) {
426 m_parseSuccess = false;
428 m_lastErrorMessage = expt.what();
429 }
430
431 return *this;
432 }
433
434 /// @private
436
437 /// @brief NaN (not-a-number) constant to indicate an invalid value.
438 constexpr static auto te_nan = std::numeric_limits<te_type>::quiet_NaN();
439 /// @brief No position, which is what get_last_error_position() returns
440 /// when there was no parsing error.
441 constexpr static int64_t npos = -1;
442 /// @private
443 // (2^48)-1
444 constexpr static double MAX_BITOPS_VAL{281474976710655}; // NOLINT
445
446 /// @returns @c true if the parser's internal type can hold `uint32_t` without
447 /// truncation.
448 [[nodiscard]]
449 constexpr static bool supports_32bit() noexcept {
450 return std::numeric_limits<te_type>::digits >=
451 std::numeric_limits<uint32_t>::digits;
452 }
453
454 /// @returns @c true if the parser's internal type can hold `uint64_t` without
455 /// truncation.
456 [[nodiscard]]
457 constexpr static bool supports_64bit() noexcept {
458 return std::numeric_limits<te_type>::digits >=
459 std::numeric_limits<uint64_t>::digits;
460 }
461
462 /// @private
463 /// @returns @c true if @c val is too large to convert to a `uint32_t`.
464 [[nodiscard]]
465 constexpr static bool te_exceeds_uint32(te_type val) noexcept {
466 if constexpr (supports_32bit()) {
467 return val > static_cast<te_type>((std::numeric_limits<uint32_t>::max)());
468 } else {
469 // UINT32_MAX rounds up to 2^32 as a float, so the bound must be exclusive
470 return val >= static_cast<te_type>(uint64_t{1} << 32);
471 }
472 }
473
474 /// @returns The bits available in the internal data type.\n
475 /// This will affect the largest integer size that can be used in bitwise
476 /// operations.
477 [[nodiscard]]
478 constexpr static int get_max_integer_bitness() noexcept {
479 return std::numeric_limits<te_type>::digits;
480 }
481
482 /// @returns The largest integer value that the parser can handle without
483 /// truncation.
484 [[nodiscard]]
486#ifdef TE_FLOAT
487 const te_type maxBit =
488 std::ldexp(static_cast<te_type>(1), FLT_MANT_DIG - 1);
489#elif defined(TE_LONG_DOUBLE)
490 const te_type maxBit =
491 std::ldexp(static_cast<te_type>(1), LDBL_MANT_DIG - 1);
492#else
493 const te_type maxBit =
494 std::ldexp(static_cast<te_type>(1), DBL_MANT_DIG - 1);
495#endif
496 return maxBit + (maxBit - 1);
497 }
498
499 /** @brief Parses the input @c expression.
500 @param expression The formula to compile.
501 @returns Whether the expression compiled or not. (This can be checked
502 by calling success() afterward as well.)
503 @sa success().
504 @note Returns NaN if division or modulus by zero occurs.
505 @throws std::runtime_error Throws an exception in the case of arithmetic
506 overflows (e.g., `1 << 64` would cause an overflow).*/
507 bool compile(std::string_view expression);
508 /** @brief Evaluates expression passed to compile() previously and returns its
509 result.
510 @returns The result, or NaN on error.
511 @throws std::runtime_error Throws an exception in the case of arithmetic
512 overflows (e.g., `1 << 64` would cause an overflow).*/
513 [[nodiscard]]
515 /** @brief Compiles and evaluates an expression and returns its result.
516 @param expression The formula to compile and evaluate.
517 @returns The result, or NaN on error.
518 @note Returns NaN if division or modulus by zero occurs.
519 @throws std::runtime_error Throws an exception in the case of arithmetic
520 overflows (e.g., `1 << 64` would cause an overflow).*/
521 [[nodiscard]]
522 te_type evaluate(std::string_view expression);
523
524 /// @returns The last call to evaluate()'s result (which will be NaN on
525 /// error).
526 [[nodiscard]]
527 te_type get_result() const noexcept {
528 return m_result;
529 }
530
531 /// @private
532 [[nodiscard]]
533 te_type get_result() const volatile noexcept {
534 return m_result;
535 }
536
537 /// @returns Whether the last call to compile() was successful.
538 /// @sa get_last_error_position().
539 [[nodiscard]]
540 bool success() const noexcept {
541 return m_parseSuccess;
542 }
543
544 [[nodiscard]]
545 bool success() const volatile noexcept {
546 return m_parseSuccess;
547 }
548
549 /// @returns The zero-based index into the last parsed expression where the
550 /// parse failed,
551 /// or te_parser::npos if no error occurred.
552 /// @note Call success() to see if the last parse succeeded or not.
553 [[nodiscard]]
554 int64_t get_last_error_position() const noexcept {
555 return m_errorPos;
556 }
557
558 /// @private
559 [[nodiscard]]
560 int64_t get_last_error_position() const volatile noexcept {
561 return m_errorPos;
562 }
563
564 /// @returns Any error message from the last parse.
565 [[nodiscard]]
566 const std::string& get_last_error_message() const noexcept {
567 return m_lastErrorMessage;
568 }
569
570 /// @brief Sets the list of custom variables and functions.
571 /// @param vars The list of variables and functions.
572 /// @note Valid variable and function names must begin with a letter from a-z
573 /// (A-Z),
574 /// followed by additional English letters, numbers, periods, or
575 /// underscores.
576 /// @throws std::runtime_error Throws an exception if an illegal character is
577 /// found
578 /// in any variable name.
579 void set_variables_and_functions(std::set<te_variable> vars) {
580 for (const auto& var : vars) {
581 validate_name(var);
582 }
583 m_customFuncsAndVars = std::move(vars);
584 }
585
586 /// @brief Adds a custom variable or function.
587 /// @param var The variable/function to add.
588 /// @note Prefer using set_variables_and_functions() as it will be more
589 /// optimal
590 /// (fewer sorts will need to be performed).
591 /// @throws std::runtime_error Throws an exception if an illegal character is
592 /// found
593 /// in the variable name.
595 validate_name(var);
596 m_customFuncsAndVars.insert(std::move(var));
597 }
598
599 /// @brief Removes a custom variable or function.
600 /// @param var The variable/function to remove (by name).
602 const auto foundVar = m_customFuncsAndVars.find(te_variable{
603 std::move(var), static_cast<te_type>(0.0), TE_DEFAULT, nullptr});
604 if (foundVar != m_customFuncsAndVars.cend()) {
605 m_customFuncsAndVars.erase(foundVar);
606 }
607 }
608
609#ifndef TE_NO_BOOKKEEPING
610 /// @brief Removes any custom variables and functions that weren't used in the
611 /// last compilation.
612 /// @details This can be useful if the parser is preloaded with a large number
613 /// of
614 /// variables and functions that needs to be pruned after the first
615 /// expression is parsed.
616 /// @warning After calling this, any custom variables and functions that
617 /// weren't found
618 /// in the previously parsed expression will no longer be available.
620 for (auto funcIter = m_customFuncsAndVars.cbegin();
621 funcIter != m_customFuncsAndVars.cend();
622 /* in loop*/) {
623 funcIter = (is_function_used(funcIter->m_name) ||
624 is_variable_used(funcIter->m_name))
625 ? ++funcIter
626 : m_customFuncsAndVars.erase(funcIter);
627 }
628 }
629#endif
630
631 /** @brief Sets a custom function to resolve unknown symbols in an expression.
632 @param usr The function to use to resolve unknown symbols.
633 @param keepResolvedVariables @c true to cache any resolved variables into
634 the parser. This means that they will not need to be resolved again on
635 subsequent calls to evaluate().\n Pass @c false to this if you wish to
636 re-resolve any previously resolved variables on later evaluations. This can
637 be useful for when a resolved variable's value is volatile and needs to be
638 re-resolved on every use.*/
640 const bool keepResolvedVariables = true) {
641 m_unknownSymbolResolve = std::move(usr);
642 m_keepResolvedVariables = keepResolvedVariables;
643 }
644
645 /// @private
646 [[nodiscard]]
647 const std::set<te_variable>& get_variables_and_functions() const noexcept {
649 }
650
651 /// @returns The list of custom variables and functions.
652 [[nodiscard]]
653 std::set<te_variable>& get_variables_and_functions() noexcept {
655 }
656
657 /// @returns The decimal separator used for numbers.
658 [[nodiscard]]
659 char get_decimal_separator() const noexcept {
660 return m_decimalSeparator;
661 }
662
663 /// @private
664 [[nodiscard]]
665 char get_decimal_separator() const volatile noexcept {
666 return m_decimalSeparator;
667 }
668
669 /// @brief Sets the decimal separator used for numbers.
670 /// @param sep The decimal separator.
671 /// @throws std::runtime_error Throws an exception if an illegal character is
672 /// used.
673 void set_decimal_separator(const char sep) {
674 if (sep != ',' && sep != '.') {
675 throw std::runtime_error(
676 "Decimal separator must be either a '.' or ','.");
677 }
678 m_decimalSeparator = sep;
679 }
680
681 /// @private
682 void set_decimal_separator(const char sep) volatile {
683 if (sep != ',' && sep != '.') {
684 throw std::runtime_error(
685 "Decimal separator must be either a '.' or ','.");
686 }
687 m_decimalSeparator = sep;
688 }
689
690 /// @brief Sets a constant variable's value.
691 /// @param name The name of the (constant) variable.
692 /// @param value The new value to set the constant to.
693 /// @note If the constant variable hasn't been added yet (via
694 /// set_variables_and_functions()),
695 /// then this will add it.\n
696 /// If a variable with the provided name is found but is not a constant,
697 /// then this will be ignored.
698 void set_constant(const std::string_view name, const te_type value) {
699 auto cvar = find_variable_or_function(name);
700 if (cvar == get_variables_and_functions().end()) {
702 } else if (is_constant(cvar->m_value)) {
703 auto nh = get_variables_and_functions().extract(cvar);
704 nh.value().m_value = value;
705 get_variables_and_functions().insert(std::move(nh));
706 // if previously compiled, then re-compile since this
707 // constant would have been optimized
708 if (!m_expression.empty()) {
710 }
711 }
712 }
713
714 /// @brief Retrieves a constant variable's value.
715 /// @param name The name of the (constant) variable.
716 /// @returns The value of the constant variable if found, NaN otherwise.
717 [[nodiscard]]
718 te_type get_constant(const std::string_view name) const {
719 auto cvar = find_variable_or_function(name);
720 if (cvar == get_variables_and_functions().cend() ||
721 !is_constant(cvar->m_value)) {
722 return te_nan;
723 }
724 if (const auto* const val = std::get_if<te_type>(&cvar->m_value);
725 val != nullptr) {
726 return *val;
727 }
728
729 return te_nan;
730 }
731
732 /// @returns The separator used between function arguments.
733 [[nodiscard]]
734 char get_list_separator() const noexcept {
735 return m_listSeparator;
736 }
737
738 /// @private
739 [[nodiscard]]
740 char get_list_separator() const volatile noexcept {
741 return m_listSeparator;
742 }
743
744 /// @brief Sets the separator used between function arguments.
745 /// @param sep The list separator.
746 /// @throws std::runtime_error Throws an exception if an illegal character is
747 /// used.
748 void set_list_separator(const char sep) {
749 if (sep != ',' && sep != ';') {
750 throw std::runtime_error("List separator must be either a ',' or ';'.");
751 }
752 m_listSeparator = sep;
753 }
754
755 /// @private
756 void set_list_separator(const char sep) volatile {
757 if (sep != ',' && sep != ';') {
758 throw std::runtime_error("List separator must be either a ',' or ';'.");
759 }
760 m_listSeparator = sep;
761 }
762#ifndef TE_NO_BOOKKEEPING
763 /// @returns @c true if @c name is a function that had been used in the last
764 /// parsed formula.
765 /// @param name The name of the function.
766 /// @sa compile() and evaluate().
767 [[nodiscard]]
768 bool is_function_used(const std::string_view name) const {
769 return m_usedFunctions.contains(te_variable::name_type{name});
770 }
771
772 /// @returns @c true if @c name is a variable that had been used in the last
773 /// parsed formula.
774 /// @param name The name of the variable.
775 /// @sa compile() and evaluate().
776 [[nodiscard]]
777 bool is_variable_used(const std::string_view name) const {
778 return m_usedVars.contains(te_variable::name_type{name});
779 }
780#endif
781 /// @returns A report of all available functions and variables.
782 [[nodiscard]]
784
785 /// @returns The last formula passed to the parser.
786 /// @note Comments will be stripped from the original expression.
787 [[nodiscard]]
788 const std::string& get_expression() const noexcept {
789 return m_expression;
790 }
791
792 /// @brief Helper function to convert a number into boolean.
793 /// @details This takes NaN into account, returning @c for NaN.
794 /// @param val The value to examine.
795 /// @returns @c true if the value is non-zero and also valid
796 /// (not NaN or infinite).
797 /// @private
798 [[nodiscard]]
799 static bool number_to_bool(te_type val) {
800 return std::isfinite(val) ? static_cast<bool>(val) : false;
801 }
802
803 /// @returns Information about how the parser is configured, its capabilities,
804 /// etc.
805 [[nodiscard]]
806 static std::string info();
807
808 private:
809 /// Reset everything from previous call.
810 void reset_state() {
812 m_lastErrorMessage.clear();
814 m_parseSuccess = false;
816 m_compiledExpression = nullptr;
817 m_currentVar = m_functions.cend();
818 m_varFound = false;
819#ifndef TE_NO_BOOKKEEPING
820 m_usedFunctions.clear();
821 m_usedVars.clear();
822#endif
823 m_resolvedVariables.clear();
824 }
825
826 /// @brief Resets any resolved variables from USR if not being cached.
829 for (const auto& resolvedVar : m_resolvedVariables) {
830 remove_variable_or_function(resolvedVar);
831 }
832 m_resolvedVariables.clear();
833 }
834 }
835
836 /// @brief Gets the compiled expression, which will be the optimized version
837 /// of the original expression.
838 /// @returns The compiled expression.
839 [[nodiscard]]
840 const te_expr* get_compiled_expression() const noexcept {
842 }
843
844 /// @private
845 [[nodiscard]]
846 const te_expr* get_compiled_expression() const volatile noexcept {
848 }
849
850 /// @brief Validates that a variable only contains legal characters
851 /// (and has a valid length).
852 /// @param var The variable to validate.
853 /// @throws std::runtime_error Throws an exception if an illegal character is
854 /// found.
855 static void validate_name(const te_variable& var) {
856 if (var.m_name.empty()) {
857 throw std::runtime_error("Variable name is empty.");
858 }
859 if (!is_letter(var.m_name[0]) && var.m_name[0] != '_') {
860 throw std::runtime_error(
861 std::string(
862 "Variable name must begin with a letter from a-z or _: ") +
863 var.m_name);
864 }
865 const auto varCharPos = std::find_if(
866 var.m_name.cbegin(), var.m_name.cend(),
867 [](const auto chr) noexcept { return !is_name_char_valid(chr); });
868 if (varCharPos != var.m_name.cend()) {
869 throw std::runtime_error(
870 std::string("Invalid character in variable name: ") + var.m_name);
871 }
872 }
873
874 /// @returns @c true if character is valid for a function or variable name.
875 /// @param chr The character to review.
876 [[nodiscard]]
877 constexpr static bool is_name_char_valid(const char chr) noexcept {
878 return (is_letter(chr) || (chr >= '0' && chr <= '9') || (chr == '_') ||
879 (chr == '.'));
880 }
881
882 /// @returns The position of @p chr at or after @p startIndex, skipping quoted
883 /// string
884 /// literals, or `std::string::npos` if not found.
885 /// @param str The string to search.
886 /// @param chr The character to search for.
887 /// @param startIndex Where to begin accepting matches.
888 /// @note Quote state is tracked from the start of @p str, so this stays
889 /// correct
890 /// after the caller has erased earlier sections.
891 [[nodiscard]]
892 static size_t find_outside_of_string(const std::string& str, const char chr,
893 const size_t startIndex) {
894 bool inString{false};
895 for (size_t i = 0; i < str.length(); ++i) {
896 if (str[i] == '"') {
897 inString = !inString;
898 } else if (!inString && str[i] == chr && i >= startIndex) {
899 return i;
900 }
901 }
902 return std::string::npos;
903 }
904
905 /// @returns An iterator to the custom variable or function with the given @c
906 /// name,
907 /// or end of get_variables_and_functions() if not found.
908 /// @param name The name of the function or variable to search for.
909 [[nodiscard]]
910 std::set<te_variable>::iterator find_variable_or_function(
911 const std::string_view name) {
912 if (name.empty()) {
913 return m_customFuncsAndVars.end();
914 }
915
917 static_cast<te_type>(0.0),
918 TE_DEFAULT, nullptr});
919 }
920
921 /// @returns An iterator to the custom variable or function with the given @c
922 /// name,
923 /// or end of get_variables_and_functions() if not found.
924 /// @param name The name of the function or variable to search for.
925 [[nodiscard]]
926 std::set<te_variable>::const_iterator find_variable_or_function(
927 const std::string_view name) const {
928 if (name.empty()) {
929 return m_customFuncsAndVars.cend();
930 }
931
933 static_cast<te_type>(0.0),
934 TE_DEFAULT, nullptr});
935 }
936
937 [[nodiscard]]
938 constexpr static auto is_pure(const te_variable_flags type) {
939 return (((type)&TE_PURE) != 0);
940 }
941
942 [[nodiscard]]
943 constexpr static auto is_variadic(const te_variable_flags type) {
944 return (((type)&TE_VARIADIC) != 0);
945 }
946
947 /// @returns Number of parameters that a function/variable takes.
948 [[nodiscard]]
949 static auto get_arity(const te_variant_type& var) {
950 return std::visit(
951 [](const auto& var0) -> size_t {
952 using T = std::decay_t<decltype(var0)>;
953 // te_arg_fun/te_arg_confun have no fixed arity, so base() sizes them
954 if constexpr (te_is_constant_v<T> || te_is_variable_v<T> ||
957 return 0;
958 } else if constexpr (te_is_closure_v<T>) {
959 return te_function_arity<T> - 1; // minus the first ctx variable.
960 } else { // te_is_function_v
962 }
963 },
964 var);
965 }
966
967 [[nodiscard]]
968 constexpr static bool is_constant(const te_variant_type& var) noexcept {
969 return var.index() == 0;
970 }
971
972 [[nodiscard]]
973 constexpr static te_type get_constant_value(const te_variant_type& var) {
974 assert(std::holds_alternative<te_type>(var));
975 return std::get<0>(var);
976 }
977
978 [[nodiscard]]
979 constexpr static bool is_variable(const te_variant_type& var) noexcept {
980 return var.index() == 1;
981 }
982
983 [[nodiscard]]
984 constexpr static const te_type* get_variable(const te_variant_type& var) {
985 assert(std::holds_alternative<const te_type*>(var));
986 return std::get<1>(var);
987 }
988
989 [[nodiscard]]
990 constexpr static bool is_function(const te_variant_type& var) {
991 return std::visit(
992 [](const auto& var0) -> bool {
993 using T = std::decay_t<decltype(var0)>;
994 return te_is_function_v<T>;
995 },
996 var);
997 }
998
999 [[nodiscard]]
1000 constexpr static bool is_string(const te_variant_type& var) noexcept {
1001 return std::holds_alternative<std::string_view>(var);
1002 }
1003
1004 [[nodiscard]]
1005 constexpr static std::string_view get_string(const te_variant_type& var) {
1006 assert(std::holds_alternative<std::string_view>(var));
1007 return std::get<std::string_view>(var);
1008 }
1009
1010 [[nodiscard]]
1011 constexpr static bool is_arg_function(const te_variant_type& var) noexcept {
1012 return std::holds_alternative<te_arg_fun>(var);
1013 }
1014
1015 [[nodiscard]]
1016 constexpr static bool is_arg_closure(const te_variant_type& var) noexcept {
1017 return std::holds_alternative<te_arg_confun>(var);
1018 }
1019
1020#define TE_DEF_FUNCTION(n) \
1021 [[nodiscard]] \
1022 constexpr static bool is_function##n(const te_variant_type& var) noexcept { \
1023 return std::holds_alternative<te_fun##n>(var); \
1024 } \
1025 [[nodiscard]] \
1026 constexpr static te_fun##n get_function##n(const te_variant_type& var) { \
1027 assert(std::holds_alternative<te_fun##n>(var)); \
1028 return std::get<te_fun##n>(var); \
1029 }
1033#undef TE_DEF_FUNCTION
1034
1035 [[nodiscard]]
1036 constexpr static bool is_closure(const te_variant_type& var) {
1037 return std::visit(
1038 [](const auto& var0) -> bool {
1039 using T = std::decay_t<decltype(var0)>;
1041 },
1042 var);
1043 }
1044
1045#define TE_DEF_CLOSURE(n) \
1046 [[nodiscard]] \
1047 constexpr static bool is_closure##n(const te_variant_type& var) noexcept { \
1048 return std::holds_alternative<te_confun##n>(var); \
1049 } \
1050 [[nodiscard]] \
1051 constexpr static te_confun##n get_closure##n(const te_variant_type& var) { \
1052 assert(std::holds_alternative<te_confun##n>(var)); \
1053 return std::get<te_confun##n>(var); \
1054 }
1058#undef TE_DEF_CLOSURE
1059
1060 /// @returns @c true for any function, including the ones taking te_arg.
1061 [[nodiscard]]
1062 constexpr static bool is_any_function(const te_variant_type& var) {
1063 return is_function(var) || is_arg_function(var);
1064 }
1065
1066 /// @returns @c true for any context function, including the ones taking
1067 /// te_arg.
1068 [[nodiscard]]
1069 constexpr static bool is_any_closure(const te_variant_type& var) {
1070 return is_closure(var) || is_arg_closure(var);
1071 }
1072
1073 /// @returns A node's real argument count, excluding a closure's context slot.
1074 /// @note Use this instead of get_arity() for te_arg_fun/te_arg_confun nodes,
1075 /// whose arity is only known once base() has parsed them.
1076 [[nodiscard]]
1077 static size_t get_parameter_count(const te_expr* texp) {
1078 assert(texp != nullptr);
1079 const auto ctxSlot = is_any_closure(texp->m_value) ? 1U : 0U;
1080 return (texp->m_parameters.size() > ctxSlot)
1081 ? texp->m_parameters.size() - ctxSlot
1082 : 0;
1083 }
1084
1085 struct state {
1100
1101 state(const char* expression, te_variable_flags varType,
1102 std::set<te_variable>& vars)
1103 : m_start(expression),
1104 m_next(expression),
1105 m_varType(varType),
1106 m_lookup(vars) {}
1107
1108 const char* m_start{nullptr};
1109 const char* m_next{nullptr};
1113 te_expr* context{nullptr};
1114 // whether the last power() wrote a unary itself
1115 // (separates "-1" from "(-1)")
1116 bool m_appliedUnary{false};
1117 // how many base() calls are currently on the stack
1118 size_t m_depth{0};
1119
1120 std::set<te_variable>& m_lookup;
1121 };
1122
1123 [[nodiscard]]
1125 const std::initializer_list<te_expr*>& parameters) {
1126 auto* ret = new te_expr{type, value};
1127 ret->m_parameters.resize(std::max<size_t>(
1128 std::max<size_t>(parameters.size(), get_arity(ret->m_value)) +
1129 (is_closure(ret->m_value) ? 1 : 0),
1130 0));
1131 if (parameters.size() != 0U) {
1132 std::ranges::copy(parameters, ret->m_parameters.begin());
1133 }
1134 return ret;
1135 }
1136
1137 [[nodiscard]]
1139 te_variant_type value) {
1140 auto* ret = new te_expr{type, value};
1141 ret->m_parameters.resize(static_cast<size_t>(get_arity(ret->m_value)) +
1142 (is_closure(ret->m_value) ? 1 : 0));
1143 return ret;
1144 }
1145
1146 [[nodiscard]]
1147 constexpr static bool is_letter(const char chr) noexcept {
1148 return (chr >= 'a' && chr <= 'z') || (chr >= 'A' && chr <= 'Z');
1149 }
1150
1151 /** @brief Parses the input expression and binds variables.
1152 @param expression The formula to parse.
1153 @param variables The collection of custom functions and
1154 variables to add to the parser.
1155 @returns null on error.*/
1156 [[nodiscard]]
1157 te_expr* te_compile(std::string_view expression,
1158 std::set<te_variable>& variables);
1159 /* Evaluates the expression. */
1160 [[nodiscard]]
1161 static te_type te_eval(const te_expr* texp);
1162
1163 /* Frees the expression. */
1164 /* This is safe to call on null pointers. */
1165 static void te_free(te_expr* texp) {
1166 if (texp == nullptr) {
1167 return;
1168 }
1169 te_free_parameters(texp);
1170 delete texp;
1171 }
1172
1173 static void te_free_parameters(te_expr* texp);
1174 static void optimize(te_expr* texp);
1175
1176 [[nodiscard]]
1177 static auto find_builtin(const std::string_view name) {
1179 static_cast<te_type>(0.0), TE_DEFAULT,
1180 nullptr});
1181 }
1182
1183 [[nodiscard]]
1184 static auto find_lookup(state* ste, const std::string_view name) {
1185 return ste->m_lookup.find(te_variable{te_variable::name_type{name},
1186 static_cast<te_type>(0.0), TE_DEFAULT,
1187 nullptr});
1188 }
1189
1190 void next_token(state* theState);
1191 // depth-limited wrapper around base_impl()
1192 [[nodiscard]]
1193 te_expr* base(state* theState);
1194 [[nodiscard]]
1196 [[nodiscard]]
1197 te_expr* power(state* theState);
1198 [[nodiscard]]
1199 te_expr* factor(state* theState);
1200 [[nodiscard]]
1201 te_expr* term(state* theState);
1202 [[nodiscard]]
1204 [[nodiscard]]
1206 [[nodiscard]]
1208 [[nodiscard]]
1210 [[nodiscard]]
1212 [[nodiscard]]
1214 [[nodiscard]]
1216 [[nodiscard]]
1218 [[nodiscard]]
1220 [[nodiscard]]
1221 te_expr* list(state* theState);
1222
1223 // built-in functions
1224 static const std::set<te_variable> m_functions;
1225
1226 // customizable settings
1227 std::set<te_variable> m_customFuncsAndVars;
1228
1230
1232
1235
1236 // state information
1237 std::string m_expression;
1239
1240 bool m_parseSuccess{false};
1241 int64_t m_errorPos{0};
1244
1245 std::set<te_variable::name_type> m_resolvedVariables;
1246
1247 std::set<te_variable>::const_iterator m_currentVar;
1248 bool m_varFound{false};
1249#ifndef TE_NO_BOOKKEEPING
1250 std::set<te_variable::name_type, te_string_less> m_usedFunctions;
1251 std::set<te_variable::name_type, te_string_less> m_usedVars;
1252#endif
1253};
1254
1255#endif // TINYEXPR_PLUS_PLUS_H
A compiled expression.
Definition tinyexpr.h:330
std::vector< te_expr * > m_parameters
Additional parameters.
Definition tinyexpr.h:353
te_expr(const te_variable_flags type) noexcept
Definition tinyexpr.h:335
te_variable_flags m_type
The type that m_value represents.
Definition tinyexpr.h:349
te_expr(const te_variable_flags type, const te_variant_type &value) noexcept
Definition tinyexpr.h:332
te_expr() noexcept=default
te_variant_type m_value
The te_type constant, te_type pointer, or function to bind to.
Definition tinyexpr.h:351
Math formula parser.
Definition tinyexpr.h:382
te_type get_constant(const std::string_view name) const
Retrieves a constant variable's value.
Definition tinyexpr.h:718
char m_listSeparator
Definition tinyexpr.h:1234
const std::set< te_variable > & get_variables_and_functions() const noexcept
Definition tinyexpr.h:647
TE_DEF_FUNCTION(0)
te_expr * m_compiledExpression
Definition tinyexpr.h:1238
te_expr * expr_level1(state *theState)
te_expr * power(state *theState)
static void optimize(te_expr *texp)
te_expr * expr_level8(state *theState)
static const std::set< te_variable > m_functions
Definition tinyexpr.h:1224
static constexpr bool is_variable(const te_variant_type &var) noexcept
Definition tinyexpr.h:979
static constexpr bool is_letter(const char chr) noexcept
Definition tinyexpr.h:1147
te_parser(const te_parser &that)
Definition tinyexpr.h:389
TE_DEF_CLOSURE(2)
static te_type get_max_integer()
Definition tinyexpr.h:485
std::set< te_variable > m_customFuncsAndVars
Definition tinyexpr.h:1227
static constexpr te_type get_constant_value(const te_variant_type &var)
Definition tinyexpr.h:973
std::set< te_variable::name_type > m_resolvedVariables
Definition tinyexpr.h:1245
char get_decimal_separator() const volatile noexcept
Definition tinyexpr.h:665
static size_t get_parameter_count(const te_expr *texp)
Definition tinyexpr.h:1077
static constexpr std::string_view get_string(const te_variant_type &var)
Definition tinyexpr.h:1005
void set_unknown_symbol_resolver(te_usr_variant_type usr, const bool keepResolvedVariables=true)
Sets a custom function to resolve unknown symbols in an expression.
Definition tinyexpr.h:639
std::set< te_variable::name_type, te_string_less > m_usedVars
Definition tinyexpr.h:1251
std::set< te_variable::name_type, te_string_less > m_usedFunctions
Definition tinyexpr.h:1250
std::set< te_variable > & get_variables_and_functions() noexcept
Definition tinyexpr.h:653
void set_list_separator(const char sep)
Sets the separator used between function arguments.
Definition tinyexpr.h:748
static auto find_lookup(state *ste, const std::string_view name)
Definition tinyexpr.h:1184
static constexpr bool is_name_char_valid(const char chr) noexcept
Definition tinyexpr.h:877
te_type evaluate(std::string_view expression)
Compiles and evaluates an expression and returns its result.
static constexpr bool is_string(const te_variant_type &var) noexcept
Definition tinyexpr.h:1000
TE_DEF_FUNCTION(1)
const te_expr * get_compiled_expression() const volatile noexcept
Definition tinyexpr.h:846
bool success() const noexcept
Definition tinyexpr.h:540
std::set< te_variable >::iterator find_variable_or_function(const std::string_view name)
Definition tinyexpr.h:910
te_usr_variant_type m_unknownSymbolResolve
Definition tinyexpr.h:1229
static constexpr bool is_function(const te_variant_type &var)
Definition tinyexpr.h:990
bool m_parseSuccess
Definition tinyexpr.h:1240
te_expr * expr_level2(state *theState)
static constexpr bool is_arg_function(const te_variant_type &var) noexcept
Definition tinyexpr.h:1011
static size_t find_outside_of_string(const std::string &str, const char chr, const size_t startIndex)
Definition tinyexpr.h:892
void reset_usr_resolved_if_necessary()
Resets any resolved variables from USR if not being cached.
Definition tinyexpr.h:827
bool is_variable_used(const std::string_view name) const
Definition tinyexpr.h:777
const te_expr * get_compiled_expression() const noexcept
Gets the compiled expression, which will be the optimized version of the original expression.
Definition tinyexpr.h:840
bool success() const volatile noexcept
Definition tinyexpr.h:545
te_expr * te_compile(std::string_view expression, std::set< te_variable > &variables)
Parses the input expression and binds variables.
TE_DEF_CLOSURE(1)
te_type m_result
Definition tinyexpr.h:1243
std::string list_available_functions_and_variables()
te_type evaluate()
Evaluates expression passed to compile() previously and returns its result.
void reset_state()
Reset everything from previous call.
Definition tinyexpr.h:810
std::set< te_variable >::const_iterator find_variable_or_function(const std::string_view name) const
Definition tinyexpr.h:926
std::string m_lastErrorMessage
Definition tinyexpr.h:1242
void add_variable_or_function(te_variable var)
Adds a custom variable or function.
Definition tinyexpr.h:594
void remove_unused_variables_and_functions()
Removes any custom variables and functions that weren't used in the last compilation.
Definition tinyexpr.h:619
void set_variables_and_functions(std::set< te_variable > vars)
Sets the list of custom variables and functions.
Definition tinyexpr.h:579
static constexpr bool supports_32bit() noexcept
Definition tinyexpr.h:449
te_expr * expr_level3(state *theState)
static constexpr bool is_closure(const te_variant_type &var)
Definition tinyexpr.h:1036
bool m_varFound
Definition tinyexpr.h:1248
char m_decimalSeparator
Definition tinyexpr.h:1233
te_expr * factor(state *theState)
static constexpr bool is_any_closure(const te_variant_type &var)
Definition tinyexpr.h:1069
std::string m_expression
Definition tinyexpr.h:1237
te_expr * expr_level7(state *theState)
static constexpr double MAX_BITOPS_VAL
Definition tinyexpr.h:444
te_expr * expr_level6(state *theState)
static constexpr bool is_any_function(const te_variant_type &var)
Definition tinyexpr.h:1062
static void te_free_parameters(te_expr *texp)
static te_type te_eval(const te_expr *texp)
static auto get_arity(const te_variant_type &var)
Definition tinyexpr.h:949
TE_DEF_CLOSURE(0)
static bool number_to_bool(te_type val)
Helper function to convert a number into boolean.
Definition tinyexpr.h:799
bool m_keepResolvedVariables
Definition tinyexpr.h:1231
static te_expr * new_expr(const te_variable_flags type, te_variant_type value)
Definition tinyexpr.h:1138
int64_t get_last_error_position() const volatile noexcept
Definition tinyexpr.h:560
static constexpr auto is_variadic(const te_variable_flags type)
Definition tinyexpr.h:943
char get_list_separator() const volatile noexcept
Definition tinyexpr.h:740
static std::string info()
static constexpr bool te_exceeds_uint32(te_type val) noexcept
Definition tinyexpr.h:465
static auto find_builtin(const std::string_view name)
Definition tinyexpr.h:1177
static te_expr * new_expr(const te_variable_flags type, te_variant_type value, const std::initializer_list< te_expr * > &parameters)
Definition tinyexpr.h:1124
const std::string & get_last_error_message() const noexcept
Definition tinyexpr.h:566
void next_token(state *theState)
te_expr * base(state *theState)
static constexpr const te_type * get_variable(const te_variant_type &var)
Definition tinyexpr.h:984
te_parser & operator=(const te_parser &that)
Definition tinyexpr.h:409
static constexpr bool supports_64bit() noexcept
Definition tinyexpr.h:457
bool compile(std::string_view expression)
Parses the input expression.
static constexpr bool is_arg_closure(const te_variant_type &var) noexcept
Definition tinyexpr.h:1016
static constexpr int get_max_integer_bitness() noexcept
Definition tinyexpr.h:478
static void validate_name(const te_variable &var)
Validates that a variable only contains legal characters (and has a valid length).
Definition tinyexpr.h:855
te_expr * expr_level5(state *theState)
bool is_function_used(const std::string_view name) const
Definition tinyexpr.h:768
void set_list_separator(const char sep) volatile
Definition tinyexpr.h:756
void set_decimal_separator(const char sep)
Sets the decimal separator used for numbers.
Definition tinyexpr.h:673
TE_DEF_FUNCTION(2)
te_expr * list(state *theState)
te_type get_result() const volatile noexcept
Definition tinyexpr.h:533
te_expr * base_impl(state *theState)
static constexpr auto te_nan
NaN (not-a-number) constant to indicate an invalid value.
Definition tinyexpr.h:438
void set_decimal_separator(const char sep) volatile
Definition tinyexpr.h:682
static constexpr auto is_pure(const te_variable_flags type)
Definition tinyexpr.h:938
te_expr * term(state *theState)
static constexpr bool is_constant(const te_variant_type &var) noexcept
Definition tinyexpr.h:968
char get_decimal_separator() const noexcept
Definition tinyexpr.h:659
void remove_variable_or_function(te_variable::name_type var)
Removes a custom variable or function.
Definition tinyexpr.h:601
te_expr * expr_level9(state *theState)
int64_t get_last_error_position() const noexcept
Definition tinyexpr.h:554
std::set< te_variable >::const_iterator m_currentVar
Definition tinyexpr.h:1247
char get_list_separator() const noexcept
Definition tinyexpr.h:734
static constexpr int64_t npos
No position, which is what get_last_error_position() returns when there was no parsing error.
Definition tinyexpr.h:441
te_expr * expr_level4(state *theState)
te_type get_result() const noexcept
Definition tinyexpr.h:527
void set_constant(const std::string_view name, const te_type value)
Sets a constant variable's value.
Definition tinyexpr.h:698
te_parser()=default
int64_t m_errorPos
Definition tinyexpr.h:1241
const std::string & get_expression() const noexcept
Definition tinyexpr.h:788
static void te_free(te_expr *texp)
Definition tinyexpr.h:1165
bool operator()(const std::string &lhv, const std::string &rhv) const
Definition tinyexpr.h:306
static constexpr char tolower(const char chr) noexcept
Definition tinyexpr.h:322
Custom variable or function that can be added to a te_parser.
Definition tinyexpr.h:357
bool operator<(const te_variable &that) const
Definition tinyexpr.h:364
te_variable_flags m_type
The type that m_value represents.
Definition tinyexpr.h:374
name_type m_name
The name as it would appear in a formula.
Definition tinyexpr.h:369
te_variant_type m_value
The te_type constant, te_type pointer, or function to bind the name to.
Definition tinyexpr.h:372
te_expr * m_context
Definition tinyexpr.h:378
std::string name_type
Definition tinyexpr.h:360
std::tuple< Args... > arg_tuple
Definition tinyexpr.h:208
static constexpr size_t arity
Definition tinyexpr.h:209
static constexpr size_t arity
Definition tinyexpr.h:202
std::tuple< Args... > arg_tuple
Definition tinyexpr.h:201
static constexpr bool value
Definition tinyexpr.h:243
static constexpr bool value
Definition tinyexpr.h:224
const char * m_start
Definition tinyexpr.h:1108
te_expr * context
Definition tinyexpr.h:1113
const char * m_next
Definition tinyexpr.h:1109
te_variable_flags m_varType
Definition tinyexpr.h:1111
std::set< te_variable > & m_lookup
Definition tinyexpr.h:1120
token_type m_type
Definition tinyexpr.h:1110
state(const char *expression, te_variable_flags varType, std::set< te_variable > &vars)
Definition tinyexpr.h:1101
te_variant_type m_value
Definition tinyexpr.h:1112
te_type(*)(const te_expr *, te_type) te_confun1
Definition tinyexpr.h:153
te_type(*)(const te_expr *, te_type, te_type, te_type) te_confun3
Definition tinyexpr.h:155
te_type(*)(const te_expr *, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type) te_confun10
Definition tinyexpr.h:162
te_type(*)(const te_expr *, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type) te_confun9
Definition tinyexpr.h:161
std::variant< te_type, std::string_view > te_arg
A function argument, either a number or a string literal.
Definition tinyexpr.h:182
te_type(*)(te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type) te_fun20
Definition tinyexpr.h:146
te_type(*)(te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type) te_fun23
Definition tinyexpr.h:149
float te_type
Define this to use float instead of double for the parser's data type.
Definition tinyexpr.h:105
te_type(*)(te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type) te_fun21
Definition tinyexpr.h:147
te_type(*)(const te_expr *, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type) te_confun18
Definition tinyexpr.h:170
std::variant< te_usr_noop, te_usr_fun0, te_usr_fun1 > te_usr_variant_type
Definition tinyexpr.h:269
te_type(*)(const te_expr *, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type) te_confun12
Definition tinyexpr.h:164
te_type(*)(const te_expr *, te_type, te_type, te_type, te_type, te_type) te_confun5
Definition tinyexpr.h:157
te_type(*)(const te_expr *, std::span< const te_arg >) te_arg_confun
Context version of te_arg_fun (te_variable passes a client's te_expr first).
Definition tinyexpr.h:193
te_type(*)(const te_expr *, te_type, te_type, te_type, te_type) te_confun4
Definition tinyexpr.h:156
constexpr int TINYEXPR_CPP_TWEAK_VERSION
Definition tinyexpr.h:86
te_type(*)(std::span< const te_arg >) te_arg_fun
A function taking any number of number-or-string arguments.
Definition tinyexpr.h:189
constexpr int TINYEXPR_CPP_MINOR_VERSION
Definition tinyexpr.h:84
te_type(*)(te_type, te_type, te_type, te_type, te_type, te_type, te_type) te_fun7
Definition tinyexpr.h:133
constexpr bool te_is_function_v
Definition tinyexpr.h:260
constexpr bool te_is_arg_function_v
Definition tinyexpr.h:254
te_variable_flags
A variable's flags, effecting how it is evaluated.
Definition tinyexpr.h:291
@ TE_VARIADIC
Function that can take 1-24 argument (unused arguments are set to NaN).
Definition tinyexpr.h:299
@ TE_PURE
Don't update when simple evaluation is run (i.e., only updated when expression is compiled).
Definition tinyexpr.h:296
@ TE_DEFAULT
Don't do anything special when evaluating.
Definition tinyexpr.h:293
constexpr bool te_is_string_v
Definition tinyexpr.h:251
te_type(*)(const te_expr *, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type) te_confun20
Definition tinyexpr.h:172
te_type(*)(const te_expr *, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type) te_confun14
Definition tinyexpr.h:166
te_type(*)(const te_expr *, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type) te_confun24
Definition tinyexpr.h:176
te_type(*)(te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type) te_fun22
Definition tinyexpr.h:148
te_type(*)(te_type, te_type, te_type, te_type, te_type, te_type) te_fun6
Definition tinyexpr.h:132
constexpr bool te_is_closure_v
Definition tinyexpr.h:247
std::variant< te_type, const te_type *, te_fun0, te_fun1, te_fun2, te_fun3, te_fun4, te_fun5, te_fun6, te_fun7, te_fun8, te_fun9, te_fun10, te_fun11, te_fun12, te_fun13, te_fun14, te_fun15, te_fun16, te_fun17, te_fun18, te_fun19, te_fun20, te_fun21, te_fun22, te_fun23, te_fun24, te_confun0, te_confun1, te_confun2, te_confun3, te_confun4, te_confun5, te_confun6, te_confun7, te_confun8, te_confun9, te_confun10, te_confun11, te_confun12, te_confun13, te_confun14, te_confun15, te_confun16, te_confun17, te_confun18, te_confun19, te_confun20, te_confun21, te_confun22, te_confun23, te_confun24, te_arg_fun, te_arg_confun, std::string_view > te_variant_type
Definition tinyexpr.h:273
te_type(*)(te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type) te_fun19
Definition tinyexpr.h:145
te_type(*)(const te_expr *, te_type, te_type, te_type, te_type, te_type, te_type) te_confun6
Definition tinyexpr.h:158
te_type(*)(const te_expr *, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type) te_confun11
Definition tinyexpr.h:163
constexpr bool te_is_arg_closure_v
Definition tinyexpr.h:257
te_type(*)(te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type) te_fun18
Definition tinyexpr.h:144
te_type(*)(const te_expr *, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type) te_confun19
Definition tinyexpr.h:171
std::function< te_type(std::string_view, std::string &)> te_usr_fun1
Definition tinyexpr.h:267
te_type(*)(const te_expr *, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type) te_confun17
Definition tinyexpr.h:169
te_type(*)(const te_expr *, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type) te_confun8
Definition tinyexpr.h:160
te_type(*)(te_type, te_type, te_type) te_fun3
Definition tinyexpr.h:129
constexpr int TINYEXPR_CPP_PATCH_VERSION
Definition tinyexpr.h:85
te_type(*)(const te_expr *, te_type, te_type, te_type, te_type, te_type, te_type, te_type) te_confun7
Definition tinyexpr.h:159
te_type(*)(te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type) te_fun9
Definition tinyexpr.h:135
te_type(*)(te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type) te_fun14
Definition tinyexpr.h:140
constexpr bool te_is_variable_v
Definition tinyexpr.h:220
te_type(*)(te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type) te_fun11
Definition tinyexpr.h:137
te_type(*)(te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type) te_fun24
Definition tinyexpr.h:150
te_type(*)(const te_expr *, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type) te_confun16
Definition tinyexpr.h:168
te_type(*)(const te_expr *, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type) te_confun15
Definition tinyexpr.h:167
te_type(*)(const te_expr *, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type) te_confun21
Definition tinyexpr.h:173
te_type(*)(te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type) te_fun10
Definition tinyexpr.h:136
std::function< te_type(std::string_view)> te_usr_fun0
Definition tinyexpr.h:266
te_type(*)(const te_expr *, te_type, te_type) te_confun2
Definition tinyexpr.h:154
te_type(*)(const te_expr *, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type) te_confun13
Definition tinyexpr.h:165
constexpr bool te_is_constant_v
Definition tinyexpr.h:217
te_type(*)(te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type) te_fun8
Definition tinyexpr.h:134
te_type(*)(te_type, te_type) te_fun2
Definition tinyexpr.h:128
te_type(*)(te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type) te_fun13
Definition tinyexpr.h:139
te_type(*)(te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type) te_fun15
Definition tinyexpr.h:141
std::function< void()> te_usr_noop
Definition tinyexpr.h:265
te_type(*)(te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type) te_fun16
Definition tinyexpr.h:142
constexpr size_t te_function_arity
Definition tinyexpr.h:214
te_type(*)() te_fun0
Definition tinyexpr.h:126
constexpr int TINYEXPR_CPP_MAJOR_VERSION
Definition tinyexpr.h:83
te_type(*)(te_type, te_type, te_type, te_type, te_type) te_fun5
Definition tinyexpr.h:131
te_type(*)(te_type) te_fun1
Definition tinyexpr.h:127
te_type(*)(const te_expr *) te_confun0
Definition tinyexpr.h:152
te_type(*)(te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type) te_fun17
Definition tinyexpr.h:143
te_type(*)(te_type, te_type, te_type, te_type) te_fun4
Definition tinyexpr.h:130
te_type(*)(te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type) te_fun12
Definition tinyexpr.h:138
te_type(*)(const te_expr *, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type) te_confun23
Definition tinyexpr.h:175
te_type(*)(const te_expr *, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type, te_type) te_confun22
Definition tinyexpr.h:174