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