#define MATHEVAL_IMPLEMENTATION #include "matheval.hpp" #include "ast.hpp" #include "evaluator.hpp" #include "parser.hpp" #include #include #include namespace mix_cc { namespace matheval { class Parser::impl { ast::operand ast; public: void parse(std::string const& expr) { auto ast_ = ast::expression{}; auto first = expr.begin(); auto last = expr.end(); boost::spirit::x3::ascii::space_type space; bool r = phrase_parse(first, last, grammar(), space, ast_); if (!r || first != last) { std::string rest(first, last); throw std::runtime_error("Parsing failed at " + rest); // NOLINT } ast = ast_; } void optimize() { ast = boost::apply_visitor(ast::ConstantFolder{}, ast); } double evaluate(std::map const& st) { return boost::apply_visitor(ast::eval{st}, ast); } }; Parser::Parser() : pimpl{std::make_unique()} {} Parser::~Parser() {} void Parser::parse(std::string const& expr) { pimpl->parse(expr); } void Parser::optimize() { pimpl->optimize(); } double Parser::evaluate(std::map const& st) { return pimpl->evaluate(st); } class Expression::impl { ast::operand ast; std::map* st_ptr; public: void parse(std::string const& expr) { auto ast_ = ast::expression{}; auto first = expr.begin(); auto last = expr.end(); boost::spirit::x3::ascii::space_type space; bool r = phrase_parse(first, last, grammar(), space, ast_); if (!r || first != last) { std::string rest(first, last); throw std::runtime_error("Parsing failed at " + rest); // NOLINT } ast = ast_; } void set_variable(std::map* const ptr) { this->st_ptr = ptr; } void optimize() { ast = boost::apply_visitor(ast::ConstantFolder{}, ast); } double evaluate() { return boost::apply_visitor(ast::eval{*st_ptr}, ast); } }; Expression::Expression(std::string const& math_expr, std::map* const ptr) : pimpl{std::make_unique()} { pimpl->parse(math_expr); pimpl->optimize(); pimpl->set_variable(ptr); } Expression::~Expression() {} double Expression::evaluate() { return pimpl->evaluate(); } } // namespace matheval } // namespace mix_cc