Bertini 2 d882924 (2026-10-06 19:56 UTC)
Numerical algebraic geometry library (C++ core)
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) 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
64 std::string Config() const
65 {
66 return config_;
67 }
68
70 std::string Input() const
71 {
72 return input_;
73 }
74
76 bool Readable() const
77 {
78 return readable_;
79 }
80
81
83 void SetInput(std::string new_input)
84 {
85 input_ = new_input;
86 }
87
89 void SetConfig(std::string new_config)
90 {
91 config_ = new_config;
92 }
93
95 void SetConfigInput(std::string c, std::string i)
96 {
97 config_ = c;
98 input_ = i;
99 }
100
102 void SetReadable(bool read)
103 {
104 readable_ = read;
105 }
106
107
108
109 // void StripComments()
110 // {
111 // std::string::const_iterator iter = config_.begin();
112 // std::string::const_iterator end = config_.end();
113 //
114 // CommentStripper<std::string::const_iterator> S;
115 //
116 // phrase_parse(iter, end, S,boost::spirit::ascii::space, config_);
117 //
118 // iter = input_.begin();
119 // end = input_.end();
120 //
121 // phrase_parse(iter, end, S,boost::spirit::ascii::space, input_);
122 // }
123
124
126 friend std::ostream& operator<<(std::ostream & out, SplitInputFile const& printme)
127 {
128 out << "--------config-----------\n\n" << printme.Config() << "\n\n-------input--------\n\n" << printme.Input();
129 return out;
130 }
131
132
133
134
135
136 private:
137 std::string config_;
138 std::string input_;
139
140 bool readable_ = true; //Input file can be split accurately
141
142 }; //re: SplitInputFile class
143
144
145
146
180 template<typename Iterator, typename Skipper = ascii::space_type> //boost::spirit::unused_type
181 struct SplitInputFileParser : qi::grammar<Iterator, SplitInputFile(), Skipper>
182 {
183
184
185 SplitInputFileParser() : SplitInputFileParser::base_type(root_rule_, "SplitInputFile")
186 {
187 namespace phx = boost::phoenix;
188 using qi::_1;
189 using qi::_2;
190 using qi::_3;
191 using qi::_4;
192 using qi::_val;
193 using qi::eps;
194 using qi::lit;
195 using qi::char_;
196 using qi::omit;
197 using boost::spirit::lexeme;
198 using boost::spirit::as_string;
199 using boost::spirit::ascii::no_case;
200
201 root_rule_.name("SplitInputFile_root_rule");
202
203 root_rule_ = both_ | unreadable_ |only_input_ ;
204
205 // NOTE ON CONVENTIONS CURRENTLY USED:
206 // 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'.
207
208 both_.name("have_both_config_and_input");
209 both_ = (
210 (omit[config_] >> end_ >> omit[input_] >> end_ >> omit[no_decl_]) [phx::bind(&SplitInputFile::SetConfigInput, _val, _1, _2)]// 15
211 |
212 (omit[config_] >> end_ >> omit[input_] >> no_decl_) [phx::bind(&SplitInputFile::SetConfigInput, _val, _1, _2)] // 14
213 |
214 (omit[config_] >> end_ >> end_ >> omit[no_decl_]) [phx::bind(&SplitInputFile::SetConfigInput, _val, _1, _2)] // 13
215 |
216 (omit[config_] >> input_ >> end_ >> omit[no_decl_]) [phx::bind(&SplitInputFile::SetConfigInput, _val, _1, _2)] // 11
217 |
218 (omit[config_] >> end_ >> no_decl_) [phx::bind(&SplitInputFile::SetConfigInput, _val, _1, _2)] // 12
219 |
220 (omit[config_] >> input_ >> no_decl_) [phx::bind(&SplitInputFile::SetConfigInput, _val, _1, _2)] // 10
221 )
222 ;
223
224 // the rule for number 11 does not currently correctly parse text which matches it... why???
225
226 //this attempt for the both_ rule doesn't work because the ends are optional...
227 // (omit[config_] >> end_ >> omit[input_] >> end_ >> omit[no_decl_]) [phx::bind(&SplitInputFile::SetConfigInput, _val, _1, _2)]
228 // |
229 // (omit[config_] >> omit[!end_] >> input_ >> end_ >> omit[no_decl_]) [phx::bind(&SplitInputFile::SetConfigInput, _val, _1, _2)]
230 // |
231 // (omit[config_] >> end_ >> omit[!input_] >> end_ >> omit[no_decl_]) [phx::bind(&SplitInputFile::SetConfigInput, _val, _1, _2)]
232 // |
233 // (omit[config_] >> omit[!end_] >> input_ >> no_decl_) [phx::bind(&SplitInputFile::SetConfigInput, _val, _1, _2)]
234 // |
235 // (omit[config_] >> end_ >> omit[!input_] >> omit[!end_] >> no_decl_) [phx::bind(&SplitInputFile::SetConfigInput, _val, _1, _2)]
236 // )
237
238
239 only_input_.name("have_only_input");
240 only_input_ = (
241 (omit[input_] >> end_ >> omit[no_decl_]) // 3
242 |
243 (omit[input_] >> no_decl_) // 2
244 |
245 (end_ >> omit[no_decl_]) // 1
246 |
247 (no_decl_) // 0
248 )
249 [phx::bind(&SplitInputFile::SetInput, _val, _1)];
250
251 unreadable_.name("unreadable_input"); //9 and 4 same as 12 and 1 to parser
252 unreadable_ = (
253 (omit[config_] >> no_decl_) // 8
254 |
255 (end_ >> omit[input_] >> end_ >> omit[no_decl_]) // 7
256 |
257 (end_ >> omit[input_] >> omit[no_decl_]) // 6
258 |
259 (end_ >> end_ >> omit[no_decl_]) // 5
260 )
261 [phx::bind(&SplitInputFile::SetReadable, _val, false)];
262
263 config_.name("config_");
264 config_ = no_case[*(char_ - "CONFIG") >> "CONFIG"];
265
266 end_.name("end_");
267 end_ = no_case[lexeme[*(char_ - "END;")] >> "END;"];
268
269 input_.name("input_");
270 input_ = no_case[lexeme[*(char_ - "INPUT")] >> "INPUT"];
271
272
273
274 no_decl_.name("no_decl_");
275 no_decl_ = lexeme[*(char_)];
276
277
278 // debug(root_rule_);
279 // debug(both_); debug(only_input_);
280 // debug(config_);
281 // debug(end_);
282 // debug(input_);
283 // debug(no_decl_);
284
285 // BOOST_SPIRIT_DEBUG_NODES((root_rule_)
286 // (both_) (only_input_)
287 // (config_) (end_) (input_)
288 // (no_decl_) )
289
290
291
292 qi::on_error<qi::fail>(
293 root_rule_,
294 phx::bind(&ReportParseError, _1, _2, _3, _4, std::string("SplitInputFileParser"))
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 qi::on_error<qi::fail>(
359 root_rule_,
360 phx::bind(&ReportParseError, _1, _2, _3, _4, std::string("CommentStripper"))
361 );
362 }
363
364 private:
365 qi::rule<Iterator, std::string(), ascii::space_type > root_rule_;
366 qi::rule<Iterator, ascii::space_type, std::string()> line_, last_line_;
367 };
368
369
370
372 SplitInputFile ParseInputFile(std::string str_input_file)
373 {
374 std::string::const_iterator iter = str_input_file.begin();
375 std::string::const_iterator end = str_input_file.end();
376
377 std::string uncommented_str_input;
379 phrase_parse(iter, end, commentparser,boost::spirit::ascii::space, uncommented_str_input);
380
381 iter = uncommented_str_input.begin();
382 end = uncommented_str_input.end();
383
385
386 SplitInputFile input_file;
387 phrase_parse(iter, end, spliter,boost::spirit::ascii::space, input_file);
388
389 return input_file;
390 }
391
392
393
397 std::tuple<std::string, std::string> SplitIntoConfigAndInput(Path const& input_file)
398 {
399 // Route through ParseInputFile, which runs the CommentStripper pass BEFORE splitting.
400 // Bertini 1 uses '%' as its comment marker; calling the raw SplitInputFileParser here --
401 // as this used to -- left '%' comments in the text, and the downstream system/settings
402 // parsers then choked ("parser did not consume entire input"). A classic input file
403 // with comments must parse, for backwards compatibility.
404 auto config_and_input = ParseInputFile(FileToString(input_file));
405 return std::make_tuple(config_and_input.Config(), config_and_input.Input());
406 }
407
408
412 void SplitIntoConfigAndInput(std::string & config_section, std::string & input_section, Path const& input_file)
413 {
414 std::tie(config_section, input_section) = SplitIntoConfigAndInput(input_file);
415 }
416
417
418 } // re: namespace classic
419
420 }// re: namespace parsing
421}// re: namespace bertini
Storage class for input file that splits up the config portion from the input portion.
Definition classic_utilities.hpp:59
void SetInput(std::string new_input)
Set the input portion.
Definition classic_utilities.hpp:83
friend std::ostream & operator<<(std::ostream &out, SplitInputFile const &printme)
Stream-insertion for a SplitInputFile, printing its config and input portions.
Definition classic_utilities.hpp:126
std::string Input() const
Get the input portion of the split input file.
Definition classic_utilities.hpp:70
bool Readable() const
Query whether the input file was readable.
Definition classic_utilities.hpp:76
void SetReadable(bool read)
Set whether the input file was readable.
Definition classic_utilities.hpp:102
void SetConfigInput(std::string c, std::string i)
Set both the config and input portions.
Definition classic_utilities.hpp:95
void SetConfig(std::string new_config)
Set the config portion.
Definition classic_utilities.hpp:89
std::string Config() const
Get the config portion of the split input file.
Definition classic_utilities.hpp:64
Provides the file_utilities screens for bertini2.
Definition classic_utilities.hpp:41
void ReportParseError(std::string::const_iterator begin, std::string::const_iterator end, std::string::const_iterator err_pos, boost::spirit::info const &what, std::string const &parser_name)
Report a parse error (via FormatParseError) to the log, for use in a Spirit on_error handler.
Definition qi_files.hpp:199
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:397
SplitInputFile ParseInputFile(std::string str_input_file)
Split a classic Bertini input file's contents into its config and input portions.
Definition classic_utilities.hpp:372
Definition classic_utilities.hpp:40
Definition algorithm_builder.hpp:36
std::string FileToString(Path const &input_path)
Read an entire file into a string.
Definition file_utilities.hpp:91
fs::path Path
Shorthand for a filesystem path.
Definition file_utilities.hpp:38
Provides all the include files needed to develop a parsing file that uses boost qi.
Qi Parser object for removing comments from a line of text and then returns the uncommented line.
Definition classic_utilities.hpp:317
CommentStripper()
Definition classic_utilities.hpp:320
Qi Parser object for parsing text into the SplitInputfile class.
Definition classic_utilities.hpp:182
SplitInputFileParser()
Definition classic_utilities.hpp:185