Aprepro 5.0x
Loading...
Searching...
No Matches
aprepro.h
Go to the documentation of this file.
1// Copyright(C) 1999-2024, 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// See packages/seacas/LICENSE for details
6
7// Might be good to add a callback function which would be called
8// when there was output -- In LexerOutput for example. Default
9// could be to just write to std::cout or to resultsOutput stringstream...
10#pragma once
11
12#include <cstdlib>
13#include <iostream>
14#include <memory>
15#include <ostream>
16#include <sstream>
17#include <stack>
18#include <string>
19#include <vector>
20
21#include "apr_symrec.h"
22
23#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || \
24 defined(__MINGW32__) || defined(_WIN64) || defined(__MINGW64__)
25#include <io.h>
26#define isatty _isatty
27#endif
28
29/** The SEAMS namespace is used to encapsulate the three parser classes
30 * SEAMS::Parser, SEAMS::Scanner and SEAMS::Aprepro */
31namespace SEAMS {
32
33 struct Symtable;
34
35 /* Global options */
37 {
38 std::string include_path{};
39 std::string include_file{};
40 bool end_on_exit{false};
41 bool errors_fatal{false};
43 bool require_defined{false}; // flag to treat undefined vars as errors
44 bool warning_msg{true};
45 bool info_msg{false};
46 bool debugging{false};
47 bool dumpvars{false};
48 bool dumpvars_json{false};
49 bool interactive{false};
50 bool immutable{false};
51 bool trace_parsing{false}; // enable debug output in the bison parser
52 bool one_based_index{false};
53 bool keep_history{false}; // Flag to keep a history of Aprepro substitutions
54 aprepro_options() = default;
55 };
56
57 /* Structure for holding file names and line counters */
58 struct file_rec
59 {
60 std::string name{"STDIN"};
61 symrec *loop_index{nullptr};
62 double loop_increment{1};
63 int lineno{1};
64 int loop_count{0};
65 int loop_level{0};
66 bool tmp_file{false};
67
68 file_rec(const char *my_name, int line_num, bool is_temp, int loop_cnt)
69 : name(my_name), lineno(line_num), loop_count(loop_cnt), tmp_file(is_temp)
70 {
71 }
72 file_rec() = default;
73 };
74
75 /* Structure for holding aprepro substitution info */
77 {
78 std::string original;
79 std::string substitution;
80 std::streampos index; // Character index in the output where the substitution begins.
81 };
82
83 /** The Aprepro class brings together all components. It creates an instance of
84 * the Parser and Scanner classes and connects them. Then the input stream is
85 * fed into the scanner object and the parser gets it's token
86 * sequence. Furthermore the aprepro object is available in the grammar rules as
87 * a parameter. Therefore the aprepro class contains a reference to the
88 * structure into which the parsed data is saved. */
89 class Aprepro
90 {
91 public:
92 /// construct a new parser aprepro context
93 Aprepro();
94 ~Aprepro();
95 Aprepro(const Aprepro &) = delete;
96 Aprepro &operator=(const Aprepro &) = delete;
97
98 enum class SYMBOL_TYPE {
99 INTERNAL = 0,
100 VARIABLE = 1,
101 STRING_VARIABLE = 2,
103 FUNCTION = 3,
104 STRING_FUNCTION = 4,
105 ARRAY_FUNCTION = 6,
106 ARRAY_VARIABLE = 7,
109 };
110
111 bool state_is_immutable() const { return stateImmutable; }
112
113 /** Return an std::ostringstream reference to get the results of
114 the parse_* call (* = stream, file, or string).
115 */
116 const std::ostringstream &parsing_results() const { return parsingResults; }
117 void clear_results();
118
119 /** Return string representation of current version of aprepro + commit date. */
120 static const std::string &version();
121
122 /** Return string representation of current version of aprepro. */
123 static const std::string &short_version();
124
125 /** Return long version: `# Algebraic Preprocessor (Aprepro) version X.X (date)` */
126 std::string long_version() const;
127
128 /** Invoke the scanner and parser for a stream.
129 * @param in input stream
130 * @param in_name stream name for error messages
131 * @return true if successfully parsed
132 */
133 bool parse_stream(std::istream &in, const std::string &in_name = "stream input");
134
135 /** Invoke the scanner and parser on an input string.
136 * @param input input string
137 * @param sname stream name for error messages
138 * @return true if successfully parsed
139 */
140 bool parse_string(const std::string &input, const std::string &sname = "string stream");
141
142 /** Invoke the scanner and parser on a vector of strings.
143 * @param input vector of input strings
144 * @param sname stream name for error messages
145 * @return true if successfully parsed
146 */
147 bool parse_strings(const std::vector<std::string> &input, const std::string &sname);
148
149 /** Invoke the scanner and parser on an input string in an
150 * interactive manner.
151 * @param input input stringInput
152 * @return true if successfully parsed
153 */
154 bool parse_string_interactive(const std::string &input);
155
156 /** Get the string interactive flag, which indicates if we are in
157 * the middle of parsing a string in an interactive manner.
158 */
159 bool string_interactive() const { return stringInteractive; }
160
161 /** Invoke the scanner and parser on a file. Use parse_stream with a
162 * std::ifstream if detection of file reading errors is required.
163 * @param filename input file name
164 * @return true if successfully parsed
165 */
166 bool parse_file(const std::string &filename);
167
168 void statistics(std::ostream *out = nullptr) const;
169
171 std::stack<file_rec> ap_file_list{};
172
173 std::stack<std::ostream *> outputStream{};
174
175 SYMBOL_TYPE get_symbol_type(const SEAMS::symrec *symbol) const;
176 SEAMS::symrec *getsym(const char *sym_name) const;
177 SEAMS::symrec *getsym(const std::string &sym_name) const;
178 SEAMS::symrec *putsym(const std::string &sym_name, SYMBOL_TYPE sym_type, bool is_internal);
179
180 void add_variable(const std::string &sym_name, const std::string &sym_value,
181 bool immutable = false, bool internal = false);
182 void add_variable(const std::string &sym_name, double sym_value, bool immutable = false,
183 bool internal = false);
184 void add_variable(const std::string &sym_name, array *value);
185
186 std::vector<std::string> get_variable_names(bool doInternal = false);
187 void remove_variable(const std::string &sym_name);
188
189 int set_option(const std::string &option, const std::string &optional_value = std::string(""));
190
191 std::fstream *open_file(const std::string &file, const char *mode);
192 std::fstream *check_open_file(const std::string &file, const char *mode);
193
194 /** Pointer to the current lexer instance, this is used to connect the
195 * parser to the scanner. It is used in the yylex macro. */
196 class Scanner *lexer{nullptr};
197
198 /** Error handling. */
199 int get_error_count() const
200 {
201 return parseErrorCount;
202 } /** Return number of errors reported during parse */
204 {
205 return parseWarningCount;
206 } /** Return number of warnings reported during parse */
207 void error(const std::string &msg, bool line_info = true, bool prefix = true) const;
208 void warning(const std::string &msg, bool line_info = true, bool prefix = true) const;
209 void info(const std::string &msg, bool line_info = false, bool prefix = true) const;
210
211 // The info stream. To only print out info messages if the -M option was
212 // specified, use info(...) instead.
213 bool closeInfo{false};
214 std::ostream *infoStream{&std::cout};
215
216 void set_error_streams(std::ostream *c_error, std::ostream *c_warning, std::ostream *c_info);
217 void set_error_streams(std::ostream *c_error, std::ostream *c_warning, std::ostream *c_info,
218 bool close_error, bool close_warning, bool close_info);
219
220 void dumpsym(const char *type, bool doInternal) const;
221 void dumpsym(int type, bool doInternal) const;
222 void dumpsym_json() const;
223 void dumpsym(int type, const char *pre, bool doInternal) const;
224
225 array *make_array(size_t r, size_t c);
226 array *make_array(const array &from);
227 void redefine_array(array *data);
228
229 private:
230 std::unique_ptr<Symtable> sym_table;
231
232 void init_table(const char *comment);
233 std::vector<array *> array_allocations{};
234 std::ostringstream parsingResults{};
235
236 // Input stream used with parse_string_interactive
237 std::istringstream stringInput{};
238
239 bool stringInteractive{false};
240 class Scanner *stringScanner{nullptr};
241
242 // For error handling
243 std::ostream *errorStream{&std::cerr};
244 std::ostream *warningStream{&std::cerr};
245 bool closeError{false};
246 bool closeWarning{false};
247
248 // For substitution history.
249 std::vector<history_data> history{};
250
251 // For repeatble and user-friendly help/dump output.
252 std::vector<SEAMS::symrec *> get_sorted_sym_table() const;
253
254 mutable int parseErrorCount{0};
255 mutable int parseWarningCount{0};
256
257 public:
258 bool stateImmutable{false};
259
260 // Flag to do Aprepro substitutions within loops. Default value is true. If set to
261 // false, content within the loop will be treated as verbatim text.
263
264 // Flag to do Aprepro substitutions when including a file. Default value is true.
265 // If set to false, content within the file will be treated as verbatim text that
266 // needs to be sent through Aprepro again later.
268
269 // Flag to indicate whether Aprepro is in the middle of collecting lines for a
270 // loop.
271 bool isCollectingLoop{false};
272
273 // Record the substitution of the current Aprepro statement. This function will also
274 // reset the historyString and add an entry to the substitution map.
275 void add_history(const std::string &original, const std::string &substitution);
276
277 // Used to avoid undefined variable warnings in old ifdef/ifndef construct
278 mutable bool inIfdefGetvar{false};
279
280 const std::vector<history_data> &get_history();
281 void clear_history();
282 };
283
284} // namespace SEAMS
Definition aprepro.h:90
bool closeError
Definition aprepro.h:245
bool closeWarning
Definition aprepro.h:246
std::unique_ptr< Symtable > sym_table
Definition aprepro.h:230
void error(const std::string &msg, bool line_info=true, bool prefix=true) const
Definition apr_aprepro.cc:223
~Aprepro()
Definition apr_aprepro.cc:101
class Scanner * lexer
Definition aprepro.h:196
std::string long_version() const
Definition apr_aprepro.cc:138
std::stack< file_rec > ap_file_list
Definition aprepro.h:171
bool stringInteractive
Definition aprepro.h:239
bool stateImmutable
Definition aprepro.h:258
const std::vector< history_data > & get_history()
Definition apr_aprepro.cc:921
std::ostream * errorStream
Definition aprepro.h:243
std::ostream * infoStream
Definition aprepro.h:214
SYMBOL_TYPE get_symbol_type(const SEAMS::symrec *symbol) const
Definition apr_aprepro.cc:368
void clear_history()
Definition apr_aprepro.cc:923
void dumpsym_json() const
Definition apr_aprepro.cc:777
std::vector< history_data > history
Definition aprepro.h:249
void warning(const std::string &msg, bool line_info=true, bool prefix=true) const
Definition apr_aprepro.cc:241
int parseErrorCount
Definition aprepro.h:254
void add_history(const std::string &original, const std::string &substitution)
Definition apr_aprepro.cc:905
std::stack< std::ostream * > outputStream
Definition aprepro.h:173
bool state_is_immutable() const
Definition aprepro.h:111
bool parse_strings(const std::vector< std::string > &input, const std::string &sname)
Definition apr_aprepro.cc:184
bool parse_stream(std::istream &in, const std::string &in_name="stream input")
Definition apr_aprepro.cc:150
array * make_array(size_t r, size_t c)
Definition apr_aprepro.cc:635
void statistics(std::ostream *out=nullptr) const
Definition apr_aprepro.cc:900
int set_option(const std::string &option, const std::string &optional_value=std::string(""))
Definition apr_aprepro.cc:472
Aprepro()
construct a new parser aprepro context
Definition apr_aprepro.cc:92
bool string_interactive() const
Definition aprepro.h:159
SEAMS::symrec * getsym(const char *sym_name) const
Definition apr_aprepro.cc:761
Aprepro(const Aprepro &)=delete
static const std::string & version()
Definition apr_aprepro.cc:135
bool inIfdefGetvar
Definition aprepro.h:278
void set_error_streams(std::ostream *c_error, std::ostream *c_warning, std::ostream *c_info)
Definition apr_aprepro.cc:302
std::vector< array * > array_allocations
Definition aprepro.h:233
void clear_results()
Definition apr_aprepro.cc:144
int get_error_count() const
Definition aprepro.h:199
const std::ostringstream & parsing_results() const
Definition aprepro.h:116
SYMBOL_TYPE
Definition aprepro.h:98
std::istringstream stringInput
Definition aprepro.h:237
std::vector< std::string > get_variable_names(bool doInternal=false)
Definition apr_aprepro.cc:715
std::ostringstream parsingResults
Definition aprepro.h:234
SEAMS::symrec * putsym(const std::string &sym_name, SYMBOL_TYPE sym_type, bool is_internal)
Definition apr_aprepro.cc:384
bool doLoopSubstitution
Definition aprepro.h:262
int parseWarningCount
Definition aprepro.h:255
void init_table(const char *comment)
Definition apr_init.cc:392
void add_variable(const std::string &sym_name, const std::string &sym_value, bool immutable=false, bool internal=false)
Definition apr_aprepro.cc:658
void redefine_array(array *data)
Definition apr_aprepro.cc:649
bool parse_string_interactive(const std::string &input)
Definition apr_aprepro.cc:193
bool closeInfo
Definition aprepro.h:213
bool isCollectingLoop
Definition aprepro.h:271
std::fstream * check_open_file(const std::string &file, const char *mode)
Definition apr_aprepro.cc:348
bool parse_file(const std::string &filename)
Definition apr_aprepro.cc:169
class Scanner * stringScanner
Definition aprepro.h:240
bool doIncludeSubstitution
Definition aprepro.h:267
aprepro_options ap_options
Definition aprepro.h:170
std::ostream * warningStream
Definition aprepro.h:244
static const std::string & short_version()
Definition apr_aprepro.cc:136
std::fstream * open_file(const std::string &file, const char *mode)
Definition apr_aprepro.cc:316
bool parse_string(const std::string &input, const std::string &sname="string stream")
Definition apr_aprepro.cc:178
void remove_variable(const std::string &sym_name)
Definition apr_aprepro.cc:743
Aprepro & operator=(const Aprepro &)=delete
std::vector< SEAMS::symrec * > get_sorted_sym_table() const
Definition apr_aprepro.cc:930
int get_warning_count() const
Definition aprepro.h:203
void dumpsym(const char *type, bool doInternal) const
Definition apr_aprepro.cc:765
void info(const std::string &msg, bool line_info=false, bool prefix=true) const
Definition apr_aprepro.cc:264
Definition apr_scanner.h:34
Definition apr_aprepro.cc:57
Definition aprepro.h:37
bool trace_parsing
Definition aprepro.h:51
bool dumpvars
Definition aprepro.h:47
bool one_based_index
Definition aprepro.h:52
bool info_msg
Definition aprepro.h:45
std::string include_path
Definition aprepro.h:38
bool keep_history
Definition aprepro.h:53
bool end_on_exit
Definition aprepro.h:40
bool errors_fatal
Definition aprepro.h:41
bool errors_and_warnings_fatal
Definition aprepro.h:42
bool immutable
Definition aprepro.h:50
bool debugging
Definition aprepro.h:46
bool warning_msg
Definition aprepro.h:44
bool require_defined
Definition aprepro.h:43
std::string include_file
Definition aprepro.h:39
bool dumpvars_json
Definition aprepro.h:48
bool interactive
Definition aprepro.h:49
Definition apr_symrec.h:17
Definition aprepro.h:59
symrec * loop_index
Definition aprepro.h:61
file_rec()=default
int loop_count
Definition aprepro.h:64
std::string name
Definition aprepro.h:60
double loop_increment
Definition aprepro.h:62
int lineno
Definition aprepro.h:63
bool tmp_file
Definition aprepro.h:66
int loop_level
Definition aprepro.h:65
file_rec(const char *my_name, int line_num, bool is_temp, int loop_cnt)
Definition aprepro.h:68
Definition aprepro.h:77
std::streampos index
Definition aprepro.h:80
std::string substitution
Definition aprepro.h:79
std::string original
Definition aprepro.h:78
Definition apr_symrec.h:26