1 /*
2 * Copyright © 2006-2020 Dynare Team
3 *
4 * This file is part of Dynare.
5 *
6 * Dynare is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * Dynare is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with Dynare. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "Statement.hh"
21 #pragma GCC diagnostic push
22 #pragma GCC diagnostic ignored "-Wold-style-cast"
23 #include <boost/xpressive/xpressive.hpp>
24 #pragma GCC diagnostic pop
25 #include <utility>
26
27 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)28 Statement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
29 {
30 }
31
32 void
writeJuliaOutput(ostream & output,const string & basename)33 Statement::writeJuliaOutput(ostream &output, const string &basename)
34 {
35 }
36
37 void
writeJsonOutput(ostream & output) const38 Statement::writeJsonOutput(ostream &output) const
39 {
40 }
41
42 void
computingPass()43 Statement::computingPass()
44 {
45 }
46
NativeStatement(string native_statement_arg)47 NativeStatement::NativeStatement(string native_statement_arg) :
48 native_statement{move(native_statement_arg)}
49 {
50 }
51
52 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const53 NativeStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
54 {
55 using namespace boost::xpressive;
56 string date_regex = R"((-?\d+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4])))";
57 sregex regex_lookbehind = sregex::compile(R"((?<!\$|\d|[a-zA-Z_]|-|'))" + date_regex);
58 sregex regex_dollar = sregex::compile(R"((\$))" + date_regex);
59
60 string ns = regex_replace(native_statement, regex_lookbehind, "dates('$&')");
61 ns = regex_replace(ns, regex_dollar, "$2"); //replace $DATE with DATE
62 output << ns << endl;
63 }
64
65 void
writeJsonOutput(ostream & output) const66 NativeStatement::writeJsonOutput(ostream &output) const
67 {
68 output << R"({"statementName": "native")"
69 << R"(, "string": ")" << native_statement << R"(")"
70 << "}";
71 }
72
VerbatimStatement(string verbatim_statement_arg)73 VerbatimStatement::VerbatimStatement(string verbatim_statement_arg) :
74 verbatim_statement{move(verbatim_statement_arg)}
75 {
76 }
77
78 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const79 VerbatimStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
80 {
81 output << verbatim_statement << endl;
82 }
83
84 void
writeJsonOutput(ostream & output) const85 VerbatimStatement::writeJsonOutput(ostream &output) const
86 {
87 output << R"({"statementName": "verbatim")"
88 << R"(, "string": ")" << verbatim_statement << R"(")"
89 << "}";
90 }
91
92 void
writeOutput(ostream & output) const93 OptionsList::writeOutput(ostream &output) const
94 {
95 for (const auto & [name, val] : num_options)
96 output << "options_." << name << " = " << val << ";" << endl;
97
98 for (const auto & [name, vals] : paired_num_options)
99 output << "options_." << name << " = [" << vals.first << "; "
100 << vals.second << "];" << endl;
101
102 for (const auto & [name, val] : string_options)
103 output << "options_." << name << " = '" << val << "';" << endl;
104
105 for (const auto & [name, val] : date_options)
106 output << "options_." << name << " = " << val << ";" << endl;
107
108 for (const auto & [name, list] : symbol_list_options)
109 list.writeOutput("options_." + name, output);
110
111 for (const auto & [name, vals] : vector_int_options)
112 {
113 output << "options_." << name << " = ";
114 if (vals.size() > 1)
115 {
116 output << "[";
117 for (int viit : vals)
118 output << viit << ";";
119 output << "];" << endl;
120 }
121 else
122 output << vals.front() << ";" << endl;
123 }
124
125 for (const auto & [name, vals] : vector_str_options)
126 {
127 output << "options_." << name << " = ";
128 if (vals.size() > 1)
129 {
130 output << "{";
131 for (const auto &viit : vals)
132 output << "'" << viit << "';";
133 output << "};" << endl;
134 }
135 else
136 output << vals.front() << ";" << endl;
137 }
138 }
139
140 void
writeOutput(ostream & output,const string & option_group) const141 OptionsList::writeOutput(ostream &output, const string &option_group) const
142 {
143 // Initialize option_group as an empty struct iff the field does not exist!
144 if (size_t idx = option_group.find_last_of(".");
145 idx != string::npos)
146 {
147 output << "if ~isfield(" << option_group.substr(0, idx) << ",'" << option_group.substr(idx+1) << "')" << endl;
148 output << " " << option_group << " = struct();" << endl;
149 output << "end" << endl;
150 }
151 else
152 output << option_group << " = struct();" << endl;
153
154 for (const auto & [name, val] : num_options)
155 output << option_group << "." << name << " = " << val << ";" << endl;
156
157 for (const auto & [name, vals] : paired_num_options)
158 output << option_group << "." << name << " = [" << vals.first << "; "
159 << vals.second << "];" << endl;
160
161 for (const auto & [name, val] : string_options)
162 output << option_group << "." << name << " = '" << val << "';" << endl;
163
164 for (const auto & [name, val] : date_options)
165 output << option_group << "." << name << " = " << val << ";" << endl;
166
167 for (const auto & [name, list] : symbol_list_options)
168 list.writeOutput(option_group + "." + name, output);
169
170 for (const auto & [name, vals] : vector_int_options)
171 {
172 output << option_group << "." << name << " = ";
173 if (vals.size() > 1)
174 {
175 output << "[";
176 for (int viit : vals)
177 output << viit << ";";
178 output << "];" << endl;
179 }
180 else
181 output << vals.front() << ";" << endl;
182 }
183
184 for (const auto & [name, vals] : vector_str_options)
185 {
186 output << option_group << "." << name << " = ";
187 if (vals.size() > 1)
188 {
189 output << "{";
190 for (const auto &viit : vals)
191 output << "'" << viit << "';";
192 output << "};" << endl;
193 }
194 else
195 output << vals.front() << ";" << endl;
196 }
197 }
198
199 void
writeJsonOutput(ostream & output) const200 OptionsList::writeJsonOutput(ostream &output) const
201 {
202 if (getNumberOfOptions() == 0)
203 return;
204
205 output << R"("options": {)";
206 for (auto it = num_options.begin();
207 it != num_options.end();)
208 {
209 output << R"(")"<< it->first << R"(": )" << it->second;
210 ++it;
211 if (it != num_options.end()
212 || !(paired_num_options.empty()
213 && string_options.empty()
214 && date_options.empty()
215 && symbol_list_options.empty()
216 && vector_int_options.empty()))
217 output << ", ";
218 }
219
220 for (auto it = paired_num_options.begin();
221 it != paired_num_options.end();)
222 {
223 output << R"(")"<< it->first << R"(": [)" << it->second.first << " " << it->second.second << "]";
224 ++it;
225 if (it != paired_num_options.end()
226 || !(string_options.empty()
227 && date_options.empty()
228 && symbol_list_options.empty()
229 && vector_int_options.empty()))
230 output << ", ";
231 }
232
233 for (auto it = string_options.begin();
234 it != string_options.end();)
235 {
236 output << R"(")"<< it->first << R"(": ")" << it->second << R"(")";
237 ++it;
238 if (it != string_options.end()
239 || !(date_options.empty()
240 && symbol_list_options.empty()
241 && vector_int_options.empty()))
242 output << ", ";
243 }
244
245 for (auto it = date_options.begin();
246 it != date_options.end();)
247 {
248 output << R"(")"<< it->first << R"(": ")" << it->second << R"(")";
249 ++it;
250 if (it != date_options.end()
251 || !(symbol_list_options.empty()
252 && vector_int_options.empty()))
253 output << ", ";
254 }
255
256 for (auto it = symbol_list_options.begin();
257 it != symbol_list_options.end();)
258 {
259 output << R"(")"<< it->first << R"(": {)";
260 it->second.writeJsonOutput(output);
261 output << "}";
262 ++it;
263 if (it != symbol_list_options.end()
264 || !vector_int_options.empty())
265 output << ", ";
266 }
267
268 for (auto it = vector_int_options.begin();
269 it != vector_int_options.end();)
270 {
271 output << R"(")"<< it->first << R"(": [)";
272 if (it->second.size() > 1)
273 {
274 for (auto viit = it->second.begin();
275 viit != it->second.end();)
276 {
277 output << *viit;
278 ++viit;
279 if (viit != it->second.end())
280 output << ", ";
281 }
282 }
283 else
284 output << it->second.front() << endl;
285 output << "]";
286 ++it;
287 if (it != vector_int_options.end())
288 output << ", ";
289 }
290
291 for (auto it = vector_str_options.begin();
292 it != vector_str_options.end();)
293 {
294 output << R"(")"<< it->first << R"(": [)";
295 if (it->second.size() > 1)
296 {
297 for (auto viit = it->second.begin();
298 viit != it->second.end();)
299 {
300 output << R"(")" << *viit << R"(")";
301 ++viit;
302 if (viit != it->second.end())
303 output << ", ";
304 }
305 }
306 else
307 output << it->second.front() << endl;
308 output << "]";
309 ++it;
310 if (it != vector_str_options.end())
311 output << ", ";
312 }
313
314 output << "}";
315 }
316
317 void
clear()318 OptionsList::clear()
319 {
320 num_options.clear();
321 paired_num_options.clear();
322 string_options.clear();
323 date_options.clear();
324 symbol_list_options.clear();
325 vector_int_options.clear();
326 vector_str_options.clear();
327 }
328
329 int
getNumberOfOptions() const330 OptionsList::getNumberOfOptions() const
331 {
332 return num_options.size()
333 + paired_num_options.size()
334 + string_options.size()
335 + date_options.size()
336 + symbol_list_options.size()
337 + vector_int_options.size()
338 + vector_str_options.size();
339 }
340