#ifndef MATHEVAL_IMPLEMENTATION #error "Do not include parser_def.hpp directly!" #endif #pragma once #include "ast.hpp" #include "ast_adapted.hpp" #include "math.hpp" #include "parser.hpp" #include #include #include #include #include #include #include #include namespace mix_cc { namespace matheval { namespace x3 = boost::spirit::x3; namespace parser { // LOOKUP struct constant_ : x3::symbols { constant_() { // clang-format off add ("e" , boost::math::constants::e()) ("epsilon", std::numeric_limits::epsilon()) ("phi" , boost::math::constants::phi()) ("pi" , boost::math::constants::pi()) ("true" , 1) ("false" , 0) ; // clang-format on } } constant; struct ufunc_ : x3::symbols { ufunc_() { // clang-format off add ("abs" , static_cast(&std::abs)) // ("acos" , static_cast(&std::acos)) // ("acosh" , static_cast(&std::acosh)) // ("asin" , static_cast(&std::asin)) // ("asinh" , static_cast(&std::asinh)) // ("atan" , static_cast(&std::atan)) // ("atanh" , static_cast(&std::atanh)) // ("cbrt" , static_cast(&std::cbrt)) ("ceil" , static_cast(&std::ceil)) ("cos" , static_cast(&std::cos)) // ("cosh" , static_cast(&std::cosh)) // ("deg" , static_cast(&math::deg)) // ("erf" , static_cast(&std::erf)) // ("erfc" , static_cast(&std::erfc)) ("exp" , static_cast(&std::exp)) // ("exp2" , static_cast(&std::exp2)) ("floor" , static_cast(&std::floor)) ("isinf" , static_cast(&math::isinf)) ("isnan" , static_cast(&math::isnan)) ("log" , static_cast(&std::log)) ("ln" , static_cast(&std::log)) ("log2" , static_cast(&std::log2)) ("log10" , static_cast(&std::log10)) // ("rad" , static_cast(&math::rad)) ("round" , static_cast(&std::round)) // ("sgn" , static_cast(&math::sgn)) ("sin" , static_cast(&std::sin)) // ("sinh" , static_cast(&std::sinh)) ("sqrt" , static_cast(&std::sqrt)) ("tan" , static_cast(&std::tan)) // ("tanh" , static_cast(&std::tanh)) // ("tgamma", static_cast(&std::tgamma)) ("B2N", static_cast(&mix_cc::B2N)) ; // clang-format on } } ufunc; struct bfunc_ : x3::symbols { bfunc_() { // clang-format off add // ("atan2", static_cast(&std::atan2)) ("max" , static_cast(&std::fmax)) ("min" , static_cast(&std::fmin)) ("pow" , static_cast(&std::pow)) ("gitbit", static_cast(&mix_cc::gitbit)) ("log", static_cast(&mix_cc::log)) ("XOR", static_cast(&mix_cc::XOR)) ; // clang-format on } } bfunc; struct unary_op_ : x3::symbols { unary_op_() { // clang-format off add ("+", static_cast(&math::plus)) ("-", static_cast(&math::minus)) ("!", static_cast(&math::unary_not)) ; // clang-format on } } unary_op; struct additive_op_ : x3::symbols { additive_op_() { // clang-format off add ("+", static_cast(&math::plus)) ("-", static_cast(&math::minus)) ; // clang-format on } } additive_op; struct multiplicative_op_ : x3::symbols { multiplicative_op_() { // clang-format off add ("*", static_cast(&math::multiplies)) ("/", static_cast(&math::divides)) ("%", static_cast(&std::fmod)) ; // clang-format on } } multiplicative_op; struct logical_op_ : x3::symbols { logical_op_() { // clang-format off add ("&&", static_cast(&math::logical_and)) ("||", static_cast(&math::logical_or)) ; // clang-format on } } logical_op; struct relational_op_ : x3::symbols { relational_op_() { // clang-format off add ("<" , static_cast(&math::less)) ("<=", static_cast(&math::less_equals)) (">" , static_cast(&math::greater)) (">=", static_cast(&math::greater_equals)) ; // clang-format on } } relational_op; struct equality_op_ : x3::symbols { equality_op_() { // clang-format off add ("==", static_cast(&math::equals)) ("!=", static_cast(&math::not_equals)) ; // clang-format on } } equality_op; struct power_ : x3::symbols { power_() { // clang-format off add ("**", static_cast(&std::pow)) ; // clang-format on } } power; // ADL markers struct expression_class; struct logical_class; struct equality_class; struct relational_class; struct additive_class; struct multiplicative_class; struct factor_class; struct primary_class; struct unary_class; struct binary_class; struct variable_class; // clang-format off // Rule declarations auto const expression = x3::rule{"expression"}; auto const logical = x3::rule{"logical"}; auto const equality = x3::rule{"equality"}; auto const relational = x3::rule{"relational"}; auto const additive = x3::rule{"additive"}; auto const multiplicative = x3::rule{"multiplicative"}; auto const factor = x3::rule{"factor"}; auto const primary = x3::rule{"primary"}; auto const unary = x3::rule{"unary"}; auto const binary = x3::rule{"binary"}; auto const variable = x3::rule{"variable"}; // Rule defintions auto const expression_def = logical ; auto const logical_def = equality >> *(logical_op > equality) ; auto const equality_def = relational >> *(equality_op > relational) ; auto const relational_def = additive >> *(relational_op > additive) ; auto const additive_def = multiplicative >> *(additive_op > multiplicative) ; auto const multiplicative_def = factor >> *(multiplicative_op > factor) ; auto const factor_def = primary >> *( power > factor ) ; auto const unary_def = ufunc > '(' > expression > ')' ; auto const binary_def = bfunc > '(' > expression > ',' > expression > ')' ; auto const variable_def = x3::raw[x3::lexeme[x3::alpha >> *(x3::alnum | '_')]] ; auto const primary_def = x3::double_ | ('(' > expression > ')') | (unary_op > primary) | binary | unary | constant | variable ; BOOST_SPIRIT_DEFINE( expression, logical, equality, relational, additive, multiplicative, factor, primary, unary, binary, variable ) // clang-format on struct expression_class { template x3::error_handler_result on_error(Iterator&, Iterator const& last, Exception const& x, Context const&) { std::cout << "Expected " << x.which() << " at \"" << std::string{x.where(), last} << "\"" << std::endl; return x3::error_handler_result::fail; } }; } // namespace parser parser::expression_type grammar() { return parser::expression; } } // namespace matheval } // namespace mix_cc