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/spirit/include/phoenix.hpp>
13 : #define BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
14 : #include <boost/spirit/include/qi.hpp>
15 :
16 : #include <cmath>
17 : #include <iostream>
18 : #include <limits>
19 : #include <sstream>
20 : #include <string>
21 :
22 : namespace matheval {
23 :
24 : namespace qi = boost::spirit::qi;
25 :
26 : namespace parser {
27 :
28 : template <typename Iterator>
29 90 : grammar<Iterator>::grammar() : grammar::base_type(expression) {
30 : qi::_2_type _2;
31 : qi::_3_type _3;
32 : qi::_4_type _4;
33 :
34 : qi::alnum_type alnum;
35 : qi::alpha_type alpha;
36 90 : qi::double_type double_;
37 : qi::lexeme_type lexeme;
38 : qi::raw_type raw;
39 :
40 : // clang-format off
41 :
42 : constant.add
43 0 : ("e" , boost::math::constants::e<double>())
44 90 : ("epsilon", std::numeric_limits<double>::epsilon())
45 90 : ("phi" , boost::math::constants::phi<double>())
46 90 : ("pi" , boost::math::constants::pi<double>())
47 : ;
48 :
49 : ufunc.add
50 : ("abs" , static_cast<double (*)(double)>(&std::abs))
51 90 : ("acos" , static_cast<double (*)(double)>(&std::acos))
52 90 : ("asin" , static_cast<double (*)(double)>(&std::asin))
53 90 : ("atan" , static_cast<double (*)(double)>(&std::atan))
54 90 : ("ceil" , static_cast<double (*)(double)>(&std::ceil))
55 90 : ("cos" , static_cast<double (*)(double)>(&std::cos))
56 90 : ("cosh" , static_cast<double (*)(double)>(&std::cosh))
57 90 : ("deg" , static_cast<double (*)(double)>(&math::deg))
58 90 : ("exp" , static_cast<double (*)(double)>(&std::exp))
59 90 : ("floor", static_cast<double (*)(double)>(&std::floor))
60 90 : ("isinf", static_cast<double (*)(double)>(&math::isinf))
61 90 : ("isnan", static_cast<double (*)(double)>(&math::isnan))
62 90 : ("log" , static_cast<double (*)(double)>(&std::log))
63 90 : ("log10", static_cast<double (*)(double)>(&std::log10))
64 90 : ("rad" , static_cast<double (*)(double)>(&math::rad))
65 90 : ("sgn" , static_cast<double (*)(double)>(&math::sgn))
66 90 : ("sin" , static_cast<double (*)(double)>(&std::sin))
67 90 : ("sinh" , static_cast<double (*)(double)>(&std::sinh))
68 90 : ("sqrt" , static_cast<double (*)(double)>(&std::sqrt))
69 90 : ("tan" , static_cast<double (*)(double)>(&std::tan))
70 90 : ("tanh" , static_cast<double (*)(double)>(&std::tanh))
71 : ;
72 :
73 : bfunc.add
74 : ("atan2", static_cast<double (*)(double, double)>(&std::atan2))
75 90 : ("pow" , static_cast<double (*)(double, double)>(&std::pow))
76 : ;
77 :
78 90 : tfunc.add
79 : ("ifthenelse", static_cast<double (*)(double, double, double)>(&math::ifthenelse))
80 : ;
81 :
82 : unary_op.add
83 : ("+", static_cast<double (*)(double)>(&math::plus))
84 90 : ("-", static_cast<double (*)(double)>(&math::minus))
85 90 : ("!", static_cast<double (*)(double)>(&math::unary_not))
86 : ;
87 :
88 : additive_op.add
89 : ("+", static_cast<double (*)(double, double)>(&math::plus))
90 90 : ("-", static_cast<double (*)(double, double)>(&math::minus))
91 : ;
92 :
93 : multiplicative_op.add
94 : ("*", static_cast<double (*)(double, double)>(&math::multiplies))
95 90 : ("/", static_cast<double (*)(double, double)>(&math::divides))
96 90 : ("%", static_cast<double (*)(double, double)>(&std::fmod))
97 : ;
98 :
99 : logical_op.add
100 : ("&&", static_cast<double (*)(double, double)>(&math::logical_and))
101 90 : ("||", static_cast<double (*)(double, double)>(&math::logical_or))
102 : ;
103 :
104 : relational_op.add
105 : ("<" , static_cast<double (*)(double, double)>(&math::less))
106 90 : ("<=", static_cast<double (*)(double, double)>(&math::less_equals))
107 90 : (">" , static_cast<double (*)(double, double)>(&math::greater))
108 90 : (">=", static_cast<double (*)(double, double)>(&math::greater_equals))
109 : ;
110 :
111 : equality_op.add
112 : ("==", static_cast<double (*)(double, double)>(&math::equals))
113 90 : ("!=", static_cast<double (*)(double, double)>(&math::not_equals))
114 : ;
115 :
116 90 : power.add
117 : ("**", static_cast<double (*)(double, double)>(&std::pow))
118 : ;
119 :
120 90 : expression =
121 : logical.alias()
122 : ;
123 :
124 90 : logical =
125 360 : equality >> *(logical_op > equality)
126 : ;
127 :
128 90 : equality =
129 360 : relational >> *(equality_op > relational)
130 : ;
131 :
132 90 : relational =
133 360 : additive >> *(relational_op > additive)
134 : ;
135 :
136 90 : additive =
137 360 : multiplicative >> *(additive_op > multiplicative)
138 : ;
139 :
140 90 : multiplicative =
141 360 : factor >> *(multiplicative_op > factor)
142 : ;
143 :
144 90 : factor =
145 360 : primary >> *( power > factor )
146 : ;
147 :
148 90 : unary =
149 360 : ufunc > '(' > expression > ')'
150 : ;
151 :
152 90 : binary =
153 540 : bfunc > '(' > expression > ',' > expression > ')'
154 : ;
155 :
156 90 : ternary =
157 720 : tfunc > '(' > expression > ',' > expression > ',' > expression > ')'
158 : ;
159 :
160 180 : variable =
161 360 : raw[lexeme[alpha >> *(alnum | '_')]]
162 : ;
163 :
164 90 : primary =
165 : double_
166 270 : | ('(' > expression > ')')
167 180 : | (unary_op > primary)
168 90 : | ternary
169 90 : | binary
170 90 : | unary
171 90 : | constant
172 180 : | variable
173 : ;
174 :
175 : // clang-format on
176 :
177 90 : expression.name("expression");
178 90 : logical.name("logical");
179 90 : equality.name("equality");
180 90 : relational.name("relational");
181 90 : additive.name("additive");
182 90 : multiplicative.name("multiplicative");
183 90 : factor.name("factor");
184 90 : variable.name("variable");
185 90 : primary.name("primary");
186 90 : unary.name("unary");
187 90 : binary.name("binary");
188 90 : ternary.name("ternary");
189 :
190 : // typedef boost::phoenix::function<error_handler<Iterator> >
191 : // error_handler_function; qi::on_error<qi::fail>(expression,
192 : // error_handler_function(error_handler<Iterator>())(
193 : // "Error! Expecting ", qi::_4, qi::_3));
194 90 : qi::on_error<qi::fail>(
195 90 : expression,
196 90 : boost::phoenix::bind(boost::phoenix::ref(err_handler), _3, _2, _4));
197 90 : }
198 :
199 : } // namespace parser
200 :
201 : } // namespace matheval
|