Aprepro  5.0x
aprepro.h
Go to the documentation of this file.
1 // Copyright (c) 2014-2017 National Technology & Engineering Solutions
2 // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with
3 // NTESS, the U.S. Government retains certain rights in this software.
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //
12 // * Redistributions in binary form must reproduce the above
13 // copyright notice, this list of conditions and the following
14 // disclaimer in the documentation and/or other materials provided
15 // with the distribution.
16 //
17 // * Neither the name of NTESS nor the names of its
18 // contributors may be used to endorse or promote products derived
19 // from this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 //
33 
34 // Might be good to add a callback function which would be called
35 // when there was output -- In LexerOutput for example. Default
36 // could be to just write to std::cout or to resultsOutput stringstream...
37 
38 #ifndef SEAMS_DRIVER_H
39 #define SEAMS_DRIVER_H
40 
41 #include <cstdlib>
42 #include <iostream>
43 #include <ostream>
44 #include <sstream>
45 #include <stack>
46 #include <string>
47 #include <vector>
48 
49 #include <cmath>
50 #ifndef math_errhandling
51 #define math_errhandling MATH_ERRNO
52 #endif
53 
54 /** The SEAMS namespace is used to encapsulate the three parser classes
55  * SEAMS::Parser, SEAMS::Scanner and SEAMS::Aprepro */
56 namespace SEAMS {
57 
58  struct array
59  {
60  std::vector<double> data;
61  int rows{0};
62  int cols{0};
63 
64  array(int r, int c) : rows(r), cols(c) { data.resize(r * c); }
65  array() = default;
66  ~array() = default;
67  };
68 
69  struct symrec
70  {
71  std::string name;
72  std::string syntax;
73  std::string info;
74  int type;
75  bool isInternal;
76  struct value
77  {
78  double var{0};
79  double (*fnctptr)(){nullptr};
80  double (*fnctptr_d)(double){nullptr};
81  double (*fnctptr_c)(char *){nullptr};
82  double (*fnctptr_dc)(double, char *){nullptr};
83  double (*fnctptr_cd)(char *, double){nullptr};
84  double (*fnctptr_cc)(char *, char *){nullptr};
85  double (*fnctptr_dd)(double, double){nullptr};
86  double (*fnctptr_ddd)(double, double, double){nullptr};
87  double (*fnctptr_ccc)(char *, char *, char *){nullptr};
88  double (*fnctptr_ccd)(char *, char *, double){nullptr};
89  double (*fnctptr_dddd)(double, double, double, double){nullptr};
90  double (*fnctptr_ddddc)(double, double, double, double, char *){nullptr};
91  double (*fnctptr_dddddd)(double, double, double, double, double, double){nullptr};
92  double (*fnctptr_a)(const array *){nullptr};
93  std::string svar;
94  const char *(*strfnct)(){nullptr};
95  const char *(*strfnct_c)(char *){nullptr};
96  const char *(*strfnct_d)(double){nullptr};
97  const char *(*strfnct_a)(const array *){nullptr};
98  const char *(*strfnct_dd)(double, double){nullptr};
99  const char *(*strfnct_cc)(char *, char *){nullptr};
100  const char *(*strfnct_ccc)(char *, char *, char *){nullptr};
101  const char *(*strfnct_dcc)(double, char *, char *){nullptr};
102  const char *(*strfnct_dcccc)(double, char *, char *, char *, char *){nullptr};
103  array *avar{nullptr}; /* Array Variable */
104  array *(*arrfnct_c)(const char *){nullptr};
105  array *(*arrfnct_cc)(const char *, const char *){nullptr};
106  array *(*arrfnct_cd)(const char *, double){nullptr};
107  array *(*arrfnct_dd)(double, double){nullptr};
108  array *(*arrfnct_d)(double){nullptr};
109  array *(*arrfnct_a)(const array *){nullptr};
110 
111  value() = default;
112  } value;
114 
115  symrec(const char *my_name, int my_type, bool is_internal = false)
116  : name(my_name), syntax(my_name), info("UNDEFINED"), type(my_type), isInternal(is_internal),
117  next(nullptr)
118  {
119  value.var = 0;
120  }
121 
122  symrec(const std::string &my_name, int my_type, bool is_internal = false)
123  : name(my_name), syntax(my_name), info("UNDEFINED"), type(my_type), isInternal(is_internal),
124  next(nullptr)
125  {
126  value.var = 0;
127  }
128  };
129 
130  /* Global options */
132  {
133  std::string include_path;
134  std::string include_file;
135  bool end_on_exit{false};
136  bool warning_msg{true};
137  bool info_msg{false};
138  bool debugging{false};
139  bool dumpvars{false};
140  bool interactive{false};
141  bool immutable{false};
142  bool trace_parsing{false}; // enable debug output in the bison parser
143  bool one_based_index{false};
144  bool keep_history{false}; // Flag to keep a history of Aprepro substitutions
145  aprepro_options() = default;
146  };
147 
148  /* Structure for holding file names and line counters */
149  struct file_rec
150  {
151  std::string name{"STDIN"};
152  int lineno{0};
153  int loop_count{0};
154  bool tmp_file{false};
155 
156  file_rec(const char *my_name, int line_num, bool is_temp, int loop_cnt)
157  : name(my_name), lineno(line_num), loop_count(loop_cnt), tmp_file(is_temp)
158  {
159  }
160  file_rec() = default;
161  };
162 
163  /* Structure for holding aprepro substitution info */
165  {
166  std::string original;
167  std::string substitution;
168  std::streampos index; // Character index in the output where the substitution begins.
169  };
170 
171  /** The Aprepro class brings together all components. It creates an instance of
172  * the Parser and Scanner classes and connects them. Then the input stream is
173  * fed into the scanner object and the parser gets it's token
174  * sequence. Furthermore the aprepro object is available in the grammar rules as
175  * a parameter. Therefore the aprepro class contains a reference to the
176  * structure into which the parsed data is saved. */
177  class Aprepro
178  {
179  public:
180  /// construct a new parser aprepro context
181  Aprepro();
182  ~Aprepro();
183 
184  enum class SYMBOL_TYPE {
185  VARIABLE = 1,
186  STRING_VARIABLE = 2,
187  UNDEFINED_VARIABLE = 5,
188  FUNCTION = 3,
189  STRING_FUNCTION = 4,
190  ARRAY_FUNCTION = 6,
191  ARRAY_VARIABLE = 7,
192  IMMUTABLE_VARIABLE = 11,
194  };
195 
196  bool state_is_immutable() const { return stateImmutable; }
197 
198  /** Return an std::ostringstream reference to get the results of
199  the parse_* call (* = stream, file, or string).
200  */
201  const std::ostringstream &parsing_results() const { return parsingResults; }
202  void clear_results();
203 
204  /** Return string representation of current version of aprepro. */
205  std::string version() const;
206 
207  /** Invoke the scanner and parser for a stream.
208  * @param in input stream
209  * @param in_name stream name for error messages
210  * @return true if successfully parsed
211  */
212  bool parse_stream(std::istream &in, const std::string &in_name = "stream input");
213 
214  /** Invoke the scanner and parser on an input string.
215  * @param input input string
216  * @param sname stream name for error messages
217  * @return true if successfully parsed
218  */
219  bool parse_string(const std::string &input, const std::string &sname = "string stream");
220 
221  /** Invoke the scanner and parser on a vector of strings.
222  * @param input vector of input strings
223  * @param sname stream name for error messages
224  * @return true if successfully parsed
225  */
226  bool parse_strings(const std::vector<std::string> &input, const std::string &sname);
227 
228  /** Invoke the scanner and parser on an input string in an
229  * interactive manner.
230  * @param input input stringInput
231  * @return true if successfully parsed
232  */
233  bool parse_string_interactive(const std::string &input);
234 
235  /** Get the string interactive flag, which indicates if we are in
236  * the middle of parsing a string in an interactive manner.
237  */
239 
240  /** Invoke the scanner and parser on a file. Use parse_stream with a
241  * std::ifstream if detection of file reading errors is required.
242  * @param filename input file name
243  * @return true if successfully parsed
244  */
245  bool parse_file(const std::string &filename);
246 
247  void statistics(std::ostream *out = nullptr) const;
248 
250  std::stack<file_rec> ap_file_list;
251 
252  std::stack<std::ostream *> outputStream;
253 
254  SEAMS::symrec *getsym(const char *sym_name) const;
255  SEAMS::symrec *getsym(const std::string &sym_name) const;
256  SEAMS::symrec *putsym(const std::string &sym_name, SYMBOL_TYPE sym_type, bool is_internal);
257 
258  void add_variable(const std::string &sym_name, const std::string &sym_value,
259  bool immutable = false, bool internal = false);
260  void add_variable(const std::string &sym_name, double sym_value, bool immutable = false,
261  bool internal = false);
262  void add_variable(const std::string &sym_name, array *value);
263 
264  std::vector<std::string> get_variable_names(bool doInternal = false);
265  void remove_variable(const std::string &sym_name);
266 
267  int set_option(const std::string &option, const std::string &optional_value = std::string(""));
268 
269  std::fstream *open_file(const std::string &file, const char *mode);
270  std::fstream *check_open_file(const std::string &file, const char *mode);
271 
272  /** Pointer to the current lexer instance, this is used to connect the
273  * parser to the scanner. It is used in the yylex macro. */
274  class Scanner *lexer{nullptr};
275 
276  /** Error handling. */
277  int get_error_count() const
278  {
279  return parseErrorCount;
280  } /** Return number of errors reported during parse */
281  void error(const std::string &msg, bool line_info = true, bool prefix = true) const;
282  void warning(const std::string &msg, bool line_info = true, bool prefix = true) const;
283  void info(const std::string &msg, bool line_info = false, bool prefix = true) const;
284 
285  // The info stream. To only print out info messages if the -M option was
286  // specified, use info(...) instead.
287  std::ostream *infoStream{&std::cout};
288 
289  void set_error_streams(std::ostream *c_error, std::ostream *c_warning, std::ostream *c_info);
290 
291  void dumpsym(const char *type, bool doInternal) const;
292  void dumpsym(int type, bool doInternal) const;
293  void dumpsym(int type, const char *pre, bool doInternal) const;
294 
295  private:
296  void init_table(const char *comment);
297  std::vector<symrec *> sym_table;
298  std::ostringstream parsingResults;
299 
300  // Input stream used with parse_string_interactive
301  std::istringstream stringInput;
302 
303  bool stringInteractive{false};
304  class Scanner *stringScanner{nullptr};
305 
306  // For error handling
307  std::ostream *errorStream{&std::cerr};
308  std::ostream *warningStream{&std::cerr};
309 
310  // For substitution history.
311  std::vector<history_data> history;
312 
313  mutable int parseErrorCount{0};
314 
315  public:
316  bool stateImmutable{false};
317 
318  // Flag to do Aprepro substitutions within loops. Default value is true. If set to
319  // false, content within the loop will be treated as verbatim text.
320  bool doLoopSubstitution{true};
321 
322  // Flag to do Aprepro substitutions when including a file. Default value is true.
323  // If set to false, content within the file will be treated as verbatim text that
324  // needs to be sent through Aprepro again later.
326 
327  // Flag to inidicate whether Aprepro is in the middle of collecting lines for a
328  // loop.
329  bool isCollectingLoop{false};
330 
331  // Record the substitution of the current Aprepro statement. This function will also
332  // reset the historyString and add an entry to the substitution map.
333  void add_history(const std::string &original, const std::string &substitution);
334 
335  // Used to avoid undefined variable warnings in old ifdef/ifndef construct
336  mutable bool inIfdefGetvar{false};
337 
338  const std::vector<history_data> &get_history();
339  void clear_history();
340  };
341 
342 } // namespace SEAMS
343 
344 #endif // SEAMS_DRIVER_H
symrec * next
Definition: aprepro.h:113
int parseErrorCount
Definition: aprepro.h:313
bool parse_strings(const std::vector< std::string > &input, const std::string &sname)
Definition: apr_aprepro.cc:141
int lineno
Definition: aprepro.h:152
void init_table(const char *comment)
Definition: apr_init.cc:376
Definition: aprepro.h:177
bool doLoopSubstitution
Definition: aprepro.h:320
std::string svar
Definition: aprepro.h:92
void set_error_streams(std::ostream *c_error, std::ostream *c_warning, std::ostream *c_info)
Definition: apr_aprepro.cc:242
std::ostream * infoStream
Definition: aprepro.h:287
bool parse_string_interactive(const std::string &input)
Definition: apr_aprepro.cc:150
std::stack< std::ostream * > outputStream
Definition: aprepro.h:252
std::string substitution
Definition: aprepro.h:167
symrec(const char *my_name, int my_type, bool is_internal=false)
Definition: aprepro.h:115
std::string include_path
Definition: aprepro.h:133
std::vector< std::string > get_variable_names(bool doInternal=false)
Definition: apr_aprepro.cc:575
Definition: aprepro.h:149
double(* fnctptr_dd)(double, double)
Definition: aprepro.h:85
const std::ostringstream & parsing_results() const
Definition: aprepro.h:201
bool immutable
Definition: aprepro.h:141
Definition: aprepro.h:69
~Aprepro()
Definition: apr_aprepro.cc:78
std::string original
Definition: aprepro.h:166
double(* fnctptr_ccd)(char *, char *, double)
Definition: aprepro.h:88
void clear_history()
Definition: apr_aprepro.cc:857
int type
Definition: aprepro.h:74
array()=default
void error(const std::string &msg, bool line_info=true, bool prefix=true) const
Definition: apr_aprepro.cc:180
void dumpsym(const char *type, bool doInternal) const
Definition: apr_aprepro.cc:664
bool warning_msg
Definition: aprepro.h:136
std::fstream * open_file(const std::string &file, const char *mode)
Definition: apr_aprepro.cc:264
bool interactive
Definition: aprepro.h:140
bool trace_parsing
Definition: aprepro.h:142
bool parse_file(const std::string &filename)
Definition: apr_aprepro.cc:126
aprepro_options ap_options
Definition: aprepro.h:249
bool isInternal
Definition: aprepro.h:75
bool parse_stream(std::istream &in, const std::string &in_name="stream input")
Definition: apr_aprepro.cc:107
struct SEAMS::symrec::value value
double(* fnctptr_d)(double)
Definition: aprepro.h:80
double(* fnctptr)()
Definition: aprepro.h:79
bool state_is_immutable() const
Definition: aprepro.h:196
int get_error_count() const
Definition: aprepro.h:277
void clear_results()
Definition: apr_aprepro.cc:101
bool one_based_index
Definition: aprepro.h:143
SYMBOL_TYPE
Definition: aprepro.h:184
std::string info
Definition: aprepro.h:73
~array()=default
std::istringstream stringInput
Definition: aprepro.h:301
void info(const std::string &msg, bool line_info=false, bool prefix=true) const
Definition: apr_aprepro.cc:221
double(* fnctptr_ddd)(double, double, double)
Definition: aprepro.h:86
double(* fnctptr_c)(char *)
Definition: aprepro.h:81
int rows
Definition: aprepro.h:61
bool isCollectingLoop
Definition: aprepro.h:329
bool inIfdefGetvar
Definition: aprepro.h:336
bool tmp_file
Definition: aprepro.h:154
const std::vector< history_data > & get_history()
Definition: apr_aprepro.cc:855
void statistics(std::ostream *out=nullptr) const
Definition: apr_aprepro.cc:779
std::streampos index
Definition: aprepro.h:168
array(int r, int c)
Definition: aprepro.h:64
bool stringInteractive
Definition: aprepro.h:303
bool stateImmutable
Definition: aprepro.h:316
SEAMS::symrec * getsym(const char *sym_name) const
Definition: apr_aprepro.cc:651
double(* fnctptr_cc)(char *, char *)
Definition: aprepro.h:84
double(* fnctptr_cd)(char *, double)
Definition: aprepro.h:83
std::string & comment()
Definition: apr_units.cc:50
std::ostream * warningStream
Definition: aprepro.h:308
bool parse_string(const std::string &input, const std::string &sname="string stream")
Definition: apr_aprepro.cc:135
class Scanner * lexer
Definition: aprepro.h:274
bool string_interactive()
Definition: aprepro.h:238
void add_variable(const std::string &sym_name, const std::string &sym_value, bool immutable=false, bool internal=false)
Definition: apr_aprepro.cc:512
void warning(const std::string &msg, bool line_info=true, bool prefix=true) const
Definition: apr_aprepro.cc:199
symrec(const std::string &my_name, int my_type, bool is_internal=false)
Definition: aprepro.h:122
std::ostringstream parsingResults
Definition: aprepro.h:298
SEAMS::symrec * putsym(const std::string &sym_name, SYMBOL_TYPE sym_type, bool is_internal)
Definition: apr_aprepro.cc:318
std::ostream * errorStream
Definition: aprepro.h:307
double(* fnctptr_ddddc)(double, double, double, double, char *)
Definition: aprepro.h:90
array * avar
Definition: aprepro.h:103
std::fstream * check_open_file(const std::string &file, const char *mode)
Definition: apr_aprepro.cc:297
std::string name
Definition: aprepro.h:151
Definition: aprepro.h:164
std::string include_file
Definition: aprepro.h:134
double(* fnctptr_dc)(double, char *)
Definition: aprepro.h:82
int loop_count
Definition: aprepro.h:153
int cols
Definition: aprepro.h:62
double(* fnctptr_dddd)(double, double, double, double)
Definition: aprepro.h:89
Definition: aprepro.h:131
bool doIncludeSubstitution
Definition: aprepro.h:325
std::string version() const
Definition: apr_aprepro.cc:99
Definition: aprepro.h:76
std::string syntax
Definition: aprepro.h:72
int set_option(const std::string &option, const std::string &optional_value=std::string(""))
Definition: apr_aprepro.cc:384
Definition: apr_scanner.h:27
std::vector< double > data
Definition: aprepro.h:60
Definition: apr_aprepro.cc:57
double(* fnctptr_a)(const array *)
Definition: aprepro.h:92
file_rec()=default
double var
Definition: aprepro.h:78
bool keep_history
Definition: aprepro.h:144
bool info_msg
Definition: aprepro.h:137
void remove_variable(const std::string &sym_name)
Definition: apr_aprepro.cc:605
bool end_on_exit
Definition: aprepro.h:135
Aprepro()
construct a new parser aprepro context
Definition: apr_aprepro.cc:70
double(* fnctptr_ccc)(char *, char *, char *)
Definition: aprepro.h:87
bool dumpvars
Definition: aprepro.h:139
class Scanner * stringScanner
Definition: aprepro.h:304
bool debugging
Definition: aprepro.h:138
double(* fnctptr_dddddd)(double, double, double, double, double, double)
Definition: aprepro.h:91
std::string name
Definition: aprepro.h:71
Definition: aprepro.h:58
std::vector< symrec * > sym_table
Definition: aprepro.h:297
void add_history(const std::string &original, const std::string &substitution)
Definition: apr_aprepro.cc:839
std::stack< file_rec > ap_file_list
Definition: aprepro.h:250
file_rec(const char *my_name, int line_num, bool is_temp, int loop_cnt)
Definition: aprepro.h:156
std::vector< history_data > history
Definition: aprepro.h:311