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
|