/ src / common / CalculatorEngineCommon / ExprtkEvaluator.cpp
ExprtkEvaluator.cpp
 1  #include "ExprtkEvaluator.h"
 2  #include "exprtk.hpp"
 3  #include <iomanip>
 4  #include <iostream>
 5  #include <sstream>
 6  #include <cmath>
 7  #include <limits>
 8  
 9  namespace ExprtkCalculator::internal
10  {
11      static double factorial(const double n)
12      {
13          // Only allow non-negative integers
14          if (n < 0.0 || std::floor(n) != n)
15          {
16              return std::numeric_limits<double>::quiet_NaN();
17          }
18          return std::tgamma(n + 1.0);
19      }
20  
21      static double sign(const double n)
22      {
23          if (n > 0.0) return 1.0;
24          if (n < 0.0) return -1.0;
25          return 0.0;
26      }
27  
28      std::wstring ToWStringFullPrecision(double value)
29      {
30          std::wostringstream oss;
31          oss << std::fixed << std::setprecision(15) << value;
32          return oss.str();
33      }
34  
35      std::wstring EvaluateExpression(
36          const std::string& expressionText,
37          const std::unordered_map<std::string, double>& constants)
38      {
39          exprtk::symbol_table<double> symbol_table;
40  
41          for (auto const& [name, value] : constants)
42          {
43              symbol_table.add_constant(name, value);
44          }
45  
46          symbol_table.add_function("factorial", factorial);
47          symbol_table.add_function("sign", sign);
48  
49          exprtk::expression<double> expression;
50          expression.register_symbol_table(symbol_table);
51  
52          exprtk::parser<double> parser;
53  
54          // Enable all base functions and arithmetic operators
55          parser.settings().enable_all_base_functions(); // Enable all base functions like sin, cos, log, etc.
56          parser.settings().enable_all_arithmetic_ops(); // Enable all arithmetic operators like +, -, *, /, etc.
57  
58          // Disable all control structures and assignment operators to ensure only expressions are evaluated
59          parser.settings().disable_all_control_structures(); // Disable control structures like if, for, while, etc.
60          parser.settings().disable_all_assignment_ops(); // Disable assignment operators like =, +=, -=, etc.
61  
62          // Disabled for now, but can be enabled later for enhanced functionality
63          parser.settings().disable_all_logic_ops(); // Disable logical operators like &&, ||, !, etc.
64          parser.settings().disable_all_inequality_ops(); // Disable inequality operators like <, >, <=, >=, !=, etc.
65  
66          if (!parser.compile(expressionText, expression))
67              return L"NaN";
68  
69          return ToWStringFullPrecision(expression.value());
70      }
71  }