Bertini 2 - C++ Core
Software for Numerical Algebraic Geometry
Loading...
Searching...
No Matches
classic_utilities.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/classic_utilities.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/classic_utilities.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
36
37
38
39namespace bertini {
40 namespace parsing {
41 namespace classic {
42
43 namespace qi = ::boost::spirit::qi;
44 namespace ascii = ::boost::spirit::ascii;
45
46
47
59 {
60 public:
61
62
63 std::string Config() const
64 {
65 return config_;
66 }
67
68 std::string Input() const
69 {
70 return input_;
71 }
72
73 bool Readable() const
74 {
75 return readable_;
76 }
77
78
79 void SetInput(std::string new_input)
80 {
81 input_ = new_input;
82 }
83
84 void SetConfig(std::string new_config)
85 {
86 config_ = new_config;
87 }
88
89 void SetConfigInput(std::string c, std::string i)
90 {
91 config_ = c;
92 input_ = i;
93 }
94
95 void SetReadable(bool read)
96 {
97 readable_ = read;
98 }
99
100
101
102 // void StripComments()
103 // {
104 // std::string::const_iterator iter = config_.begin();
105 // std::string::const_iterator end = config_.end();
106 //
107 // CommentStripper<std::string::const_iterator> S;
108 //
109 // phrase_parse(iter, end, S,boost::spirit::ascii::space, config_);
110 //
111 // iter = input_.begin();
112 // end = input_.end();
113 //
114 // phrase_parse(iter, end, S,boost::spirit::ascii::space, input_);
115 // }
116
117
118 friend std::ostream& operator<<(std::ostream & out, SplitInputFile const& printme)
119 {
120 out << "--------config-----------\n\n" << printme.Config() << "\n\n-------input--------\n\n" << printme.Input();
121 return out;
122 }
123
124
125
126
127
128 private:
129 std::string config_;
130 std::string input_;
131
132 bool readable_ = true; //Input file can be split accurately
133
134 }; //re: SplitInputFile class
135
136
137
138
172 template<typename Iterator, typename Skipper = ascii::space_type> //boost::spirit::unused_type
173 struct SplitInputFileParser : qi::grammar<Iterator, SplitInputFile(), Skipper>
174 {
175
176
177 SplitInputFileParser() : SplitInputFileParser::base_type(root_rule_, "SplitInputFile")
178 {
179 namespace phx = boost::phoenix;
180 using qi::_1;
181 using qi::_2;
182 using qi::_3;
183 using qi::_4;
184 using qi::_val;
185 using qi::eps;
186 using qi::lit;
187 using qi::char_;
188 using qi::omit;
189 using boost::spirit::lexeme;
190 using boost::spirit::as_string;
191 using boost::spirit::ascii::no_case;
192
193 root_rule_.name("SplitInputFile_root_rule");
194
195 root_rule_ = both_ | unreadable_ |only_input_ ;
196
197 // NOTE ON CONVENTIONS CURRENTLY USED:
198 // the various rules are constructed to obtain the text BEFORE the named marker, so e.g, rule config_ gets all text in the string before 'CONFIG'. similarly for 'END;' and 'INPUT'.
199
200 both_.name("have_both_config_and_input");
201 both_ = (
202 (omit[config_] >> end_ >> omit[input_] >> end_ >> omit[no_decl_]) [phx::bind(&SplitInputFile::SetConfigInput, _val, _1, _2)]// 15
203 |
204 (omit[config_] >> end_ >> omit[input_] >> no_decl_) [phx::bind(&SplitInputFile::SetConfigInput, _val, _1, _2)] // 14
205 |
206 (omit[config_] >> end_ >> end_ >> omit[no_decl_]) [phx::bind(&SplitInputFile::SetConfigInput, _val, _1, _2)] // 13
207 |
208 (omit[config_] >> input_ >> end_ >> omit[no_decl_]) [phx::bind(&SplitInputFile::SetConfigInput, _val, _1, _2)] // 11
209 |
210 (omit[config_] >> end_ >> no_decl_) [phx::bind(&SplitInputFile::SetConfigInput, _val, _1, _2)] // 12
211 |
212 (omit[config_] >> input_ >> no_decl_) [phx::bind(&SplitInputFile::SetConfigInput, _val, _1, _2)] // 10
213 )
214 ;
215
216 // the rule for number 11 does not currently correctly parse text which matches it... why???
217
218 //this attempt for the both_ rule doesn't work because the ends are optional...
219 // (omit[config_] >> end_ >> omit[input_] >> end_ >> omit[no_decl_]) [phx::bind(&SplitInputFile::SetConfigInput, _val, _1, _2)]
220 // |
221 // (omit[config_] >> omit[!end_] >> input_ >> end_ >> omit[no_decl_]) [phx::bind(&SplitInputFile::SetConfigInput, _val, _1, _2)]
222 // |
223 // (omit[config_] >> end_ >> omit[!input_] >> end_ >> omit[no_decl_]) [phx::bind(&SplitInputFile::SetConfigInput, _val, _1, _2)]
224 // |
225 // (omit[config_] >> omit[!end_] >> input_ >> no_decl_) [phx::bind(&SplitInputFile::SetConfigInput, _val, _1, _2)]
226 // |
227 // (omit[config_] >> end_ >> omit[!input_] >> omit[!end_] >> no_decl_) [phx::bind(&SplitInputFile::SetConfigInput, _val, _1, _2)]
228 // )
229
230
231 only_input_.name("have_only_input");
232 only_input_ = (
233 (omit[input_] >> end_ >> omit[no_decl_]) // 3
234 |
235 (omit[input_] >> no_decl_) // 2
236 |
237 (end_ >> omit[no_decl_]) // 1
238 |
239 (no_decl_) // 0
240 )
241 [phx::bind(&SplitInputFile::SetInput, _val, _1)];
242
243 unreadable_.name("unreadable_input"); //9 and 4 same as 12 and 1 to parser
244 unreadable_ = (
245 (omit[config_] >> no_decl_) // 8
246 |
247 (end_ >> omit[input_] >> end_ >> omit[no_decl_]) // 7
248 |
249 (end_ >> omit[input_] >> omit[no_decl_]) // 6
250 |
251 (end_ >> end_ >> omit[no_decl_]) // 5
252 )
253 [phx::bind(&SplitInputFile::SetReadable, _val, false)];
254
255 config_.name("config_");
256 config_ = no_case[*(char_ - "CONFIG") >> "CONFIG"];
257
258 end_.name("end_");
259 end_ = no_case[lexeme[*(char_ - "END;")] >> "END;"];
260
261 input_.name("input_");
262 input_ = no_case[lexeme[*(char_ - "INPUT")] >> "INPUT"];
263
264
265
266 no_decl_.name("no_decl_");
267 no_decl_ = lexeme[*(char_)];
268
269
270 // debug(root_rule_);
271 // debug(both_); debug(only_input_);
272 // debug(config_);
273 // debug(end_);
274 // debug(input_);
275 // debug(no_decl_);
276
277 // BOOST_SPIRIT_DEBUG_NODES((root_rule_)
278 // (both_) (only_input_)
279 // (config_) (end_) (input_)
280 // (no_decl_) )
281
282
283
284 using phx::val;
285 using phx::construct;
286 using namespace qi::labels;
287 qi::on_error<qi::fail>
288 ( root_rule_ ,
289 std::cout<<
290 val("config/input split parser could not complete parsing. Expecting ")<<
291 _4<<
292 val(" here: ")<<
293 construct<std::string>(_3,_2)<<
294 std::endl
295 );
296 }
297
298 private:
299 qi::rule<Iterator, SplitInputFile(), ascii::space_type > root_rule_, both_, only_input_, unreadable_;
300 qi::rule<Iterator, ascii::space_type, std::string()> end_, input_, no_decl_;
301 qi::rule<Iterator, ascii::space_type> config_;
302 };
303
304
305
306
307
308
315 template<typename Iterator, typename Skipper = ascii::space_type> //boost::spirit::unused_type
316 struct CommentStripper : qi::grammar<Iterator, std::string(), Skipper>
317 {
318
319
320 CommentStripper() : CommentStripper::base_type(root_rule_, "CommentStripper")
321 {
322 namespace phx = boost::phoenix;
323 using qi::_1;
324 using qi::_2;
325 using qi::_3;
326 using qi::_4;
327 using qi::_val;
328 using qi::eol;
329 using qi::eoi;
330 using qi::eps;
331 using qi::lit;
332 using qi::char_;
333 using qi::omit;
334 using boost::spirit::lexeme;
335 using boost::spirit::as_string;
336
337 root_rule_.name("CommentStripper_root_rule");
338
339 root_rule_ = eps[_val = ""] >> *line_[_val = _val + _1 + "\n"] >> -last_line_[_val = _val + _1 + "\n"];//+line_ | qi::eoi;
340
341
342 line_.name("line_of_commented_input");
343 line_ = lexeme[*(char_ - eol - "%") >> omit[-( "%" >> lexeme[*(char_ - eol)] )] >> (eol ) ];
344
345 last_line_.name("line_of_commented_input_with_no_eol");
346 last_line_ = lexeme[*(char_ - "%") >> omit[-( "%" >> lexeme[*(char_ - eol)] )]] ;
347
348
349 // debug(root_rule_);
350 // debug(line_);
351 // debug(last_line_);
352 //
353 // BOOST_SPIRIT_DEBUG_NODES((root_rule_)
354 // (line_) (last_line_) )
355
356
357
358 using phx::val;
359 using phx::construct;
360 using namespace qi::labels;
361 qi::on_error<qi::fail>
362 ( root_rule_ ,
363 std::cout<<
364 val("config/input split parser could not complete parsing. Expecting ")<<
365 _4<<
366 val(" here: ")<<
367 construct<std::string>(_3,_2)<<
368 std::endl
369 );
370 }
371
372 private:
373 qi::rule<Iterator, std::string(), ascii::space_type > root_rule_;
374 qi::rule<Iterator, ascii::space_type, std::string()> line_, last_line_;
375 };
376
377
378
379 SplitInputFile ParseInputFile(std::string str_input_file)
380 {
381 std::string::const_iterator iter = str_input_file.begin();
382 std::string::const_iterator end = str_input_file.end();
383
384 std::string uncommented_str_input;
386 phrase_parse(iter, end, commentparser,boost::spirit::ascii::space, uncommented_str_input);
387
388 iter = uncommented_str_input.begin();
389 end = uncommented_str_input.end();
390
392
393 SplitInputFile input_file;
394 phrase_parse(iter, end, spliter,boost::spirit::ascii::space, input_file);
395
396 return input_file;
397 }
398
399
400
404 std::tuple<std::string, std::string> SplitIntoConfigAndInput(Path const& input_file)
405 {
406 auto file_as_string = FileToString(input_file);
407
409 SplitInputFile config_and_input;
410 std::string::const_iterator iter = file_as_string.begin();
411 std::string::const_iterator end = file_as_string.end();
412 phrase_parse(iter, end, parser, boost::spirit::ascii::space, config_and_input);
413
414 return std::make_tuple(config_and_input.Config(), config_and_input.Input());
415 }
416
417
421 void SplitIntoConfigAndInput(std::string & config_section, std::string & input_section, Path const& input_file)
422 {
423 std::tie(config_section, input_section) = SplitIntoConfigAndInput(input_file);
424 }
425
426
427 } // re: namespace classic
428
429 }// re: namespace parsing
430}// re: namespace bertini
Storage class for input file that splits up the config portion from the input portion.
Definition classic_utilities.hpp:59
std::tuple< std::string, std::string > SplitIntoConfigAndInput(Path const &input_file)
Function for splitting a Bertini Classic style input file into config and input.
Definition classic_utilities.hpp:404
Provides the file_utilities screens for bertini2.
std::string FileToString(Path const &input_path)
Read an entire file into a string.
Definition file_utilities.hpp:93
Provides all the include files needed to develop a parsing file that uses boost qi.
Definition classic_utilities.hpp:317
Qi Parser object for parsing text into the SplitInputFile class.
Definition classic_utilities.hpp:174