eis/mix_cc/matheval/matheval.hpp

95 lines
2.5 KiB
C++

/**
* @file mix_cc/matheval/matheval.hpp
* @brief 最终头文件
* @author Cat (null.null.null@qq.com)
* @version 0.1
* @date 2021-09-17
*
* Copyright: Baosight Co. Ltd.
* DO NOT COPY/USE WITHOUT PERMISSION
*
*/
#pragma once
#include <map>
#include <memory>
#include <string>
namespace mix_cc {
namespace matheval {
/// @brief Parse a mathematical expression
///
/// This can parse and evaluate a mathematical expression for a given
/// symbol table using Boost.Spirit X3. The templates of Boost.Spirit
/// are very expensive to parse and instantiate, which is why we hide
/// it behind an opaque pointer.
///
/// The drawback of this approach is that calls can no longer be
/// inlined and because the pointer crosses translation unit
/// boundaries, dereferencing it can also not be optimized out at
/// compile time. We have to rely entirely on link-time optimization
/// which might be not as good.
///
/// The pointer to the implementation is a std::unique_ptr which makes
/// the class not copyable but only moveable. Copying shouldn't be
/// required but is easy to implement.
class Parser {
class impl;
std::unique_ptr<impl> pimpl;
public:
/// @brief Constructor
Parser();
/// @brief Destructor
~Parser();
/// @brief Parse the mathematical expression into an abstract syntax tree
///
/// @param[in] expr The expression given as a std::string
void parse(std::string const& expr);
/// @brief Perform constant folding onto the abstract syntax tree
void optimize();
/// @brief Evaluate the abstract syntax tree for a given symbol table
///
/// @param[in] st The symbol table
double evaluate(std::map<std::string, double> const& st = {});
};
/// @brief Parse a mathematical expression
class Expression {
class impl;
std::unique_ptr<impl> pimpl;
public:
///@brief build math expression
Expression(std::string const& math_expr, std::map<std::string, double>* const);
~Expression();
///@brief evaluate the value of input expression
double evaluate();
};
/// @brief Convenience function
///
/// This function builds the grammar, parses the iterator to an AST,
/// evaluates it, and returns the result.
///
/// @param[in] expr mathematical expression
/// @param[in] st the symbol table for variables
inline double parse(std::string const& expr,
std::map<std::string, double> const& st = {}) {
Parser parser;
parser.parse(expr);
return parser.evaluate(st);
}
} // namespace matheval
} // namespace mix_cc