Bertini 2 - C++ Core
Software for Numerical Algebraic Geometry
Loading...
Searching...
No Matches
function_rules.hpp
Go to the documentation of this file.
1//This file is part of Bertini 2.
2//
3//bertini2/io/parsers.hpp is free software: you can redistribute it and/or modify
4//it under the terms of the GNU General Public License as published by
5//the Free Software Foundation, either version 3 of the License, or
6//(at your option) any later version.
7//
8//bertini2/io/parsing/function_rules.hpp is distributed in the hope that it will be useful,
9//but WITHOUT ANY WARRANTY; without even the implied warranty of
10//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11//GNU General Public License for more details.
12//
13//You should have received a copy of the GNU General Public License
14//along with bertini2/io/parsing/function_rules.hpp. If not, see <http://www.gnu.org/licenses/>.
15//
16// Copyright(C) 2015 - 2017 by Bertini2 Development Team
17//
18// See <http://www.gnu.org/licenses/> for a copy of the license,
19// as well as COPYING. Bertini2 is provided with permitted
20// additional terms in the b2/licenses/ directory.
21
22
28
29#pragma once
30
31
32
33
35
38
41
44
46
47
48
49// see the following link for reading from arbitrary streams without putting the content into a std::string first
50//http://boost-spirit.com/home/articles/qi-example/tracking-the-input-position-while-parsing/
51
52
53
54namespace {
55 // this solution for *lazy* make shared comes from the SO forum, asked by polytheme, answered by user sehe.
56 // https://stackoverflow.com/questions/21516201/how-to-create-boost-phoenix-make-shared
57 // post found using google search terms `phoenix construct shared_ptr`
58 // the code has been adapted slightly to fit the naming conventions of this project.
59 template <typename T>
60 struct MakeSharedFunctor
61 {
62 template <typename... A>
63 struct result
64 {
65 typedef std::shared_ptr<T> type;
66 };
67
68 template <typename... A>
69 typename result<A...>::type operator()(A&&... a) const
70 {
71 return T::Make(std::forward<A>(a)...);
72 }
73 };
74
75 template <typename T>
76 using make_shared_ = boost::phoenix::function<MakeSharedFunctor<T> >;
77}
78
79
80
81
82
83
84
86//
87// the following code adapts the trig functions and other special functions to be phoenix-callable.
88//
90
91// http://www.boost.org/doc/libs/1_58_0/libs/phoenix/doc/html/phoenix/modules/function/adapting_functions.html
92
93//
94// form is as follows:
95//
96//BOOST_PHOENIX_ADAPT_FUNCTION(
97// RETURN_TYPE
98// , LAZY_FUNCTION
99// , FUNCTION
100// , FUNCTION_ARITY
101// )
102
103
104
105BOOST_PHOENIX_ADAPT_FUNCTION(std::shared_ptr<bertini::node::Node>, cos_lazy, cos, 1);
106BOOST_PHOENIX_ADAPT_FUNCTION(std::shared_ptr<bertini::node::Node>, sin_lazy, sin, 1);
107BOOST_PHOENIX_ADAPT_FUNCTION(std::shared_ptr<bertini::node::Node>, tan_lazy, tan, 1);
108
109BOOST_PHOENIX_ADAPT_FUNCTION(std::shared_ptr<bertini::node::Node>, log_lazy, log, 1);
110BOOST_PHOENIX_ADAPT_FUNCTION(std::shared_ptr<bertini::node::Node>, exp_lazy, exp, 1);
111BOOST_PHOENIX_ADAPT_FUNCTION(std::shared_ptr<bertini::node::Node>, sqrt_lazy, sqrt, 1);
112
113
114
115
116
117
118
119namespace bertini {
120 namespace parsing {
121 namespace classic {
122
123
124
125 namespace qi = ::boost::spirit::qi;
126 namespace ascii = ::boost::spirit::ascii;
127
128
129
130
131
141 template<typename Iterator>
142 struct FunctionParser : qi::grammar<Iterator, std::shared_ptr<node::Node>(), boost::spirit::ascii::space_type>
143 {
144 using Node = node::Node;
145 using Function = node::Function;
146 using Float = node::Float;
147 using Integer = node::Integer;
148 using Rational = node::Rational;
149
150 FunctionParser(qi::symbols<char,std::shared_ptr<Node> > * encountered_symbols) : FunctionParser::base_type(root_rule_,"FunctionParser")
151 {
152 namespace phx = boost::phoenix;
153 using qi::_1;
154 using qi::_2;
155 using qi::_3;
156 using qi::_4;
157 using qi::_val;
158 using qi::eps;
159 using qi::lit;
160
161 using std::pow;
162 using ::pow;
163
164 root_rule_.name("function_");
165 root_rule_ = expression_ [ _val = make_shared_<Function>()(_1)];
166
167
169 expression_.name("expression_");
170 expression_ =
171 term_ [_val = _1]
172 >> *( (lit('+') > term_ [_val += _1])
173 | (lit('-') > term_ [_val -= _1])
174 )
175 ;
176
177 term_.name("term_");
178 term_ =
179 factor_ [_val = _1]
180 >> *( (lit('*') > factor_ [_val *= _1])
181 | (lit('/') > factor_ [_val /= _1])
182 )
183 ;
184
185 factor_.name("factor_");
186 factor_ =
187 exp_elem_ [_val = _1]
188 >> *(lit('^') // any number of ^somethings
189 > exp_elem_ [ phx::bind( []
190 (std::shared_ptr<Node> & B, std::shared_ptr<Node> P)
191 {
192 B = pow(B,P);
193 },
194 _val,_1)] )
195 ;
196
197 exp_elem_.name("exp_elem_");
198 exp_elem_ =
199 (symbol_ >> !qi::alnum) [_val = _1]
200 | ( '(' > expression_ [_val = _1] > ')' ) // using the > expectation here.
201 | (lit('-') > expression_ [_val = -_1])
202 | (lit('+') > expression_ [_val = _1])
203 | (lit("sin") > '(' > expression_ [_val = sin_lazy(_1)] > ')' )
204 | (lit("cos") > '(' > expression_ [_val = cos_lazy(_1)] > ')' )
205 | (lit("tan") > '(' > expression_ [_val = tan_lazy(_1)] > ')' )
206 | (lit("exp") > '(' > expression_ [_val = exp_lazy(_1)] > ')' )
207 | (lit("log") > '(' > expression_ [_val = log_lazy(_1)] > ')' )
208 | (lit("sqrt") > '(' > expression_ [_val = sqrt_lazy(_1)] > ')' )
209 ;
210
211
212
213
214
215
216
217
218 symbol_.name("symbol_");
219 symbol_ %=
220 (*encountered_symbols) // the star here is the dereferencing of the encountered_symbols parameter to the constructor.
221 |
222 number_
223 ;
224
225
226
227
228
229
230
231
232
233
234
235 number_.name("number_");
236 number_ =
237 mpfr_rules_.long_number_string_ [ _val = make_shared_<Float>()(_1) ]
238 |
239 mpfr_rules_.integer_string_ [ _val = make_shared_<Integer>()(_1) ];
240
241
242
243
244
245
246
247
248 using qi::on_error;
249 using boost::phoenix::val;
250 using boost::phoenix::construct;
251
252
253 on_error<qi::fail>
254 (
255 root_rule_
256 , std::cout
257 << val("Function parser error: expecting ")
258 << _4
259 << val(" here: \"")
260 << construct<std::string>(_3, _2)
261 << val("\"")
262 << std::endl
263 );
264
265
266
267
268
269 // debug(root_rule_);
270 // debug(expression_);
271 // debug(term_);
272 // debug(factor_);
273 // debug(exp_elem_);
274 // debug(number_);
275 // debug(number_with_no_point_);
276 // debug(number_with_digits_after_point_);
277 // debug(number_with_digits_before_point_);
278 // debug(exponent_notation_);
279 }
280
281
282
283
284
285
286 qi::rule<Iterator, std::shared_ptr<Node>(), ascii::space_type > root_rule_;
287 // the rule for kicking the entire thing off
288
289 qi::rule<Iterator, std::shared_ptr<Node>(), ascii::space_type> expression_, term_, factor_, exp_elem_;
290 // rules for how to turn +-*/^ into operator nodes.
291
292
293
294 qi::rule<Iterator, std::shared_ptr<Node>(), ascii::space_type > symbol_;
295 // any of the variables and numbers will be symbols.
296
297 qi::rule<Iterator, std::shared_ptr<Node>(), ascii::space_type > variable_; // finds a previously encountered number, and associates the correct variable node with it.
298
299 // the number_ rule wants to find strings from the various other number_ rules, and produces a Number node
300 qi::rule<Iterator, std::shared_ptr<Node>(), ascii::space_type > number_;
301
302 parsing::rules::LongNum<Iterator> mpfr_rules_;
303 };
304
305 } // re: namespace classic
306
307 } // re: namespace parsing
308
309} // re: namespace bertini
Provides the artithmetic Node types, such as Sum and Power.
Number type for storing floating point numbers within an expression tree.
Definition number.hpp:250
Formal entry point into an expression tree.
Definition function.hpp:218
Signed real Integer storage in an expression tree.
Definition number.hpp:173
Abstract base class for the Bertini hybrid-precision (double-multiple) expression tree.
Definition node.hpp:142
The Rational number type for Bertini2 expression trees.
Definition number.hpp:323
dbl pow(const dbl &z, int power)
Definition double_extensions.hpp:88
Provides the Function Node type, a NamedSymbol.
Defines the abstract Node base class.
Provides the Number Node types, including Rational, Float, and Integer.
Provides the parsersing rules for numbers in bertini2.
Provides all the include files needed to develop a parsing file that uses boost qi.
Provides the abstract TrigOperator, and the concrete types such as SinOperator.
Provides the Variable Node class.