LCOV - code coverage report
Current view: top level - src/x3 - parser_def.hpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 84 84 100.0 %
Date: 2022-11-05 14:57:37 Functions: 25 25 100.0 %

          Line data    Source code
       1             : #ifndef MATHEVAL_IMPLEMENTATION
       2             : #error "Do not include parser_def.hpp directly!"
       3             : #endif
       4             : 
       5             : #pragma once
       6             : 
       7             : #include "ast.hpp"
       8             : #include "ast_adapted.hpp"
       9             : #include "math.hpp"
      10             : #include "parser.hpp"
      11             : 
      12             : #include <boost/math/constants/constants.hpp>
      13             : #include <boost/spirit/home/x3.hpp>
      14             : 
      15             : #include <cmath>
      16             : #include <iostream>
      17             : #include <limits>
      18             : #include <string>
      19             : 
      20             : namespace matheval {
      21             : 
      22             : namespace x3 = boost::spirit::x3;
      23             : 
      24             : namespace parser {
      25             : 
      26             : // LOOKUP
      27             : 
      28             : struct constant_ : x3::symbols<double> {
      29           8 :     constant_() {
      30             :         // clang-format off
      31             :         add
      32           8 :             ("e"      , boost::math::constants::e<double>())
      33           8 :             ("epsilon", std::numeric_limits<double>::epsilon())
      34           8 :             ("phi"    , boost::math::constants::phi<double>())
      35           8 :             ("pi"     , boost::math::constants::pi<double>())
      36             :             ;
      37             :         // clang-format on
      38           8 :     }
      39             : } constant;
      40             : 
      41             : struct ufunc_ : x3::symbols<double (*)(double)> {
      42           8 :     ufunc_() {
      43             :         // clang-format off
      44             :         add
      45           8 :             ("abs"   , static_cast<double (*)(double)>(&std::abs))
      46           8 :             ("acos"  , static_cast<double (*)(double)>(&std::acos))
      47           8 :             ("acosh" , static_cast<double (*)(double)>(&std::acosh))
      48           8 :             ("asin"  , static_cast<double (*)(double)>(&std::asin))
      49           8 :             ("asinh" , static_cast<double (*)(double)>(&std::asinh))
      50           8 :             ("atan"  , static_cast<double (*)(double)>(&std::atan))
      51           8 :             ("atanh" , static_cast<double (*)(double)>(&std::atanh))
      52           8 :             ("cbrt"  , static_cast<double (*)(double)>(&std::cbrt))
      53           8 :             ("ceil"  , static_cast<double (*)(double)>(&std::ceil))
      54           8 :             ("cos"   , static_cast<double (*)(double)>(&std::cos))
      55           8 :             ("cosh"  , static_cast<double (*)(double)>(&std::cosh))
      56           8 :             ("deg"   , static_cast<double (*)(double)>(&math::deg))
      57           8 :             ("erf"   , static_cast<double (*)(double)>(&std::erf))
      58           8 :             ("erfc"  , static_cast<double (*)(double)>(&std::erfc))
      59           8 :             ("exp"   , static_cast<double (*)(double)>(&std::exp))
      60           8 :             ("exp2"  , static_cast<double (*)(double)>(&std::exp2))
      61           8 :             ("floor" , static_cast<double (*)(double)>(&std::floor))
      62           8 :             ("isinf" , static_cast<double (*)(double)>(&math::isinf))
      63           8 :             ("isnan" , static_cast<double (*)(double)>(&math::isnan))
      64           8 :             ("log"   , static_cast<double (*)(double)>(&std::log))
      65           8 :             ("log2"  , static_cast<double (*)(double)>(&std::log2))
      66           8 :             ("log10" , static_cast<double (*)(double)>(&std::log10))
      67           8 :             ("rad"   , static_cast<double (*)(double)>(&math::rad))
      68           8 :             ("round" , static_cast<double (*)(double)>(&std::round))
      69           8 :             ("sgn"   , static_cast<double (*)(double)>(&math::sgn))
      70           8 :             ("sin"   , static_cast<double (*)(double)>(&std::sin))
      71           8 :             ("sinh"  , static_cast<double (*)(double)>(&std::sinh))
      72           8 :             ("sqrt"  , static_cast<double (*)(double)>(&std::sqrt))
      73           8 :             ("tan"   , static_cast<double (*)(double)>(&std::tan))
      74           8 :             ("tanh"  , static_cast<double (*)(double)>(&std::tanh))
      75           8 :             ("tgamma", static_cast<double (*)(double)>(&std::tgamma))
      76             :             ;
      77             :         // clang-format on
      78           8 :     }
      79             : } ufunc;
      80             : 
      81             : struct bfunc_ : x3::symbols<double (*)(double, double)> {
      82           8 :     bfunc_() {
      83             :         // clang-format off
      84             :         add
      85           8 :             ("atan2", static_cast<double (*)(double, double)>(&std::atan2))
      86           8 :             ("max"  , static_cast<double (*)(double, double)>(&std::fmax))
      87           8 :             ("min"  , static_cast<double (*)(double, double)>(&std::fmin))
      88           8 :             ("pow"  , static_cast<double (*)(double, double)>(&std::pow))
      89             :             ;
      90             :         // clang-format on
      91           8 :     }
      92             : } bfunc;
      93             : 
      94             : struct tfunc_ : x3::symbols<double (*)(double, double, double)> {
      95           8 :     tfunc_() {
      96             :         // clang-format off
      97             :         add
      98           8 :             ("ifthenelse", static_cast<double (*)(double, double, double)>(&math::ifthenelse))
      99             :             ;
     100             :         // clang-format on
     101           8 :     }
     102             : } tfunc;
     103             : 
     104             : struct unary_op_ : x3::symbols<double (*)(double)> {
     105           8 :     unary_op_() {
     106             :         // clang-format off
     107             :         add
     108           8 :             ("+", static_cast<double (*)(double)>(&math::plus))
     109           8 :             ("-", static_cast<double (*)(double)>(&math::minus))
     110           8 :             ("!", static_cast<double (*)(double)>(&math::unary_not))
     111             :             ;
     112             :         // clang-format on
     113           8 :     }
     114             : } unary_op;
     115             : 
     116             : struct additive_op_ : x3::symbols<double (*)(double, double)> {
     117           8 :     additive_op_() {
     118             :         // clang-format off
     119             :         add
     120           8 :             ("+", static_cast<double (*)(double, double)>(&math::plus))
     121           8 :             ("-", static_cast<double (*)(double, double)>(&math::minus))
     122             :             ;
     123             :         // clang-format on
     124           8 :     }
     125             : } additive_op;
     126             : 
     127             : struct multiplicative_op_ : x3::symbols<double (*)(double, double)> {
     128           8 :     multiplicative_op_() {
     129             :         // clang-format off
     130             :         add
     131           8 :             ("*", static_cast<double (*)(double, double)>(&math::multiplies))
     132           8 :             ("/", static_cast<double (*)(double, double)>(&math::divides))
     133           8 :             ("%", static_cast<double (*)(double, double)>(&std::fmod))
     134             :             ;
     135             :         // clang-format on
     136           8 :     }
     137             : } multiplicative_op;
     138             : 
     139             : struct logical_op_ : x3::symbols<double (*)(double, double)> {
     140           8 :     logical_op_() {
     141             :         // clang-format off
     142             :         add
     143           8 :             ("&&", static_cast<double (*)(double, double)>(&math::logical_and))
     144           8 :             ("||", static_cast<double (*)(double, double)>(&math::logical_or))
     145             :             ;
     146             :         // clang-format on
     147           8 :     }
     148             : } logical_op;
     149             : 
     150             : struct relational_op_ : x3::symbols<double (*)(double, double)> {
     151           8 :     relational_op_() {
     152             :         // clang-format off
     153             :         add
     154           8 :             ("<" , static_cast<double (*)(double, double)>(&math::less))
     155           8 :             ("<=", static_cast<double (*)(double, double)>(&math::less_equals))
     156           8 :             (">" , static_cast<double (*)(double, double)>(&math::greater))
     157           8 :             (">=", static_cast<double (*)(double, double)>(&math::greater_equals))
     158             :             ;
     159             :         // clang-format on
     160           8 :     }
     161             : } relational_op;
     162             : 
     163             : struct equality_op_ : x3::symbols<double (*)(double, double)> {
     164           8 :     equality_op_() {
     165             :         // clang-format off
     166             :         add
     167           8 :             ("==", static_cast<double (*)(double, double)>(&math::equals))
     168           8 :             ("!=", static_cast<double (*)(double, double)>(&math::not_equals))
     169             :             ;
     170             :         // clang-format on
     171           8 :     }
     172             : } equality_op;
     173             : 
     174             : struct power_ : x3::symbols<double (*)(double, double)> {
     175           8 :     power_() {
     176             :         // clang-format off
     177             :         add
     178           8 :             ("**", static_cast<double (*)(double, double)>(&std::pow))
     179             :             ;
     180             :         // clang-format on
     181           8 :     }
     182             : } power;
     183             : 
     184             : // ADL markers
     185             : 
     186             : struct expression_class;
     187             : struct logical_class;
     188             : struct equality_class;
     189             : struct relational_class;
     190             : struct additive_class;
     191             : struct multiplicative_class;
     192             : struct factor_class;
     193             : struct primary_class;
     194             : struct unary_class;
     195             : struct binary_class;
     196             : struct ternary_class;
     197             : struct variable_class;
     198             : 
     199             : // clang-format off
     200             : 
     201             : // Rule declarations
     202             : 
     203             : auto const expression     = x3::rule<expression_class    , ast::expression>{"expression"};
     204             : auto const logical        = x3::rule<logical_class       , ast::expression>{"logical"};
     205             : auto const equality       = x3::rule<equality_class      , ast::expression>{"equality"};
     206             : auto const relational     = x3::rule<relational_class    , ast::expression>{"relational"};
     207             : auto const additive       = x3::rule<additive_class      , ast::expression>{"additive"};
     208             : auto const multiplicative = x3::rule<multiplicative_class, ast::expression>{"multiplicative"};
     209             : auto const factor         = x3::rule<factor_class        , ast::expression>{"factor"};
     210             : auto const primary        = x3::rule<primary_class       , ast::operand   >{"primary"};
     211             : auto const unary          = x3::rule<unary_class         , ast::unary_op  >{"unary"};
     212             : auto const binary         = x3::rule<binary_class        , ast::binary_op >{"binary"};
     213             : auto const ternary        = x3::rule<ternary_class       , ast::ternary_op>{"ternary"};
     214             : auto const variable       = x3::rule<variable_class      , std::string    >{"variable"};
     215             : 
     216             : // Rule defintions
     217             : 
     218             : auto const expression_def =
     219             :     logical
     220             :     ;
     221             : 
     222             : auto const logical_def =
     223             :     equality >> *(logical_op > equality)
     224             :     ;
     225             : 
     226             : auto const equality_def =
     227             :     relational >> *(equality_op > relational)
     228             :     ;
     229             : 
     230             : auto const relational_def =
     231             :     additive >> *(relational_op > additive)
     232             :     ;
     233             : 
     234             : auto const additive_def =
     235             :     multiplicative >> *(additive_op > multiplicative)
     236             :     ;
     237             : 
     238             : auto const multiplicative_def =
     239             :     factor >> *(multiplicative_op > factor)
     240             :     ;
     241             : 
     242             : auto const factor_def =
     243             :     primary >> *( power > factor )
     244             :     ;
     245             : 
     246             : auto const unary_def =
     247             :     ufunc > '(' > expression > ')'
     248             :     ;
     249             : 
     250             : auto const binary_def =
     251             :     bfunc > '(' > expression > ',' > expression > ')'
     252             :     ;
     253             : 
     254             : auto const ternary_def =
     255             :     tfunc > '(' > expression > ',' > expression > ',' > expression > ')'
     256             :     ;
     257             : 
     258             : auto const variable_def =
     259             :     x3::raw[x3::lexeme[x3::alpha >> *(x3::alnum | '_')]]
     260             :     ;
     261             : 
     262             : auto const primary_def =
     263             :       x3::double_
     264             :     | ('(' > expression > ')')
     265             :     | (unary_op > primary)
     266             :     | ternary
     267             :     | binary
     268             :     | unary
     269             :     | constant
     270             :     | variable
     271             :     ;
     272             : 
     273        2012 : BOOST_SPIRIT_DEFINE(
     274             :     expression,
     275             :     logical,
     276             :     equality,
     277             :     relational,
     278             :     additive,
     279             :     multiplicative,
     280             :     factor,
     281             :     primary,
     282             :     unary,
     283             :     binary,
     284             :     ternary,
     285             :     variable
     286             : )
     287             : 
     288             : // clang-format on
     289             : 
     290             : struct expression_class {
     291             :     template <typename Iterator, typename Exception, typename Context>
     292           2 :     x3::error_handler_result on_error(Iterator &, Iterator const &last,
     293             :                                       Exception const &x, Context const &) {
     294             :         std::cout << "Expected " << x.which() << " at \""
     295           2 :                   << std::string{x.where(), last} << "\"" << std::endl;
     296           2 :         return x3::error_handler_result::fail;
     297             :     }
     298             : };
     299             : 
     300             : } // namespace parser
     301             : 
     302         102 : parser::expression_type grammar() { return parser::expression; }
     303             : 
     304             : } // namespace matheval

Generated by: LCOV version 1.14