1 /*
2  * Copyright © 2003-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 <fstream>
21 #include <iostream>
22 #include <cassert>
23 #include <sstream>
24 #include <cmath>
25 
26 #include "ParsingDriver.hh"
27 #include "Statement.hh"
28 #include "ExprNode.hh"
29 #include "WarningConsolidation.hh"
30 
31 bool
symbol_exists_and_is_not_modfile_local_or_external_function(const string & s)32 ParsingDriver::symbol_exists_and_is_not_modfile_local_or_external_function(const string &s)
33 {
34   if (!mod_file->symbol_table.exists(s))
35     return false;
36 
37   SymbolType type = mod_file->symbol_table.getType(s);
38 
39   return type != SymbolType::modFileLocalVariable && type != SymbolType::externalFunction;
40 }
41 
42 void
check_symbol_existence_in_model_block(const string & name)43 ParsingDriver::check_symbol_existence_in_model_block(const string &name)
44 {
45   if (!mod_file->symbol_table.exists(name)
46       || undeclared_model_vars.find(name) != undeclared_model_vars.end())
47     undeclared_model_variable_error("Unknown symbol: " + name, name);
48 }
49 
50 void
check_symbol_existence(const string & name)51 ParsingDriver::check_symbol_existence(const string &name)
52 {
53   if (!mod_file->symbol_table.exists(name))
54     error("Unknown symbol: " + name + ".\nIf referenced from the 'initval', 'endval', 'histval', or 'shocks' block, you can pass the 'nostrict' option to dynare to have this line ignored.");
55 }
56 
57 void
check_symbol_is_parameter(const string & name)58 ParsingDriver::check_symbol_is_parameter(const string &name)
59 {
60   check_symbol_existence(name);
61   int symb_id = mod_file->symbol_table.getID(name);
62   if (mod_file->symbol_table.getType(symb_id) != SymbolType::parameter)
63     error(name + " is not a parameter");
64 }
65 
66 void
set_current_data_tree(DataTree * data_tree_arg)67 ParsingDriver::set_current_data_tree(DataTree *data_tree_arg)
68 {
69   data_tree = data_tree_arg;
70   model_tree = dynamic_cast<ModelTree *>(data_tree_arg);
71   dynamic_model = dynamic_cast<DynamicModel *>(data_tree_arg);
72 }
73 
74 void
reset_data_tree()75 ParsingDriver::reset_data_tree()
76 {
77   set_current_data_tree(&mod_file->expressions_tree);
78 }
79 
80 void
reset_current_external_function_options()81 ParsingDriver::reset_current_external_function_options()
82 {
83   current_external_function_options.nargs = ExternalFunctionsTable::defaultNargs;
84   current_external_function_options.firstDerivSymbID = ExternalFunctionsTable::IDNotSet;
85   current_external_function_options.secondDerivSymbID = ExternalFunctionsTable::IDNotSet;
86   current_external_function_id = ExternalFunctionsTable::IDNotSet;
87 }
88 
89 unique_ptr<ModFile>
parse(istream & in,bool debug)90 ParsingDriver::parse(istream &in, bool debug)
91 {
92   mod_file = make_unique<ModFile>(warnings);
93 
94   symbol_list.setSymbolTable(mod_file->symbol_table);
95 
96   reset_data_tree();
97   estim_params.init(*data_tree);
98   osr_params.init(*data_tree);
99   reset_current_external_function_options();
100 
101   lexer = make_unique<DynareFlex>(&in);
102   lexer->set_debug(debug);
103 
104   Dynare::parser parser(*this);
105   parser.set_debug_level(debug);
106   parser.parse();
107 
108   return move(mod_file);
109 }
110 
111 void
error(const Dynare::parser::location_type & l,const string & m)112 ParsingDriver::error(const Dynare::parser::location_type &l, const string &m)
113 {
114   create_error_string(l, m, cerr);
115   exit(EXIT_FAILURE);
116 }
117 
118 void
error(const string & m)119 ParsingDriver::error(const string &m)
120 {
121   error(location, m);
122 }
123 
124 void
create_error_string(const Dynare::parser::location_type & l,const string & m,ostream & stream)125 ParsingDriver::create_error_string(const Dynare::parser::location_type &l, const string &m, ostream &stream)
126 {
127   stream << "ERROR: " << *l.begin.filename << ": line " << l.begin.line;
128   if (l.begin.line == l.end.line)
129     if (l.begin.column == l.end.column - 1)
130       stream << ", col " << l.begin.column;
131     else
132       stream << ", cols " << l.begin.column << "-" << l.end.column - 1;
133   else
134     stream << ", col " << l.begin.column << " -"
135            << " line " << l.end.line << ", col " << l.end.column - 1;
136   stream << ": " << m << endl;
137 }
138 
139 void
create_error_string(const Dynare::parser::location_type & l,const string & m,const string & var)140 ParsingDriver::create_error_string(const Dynare::parser::location_type &l, const string &m, const string &var)
141 {
142   ostringstream stream;
143   create_error_string(l, m, stream);
144   model_errors.emplace_back(var, stream.str());
145 }
146 
147 void
model_error(const string & m,const string & var)148 ParsingDriver::model_error(const string &m, const string &var)
149 {
150   create_error_string(location, m, var);
151 }
152 
153 void
undeclared_model_variable_error(const string & m,const string & var)154 ParsingDriver::undeclared_model_variable_error(const string &m, const string &var)
155 {
156   ostringstream stream;
157   if (!nostrict)
158     {
159       stream << "ERROR: " << *location.begin.filename << ": line " << location.begin.line;
160       if (location.begin.line == location.end.line)
161         if (location.begin.column == location.end.column - 1)
162           stream << ", col " << location.begin.column;
163         else
164           stream << ", cols " << location.begin.column << "-" << location.end.column - 1;
165       else
166         stream << ", col " << location.begin.column << " -"
167                << " line " << location.end.line << ", col " << location.end.column - 1;
168       stream << ": ";
169     }
170   stream << m;
171   if (nostrict)
172     stream << " automatically declared exogenous.";
173   undeclared_model_variable_errors.emplace_back(var, stream.str());
174 }
175 
176 void
warning(const string & m)177 ParsingDriver::warning(const string &m)
178 {
179   warnings << "WARNING: " << location << ": " << m << endl;
180 }
181 
182 void
declare_symbol(const string & name,SymbolType type,const string & tex_name,const vector<pair<string,string>> & partition_value)183 ParsingDriver::declare_symbol(const string &name, SymbolType type, const string &tex_name, const vector<pair<string, string>> &partition_value)
184 {
185   try
186     {
187       mod_file->symbol_table.addSymbol(name, type, tex_name, partition_value);
188     }
189   catch (SymbolTable::AlreadyDeclaredException &e)
190     {
191       if (e.same_type)
192         warning("Symbol " + name + " declared twice.");
193       else
194         error("Symbol " + name + " declared twice with different types!");
195     }
196 }
197 
198 void
declare_endogenous(const string & name,const string & tex_name,const vector<pair<string,string>> & partition_value)199 ParsingDriver::declare_endogenous(const string &name, const string &tex_name, const vector<pair<string, string>> &partition_value)
200 {
201   declare_symbol(name, SymbolType::endogenous, tex_name, partition_value);
202 }
203 
204 void
declare_var_endogenous(const string & name)205 ParsingDriver::declare_var_endogenous(const string &name)
206 {
207   if (mod_file->symbol_table.exists(name))
208     {
209       SymbolType type = mod_file->symbol_table.getType(name);
210       if (type != SymbolType::endogenous && type != SymbolType::exogenous && type != SymbolType::exogenousDet)
211         error("Symbol " + name + " used in a VAR must be either endogenous or "
212               +"exogenous if it is also used elsewhere in the .mod file");
213       add_in_symbol_list(name);
214       return;
215     }
216 
217   declare_symbol(name, SymbolType::endogenousVAR, "", {});
218   add_in_symbol_list(name);
219 }
220 
221 void
declare_exogenous(const string & name,const string & tex_name,const vector<pair<string,string>> & partition_value)222 ParsingDriver::declare_exogenous(const string &name, const string &tex_name, const vector<pair<string, string>> &partition_value)
223 {
224   declare_symbol(name, SymbolType::exogenous, tex_name, partition_value);
225 }
226 
227 void
declare_exogenous_det(const string & name,const string & tex_name,const vector<pair<string,string>> & partition_value)228 ParsingDriver::declare_exogenous_det(const string &name, const string &tex_name, const vector<pair<string, string>> &partition_value)
229 {
230   declare_symbol(name, SymbolType::exogenousDet, tex_name, partition_value);
231 }
232 
233 void
declare_parameter(const string & name,const string & tex_name,const vector<pair<string,string>> & partition_value)234 ParsingDriver::declare_parameter(const string &name, const string &tex_name, const vector<pair<string, string>> &partition_value)
235 {
236   declare_symbol(name, SymbolType::parameter, tex_name, partition_value);
237 }
238 
239 void
declare_statement_local_variable(const string & name)240 ParsingDriver::declare_statement_local_variable(const string &name)
241 {
242   if (mod_file->symbol_table.exists(name))
243     error("Symbol " + name + " cannot be assigned within a statement "
244           +"while being assigned elsewhere in the modfile");
245   declare_symbol(name, SymbolType::statementDeclaredVariable, "", {});
246 }
247 
248 void
set_planner_discount(expr_t value)249 ParsingDriver::set_planner_discount(expr_t value)
250 {
251   planner_discount = value;
252 }
253 
254 void
set_planner_discount_latex_name(string tex_name)255 ParsingDriver::set_planner_discount_latex_name(string tex_name)
256 {
257   planner_discount_latex_name = move(tex_name);
258 }
259 
260 void
begin_trend()261 ParsingDriver::begin_trend()
262 {
263   set_current_data_tree(&mod_file->dynamic_model);
264 }
265 
266 void
declare_trend_var(bool log_trend,const string & name,const string & tex_name)267 ParsingDriver::declare_trend_var(bool log_trend, const string &name, const string &tex_name)
268 {
269   declare_symbol(name, log_trend ? SymbolType::logTrend : SymbolType::trend, tex_name, {});
270   declared_trend_vars.push_back(mod_file->symbol_table.getID(name));
271 }
272 
273 void
end_trend_var(expr_t growth_factor)274 ParsingDriver::end_trend_var(expr_t growth_factor)
275 {
276   try
277     {
278       dynamic_model->addTrendVariables(declared_trend_vars, growth_factor);
279     }
280   catch (DataTree::TrendException &e)
281     {
282       error("Trend variable " + e.name + " was declared twice.");
283     }
284   declared_trend_vars.clear();
285   reset_data_tree();
286 }
287 
288 void
add_predetermined_variable(const string & name)289 ParsingDriver::add_predetermined_variable(const string &name)
290 {
291   check_symbol_is_endogenous(name);
292   int symb_id = mod_file->symbol_table.getID(name);
293   mod_file->symbol_table.markPredetermined(symb_id);
294 }
295 
296 void
add_equation_tags(string key,string value)297 ParsingDriver::add_equation_tags(string key, string value)
298 {
299   eq_tags.emplace_back(key, value);
300 
301   transform(key.begin(), key.end(), key.begin(), ::tolower);
302   if (key.compare("endogenous") == 0)
303     declare_or_change_type(SymbolType::endogenous, value);
304 }
305 
306 expr_t
add_non_negative_constant(const string & constant)307 ParsingDriver::add_non_negative_constant(const string &constant)
308 {
309   return data_tree->AddNonNegativeConstant(constant);
310 }
311 
312 expr_t
add_nan_constant()313 ParsingDriver::add_nan_constant()
314 {
315   return data_tree->NaN;
316 }
317 
318 expr_t
add_inf_constant()319 ParsingDriver::add_inf_constant()
320 {
321   return data_tree->Infinity;
322 }
323 
324 expr_t
add_model_variable(const string & name)325 ParsingDriver::add_model_variable(const string &name)
326 {
327   if (name.find(".") != string::npos)
328     error(name + " treated as a variable, but it contains a '.'");
329 
330   check_symbol_existence_in_model_block(name);
331   int symb_id;
332   try
333     {
334       symb_id = mod_file->symbol_table.getID(name);
335     }
336   catch (SymbolTable::UnknownSymbolNameException &e)
337     {
338       // Declare variable as exogenous to continue parsing
339       // processing will end at end of model block if nostrict option was not passed
340       declare_exogenous(name);
341       undeclared_model_vars.insert(name);
342       symb_id = mod_file->symbol_table.getID(name);
343     }
344   return add_model_variable(symb_id, 0);
345 }
346 
347 expr_t
declare_or_change_type(SymbolType new_type,const string & name)348 ParsingDriver::declare_or_change_type(SymbolType new_type, const string &name)
349 {
350   int symb_id;
351   try
352     {
353       symb_id = mod_file->symbol_table.getID(name);
354       mod_file->symbol_table.changeType(symb_id, new_type);
355 
356       // remove error messages
357       undeclared_model_vars.erase(name);
358       for (auto it = undeclared_model_variable_errors.begin();
359            it != undeclared_model_variable_errors.end();)
360         if (it->first == name)
361           it = undeclared_model_variable_errors.erase(it);
362         else
363           ++it;
364     }
365   catch (SymbolTable::UnknownSymbolNameException &e)
366     {
367       switch (new_type)
368         {
369         case SymbolType::endogenous:
370           declare_endogenous(name);
371           break;
372         case SymbolType::exogenous:
373           declare_exogenous(name);
374           break;
375         case SymbolType::parameter:
376           declare_parameter(name);
377           break;
378         default:
379           error("Type not yet supported");
380         }
381       symb_id = mod_file->symbol_table.getID(name);
382     }
383   return add_model_variable(symb_id, 0);
384 
385 }
386 
387 expr_t
add_model_variable(int symb_id,int lag)388 ParsingDriver::add_model_variable(int symb_id, int lag)
389 {
390   assert(symb_id >= 0);
391   SymbolType type = mod_file->symbol_table.getType(symb_id);
392 
393   if (type == SymbolType::modFileLocalVariable)
394     error("Variable " + mod_file->symbol_table.getName(symb_id)
395           +" not allowed inside model declaration. Its scope is only outside model.");
396 
397   if (type == SymbolType::externalFunction)
398     error("Symbol " + mod_file->symbol_table.getName(symb_id)
399           +" is a function name external to Dynare. It cannot be used like a variable without input argument inside model.");
400 
401   if (type == SymbolType::modelLocalVariable && lag != 0)
402     error("Model local variable " + mod_file->symbol_table.getName(symb_id) + " cannot be given a lead or a lag.");
403 
404   if (dynamic_cast<StaticModel *>(model_tree) && lag != 0)
405     error("Leads and lags on variables are forbidden in 'planner_objective'.");
406 
407   if (dynamic_cast<StaticModel *>(model_tree) && type == SymbolType::modelLocalVariable)
408     error("Model local variable " + mod_file->symbol_table.getName(symb_id) + " cannot be used in 'planner_objective'.");
409 
410   // It makes sense to allow a lead/lag on parameters: during steady state calibration, endogenous and parameters can be swapped
411   return model_tree->AddVariable(symb_id, lag);
412 }
413 
414 expr_t
add_expression_variable(const string & name)415 ParsingDriver::add_expression_variable(const string &name)
416 {
417   if (name.find(".") != string::npos)
418     error(name + " treated as a variable, but it contains a '.'");
419 
420   if (parsing_epilogue && !mod_file->symbol_table.exists(name))
421     error("Variable " + name + " used in the epilogue block but was not declared.");
422 
423   // If symbol doesn't exist, then declare it as a mod file local variable
424   if (!mod_file->symbol_table.exists(name))
425     mod_file->symbol_table.addSymbol(name, SymbolType::modFileLocalVariable);
426 
427   // This check must come after the previous one!
428   if (mod_file->symbol_table.getType(name) == SymbolType::modelLocalVariable)
429     error("Variable " + name + " not allowed outside model declaration. Its scope is only inside model.");
430 
431   if (mod_file->symbol_table.getType(name) == SymbolType::trend
432       || mod_file->symbol_table.getType(name) == SymbolType::logTrend)
433     error("Variable " + name + " not allowed outside model declaration, because it is a trend variable.");
434 
435   if (mod_file->symbol_table.getType(name) == SymbolType::externalFunction)
436     error("Symbol '" + name + "' is the name of a MATLAB/Octave function, and cannot be used as a variable.");
437 
438   int symb_id = mod_file->symbol_table.getID(name);
439   return data_tree->AddVariable(symb_id);
440 }
441 
442 void
declare_nonstationary_var(const string & name,const string & tex_name,const vector<pair<string,string>> & partition_value)443 ParsingDriver::declare_nonstationary_var(const string &name, const string &tex_name, const vector<pair<string, string>> &partition_value)
444 {
445   declare_endogenous(name, tex_name, partition_value);
446 
447   declared_nonstationary_vars.push_back(mod_file->symbol_table.getID(name));
448   mod_file->nonstationary_variables = true;
449 }
450 
451 void
end_nonstationary_var(bool log_deflator,expr_t deflator)452 ParsingDriver::end_nonstationary_var(bool log_deflator, expr_t deflator)
453 {
454   try
455     {
456       dynamic_model->addNonstationaryVariables(declared_nonstationary_vars, log_deflator, deflator);
457     }
458   catch (DataTree::TrendException &e)
459     {
460       error("Variable " + e.name + " was listed more than once as following a trend.");
461     }
462 
463   set<int> r;
464   deflator->collectVariables(SymbolType::endogenous, r);
465   for (int it : r)
466     if (dynamic_model->isNonstationary(it))
467       error("The deflator contains a non-stationary endogenous variable. This is not allowed. Please use only stationary endogenous and/or {log_}trend_vars.");
468 
469   declared_nonstationary_vars.clear();
470   reset_data_tree();
471 }
472 
473 void
begin_VAR_restrictions()474 ParsingDriver::begin_VAR_restrictions()
475 {
476   clear_VAR_storage();
477 }
478 
479 void
end_VAR_restrictions(const string & var_model_name)480 ParsingDriver::end_VAR_restrictions(const string &var_model_name)
481 {
482   mod_file->addStatement(make_unique<VarRestrictionsStatement>(var_model_name,
483                                                                var_map,
484                                                                exclusion_restrictions,
485                                                                equation_restrictions,
486                                                                crossequation_restrictions,
487                                                                covariance_number_restriction,
488                                                                covariance_pair_restriction,
489                                                                mod_file->symbol_table));
490   clear_VAR_storage();
491 }
492 
493 void
clear_VAR_storage()494 ParsingDriver::clear_VAR_storage()
495 {
496   exclusion_restriction.clear();
497   exclusion_restrictions.clear();
498   symbol_list.clear();
499   var_restriction_eq_or_crosseq.clear();
500   equation_restrictions.clear();
501   crossequation_restrictions.clear();
502   covariance_number_restriction.clear();
503   covariance_pair_restriction.clear();
504 }
505 
506 void
add_VAR_exclusion_restriction(const string & lagstr)507 ParsingDriver::add_VAR_exclusion_restriction(const string &lagstr)
508 {
509   int lag = stoi(lagstr);
510   if (auto it = exclusion_restrictions.find(lag);
511       it == exclusion_restrictions.end())
512     exclusion_restrictions[lag] = exclusion_restriction;
513   else
514     for (auto &it1 : exclusion_restriction)
515       it->second[it1.first] = it1.second;
516 
517   exclusion_restriction.clear();
518 }
519 
520 void
add_VAR_restriction_coeff(const string & name1,const string & name2,const string & lagstr)521 ParsingDriver::add_VAR_restriction_coeff(const string &name1, const string &name2, const string &lagstr)
522 {
523   int symb_id1 = mod_file->symbol_table.getID(name1);
524   int symb_id2 = name2.empty() ? -1 : mod_file->symbol_table.getID(name2);
525   int lag = stoi(lagstr);
526 
527   var_restriction_coeff = { symb_id1, { symb_id2, lag } };
528 }
529 
530 void
add_VAR_restriction_eq_or_crosseq(expr_t expr)531 ParsingDriver::add_VAR_restriction_eq_or_crosseq(expr_t expr)
532 {
533   var_restriction_eq_or_crosseq.emplace_back(var_restriction_coeff, expr);
534 }
535 
536 void
add_VAR_restriction_equation_or_crossequation(const string & numberstr)537 ParsingDriver::add_VAR_restriction_equation_or_crossequation(const string &numberstr)
538 {
539   assert(var_restriction_eq_or_crosseq.size() > 0 && var_restriction_eq_or_crosseq.size() < 3);
540   double number = stod(numberstr);
541   if (var_restriction_eq_or_crosseq.size() == 1)
542     var_restriction_equation_or_crossequation = { { var_restriction_eq_or_crosseq[0], { { -1, { -1, -1 } }, nullptr } }, number };
543   else
544     var_restriction_equation_or_crossequation = { { var_restriction_eq_or_crosseq[0], var_restriction_eq_or_crosseq[1] }, number };
545   var_restriction_eq_or_crosseq.clear();
546 }
547 
548 void
multiply_arg2_by_neg_one()549 ParsingDriver::multiply_arg2_by_neg_one()
550 {
551   assert(var_restriction_eq_or_crosseq.size() == 2);
552   expr_t exprtm1 = add_times(var_restriction_eq_or_crosseq[1].second,
553                              add_uminus(add_non_negative_constant("-1")));
554   var_restriction_eq_or_crosseq[1] = { var_restriction_eq_or_crosseq[1].first, exprtm1 };
555 }
556 
557 void
add_VAR_restriction_equation_or_crossequation_final(const string & name)558 ParsingDriver::add_VAR_restriction_equation_or_crossequation_final(const string &name)
559 {
560   if (!name.empty())
561     {
562       int symb_id = mod_file->symbol_table.getID(name);
563       equation_restrictions[symb_id] = var_restriction_equation_or_crossequation;
564     }
565   else
566     crossequation_restrictions.push_back(var_restriction_equation_or_crossequation);
567 }
568 
569 void
add_VAR_restriction_exclusion_equation(const string & name)570 ParsingDriver::add_VAR_restriction_exclusion_equation(const string &name)
571 {
572   int symb_id = mod_file->symbol_table.getID(name);
573   exclusion_restriction[symb_id] = symbol_list;
574   symbol_list.clear();
575 }
576 
577 void
add_VAR_covariance_number_restriction(const string & name1,const string & name2,const string & valuestr)578 ParsingDriver::add_VAR_covariance_number_restriction(const string &name1, const string &name2, const string &valuestr)
579 {
580   int symb_id1 = mod_file->symbol_table.getID(name1);
581   int symb_id2 = mod_file->symbol_table.getID(name2);
582   double value = stod(valuestr);
583   covariance_number_restriction[{ symb_id1, symb_id2 }] = value;
584 }
585 
586 void
add_VAR_covariance_pair_restriction(const string & name11,const string & name12,const string & name21,const string & name22)587 ParsingDriver::add_VAR_covariance_pair_restriction(const string &name11, const string &name12, const string &name21, const string &name22)
588 {
589   int symb_id11 = mod_file->symbol_table.getID(name11);
590   int symb_id12 = mod_file->symbol_table.getID(name12);
591   int symb_id21 = mod_file->symbol_table.getID(name21);
592   int symb_id22 = mod_file->symbol_table.getID(name22);
593   covariance_pair_restriction[{ symb_id11, symb_id12 }] = { symb_id21, symb_id22 };
594 }
595 
596 void
run_var_estimation()597 ParsingDriver::run_var_estimation()
598 {
599   mod_file->addStatement(make_unique<VarEstimationStatement>(options_list));
600 }
601 
602 void
periods(const string & periods)603 ParsingDriver::periods(const string &periods)
604 {
605   warning("periods: this command is now deprecated and may be removed in a future version of Dynare. Please use the ''periods'' option of the ''simul'' command instead.");
606 
607   int periods_val = stoi(periods);
608   mod_file->addStatement(make_unique<PeriodsStatement>(periods_val));
609 }
610 
611 void
dsample(const string & arg1)612 ParsingDriver::dsample(const string &arg1)
613 {
614   int arg1_val = stoi(arg1);
615   mod_file->addStatement(make_unique<DsampleStatement>(arg1_val));
616 }
617 
618 void
dsample(const string & arg1,const string & arg2)619 ParsingDriver::dsample(const string &arg1, const string &arg2)
620 {
621   int arg1_val = stoi(arg1);
622   int arg2_val = stoi(arg2);
623   mod_file->addStatement(make_unique<DsampleStatement>(arg1_val, arg2_val));
624 }
625 
626 void
init_param(const string & name,expr_t rhs)627 ParsingDriver::init_param(const string &name, expr_t rhs)
628 {
629   check_symbol_is_parameter(name);
630   int symb_id = mod_file->symbol_table.getID(name);
631   mod_file->addStatement(make_unique<InitParamStatement>(symb_id, rhs, mod_file->symbol_table));
632 }
633 
634 void
init_val(const string & name,expr_t rhs)635 ParsingDriver::init_val(const string &name, expr_t rhs)
636 {
637   if (nostrict)
638     if (!mod_file->symbol_table.exists(name))
639       {
640         warning("discarding '" + name + "' as it was not recognized in the initval or endval statement");
641         return;
642       }
643 
644   check_symbol_is_endogenous_or_exogenous(name);
645   int symb_id = mod_file->symbol_table.getID(name);
646   init_values.emplace_back(symb_id, rhs);
647 }
648 
649 void
initval_file(const string & filename)650 ParsingDriver::initval_file(const string &filename)
651 {
652   mod_file->addStatement(make_unique<InitvalFileStatement>(filename));
653 }
654 
655 void
hist_val(const string & name,const string & lag,expr_t rhs)656 ParsingDriver::hist_val(const string &name, const string &lag, expr_t rhs)
657 {
658   if (nostrict)
659     if (!mod_file->symbol_table.exists(name))
660       {
661         warning("discarding '" + name + "' as it was not recognized in the histval block");
662         return;
663       }
664 
665   check_symbol_is_endogenous_or_exogenous(name);
666   int symb_id = mod_file->symbol_table.getID(name);
667 
668   int ilag = stoi(lag);
669   if (ilag > 0)
670     error("histval: the lag on " + name + " should be less than or equal to 0");
671 
672   pair<int, int> key(symb_id, ilag);
673 
674   if (hist_values.find(key) != hist_values.end())
675     error("hist_val: (" + name + ", " + lag + ") declared twice");
676 
677   hist_values[key] = rhs;
678 }
679 
680 void
homotopy_val(const string & name,expr_t val1,expr_t val2)681 ParsingDriver::homotopy_val(const string &name, expr_t val1, expr_t val2)
682 {
683   check_symbol_existence(name);
684   int symb_id = mod_file->symbol_table.getID(name);
685   SymbolType type = mod_file->symbol_table.getType(symb_id);
686 
687   if (type != SymbolType::parameter
688       && type != SymbolType::exogenous
689       && type != SymbolType::exogenousDet)
690     error("homotopy_val: " + name + " should be a parameter or exogenous variable");
691 
692   homotopy_values.emplace_back(symb_id, val1, val2);
693 }
694 
695 void
end_generate_irfs()696 ParsingDriver::end_generate_irfs()
697 {
698   mod_file->addStatement(make_unique<GenerateIRFsStatement>(options_list, generate_irf_names, generate_irf_elements));
699 
700   generate_irf_elements.clear();
701   generate_irf_names.clear();
702   options_list.clear();
703 }
704 
705 void
add_generate_irfs_element(string name)706 ParsingDriver::add_generate_irfs_element(string name)
707 {
708   for (const auto &it : generate_irf_names)
709     if (it == name)
710       error("Names in the generate_irfs block must be unique but you entered '"
711             + name + "' more than once.");
712 
713   generate_irf_names.push_back(move(name));
714   generate_irf_elements.push_back(generate_irf_exos);
715 
716   generate_irf_exos.clear();
717 }
718 
719 void
add_generate_irfs_exog_element(string exo,const string & value)720 ParsingDriver::add_generate_irfs_exog_element(string exo, const string &value)
721 {
722   check_symbol_is_exogenous(exo);
723   if (generate_irf_exos.find(exo) != generate_irf_exos.end())
724     error("You have set the exogenous variable " + exo + " twice.");
725 
726   generate_irf_exos[move(exo)] = stod(value);
727 }
728 
729 void
forecast()730 ParsingDriver::forecast()
731 {
732   mod_file->addStatement(make_unique<ForecastStatement>(symbol_list, options_list));
733   symbol_list.clear();
734   options_list.clear();
735 }
736 
737 void
use_dll()738 ParsingDriver::use_dll()
739 {
740   mod_file->use_dll = true;
741 }
742 
743 void
block()744 ParsingDriver::block()
745 {
746   mod_file->block = true;
747 }
748 
749 void
linear_decomposition()750 ParsingDriver::linear_decomposition()
751 {
752   mod_file->linear_decomposition = true;
753 }
754 
755 void
no_static()756 ParsingDriver::no_static()
757 {
758   mod_file->no_static = true;
759 }
760 
761 void
byte_code()762 ParsingDriver::byte_code()
763 {
764   mod_file->byte_code = true;
765 }
766 
767 void
differentiate_forward_vars_all()768 ParsingDriver::differentiate_forward_vars_all()
769 {
770   mod_file->differentiate_forward_vars = true;
771 }
772 
773 void
differentiate_forward_vars_some()774 ParsingDriver::differentiate_forward_vars_some()
775 {
776   mod_file->differentiate_forward_vars = true;
777   mod_file->differentiate_forward_vars_subset = symbol_list.get_symbols();
778   for (auto &it : mod_file->differentiate_forward_vars_subset)
779     check_symbol_is_endogenous(it);
780   symbol_list.clear();
781 }
782 
783 void
cutoff(const string & value)784 ParsingDriver::cutoff(const string &value)
785 {
786   double val = stod(value);
787   mod_file->dynamic_model.cutoff = val;
788   mod_file->static_model.cutoff = val;
789 }
790 
791 void
mfs(const string & value)792 ParsingDriver::mfs(const string &value)
793 {
794   int val = stoi(value);
795   mod_file->dynamic_model.mfs = val;
796   mod_file->static_model.mfs = val;
797 }
798 
799 void
compilation_setup_substitute_flags(const string & flags)800 ParsingDriver::compilation_setup_substitute_flags(const string &flags)
801 {
802   mod_file->dynamic_model.user_set_subst_flags = flags;
803 }
804 
805 void
compilation_setup_add_flags(const string & flags)806 ParsingDriver::compilation_setup_add_flags(const string &flags)
807 {
808   mod_file->dynamic_model.user_set_add_flags = flags;
809 }
810 
811 void
compilation_setup_substitute_libs(const string & libs)812 ParsingDriver::compilation_setup_substitute_libs(const string &libs)
813 {
814   mod_file->dynamic_model.user_set_subst_libs = libs;
815 }
816 
817 void
compilation_setup_add_libs(const string & libs)818 ParsingDriver::compilation_setup_add_libs(const string &libs)
819 {
820   mod_file->dynamic_model.user_set_add_libs = libs;
821 }
822 
823 void
compilation_setup_compiler(const string & compiler)824 ParsingDriver::compilation_setup_compiler(const string &compiler)
825 {
826   mod_file->dynamic_model.user_set_compiler = compiler;
827 }
828 
829 void
balanced_growth_test_tol(const string & value)830 ParsingDriver::balanced_growth_test_tol(const string &value)
831 {
832   mod_file->dynamic_model.balanced_growth_test_tol = stod(value);
833 }
834 
835 void
end_initval(bool all_values_required)836 ParsingDriver::end_initval(bool all_values_required)
837 {
838   mod_file->addStatement(make_unique<InitValStatement>(init_values, mod_file->symbol_table, all_values_required));
839   init_values.clear();
840 }
841 
842 void
end_endval(bool all_values_required)843 ParsingDriver::end_endval(bool all_values_required)
844 {
845   mod_file->addStatement(make_unique<EndValStatement>(init_values, mod_file->symbol_table, all_values_required));
846   init_values.clear();
847 }
848 
849 void
end_histval(bool all_values_required)850 ParsingDriver::end_histval(bool all_values_required)
851 {
852   mod_file->addStatement(make_unique<HistValStatement>(hist_values, mod_file->symbol_table, all_values_required));
853   hist_values.clear();
854 }
855 
856 void
end_homotopy()857 ParsingDriver::end_homotopy()
858 {
859   mod_file->addStatement(make_unique<HomotopyStatement>(homotopy_values, mod_file->symbol_table));
860   homotopy_values.clear();
861 }
862 
863 void
begin_epilogue()864 ParsingDriver::begin_epilogue()
865 {
866   parsing_epilogue = true;
867   set_current_data_tree(&mod_file->epilogue);
868 }
869 
870 void
end_epilogue()871 ParsingDriver::end_epilogue()
872 {
873   parsing_epilogue = false;
874   reset_data_tree();
875 }
876 
877 void
add_epilogue_variable(const string & name)878 ParsingDriver::add_epilogue_variable(const string &name)
879 {
880   declare_symbol(name, SymbolType::epilogue, "", {});
881 }
882 
883 void
add_epilogue_equal(const string & name,expr_t expr)884 ParsingDriver::add_epilogue_equal(const string &name, expr_t expr)
885 {
886   mod_file->epilogue.addDefinition(mod_file->symbol_table.getID(name), expr);
887 }
888 
889 void
begin_model()890 ParsingDriver::begin_model()
891 {
892   set_current_data_tree(&mod_file->dynamic_model);
893 }
894 
895 void
end_model()896 ParsingDriver::end_model()
897 {
898   bool exit_after_write = false;
899   if (model_errors.size() > 0)
900     for (auto &it : model_errors)
901       {
902         if (it.first.empty())
903           exit_after_write = true;
904         cerr << it.second;
905       }
906 
907   if (undeclared_model_variable_errors.size() > 0)
908     for (auto &it : undeclared_model_variable_errors)
909       if (nostrict)
910         warning(it.second);
911       else
912         {
913           exit_after_write = true;
914           cerr << it.second << endl;
915         }
916 
917   if (exit_after_write)
918     exit(EXIT_FAILURE);
919 
920   reset_data_tree();
921 }
922 
923 void
end_shocks(bool overwrite)924 ParsingDriver::end_shocks(bool overwrite)
925 {
926   mod_file->addStatement(make_unique<ShocksStatement>(overwrite, det_shocks, var_shocks, std_shocks,
927                                                       covar_shocks, corr_shocks, mod_file->symbol_table));
928   det_shocks.clear();
929   var_shocks.clear();
930   std_shocks.clear();
931   covar_shocks.clear();
932   corr_shocks.clear();
933 }
934 
935 void
end_mshocks(bool overwrite)936 ParsingDriver::end_mshocks(bool overwrite)
937 {
938   mod_file->addStatement(make_unique<MShocksStatement>(overwrite, det_shocks, mod_file->symbol_table));
939   det_shocks.clear();
940 }
941 
942 void
add_det_shock(const string & var,bool conditional_forecast)943 ParsingDriver::add_det_shock(const string &var, bool conditional_forecast)
944 {
945   if (conditional_forecast)
946     check_symbol_is_endogenous(var);
947   else
948     check_symbol_is_exogenous(var);
949 
950   int symb_id = mod_file->symbol_table.getID(var);
951 
952   if (det_shocks.find(symb_id) != det_shocks.end())
953     error("shocks/conditional_forecast_paths: variable " + var + " declared twice");
954 
955   if (det_shocks_periods.size() != det_shocks_values.size())
956     error("shocks/conditional_forecast_paths: variable " + var + ": number of periods is different from number of shock values");
957 
958   vector<ShocksStatement::DetShockElement> v;
959 
960   for (size_t i = 0; i < det_shocks_periods.size(); i++)
961     {
962       ShocksStatement::DetShockElement dse;
963       dse.period1 = det_shocks_periods[i].first;
964       dse.period2 = det_shocks_periods[i].second;
965       dse.value = det_shocks_values[i];
966       v.push_back(dse);
967     }
968 
969   det_shocks[symb_id] = v;
970 
971   det_shocks_periods.clear();
972   det_shocks_values.clear();
973 }
974 
975 void
add_stderr_shock(const string & var,expr_t value)976 ParsingDriver::add_stderr_shock(const string &var, expr_t value)
977 {
978   if (nostrict)
979     if (!mod_file->symbol_table.exists(var))
980       {
981         warning("discarding shocks block declaration of the standard error of '" + var + "' as it was not declared");
982         return;
983       }
984 
985   check_symbol_existence(var);
986   int symb_id = mod_file->symbol_table.getID(var);
987 
988   if (var_shocks.find(symb_id) != var_shocks.end()
989       || std_shocks.find(symb_id) != std_shocks.end())
990     error("shocks: variance or stderr of shock on " + var + " declared twice");
991 
992   std_shocks[symb_id] = value;
993 }
994 
995 void
add_var_shock(const string & var,expr_t value)996 ParsingDriver::add_var_shock(const string &var, expr_t value)
997 {
998   if (nostrict)
999     if (!mod_file->symbol_table.exists(var))
1000       {
1001         warning("discarding shocks block declaration of the variance of '" + var + "' as it was not declared");
1002         return;
1003       }
1004 
1005   check_symbol_existence(var);
1006   int symb_id = mod_file->symbol_table.getID(var);
1007 
1008   if (var_shocks.find(symb_id) != var_shocks.end()
1009       || std_shocks.find(symb_id) != std_shocks.end())
1010     error("shocks: variance or stderr of shock on " + var + " declared twice");
1011 
1012   var_shocks[symb_id] = value;
1013 }
1014 
1015 void
add_covar_shock(const string & var1,const string & var2,expr_t value)1016 ParsingDriver::add_covar_shock(const string &var1, const string &var2, expr_t value)
1017 {
1018   if (nostrict)
1019     if (!mod_file->symbol_table.exists(var1) || !mod_file->symbol_table.exists(var2))
1020       {
1021         warning("discarding shocks block declaration of the covariance of '" + var1 + "' and '" + var2 + "' as at least one was not declared");
1022         return;
1023       }
1024 
1025   check_symbol_existence(var1);
1026   check_symbol_existence(var2);
1027   int symb_id1 = mod_file->symbol_table.getID(var1);
1028   int symb_id2 = mod_file->symbol_table.getID(var2);
1029 
1030   pair<int, int> key(symb_id1, symb_id2), key_inv(symb_id2, symb_id1);
1031 
1032   if (covar_shocks.find(key) != covar_shocks.end()
1033       || covar_shocks.find(key_inv) != covar_shocks.end()
1034       || corr_shocks.find(key) != corr_shocks.end()
1035       || corr_shocks.find(key_inv) != corr_shocks.end())
1036     error("shocks: covariance or correlation shock on variable pair (" + var1 + ", "
1037           + var2 + ") declared twice");
1038 
1039   covar_shocks[key] = value;
1040 }
1041 
1042 void
add_correl_shock(const string & var1,const string & var2,expr_t value)1043 ParsingDriver::add_correl_shock(const string &var1, const string &var2, expr_t value)
1044 {
1045   if (nostrict)
1046     if (!mod_file->symbol_table.exists(var1) || !mod_file->symbol_table.exists(var2))
1047       {
1048         warning("discarding shocks block declaration of the correlation of '" + var1 + "' and '" + var2 + "' as at least one was not declared");
1049         return;
1050       }
1051 
1052   check_symbol_existence(var1);
1053   check_symbol_existence(var2);
1054   int symb_id1 = mod_file->symbol_table.getID(var1);
1055   int symb_id2 = mod_file->symbol_table.getID(var2);
1056 
1057   pair<int, int> key(symb_id1, symb_id2), key_inv(symb_id2, symb_id1);
1058 
1059   if (covar_shocks.find(key) != covar_shocks.end()
1060       || covar_shocks.find(key_inv) != covar_shocks.end()
1061       || corr_shocks.find(key) != corr_shocks.end()
1062       || corr_shocks.find(key_inv) != corr_shocks.end())
1063     error("shocks: covariance or correlation shock on variable pair (" + var1 + ", "
1064           + var2 + ") declared twice");
1065 
1066   corr_shocks[key] = value;
1067 }
1068 
1069 void
add_period(const string & p1,const string & p2)1070 ParsingDriver::add_period(const string &p1, const string &p2)
1071 {
1072   int p1_val = stoi(p1);
1073   int p2_val = stoi(p2);
1074   if (p1_val > p2_val)
1075     error("shocks/conditional_forecast_paths: can't have first period index greater than second index in range specification");
1076   det_shocks_periods.emplace_back(p1_val, p2_val);
1077 }
1078 
1079 void
add_period(const string & p1)1080 ParsingDriver::add_period(const string &p1)
1081 {
1082   int p1_val = stoi(p1);
1083   det_shocks_periods.emplace_back(p1_val, p1_val);
1084 }
1085 
1086 void
add_value(expr_t value)1087 ParsingDriver::add_value(expr_t value)
1088 {
1089   det_shocks_values.push_back(value);
1090 }
1091 
1092 void
add_value(const string & v)1093 ParsingDriver::add_value(const string &v)
1094 {
1095   expr_t id;
1096 
1097   if (v.at(0) == '-')
1098     id = data_tree->AddUMinus(data_tree->AddNonNegativeConstant(v.substr(1, string::npos)));
1099   else
1100     id = data_tree->AddNonNegativeConstant(v);
1101 
1102   det_shocks_values.push_back(id);
1103 }
1104 
1105 void
begin_svar_identification()1106 ParsingDriver::begin_svar_identification()
1107 {
1108   svar_upper_cholesky = false;
1109   svar_lower_cholesky = false;
1110   svar_constants_exclusion = false;
1111 }
1112 
1113 void
end_svar_identification()1114 ParsingDriver::end_svar_identification()
1115 {
1116   mod_file->addStatement(make_unique<SvarIdentificationStatement>(svar_ident_restrictions,
1117                                                                   svar_upper_cholesky,
1118                                                                   svar_lower_cholesky,
1119                                                                   svar_constants_exclusion,
1120                                                                   mod_file->symbol_table));
1121   svar_restriction_symbols.clear();
1122   svar_equation_restrictions.clear();
1123   svar_ident_restrictions.clear();
1124   svar_Qi_restriction_nbr.clear();
1125   svar_Ri_restriction_nbr.clear();
1126 }
1127 
1128 void
combine_lag_and_restriction(const string & lag)1129 ParsingDriver::combine_lag_and_restriction(const string &lag)
1130 {
1131   int current_lag = stoi(lag);
1132 
1133   for (const auto &it : svar_ident_restrictions)
1134     if (it.lag == current_lag)
1135       error("lag " + lag + " used more than once.");
1136 
1137   for (const auto &it : svar_equation_restrictions)
1138     for (auto it1 : it.second)
1139       {
1140         SvarIdentificationStatement::svar_identification_restriction new_restriction;
1141         new_restriction.equation = it.first;
1142         if (current_lag > 0)
1143           new_restriction.restriction_nbr = ++svar_Ri_restriction_nbr[it.first];
1144         else
1145           new_restriction.restriction_nbr = ++svar_Qi_restriction_nbr[it.first];
1146         new_restriction.lag = current_lag;
1147         new_restriction.variable = it1;
1148         new_restriction.value = data_tree->One;
1149         svar_ident_restrictions.push_back(new_restriction);
1150       }
1151 
1152   svar_upper_cholesky = false;
1153   svar_lower_cholesky = false;
1154   svar_equation_restrictions.clear();
1155 }
1156 
1157 void
add_restriction_in_equation(const string & equation)1158 ParsingDriver::add_restriction_in_equation(const string &equation)
1159 {
1160   int eqn = stoi(equation);
1161   if (eqn < 1)
1162     error("equation numbers must be greater than or equal to 1.");
1163 
1164   if (svar_equation_restrictions.count(eqn) > 0)
1165     error("equation number " + equation + " referenced more than once under a single lag.");
1166 
1167   svar_equation_restrictions[eqn] = svar_restriction_symbols;
1168 
1169   svar_restriction_symbols.clear();
1170 }
1171 
1172 void
add_in_svar_restriction_symbols(const string & tmp_var)1173 ParsingDriver::add_in_svar_restriction_symbols(const string &tmp_var)
1174 {
1175   check_symbol_existence(tmp_var);
1176   int symb_id = mod_file->symbol_table.getID(tmp_var);
1177 
1178   for (const auto &viit : svar_restriction_symbols)
1179     if (symb_id == viit)
1180       error(tmp_var + " restriction added twice.");
1181 
1182   svar_restriction_symbols.push_back(symb_id);
1183 }
1184 
1185 void
add_restriction_equation_nbr(const string & eq_nbr)1186 ParsingDriver::add_restriction_equation_nbr(const string &eq_nbr)
1187 {
1188   svar_equation_nbr = stoi(eq_nbr);
1189   svar_left_handside = true;
1190   // reinitialize restriction type that must be set from the first restriction element
1191   svar_restriction_type = SvarRestrictionType::NOT_SET;
1192 }
1193 
1194 void
add_restriction_equal()1195 ParsingDriver::add_restriction_equal()
1196 {
1197   if (svar_left_handside)
1198     svar_left_handside = false;
1199   else
1200     error("svar_identification: there are more than one EQUAL sign in a restriction equation");
1201 }
1202 
1203 void
add_positive_restriction_element(expr_t value,const string & variable,const string & lag)1204 ParsingDriver::add_positive_restriction_element(expr_t value, const string &variable, const string &lag)
1205 {
1206   // if the expression is not on the left handside, change its sign
1207   if (!svar_left_handside)
1208     value = add_uminus(value);
1209 
1210   add_restriction_element(value, variable, lag);
1211 }
1212 
1213 void
add_positive_restriction_element(const string & variable,const string & lag)1214 ParsingDriver::add_positive_restriction_element(const string &variable, const string &lag)
1215 {
1216   expr_t value(data_tree->One);
1217 
1218   // if the expression is not on the left handside, change its sign
1219   if (!svar_left_handside)
1220     value = add_uminus(value);
1221 
1222   add_restriction_element(value, variable, lag);
1223 }
1224 
1225 void
add_negative_restriction_element(expr_t value,const string & variable,const string & lag)1226 ParsingDriver::add_negative_restriction_element(expr_t value, const string &variable, const string &lag)
1227 {
1228   // if the expression is on the left handside, change its sign
1229   if (svar_left_handside)
1230     value = add_uminus(value);
1231 
1232   add_restriction_element(value, variable, lag);
1233 }
1234 
1235 void
add_negative_restriction_element(const string & variable,const string & lag)1236 ParsingDriver::add_negative_restriction_element(const string &variable, const string &lag)
1237 {
1238   expr_t value(data_tree->One);
1239 
1240   // if the expression is on the left handside, change its sign
1241   if (svar_left_handside)
1242     value = add_uminus(value);
1243 
1244   add_restriction_element(value, variable, lag);
1245 }
1246 
1247 void
add_restriction_element(expr_t value,const string & variable,const string & lag)1248 ParsingDriver::add_restriction_element(expr_t value, const string &variable, const string &lag)
1249 {
1250   check_symbol_existence(variable);
1251   int symb_id = mod_file->symbol_table.getID(variable);
1252 
1253   int current_lag = stoi(lag);
1254   if (svar_restriction_type == SvarRestrictionType::NOT_SET)
1255     {
1256       if (current_lag == 0)
1257         {
1258           svar_restriction_type = SvarRestrictionType::Qi_TYPE;
1259           ++svar_Qi_restriction_nbr[svar_equation_nbr];
1260         }
1261       else
1262         {
1263           svar_restriction_type = SvarRestrictionType::Ri_TYPE;
1264           ++svar_Ri_restriction_nbr[svar_equation_nbr];
1265         }
1266     }
1267   else
1268     {
1269       if ((svar_restriction_type == SvarRestrictionType::Qi_TYPE && current_lag > 0)
1270           || (svar_restriction_type == SvarRestrictionType::Ri_TYPE && current_lag == 0))
1271         error("SVAR_IDENTIFICATION: a single restrictions must affect either Qi or Ri, but not both");
1272     }
1273   SvarIdentificationStatement::svar_identification_restriction new_restriction;
1274   new_restriction.equation = svar_equation_nbr;
1275   if (current_lag > 0)
1276     new_restriction.restriction_nbr = svar_Ri_restriction_nbr[svar_equation_nbr];
1277   else
1278     new_restriction.restriction_nbr = svar_Qi_restriction_nbr[svar_equation_nbr];
1279   new_restriction.lag = current_lag;
1280   new_restriction.variable = symb_id;
1281   new_restriction.value = value;
1282 
1283   svar_ident_restrictions.push_back(new_restriction);
1284 }
1285 
1286 void
check_restriction_expression_constant(expr_t value)1287 ParsingDriver::check_restriction_expression_constant(expr_t value)
1288 {
1289   if (value->eval({}) != 0)
1290     error("SVAR_INDENTIFICATION restrictions must be homogenous");
1291 }
1292 
1293 void
add_upper_cholesky()1294 ParsingDriver::add_upper_cholesky()
1295 {
1296   svar_upper_cholesky = true;
1297 }
1298 
1299 void
add_lower_cholesky()1300 ParsingDriver::add_lower_cholesky()
1301 {
1302   svar_lower_cholesky = true;
1303 }
1304 
1305 void
add_constants_exclusion()1306 ParsingDriver::add_constants_exclusion()
1307 {
1308   svar_constants_exclusion = true;
1309 }
1310 
1311 void
add_svar_global_identification_check()1312 ParsingDriver::add_svar_global_identification_check()
1313 {
1314   mod_file->addStatement(make_unique<SvarGlobalIdentificationCheckStatement>());
1315 }
1316 
1317 void
do_sigma_e()1318 ParsingDriver::do_sigma_e()
1319 {
1320   warning("Sigma_e: this command is now deprecated and may be removed in a future version of Dynare. Please use the ''shocks'' command instead.");
1321 
1322   try
1323     {
1324       mod_file->addStatement(make_unique<SigmaeStatement>(sigmae_matrix));
1325     }
1326   catch (SigmaeStatement::MatrixFormException &e)
1327     {
1328       error("Sigma_e: matrix is neither upper triangular nor lower triangular");
1329     }
1330   sigmae_matrix.clear();
1331 }
1332 
1333 void
end_of_row()1334 ParsingDriver::end_of_row()
1335 {
1336   sigmae_matrix.push_back(sigmae_row);
1337   sigmae_row.clear();
1338 }
1339 
1340 void
add_to_row_const(const string & v)1341 ParsingDriver::add_to_row_const(const string &v)
1342 {
1343   expr_t id;
1344 
1345   if (v.at(0) == '-')
1346     id = data_tree->AddUMinus(data_tree->AddNonNegativeConstant(v.substr(1, string::npos)));
1347   else
1348     id = data_tree->AddNonNegativeConstant(v);
1349 
1350   sigmae_row.push_back(id);
1351 }
1352 
1353 void
add_to_row(expr_t v)1354 ParsingDriver::add_to_row(expr_t v)
1355 {
1356   sigmae_row.push_back(v);
1357 }
1358 
1359 void
steady()1360 ParsingDriver::steady()
1361 {
1362   mod_file->addStatement(make_unique<SteadyStatement>(options_list));
1363   options_list.clear();
1364 }
1365 
1366 void
option_num(string name_option,string opt1,string opt2)1367 ParsingDriver::option_num(string name_option, string opt1, string opt2)
1368 {
1369   if (options_list.paired_num_options.find(name_option)
1370       != options_list.paired_num_options.end())
1371     error("option " + name_option + " declared twice");
1372 
1373   options_list.paired_num_options[move(name_option)] = { move(opt1), move(opt2) };
1374 }
1375 
1376 void
option_num(string name_option,string opt)1377 ParsingDriver::option_num(string name_option, string opt)
1378 {
1379   if (options_list.num_options.find(name_option) != options_list.num_options.end())
1380     error("option " + name_option + " declared twice");
1381 
1382   options_list.num_options[move(name_option)] = move(opt);
1383 }
1384 
1385 void
option_str(string name_option,string opt)1386 ParsingDriver::option_str(string name_option, string opt)
1387 {
1388   if (options_list.string_options.find(name_option)
1389       != options_list.string_options.end())
1390     error("option " + name_option + " declared twice");
1391 
1392   options_list.string_options[move(name_option)] = move(opt);
1393 }
1394 
1395 void
option_date(string name_option,string opt)1396 ParsingDriver::option_date(string name_option, string opt)
1397 {
1398   if (options_list.date_options.find(name_option)
1399       != options_list.date_options.end())
1400     error("option " + name_option + " declared twice");
1401 
1402   options_list.date_options[move(name_option)] = move(opt);
1403 }
1404 
1405 void
option_symbol_list(string name_option)1406 ParsingDriver::option_symbol_list(string name_option)
1407 {
1408   if (options_list.symbol_list_options.find(name_option)
1409       != options_list.symbol_list_options.end())
1410     error("option " + name_option + " declared twice");
1411 
1412   if (name_option.compare("irf_shocks") == 0)
1413     {
1414       vector<string> shocks = symbol_list.get_symbols();
1415       for (auto &shock : shocks)
1416         {
1417           if (!mod_file->symbol_table.exists(shock))
1418             error("Unknown symbol: " + shock);
1419           if (mod_file->symbol_table.getType(shock) != SymbolType::exogenous)
1420             error("Variables passed to irf_shocks must be exogenous. Caused by: " + shock);
1421         }
1422     }
1423 
1424   if (name_option.compare("ms.parameters") == 0)
1425     {
1426       vector<string> parameters = symbol_list.get_symbols();
1427       for (auto &it : parameters)
1428         if (mod_file->symbol_table.getType(it) != SymbolType::parameter)
1429           error("Variables passed to the parameters option of the markov_switching statement must be parameters. Caused by: " + it);
1430     }
1431 
1432   options_list.symbol_list_options[move(name_option)] = symbol_list;
1433   symbol_list.clear();
1434 }
1435 
1436 void
option_vec_int(string name_option,vector<int> opt)1437 ParsingDriver::option_vec_int(string name_option, vector<int> opt)
1438 {
1439   if (options_list.vector_int_options.find(name_option)
1440       != options_list.vector_int_options.end())
1441     error("option " + name_option + " declared twice");
1442 
1443   if (opt.empty())
1444     error("option " + name_option + " was passed an empty vector.");
1445 
1446   options_list.vector_int_options[move(name_option)] = move(opt);
1447 }
1448 
1449 void
option_vec_str(string name_option,vector<string> opt)1450 ParsingDriver::option_vec_str(string name_option, vector<string> opt)
1451 {
1452   if (options_list.vector_str_options.find(name_option)
1453       != options_list.vector_str_options.end())
1454     error("option " + name_option + " declared twice");
1455 
1456   if (opt.empty())
1457     error("option " + name_option + " was passed an empty vector.");
1458 
1459   options_list.vector_str_options[move(name_option)] = move(opt);
1460 }
1461 
1462 void
linear()1463 ParsingDriver::linear()
1464 {
1465   mod_file->linear = true;
1466 }
1467 
1468 void
add_in_symbol_list(const string & tmp_var)1469 ParsingDriver::add_in_symbol_list(const string &tmp_var)
1470 {
1471   symbol_list.addSymbol(tmp_var);
1472 }
1473 
1474 void
rplot()1475 ParsingDriver::rplot()
1476 {
1477   mod_file->addStatement(make_unique<RplotStatement>(symbol_list));
1478   symbol_list.clear();
1479 }
1480 
1481 void
stoch_simul()1482 ParsingDriver::stoch_simul()
1483 {
1484   mod_file->addStatement(make_unique<StochSimulStatement>(symbol_list, options_list));
1485   symbol_list.clear();
1486   options_list.clear();
1487 }
1488 
1489 void
trend_component_model()1490 ParsingDriver::trend_component_model()
1491 {
1492   auto its = options_list.string_options.find("trend_component.name");
1493   if (its == options_list.string_options.end())
1494     error("You must pass the model_name option to the trend_component_model statement.");
1495   auto name = its->second;
1496 
1497   auto itvs = options_list.vector_str_options.find("trend_component.eqtags");
1498   if (itvs == options_list.vector_str_options.end())
1499     error("You must pass the eqtags option to the trend_component_model statement.");
1500   auto eqtags = itvs->second;
1501 
1502   auto itvs1 = options_list.vector_str_options.find("trend_component.targets");
1503   if (itvs1 == options_list.vector_str_options.end())
1504     error("You must pass the targets option to the trend_component_model statement.");
1505   auto targets = itvs1->second;
1506 
1507   mod_file->trend_component_model_table.addTrendComponentModel(name, eqtags, targets);
1508   options_list.clear();
1509 }
1510 
1511 void
var_model()1512 ParsingDriver::var_model()
1513 {
1514   auto its = options_list.string_options.find("var.model_name");
1515   if (its == options_list.string_options.end())
1516     error("You must pass the model_name option to the var_model statement.");
1517   auto name = its->second;
1518 
1519   int order = 0;
1520   auto itn = options_list.num_options.find("var.order");
1521   if (itn != options_list.num_options.end())
1522     order = stoi(itn->second);
1523   else
1524     if (!symbol_list.empty())
1525       error("You must pass the order option when passing a symbol list to the var_model statement");
1526 
1527   vector<string> eqtags;
1528   auto itvs = options_list.vector_str_options.find("var.eqtags");
1529   if (itvs != options_list.vector_str_options.end())
1530     {
1531       eqtags = itvs->second;
1532       if (!symbol_list.empty())
1533         error("You cannot pass a symbol list when passing equation tags to the var_model statement");
1534       else if (itn != options_list.num_options.end())
1535         error("You cannot pass the order option when passing equation tags to the var_model statement");
1536     }
1537 
1538   mod_file->var_model_table.addVarModel(name, eqtags, {symbol_list, order});
1539   symbol_list.clear();
1540   options_list.clear();
1541   var_map[its->second] = symbol_list.getSymbols();
1542 }
1543 
1544 void
simul()1545 ParsingDriver::simul()
1546 {
1547   warning("The 'simul' statement is deprecated. Please use 'perfect_foresight_setup' and 'perfect_foresight_solver' instead.");
1548   mod_file->addStatement(make_unique<SimulStatement>(options_list));
1549   options_list.clear();
1550 }
1551 
1552 void
model_info()1553 ParsingDriver::model_info()
1554 {
1555   mod_file->addStatement(make_unique<ModelInfoStatement>(options_list));
1556   options_list.clear();
1557 }
1558 
1559 void
check()1560 ParsingDriver::check()
1561 {
1562   mod_file->addStatement(make_unique<CheckStatement>(options_list));
1563   options_list.clear();
1564 }
1565 
1566 void
add_estimated_params_element()1567 ParsingDriver::add_estimated_params_element()
1568 {
1569   if (estim_params.name != "dsge_prior_weight")
1570     {
1571       check_symbol_existence(estim_params.name);
1572       SymbolType type = mod_file->symbol_table.getType(estim_params.name);
1573       switch (estim_params.type)
1574         {
1575         case 1:
1576           if (type != SymbolType::endogenous && type != SymbolType::exogenous)
1577             error(estim_params.name + " must be an endogenous or an exogenous variable");
1578           break;
1579         case 2:
1580           check_symbol_is_parameter(estim_params.name);
1581           break;
1582         case 3:
1583           check_symbol_existence(estim_params.name2);
1584           SymbolType type2 = mod_file->symbol_table.getType(estim_params.name2);
1585           if ((type != SymbolType::endogenous && type != SymbolType::exogenous) || type != type2)
1586             error(estim_params.name + " and " + estim_params.name2 + " must either be both endogenous variables or both exogenous");
1587           break;
1588         }
1589     }
1590   estim_params_list.push_back(estim_params);
1591   estim_params.init(*data_tree);
1592 }
1593 
1594 void
estimated_params()1595 ParsingDriver::estimated_params()
1596 {
1597   mod_file->addStatement(make_unique<EstimatedParamsStatement>(estim_params_list, mod_file->symbol_table));
1598   estim_params_list.clear();
1599 }
1600 
1601 void
estimated_params_init(bool use_calibration)1602 ParsingDriver::estimated_params_init(bool use_calibration)
1603 {
1604   mod_file->addStatement(make_unique<EstimatedParamsInitStatement>(estim_params_list, mod_file->symbol_table, use_calibration));
1605   estim_params_list.clear();
1606 }
1607 
1608 void
estimated_params_bounds()1609 ParsingDriver::estimated_params_bounds()
1610 {
1611   mod_file->addStatement(make_unique<EstimatedParamsBoundsStatement>(estim_params_list, mod_file->symbol_table));
1612   estim_params_list.clear();
1613 }
1614 
1615 void
add_osr_params_element()1616 ParsingDriver::add_osr_params_element()
1617 {
1618   check_symbol_existence(osr_params.name);
1619   SymbolType type = mod_file->symbol_table.getType(osr_params.name);
1620   if (type != SymbolType::parameter)
1621     error(osr_params.name + " must be a parameter to be used in the osr_bounds block");
1622   osr_params_list.push_back(osr_params);
1623   osr_params.init(*data_tree);
1624 }
1625 
1626 void
osr_params_bounds()1627 ParsingDriver::osr_params_bounds()
1628 {
1629   mod_file->addStatement(make_unique<OsrParamsBoundsStatement>(osr_params_list));
1630   osr_params_list.clear();
1631 }
1632 
1633 void
set_unit_root_vars()1634 ParsingDriver::set_unit_root_vars()
1635 {
1636   mod_file->addStatement(make_unique<UnitRootVarsStatement>());
1637   warning("''unit_root_vars'' is now obsolete; use the ''diffuse_filter'' option of ''estimation'' instead");
1638   symbol_list.clear();
1639 }
1640 
1641 void
set_time(const string & arg)1642 ParsingDriver::set_time(const string &arg)
1643 {
1644   option_date("initial_period", arg);
1645   mod_file->addStatement(make_unique<SetTimeStatement>(options_list));
1646   options_list.clear();
1647 }
1648 
1649 void
estimation_data()1650 ParsingDriver::estimation_data()
1651 {
1652   mod_file->addStatement(make_unique<EstimationDataStatement>(options_list));
1653   options_list.clear();
1654 }
1655 
1656 void
set_subsamples(string name1,string name2)1657 ParsingDriver::set_subsamples(string name1, string name2)
1658 {
1659   check_symbol_existence(name1);
1660   if (!name2.empty())
1661     check_symbol_existence(name2);
1662 
1663   mod_file->addStatement(make_unique<SubsamplesStatement>(name1, name2, subsample_declaration_map,
1664                                                           mod_file->symbol_table));
1665   subsample_declarations[{ move(name1), move(name2) }] = subsample_declaration_map;
1666   subsample_declaration_map.clear();
1667 }
1668 
1669 void
copy_subsamples(string to_name1,string to_name2,string from_name1,string from_name2)1670 ParsingDriver::copy_subsamples(string to_name1, string to_name2, string from_name1, string from_name2)
1671 {
1672   check_symbol_existence(to_name1);
1673   check_symbol_existence(from_name1);
1674   if (!to_name2.empty())
1675     check_symbol_existence(to_name2);
1676   if (!from_name2.empty())
1677     check_symbol_existence(from_name2);
1678 
1679   if (subsample_declarations.find({ from_name1, from_name2 }) == subsample_declarations.end())
1680     {
1681       string err{from_name1};
1682       if (!from_name2.empty())
1683         err.append(",").append(from_name2);
1684       error(err + " does not have an associated subsample statement.");
1685     }
1686 
1687   mod_file->addStatement(make_unique<SubsamplesEqualStatement>(to_name1, to_name2, from_name1, from_name2,
1688                                                                mod_file->symbol_table));
1689 
1690   subsample_declarations[{ move(to_name1), move(to_name2) }]
1691     = subsample_declarations[{ move(from_name1), move(from_name2) }];
1692 }
1693 
1694 void
check_symbol_is_statement_variable(const string & name)1695 ParsingDriver::check_symbol_is_statement_variable(const string &name)
1696 {
1697   check_symbol_existence(name);
1698   int symb_id = mod_file->symbol_table.getID(name);
1699   if (mod_file->symbol_table.getType(symb_id) != SymbolType::statementDeclaredVariable)
1700     error(name + " is not a variable assigned in a statement");
1701 }
1702 
1703 void
set_subsample_name_equal_to_date_range(string name,string date1,string date2)1704 ParsingDriver::set_subsample_name_equal_to_date_range(string name, string date1, string date2)
1705 {
1706   if (subsample_declaration_map.find(name) != subsample_declaration_map.end())
1707     error("Symbol " + name + " may only be assigned once in a SUBSAMPLE statement");
1708   subsample_declaration_map[move(name)] = { move(date1), move(date2) };
1709 }
1710 
1711 void
check_subsample_declaration_exists(const string & name1,const string & subsample_name)1712 ParsingDriver::check_subsample_declaration_exists(const string &name1, const string &subsample_name)
1713 {
1714   if (subsample_name.empty())
1715     return;
1716 
1717   check_subsample_declaration_exists(name1, "", subsample_name);
1718 }
1719 
1720 void
check_subsample_declaration_exists(const string & name1,const string & name2,const string & subsample_name)1721 ParsingDriver::check_subsample_declaration_exists(const string &name1, const string &name2, const string &subsample_name)
1722 {
1723   if (subsample_name.empty())
1724     return;
1725 
1726   check_symbol_existence(name1);
1727   if (!name2.empty())
1728     check_symbol_existence(name2);
1729 
1730   auto it = subsample_declarations.find({ name1, name2 });
1731   if (it == subsample_declarations.end())
1732     {
1733       it = subsample_declarations.find({ name2, name1 });
1734       if (it == subsample_declarations.end())
1735         {
1736           string err{name1};
1737           if (!name2.empty())
1738             err.append(",").append(name2);
1739           error("A subsample statement has not been issued for " + err);
1740         }
1741     }
1742 
1743   auto tmp_map = it->second;
1744   if (tmp_map.find(subsample_name) == tmp_map.end())
1745     error("The subsample name " + subsample_name + " was not previously declared in a subsample statement.");
1746 }
1747 
1748 void
set_prior(const string & name,const string & subsample_name)1749 ParsingDriver::set_prior(const string &name, const string &subsample_name)
1750 {
1751   check_symbol_is_parameter(name);
1752   check_subsample_declaration_exists(name, subsample_name);
1753   mod_file->addStatement(make_unique<PriorStatement>(name, subsample_name, prior_shape, prior_variance, options_list));
1754   options_list.clear();
1755   set_prior_variance();
1756   prior_shape = PriorDistributions::noShape;
1757 }
1758 
1759 void
set_joint_prior(const vector<string> & symbol_vec)1760 ParsingDriver::set_joint_prior(const vector<string> &symbol_vec)
1761 {
1762   for (auto &it : symbol_vec)
1763     add_joint_parameter(it);
1764   mod_file->addStatement(make_unique<JointPriorStatement>(joint_parameters, prior_shape, options_list));
1765   joint_parameters.clear();
1766   options_list.clear();
1767   prior_shape = PriorDistributions::noShape;
1768 }
1769 
1770 void
add_joint_parameter(string name)1771 ParsingDriver::add_joint_parameter(string name)
1772 {
1773   check_symbol_is_parameter(name);
1774   joint_parameters.push_back(move(name));
1775 }
1776 
1777 void
set_prior_variance(expr_t variance)1778 ParsingDriver::set_prior_variance(expr_t variance)
1779 {
1780   prior_variance = variance;
1781 }
1782 
1783 void
copy_prior(const string & to_declaration_type,const string & to_name1,const string & to_name2,const string & to_subsample_name,const string & from_declaration_type,const string & from_name1,const string & from_name2,const string & from_subsample_name)1784 ParsingDriver::copy_prior(const string &to_declaration_type, const string &to_name1,
1785                           const string &to_name2, const string &to_subsample_name,
1786                           const string &from_declaration_type, const string &from_name1,
1787                           const string &from_name2, const string &from_subsample_name)
1788 {
1789   if (to_declaration_type == "par")
1790     check_symbol_is_parameter(to_name1);
1791   else
1792     {
1793       check_symbol_is_endogenous_or_exogenous(to_name1);
1794       if (!to_name2.empty())
1795         check_symbol_is_endogenous_or_exogenous(to_name2);
1796     }
1797 
1798   if (from_declaration_type == "par")
1799     check_symbol_is_parameter(from_name1);
1800   else
1801     {
1802       check_symbol_is_endogenous_or_exogenous(from_name1);
1803       if (!from_name2.empty())
1804         check_symbol_is_endogenous_or_exogenous(from_name2);
1805     }
1806 
1807   mod_file->addStatement(make_unique<PriorEqualStatement>(to_declaration_type, to_name1,
1808                                                           to_name2, to_subsample_name,
1809                                                           from_declaration_type, from_name1,
1810                                                           from_name2, from_subsample_name,
1811                                                           mod_file->symbol_table));
1812 }
1813 
1814 void
set_options(const string & name,const string & subsample_name)1815 ParsingDriver::set_options(const string &name, const string &subsample_name)
1816 {
1817   check_symbol_is_parameter(name);
1818   check_subsample_declaration_exists(name, subsample_name);
1819   mod_file->addStatement(make_unique<OptionsStatement>(name, subsample_name, options_list));
1820   options_list.clear();
1821 }
1822 
1823 void
copy_options(const string & to_declaration_type,const string & to_name1,const string & to_name2,const string & to_subsample_name,const string & from_declaration_type,const string & from_name1,const string & from_name2,const string & from_subsample_name)1824 ParsingDriver::copy_options(const string &to_declaration_type, const string &to_name1,
1825                             const string &to_name2, const string &to_subsample_name,
1826                             const string &from_declaration_type, const string &from_name1,
1827                             const string &from_name2, const string &from_subsample_name)
1828 {
1829   if (to_declaration_type == "par")
1830     check_symbol_is_parameter(to_name1);
1831   else
1832     {
1833       check_symbol_is_endogenous_or_exogenous(to_name1);
1834       if (!to_name2.empty())
1835         check_symbol_is_endogenous_or_exogenous(to_name2);
1836     }
1837 
1838   if (from_declaration_type == "par")
1839     check_symbol_is_parameter(from_name1);
1840   else
1841     {
1842       check_symbol_is_endogenous_or_exogenous(from_name1);
1843       if (!from_name2.empty())
1844         check_symbol_is_endogenous_or_exogenous(from_name2);
1845     }
1846 
1847   mod_file->addStatement(make_unique<OptionsEqualStatement>(to_declaration_type, to_name1,
1848                                                             to_name2, to_subsample_name,
1849                                                             from_declaration_type, from_name1,
1850                                                             from_name2, from_subsample_name,
1851                                                             mod_file->symbol_table));
1852 }
1853 
1854 void
check_symbol_is_endogenous_or_exogenous(const string & name)1855 ParsingDriver::check_symbol_is_endogenous_or_exogenous(const string &name)
1856 {
1857   check_symbol_existence(name);
1858   switch (mod_file->symbol_table.getType(name))
1859     {
1860     case SymbolType::endogenous:
1861     case SymbolType::exogenous:
1862     case SymbolType::exogenousDet:
1863       break;
1864     default:
1865       error(name + " is neither endogenous or exogenous.");
1866     }
1867 }
1868 
1869 void
check_symbol_is_endogenous(const string & name)1870 ParsingDriver::check_symbol_is_endogenous(const string &name)
1871 {
1872   check_symbol_existence(name);
1873   if (mod_file->symbol_table.getType(name) != SymbolType::endogenous)
1874     error(name + " is not endogenous.");
1875 }
1876 
1877 void
check_symbol_is_exogenous(const string & name)1878 ParsingDriver::check_symbol_is_exogenous(const string &name)
1879 {
1880   check_symbol_existence(name);
1881   switch (mod_file->symbol_table.getType(name))
1882     {
1883     case SymbolType::exogenous:
1884     case SymbolType::exogenousDet:
1885       break;
1886     default:
1887       error(name + " is not exogenous.");
1888     }
1889 }
1890 
1891 void
set_std_prior(const string & name,const string & subsample_name)1892 ParsingDriver::set_std_prior(const string &name, const string &subsample_name)
1893 {
1894   check_symbol_is_endogenous_or_exogenous(name);
1895   check_subsample_declaration_exists(name, subsample_name);
1896   mod_file->addStatement(make_unique<StdPriorStatement>(name, subsample_name, prior_shape, prior_variance,
1897                                                         options_list, mod_file->symbol_table));
1898   options_list.clear();
1899   set_prior_variance();
1900   prior_shape = PriorDistributions::noShape;
1901 }
1902 
1903 void
set_std_options(const string & name,const string & subsample_name)1904 ParsingDriver::set_std_options(const string &name, const string &subsample_name)
1905 {
1906   check_symbol_is_endogenous_or_exogenous(name);
1907   check_subsample_declaration_exists(name, subsample_name);
1908   mod_file->addStatement(make_unique<StdOptionsStatement>(name, subsample_name, options_list, mod_file->symbol_table));
1909   options_list.clear();
1910 }
1911 
1912 void
set_corr_prior(const string & name1,const string & name2,const string & subsample_name)1913 ParsingDriver::set_corr_prior(const string &name1, const string &name2, const string &subsample_name)
1914 {
1915   check_symbol_is_endogenous_or_exogenous(name1);
1916   check_symbol_is_endogenous_or_exogenous(name2);
1917   check_subsample_declaration_exists(name1, name2, subsample_name);
1918   mod_file->addStatement(make_unique<CorrPriorStatement>(name1, name2, subsample_name, prior_shape, prior_variance,
1919                                                          options_list, mod_file->symbol_table));
1920   options_list.clear();
1921   set_prior_variance();
1922   prior_shape = PriorDistributions::noShape;
1923 }
1924 
1925 void
set_corr_options(const string & name1,const string & name2,const string & subsample_name)1926 ParsingDriver::set_corr_options(const string &name1, const string &name2, const string &subsample_name)
1927 {
1928   check_symbol_is_endogenous_or_exogenous(name1);
1929   check_symbol_is_endogenous_or_exogenous(name2);
1930   check_subsample_declaration_exists(name1, name2, subsample_name);
1931   mod_file->addStatement(make_unique<CorrOptionsStatement>(name1, name2, subsample_name, options_list, mod_file->symbol_table));
1932   options_list.clear();
1933 }
1934 
1935 void
run_estimation()1936 ParsingDriver::run_estimation()
1937 {
1938   mod_file->addStatement(make_unique<EstimationStatement>(mod_file->symbol_table, symbol_list, options_list));
1939   symbol_list.clear();
1940   options_list.clear();
1941 }
1942 
1943 void
dynare_sensitivity()1944 ParsingDriver::dynare_sensitivity()
1945 {
1946   mod_file->addStatement(make_unique<DynareSensitivityStatement>(options_list));
1947   options_list.clear();
1948 }
1949 
1950 void
optim_options_helper(const string & name)1951 ParsingDriver::optim_options_helper(const string &name)
1952 {
1953   if (options_list.string_options.find("optim_opt") == options_list.string_options.end())
1954     options_list.string_options["optim_opt"] = "";
1955   else
1956     options_list.string_options["optim_opt"] += ",";
1957   options_list.string_options["optim_opt"] += "''" + name + "'',";
1958 }
1959 
1960 void
optim_options_string(const string & name,const string & value)1961 ParsingDriver::optim_options_string(const string &name, const string &value)
1962 {
1963   optim_options_helper(name);
1964   options_list.string_options["optim_opt"] += "''" + value + "''";
1965 }
1966 
1967 void
optim_options_num(const string & name,const string & value)1968 ParsingDriver::optim_options_num(const string &name, const string &value)
1969 {
1970   optim_options_helper(name);
1971   options_list.string_options["optim_opt"] += value;
1972 }
1973 
1974 void
sampling_options_helper(const string & name)1975 ParsingDriver::sampling_options_helper(const string &name)
1976 {
1977   if (options_list.string_options.find("posterior_sampler_options.sampling_opt") ==
1978       options_list.string_options.end())
1979     options_list.string_options["posterior_sampler_options.sampling_opt"] = "";
1980   else
1981     options_list.string_options["posterior_sampler_options.sampling_opt"] += ",";
1982   options_list.string_options["posterior_sampler_options.sampling_opt"] += "''" + name + "'',";
1983 }
1984 
1985 void
sampling_options_string(const string & name,const string & value)1986 ParsingDriver::sampling_options_string(const string &name, const string &value)
1987 {
1988   sampling_options_helper(name);
1989   options_list.string_options["posterior_sampler_options.sampling_opt"] += "''" + value + "''";
1990 }
1991 
1992 void
sampling_options_num(const string & name,const string & value)1993 ParsingDriver::sampling_options_num(const string &name, const string &value)
1994 {
1995   sampling_options_helper(name);
1996   options_list.string_options["posterior_sampler_options.sampling_opt"] += value;
1997 }
1998 
1999 void
sampling_options_vec_str(const string & name,vector<string> value)2000 ParsingDriver::sampling_options_vec_str(const string &name, vector<string> value)
2001 {
2002   sampling_options_helper(name);
2003   options_list.string_options["posterior_sampler_options.sampling_opt"] += "{";
2004   for (auto &it : value)
2005     {
2006       if (&it != &value.front())
2007         options_list.string_options["posterior_sampler_options.sampling_opt"] += ",";
2008       options_list.string_options["posterior_sampler_options.sampling_opt"] += "''" + it + "''";
2009     }
2010   options_list.string_options["posterior_sampler_options.sampling_opt"] += "}";
2011 }
2012 
2013 void
check_varobs()2014 ParsingDriver::check_varobs()
2015 {
2016   if (mod_file->symbol_table.observedVariablesNbr() > 0)
2017     error("varobs: you cannot have several 'varobs' statements in the same MOD file");
2018 }
2019 
2020 void
add_varobs(const string & name)2021 ParsingDriver::add_varobs(const string &name)
2022 {
2023   check_symbol_is_endogenous(name);
2024   int symb_id = mod_file->symbol_table.getID(name);
2025   mod_file->symbol_table.addObservedVariable(symb_id);
2026 }
2027 
2028 void
check_varexobs()2029 ParsingDriver::check_varexobs()
2030 {
2031   if (mod_file->symbol_table.observedExogenousVariablesNbr() > 0)
2032     error("varexobs: you cannot have several 'varexobs' statements in the same MOD file");
2033 }
2034 
2035 void
add_varexobs(const string & name)2036 ParsingDriver::add_varexobs(const string &name)
2037 {
2038   check_symbol_existence(name);
2039   int symb_id = mod_file->symbol_table.getID(name);
2040   if (mod_file->symbol_table.getType(symb_id) != SymbolType::exogenous)
2041     error("varexobs: " + name + " is not an exogenous variable");
2042   mod_file->symbol_table.addObservedExogenousVariable(symb_id);
2043 }
2044 
2045 void
set_trends()2046 ParsingDriver::set_trends()
2047 {
2048   mod_file->addStatement(make_unique<ObservationTrendsStatement>(trend_elements, mod_file->symbol_table));
2049   trend_elements.clear();
2050 }
2051 
2052 void
set_trend_element(string arg1,expr_t arg2)2053 ParsingDriver::set_trend_element(string arg1, expr_t arg2)
2054 {
2055   check_symbol_existence(arg1);
2056   if (trend_elements.find(arg1) != trend_elements.end())
2057     error("observation_trends: " + arg1 + " declared twice");
2058   trend_elements[move(arg1)] = arg2;
2059 }
2060 
2061 void
set_optim_weights(string name,expr_t value)2062 ParsingDriver::set_optim_weights(string name, expr_t value)
2063 {
2064   check_symbol_is_endogenous(name);
2065   if (var_weights.find(name) != var_weights.end())
2066     error("optim_weights: " + name + " declared twice");
2067   var_weights[move(name)] = move(value);
2068 }
2069 
2070 void
set_optim_weights(const string & name1,const string & name2,expr_t value)2071 ParsingDriver::set_optim_weights(const string &name1, const string &name2, expr_t value)
2072 {
2073   check_symbol_is_endogenous(name1);
2074   check_symbol_is_endogenous(name2);
2075 
2076   pair<string, string> covar_key{name1, name2};
2077 
2078   if (covar_weights.find(covar_key) != covar_weights.end())
2079     error("optim_weights: pair of variables (" + name1 + ", " + name2
2080           + ") declared twice");
2081 
2082   covar_weights[covar_key] = value;
2083 }
2084 
2085 void
optim_weights()2086 ParsingDriver::optim_weights()
2087 {
2088   mod_file->addStatement(make_unique<OptimWeightsStatement>(var_weights, covar_weights, mod_file->symbol_table));
2089   var_weights.clear();
2090   covar_weights.clear();
2091 }
2092 
2093 void
set_osr_params()2094 ParsingDriver::set_osr_params()
2095 {
2096   mod_file->addStatement(make_unique<OsrParamsStatement>(symbol_list, mod_file->symbol_table));
2097   symbol_list.clear();
2098 }
2099 
2100 void
run_osr()2101 ParsingDriver::run_osr()
2102 {
2103   mod_file->addStatement(make_unique<OsrStatement>(symbol_list, options_list));
2104   symbol_list.clear();
2105   options_list.clear();
2106 }
2107 
2108 void
run_dynatype(const string & filename)2109 ParsingDriver::run_dynatype(const string &filename)
2110 {
2111   mod_file->addStatement(make_unique<DynaTypeStatement>(symbol_list, filename));
2112   symbol_list.clear();
2113 }
2114 
2115 void
run_dynasave(const string & filename)2116 ParsingDriver::run_dynasave(const string &filename)
2117 {
2118   mod_file->addStatement(make_unique<DynaSaveStatement>(symbol_list, filename));
2119   symbol_list.clear();
2120 }
2121 
2122 void
run_load_params_and_steady_state(const string & filename)2123 ParsingDriver::run_load_params_and_steady_state(const string &filename)
2124 {
2125   mod_file->addStatement(make_unique<LoadParamsAndSteadyStateStatement>(filename, mod_file->symbol_table, warnings));
2126 }
2127 
2128 void
run_save_params_and_steady_state(const string & filename)2129 ParsingDriver::run_save_params_and_steady_state(const string &filename)
2130 {
2131   mod_file->addStatement(make_unique<SaveParamsAndSteadyStateStatement>(filename));
2132 }
2133 
2134 void
run_identification()2135 ParsingDriver::run_identification()
2136 {
2137   mod_file->addStatement(make_unique<IdentificationStatement>(options_list));
2138   options_list.clear();
2139 }
2140 
2141 void
add_mc_filename(string filename,string prior)2142 ParsingDriver::add_mc_filename(string filename, string prior)
2143 {
2144   for (auto &it : filename_list)
2145     if (it.first == filename)
2146       error("model_comparison: filename " + filename + " declared twice");
2147   filename_list.emplace_back(move(filename), move(prior));
2148 }
2149 
2150 void
run_model_comparison()2151 ParsingDriver::run_model_comparison()
2152 {
2153   mod_file->addStatement(make_unique<ModelComparisonStatement>(filename_list, options_list));
2154   filename_list.clear();
2155   options_list.clear();
2156 }
2157 
2158 void
begin_planner_objective()2159 ParsingDriver::begin_planner_objective()
2160 {
2161   planner_objective = make_unique<StaticModel>(mod_file->symbol_table,
2162                                                mod_file->num_constants,
2163                                                mod_file->external_functions_table);
2164   set_current_data_tree(planner_objective.get());
2165 }
2166 
2167 void
end_planner_objective(expr_t expr)2168 ParsingDriver::end_planner_objective(expr_t expr)
2169 {
2170   // Add equation corresponding to expression
2171   expr_t eq = model_tree->AddEqual(expr, model_tree->Zero);
2172   model_tree->addEquation(eq, location.begin.line);
2173 
2174   mod_file->addStatement(make_unique<PlannerObjectiveStatement>(*planner_objective));
2175 
2176   reset_data_tree();
2177 }
2178 
2179 void
ramsey_model()2180 ParsingDriver::ramsey_model()
2181 {
2182   if (!mod_file->symbol_table.exists("optimal_policy_discount_factor"))
2183     {
2184       if (!planner_discount)
2185         planner_discount = data_tree->One;
2186       declare_parameter("optimal_policy_discount_factor", planner_discount_latex_name);
2187       init_param("optimal_policy_discount_factor", planner_discount);
2188     }
2189   else if (planner_discount)
2190     error("ramsey_model: the 'planner_discount' option cannot be used when the 'optimal_policy_discount_factor' parameter is explicitly declared.");
2191 
2192   mod_file->addStatement(make_unique<RamseyModelStatement>(options_list));
2193   options_list.clear();
2194   planner_discount = nullptr;
2195   planner_discount_latex_name.clear();
2196 }
2197 
2198 void
ramsey_policy()2199 ParsingDriver::ramsey_policy()
2200 {
2201   warning("The 'ramsey_policy' statement is deprecated. Please use 'ramsey_model', 'stoch_simul', and 'evaluate_planner_objective' instead.");
2202 
2203   if (!mod_file->symbol_table.exists("optimal_policy_discount_factor"))
2204     {
2205       if (!planner_discount)
2206         planner_discount = data_tree->One;
2207       declare_parameter("optimal_policy_discount_factor");
2208       init_param("optimal_policy_discount_factor", planner_discount);
2209     }
2210   else if (planner_discount)
2211     error("ramsey_policy: the 'planner_discount' option cannot be used when the 'optimal_policy_discount_factor' parameter is explicitly declared.");
2212 
2213   mod_file->addStatement(make_unique<RamseyPolicyStatement>(mod_file->symbol_table,
2214                                                             symbol_list, options_list));
2215   options_list.clear();
2216   symbol_list.clear();
2217   planner_discount = nullptr;
2218 }
2219 
2220 void
evaluate_planner_objective()2221 ParsingDriver::evaluate_planner_objective()
2222 {
2223   mod_file->addStatement(make_unique<EvaluatePlannerObjective>());
2224 }
2225 
2226 void
discretionary_policy()2227 ParsingDriver::discretionary_policy()
2228 {
2229   /* The logic here is different from “ramsey_policy” and “ramsey_model”,
2230      because we want to allow several instances of “discretionary_policy” in
2231      the same .mod file. */
2232   if (!mod_file->symbol_table.exists("optimal_policy_discount_factor"))
2233     declare_parameter("optimal_policy_discount_factor");
2234 
2235   if (!planner_discount)
2236     planner_discount = data_tree->One;
2237   init_param("optimal_policy_discount_factor", planner_discount);
2238 
2239   mod_file->addStatement(make_unique<DiscretionaryPolicyStatement>(symbol_list, options_list));
2240   symbol_list.clear();
2241   options_list.clear();
2242   planner_discount = nullptr;
2243 }
2244 
2245 void
write_latex_dynamic_model(bool write_equation_tags)2246 ParsingDriver::write_latex_dynamic_model(bool write_equation_tags)
2247 {
2248   mod_file->addStatement(make_unique<WriteLatexDynamicModelStatement>(mod_file->dynamic_model, write_equation_tags));
2249 }
2250 
2251 void
write_latex_static_model(bool write_equation_tags)2252 ParsingDriver::write_latex_static_model(bool write_equation_tags)
2253 {
2254   mod_file->addStatement(make_unique<WriteLatexStaticModelStatement>(mod_file->static_model, write_equation_tags));
2255 }
2256 
2257 void
write_latex_original_model(bool write_equation_tags)2258 ParsingDriver::write_latex_original_model(bool write_equation_tags)
2259 {
2260   mod_file->addStatement(make_unique<WriteLatexOriginalModelStatement>(mod_file->original_model, write_equation_tags));
2261 }
2262 
2263 void
write_latex_steady_state_model()2264 ParsingDriver::write_latex_steady_state_model()
2265 {
2266   mod_file->addStatement(make_unique<WriteLatexSteadyStateModelStatement>(mod_file->steady_state_model));
2267 }
2268 
2269 void
bvar_density(const string & maxnlags)2270 ParsingDriver::bvar_density(const string &maxnlags)
2271 {
2272   mod_file->addStatement(make_unique<BVARDensityStatement>(stoi(maxnlags), options_list));
2273   options_list.clear();
2274 }
2275 
2276 void
bvar_forecast(const string & nlags)2277 ParsingDriver::bvar_forecast(const string &nlags)
2278 {
2279   mod_file->addStatement(make_unique<BVARForecastStatement>(stoi(nlags), options_list));
2280   options_list.clear();
2281 }
2282 
2283 void
sbvar()2284 ParsingDriver::sbvar()
2285 {
2286   mod_file->addStatement(make_unique<SBVARStatement>(options_list));
2287   options_list.clear();
2288 }
2289 
2290 void
ms_estimation()2291 ParsingDriver::ms_estimation()
2292 {
2293   mod_file->addStatement(make_unique<MSSBVAREstimationStatement>(options_list));
2294   options_list.clear();
2295 }
2296 
2297 void
ms_simulation()2298 ParsingDriver::ms_simulation()
2299 {
2300   mod_file->addStatement(make_unique<MSSBVARSimulationStatement>(options_list));
2301   options_list.clear();
2302 }
2303 
2304 void
ms_compute_mdd()2305 ParsingDriver::ms_compute_mdd()
2306 {
2307   mod_file->addStatement(make_unique<MSSBVARComputeMDDStatement>(options_list));
2308   options_list.clear();
2309 }
2310 
2311 void
ms_compute_probabilities()2312 ParsingDriver::ms_compute_probabilities()
2313 {
2314   mod_file->addStatement(make_unique<MSSBVARComputeProbabilitiesStatement>(options_list));
2315   options_list.clear();
2316 }
2317 
2318 void
ms_irf()2319 ParsingDriver::ms_irf()
2320 {
2321   mod_file->addStatement(make_unique<MSSBVARIrfStatement>(symbol_list, options_list));
2322   symbol_list.clear();
2323   options_list.clear();
2324 }
2325 
2326 void
ms_forecast()2327 ParsingDriver::ms_forecast()
2328 {
2329   mod_file->addStatement(make_unique<MSSBVARForecastStatement>(options_list));
2330   options_list.clear();
2331 }
2332 
2333 void
ms_variance_decomposition()2334 ParsingDriver::ms_variance_decomposition()
2335 {
2336   mod_file->addStatement(make_unique<MSSBVARVarianceDecompositionStatement>(options_list));
2337   options_list.clear();
2338 }
2339 
2340 void
svar()2341 ParsingDriver::svar()
2342 {
2343   auto it0 = options_list.string_options.find("ms.coefficients"),
2344     it1 = options_list.string_options.find("ms.variances"),
2345     it2 = options_list.string_options.find("ms.constants");
2346   if (it0 == options_list.string_options.end()
2347       && it1 == options_list.string_options.end()
2348       && it2 == options_list.string_options.end())
2349     error("You must pass one of 'coefficients', 'variances', or 'constants'.");
2350 
2351   if ((it0 != options_list.string_options.end()
2352        && it1 != options_list.string_options.end())
2353       || (it1 != options_list.string_options.end()
2354           && it2 != options_list.string_options.end())
2355       || (it0 != options_list.string_options.end()
2356           && it2 != options_list.string_options.end()))
2357     error("You may only pass one of 'coefficients', 'variances', or 'constants'.");
2358 
2359   if (auto itn = options_list.num_options.find("ms.chain");
2360       itn == options_list.num_options.end())
2361     error("A chain option must be passed to the svar statement.");
2362   else if (stoi(itn->second) <= 0)
2363     error("The value passed to the chain option must be greater than zero.");
2364 
2365   if (auto itv = options_list.vector_int_options.find("ms.equations");
2366       itv != options_list.vector_int_options.end())
2367     for (int viit : itv->second)
2368       if (viit <= 0)
2369         error("The value(s) passed to the equation option must be greater than zero.");
2370 
2371   mod_file->addStatement(make_unique<SvarStatement>(options_list));
2372   options_list.clear();
2373 }
2374 
2375 void
markov_switching()2376 ParsingDriver::markov_switching()
2377 {
2378   auto it0 = options_list.num_options.find("ms.chain");
2379   if (it0 == options_list.num_options.end())
2380     error("A chain option must be passed to the markov_switching statement.");
2381   else if (stoi(it0->second) <= 0)
2382     error("The value passed to the chain option must be greater than zero.");
2383 
2384   it0 = options_list.num_options.find("ms.number_of_regimes");
2385   if (it0 == options_list.num_options.end())
2386     error("A number_of_regimes option must be passed to the markov_switching statement.");
2387   else if (stoi(it0->second) <= 0)
2388     error("The value passed to the number_of_regimes option must be greater than zero.");
2389 
2390   it0 = options_list.num_options.find("ms.duration");
2391   if (it0 == options_list.num_options.end())
2392     error("A duration option must be passed to the markov_switching statement.");
2393 
2394   mod_file->addStatement(make_unique<MarkovSwitchingStatement>(options_list));
2395   options_list.clear();
2396 }
2397 
2398 void
shock_decomposition()2399 ParsingDriver::shock_decomposition()
2400 {
2401   mod_file->addStatement(make_unique<ShockDecompositionStatement>(symbol_list, options_list));
2402   symbol_list.clear();
2403   options_list.clear();
2404 }
2405 
2406 void
realtime_shock_decomposition()2407 ParsingDriver::realtime_shock_decomposition()
2408 {
2409   mod_file->addStatement(make_unique<RealtimeShockDecompositionStatement>(symbol_list, options_list));
2410   symbol_list.clear();
2411   options_list.clear();
2412 }
2413 
2414 void
plot_shock_decomposition()2415 ParsingDriver::plot_shock_decomposition()
2416 {
2417   mod_file->addStatement(make_unique<PlotShockDecompositionStatement>(symbol_list, options_list));
2418   symbol_list.clear();
2419   options_list.clear();
2420 }
2421 
2422 void
initial_condition_decomposition()2423 ParsingDriver::initial_condition_decomposition()
2424 {
2425   mod_file->addStatement(make_unique<InitialConditionDecompositionStatement>(symbol_list, options_list));
2426   symbol_list.clear();
2427   options_list.clear();
2428 }
2429 
2430 void
squeeze_shock_decomposition()2431 ParsingDriver::squeeze_shock_decomposition()
2432 {
2433   mod_file->addStatement(make_unique<SqueezeShockDecompositionStatement>(symbol_list));
2434   symbol_list.clear();
2435 }
2436 
2437 void
conditional_forecast()2438 ParsingDriver::conditional_forecast()
2439 {
2440   mod_file->addStatement(make_unique<ConditionalForecastStatement>(options_list));
2441   options_list.clear();
2442 }
2443 
2444 void
plot_conditional_forecast(const string & periods)2445 ParsingDriver::plot_conditional_forecast(const string &periods)
2446 {
2447   int nperiods = periods.empty() ? -1 : stoi(periods);
2448   mod_file->addStatement(make_unique<PlotConditionalForecastStatement>(nperiods, symbol_list));
2449   symbol_list.clear();
2450 }
2451 
2452 void
conditional_forecast_paths()2453 ParsingDriver::conditional_forecast_paths()
2454 {
2455   mod_file->addStatement(make_unique<ConditionalForecastPathsStatement>(det_shocks, mod_file->symbol_table));
2456   det_shocks.clear();
2457 }
2458 
2459 void
calib_smoother()2460 ParsingDriver::calib_smoother()
2461 {
2462   mod_file->addStatement(make_unique<CalibSmootherStatement>(symbol_list, options_list));
2463   symbol_list.clear();
2464   options_list.clear();
2465 }
2466 
2467 void
extended_path()2468 ParsingDriver::extended_path()
2469 {
2470   mod_file->addStatement(make_unique<ExtendedPathStatement>(options_list));
2471   options_list.clear();
2472 }
2473 
2474 expr_t
add_model_equal(expr_t arg1,expr_t arg2)2475 ParsingDriver::add_model_equal(expr_t arg1, expr_t arg2)
2476 {
2477   expr_t id = model_tree->AddEqual(arg1, arg2);
2478 
2479   // Detect if the equation is tagged [static]
2480   bool is_static_only = false;
2481   for (auto &eq_tag : eq_tags)
2482     if (eq_tag.first == "static")
2483       {
2484         is_static_only = true;
2485         break;
2486       }
2487 
2488   if (is_static_only)
2489     {
2490       if (!id->isInStaticForm())
2491         error("An equation tagged [static] cannot contain leads, lags, expectations or STEADY_STATE operators");
2492 
2493       dynamic_model->addStaticOnlyEquation(id, location.begin.line, eq_tags);
2494     }
2495   else
2496     model_tree->addEquation(id, location.begin.line, eq_tags);
2497 
2498   eq_tags.clear();
2499   return id;
2500 }
2501 
2502 expr_t
add_model_equal_with_zero_rhs(expr_t arg)2503 ParsingDriver::add_model_equal_with_zero_rhs(expr_t arg)
2504 {
2505   return add_model_equal(arg, model_tree->Zero);
2506 }
2507 
2508 void
declare_model_local_variable(const string & name,const string & tex_name)2509 ParsingDriver::declare_model_local_variable(const string &name, const string &tex_name)
2510 {
2511   declare_symbol(name, SymbolType::modelLocalVariable, tex_name, {});
2512 }
2513 
2514 void
declare_and_init_model_local_variable(const string & name,expr_t rhs)2515 ParsingDriver::declare_and_init_model_local_variable(const string &name, expr_t rhs)
2516 {
2517   int symb_id;
2518   try
2519     {
2520       symb_id = mod_file->symbol_table.addSymbol(name, SymbolType::modelLocalVariable);
2521     }
2522   catch (SymbolTable::AlreadyDeclaredException &e)
2523     {
2524       // It can have already been declared in a steady_state_model block, check that it is indeed a ModelLocalVariable
2525       symb_id = mod_file->symbol_table.getID(name);
2526       if (mod_file->symbol_table.getType(symb_id) != SymbolType::modelLocalVariable)
2527         error(name + " has wrong type or was already used on the right-hand side. You cannot use it on the left-hand side of a pound ('#') expression");
2528     }
2529 
2530   try
2531     {
2532       model_tree->AddLocalVariable(symb_id, rhs);
2533     }
2534   catch (DataTree::LocalVariableException &e)
2535     {
2536       error("Local model variable " + name + " declared twice.");
2537     }
2538 }
2539 
2540 void
change_type(SymbolType new_type,const vector<string> & var_list)2541 ParsingDriver::change_type(SymbolType new_type, const vector<string> &var_list)
2542 {
2543   for (auto &it : var_list)
2544     {
2545       int id;
2546       try
2547         {
2548           id = mod_file->symbol_table.getID(it);
2549         }
2550       catch (SymbolTable::UnknownSymbolNameException &e)
2551         {
2552           error("Unknown variable " + it);
2553         }
2554 
2555       // Check if symbol already used in a VariableNode
2556       if (mod_file->expressions_tree.isSymbolUsed(id)
2557           || mod_file->dynamic_model.isSymbolUsed(id))
2558         error("You cannot modify the type of symbol " + it + " after having used it in an expression");
2559 
2560       mod_file->symbol_table.changeType(id, new_type);
2561     }
2562 }
2563 
2564 expr_t
add_plus(expr_t arg1,expr_t arg2)2565 ParsingDriver::add_plus(expr_t arg1, expr_t arg2)
2566 {
2567   return data_tree->AddPlus(arg1, arg2);
2568 }
2569 
2570 expr_t
add_minus(expr_t arg1,expr_t arg2)2571 ParsingDriver::add_minus(expr_t arg1, expr_t arg2)
2572 {
2573   return data_tree->AddMinus(arg1, arg2);
2574 }
2575 
2576 expr_t
add_uminus(expr_t arg1)2577 ParsingDriver::add_uminus(expr_t arg1)
2578 {
2579   return data_tree->AddUMinus(arg1);
2580 }
2581 
2582 expr_t
add_times(expr_t arg1,expr_t arg2)2583 ParsingDriver::add_times(expr_t arg1, expr_t arg2)
2584 {
2585   return data_tree->AddTimes(arg1, arg2);
2586 }
2587 
2588 expr_t
add_divide(expr_t arg1,expr_t arg2)2589 ParsingDriver::add_divide(expr_t arg1, expr_t arg2)
2590 {
2591   try
2592     {
2593       return data_tree->AddDivide(arg1, arg2);
2594     }
2595   catch (DataTree::DivisionByZeroException)
2596     {
2597       error("Division by zero error encountered when reading model from .mod file");
2598     }
2599 }
2600 
2601 expr_t
add_less(expr_t arg1,expr_t arg2)2602 ParsingDriver::add_less(expr_t arg1, expr_t arg2)
2603 {
2604   return data_tree->AddLess(arg1, arg2);
2605 }
2606 
2607 expr_t
add_greater(expr_t arg1,expr_t arg2)2608 ParsingDriver::add_greater(expr_t arg1, expr_t arg2)
2609 {
2610   return data_tree->AddGreater(arg1, arg2);
2611 }
2612 
2613 expr_t
add_less_equal(expr_t arg1,expr_t arg2)2614 ParsingDriver::add_less_equal(expr_t arg1, expr_t arg2)
2615 {
2616   return data_tree->AddLessEqual(arg1, arg2);
2617 }
2618 
2619 expr_t
add_greater_equal(expr_t arg1,expr_t arg2)2620 ParsingDriver::add_greater_equal(expr_t arg1, expr_t arg2)
2621 {
2622   return data_tree->AddGreaterEqual(arg1, arg2);
2623 }
2624 
2625 expr_t
add_equal_equal(expr_t arg1,expr_t arg2)2626 ParsingDriver::add_equal_equal(expr_t arg1, expr_t arg2)
2627 {
2628   return data_tree->AddEqualEqual(arg1, arg2);
2629 }
2630 
2631 expr_t
add_different(expr_t arg1,expr_t arg2)2632 ParsingDriver::add_different(expr_t arg1, expr_t arg2)
2633 {
2634   return data_tree->AddDifferent(arg1, arg2);
2635 }
2636 
2637 expr_t
add_power(expr_t arg1,expr_t arg2)2638 ParsingDriver::add_power(expr_t arg1, expr_t arg2)
2639 {
2640   return data_tree->AddPower(arg1, arg2);
2641 }
2642 
2643 expr_t
add_expectation(const string & arg1,expr_t arg2)2644 ParsingDriver::add_expectation(const string &arg1, expr_t arg2)
2645 {
2646   return data_tree->AddExpectation(stoi(arg1), arg2);
2647 }
2648 
2649 expr_t
add_var_expectation(const string & model_name)2650 ParsingDriver::add_var_expectation(const string &model_name)
2651 {
2652   return data_tree->AddVarExpectation(model_name);
2653 }
2654 
2655 expr_t
add_pac_expectation(const string & var_model_name)2656 ParsingDriver::add_pac_expectation(const string &var_model_name)
2657 {
2658   return data_tree->AddPacExpectation(var_model_name);
2659 }
2660 
2661 void
begin_pac_growth()2662 ParsingDriver::begin_pac_growth()
2663 {
2664   set_current_data_tree(&mod_file->dynamic_model);
2665 }
2666 
2667 void
begin_pac_model()2668 ParsingDriver::begin_pac_model()
2669 {
2670   parsing_pac_model = true;
2671   pac_growth = nullptr;
2672   pac_steady_state_growth_rate_number = -1;
2673   pac_steady_state_growth_rate_symb_id = -1;
2674   options_list.clear();
2675 }
2676 
2677 void
pac_model()2678 ParsingDriver::pac_model()
2679 {
2680   auto it = options_list.string_options.find("pac.model_name");
2681   if (it == options_list.string_options.end())
2682     error("You must pass the model_name option to the pac_model statement.");
2683   auto name = it->second;
2684 
2685   bool pac_growth_is_param = false;
2686   if (pac_growth && dynamic_cast<VariableNode *>(pac_growth))
2687     {
2688       set<int> params;
2689       pac_growth->collectVariables(SymbolType::parameter, params);
2690       if (params.size() == 1)
2691         pac_growth_is_param = true;
2692       pac_growth->collectVariables(SymbolType::endogenous, params);
2693       pac_growth->collectVariables(SymbolType::exogenous, params);
2694       if (params.size() != 1)
2695         pac_growth_is_param = false;
2696     }
2697 
2698   string aux_model_name;
2699   it = options_list.string_options.find("pac.aux_model_name");
2700   if (it != options_list.string_options.end())
2701     {
2702       aux_model_name = it->second;
2703       if (pac_steady_state_growth_rate_number >= 0 || pac_steady_state_growth_rate_symb_id >= 0)
2704         {
2705           pac_steady_state_growth_rate_number = -1;
2706           pac_steady_state_growth_rate_symb_id = -1;
2707           warning("when aux_model_name is used in the pac_model statement, steady_state_growth is ignored");
2708         }
2709     }
2710   else
2711     if (pac_growth_is_param
2712         && (pac_steady_state_growth_rate_number >= 0 || pac_steady_state_growth_rate_symb_id >= 0))
2713       warning("If growth option is constant, steady_state_growth is ignored");
2714     else if (pac_growth && !pac_growth_is_param
2715              && (pac_steady_state_growth_rate_number < 0 || pac_steady_state_growth_rate_symb_id < 0))
2716       error("The steady state growth rate of the target must be provided (steady_state_growth option) if option growth is not constant");
2717 
2718   if (pac_steady_state_growth_rate_symb_id >= 0
2719       && mod_file->symbol_table.getType(pac_steady_state_growth_rate_symb_id) != SymbolType::parameter)
2720     error("pac_model: steady_state_growth accepts either a number or a parameter");
2721 
2722   it = options_list.string_options.find("pac.discount");
2723   if (it == options_list.string_options.end())
2724     error("You must pass the discount option to the pac_model statement.");
2725   auto discount = it->second;
2726 
2727   mod_file->addStatement(make_unique<PacModelStatement>(name, aux_model_name, discount,
2728                                                         pac_growth,
2729                                                         pac_steady_state_growth_rate_number,
2730                                                         pac_steady_state_growth_rate_symb_id,
2731                                                         mod_file->symbol_table));
2732   parsing_pac_model = false;
2733 }
2734 
2735 void
set_pac_growth(expr_t pac_growth_arg)2736 ParsingDriver::set_pac_growth(expr_t pac_growth_arg)
2737 {
2738   pac_growth = pac_growth_arg;
2739   reset_data_tree();
2740 }
2741 
2742 void
set_pac_steady_state_growth(const string & name_or_number)2743 ParsingDriver::set_pac_steady_state_growth(const string &name_or_number)
2744 {
2745   try
2746     {
2747       pac_steady_state_growth_rate_number = stod(name_or_number);
2748     }
2749   catch (...)
2750     {
2751       if (!mod_file->symbol_table.exists(name_or_number))
2752         error("Unknown symbol used in pac_steady_state_growth option: " + name_or_number + "\n");
2753       pac_steady_state_growth_rate_symb_id = mod_file->symbol_table.getID(name_or_number);
2754     }
2755 }
2756 
2757 expr_t
add_exp(expr_t arg1)2758 ParsingDriver::add_exp(expr_t arg1)
2759 {
2760   return data_tree->AddExp(arg1);
2761 }
2762 
2763 expr_t
add_diff(expr_t arg1)2764 ParsingDriver::add_diff(expr_t arg1)
2765 {
2766   return data_tree->AddDiff(arg1);
2767 }
2768 
2769 expr_t
add_adl(expr_t arg1,const string & name,const string & lag)2770 ParsingDriver::add_adl(expr_t arg1, const string &name, const string &lag)
2771 {
2772   vector<int> lags;
2773   for (int i = 1; i <= stoi(lag); i++)
2774     lags.push_back(i);
2775 
2776   return add_adl(arg1, name, lags);
2777 }
2778 
2779 expr_t
add_adl(expr_t arg1,const string & name,const vector<int> & lags)2780 ParsingDriver::add_adl(expr_t arg1, const string &name, const vector<int> &lags)
2781 {
2782   expr_t id = data_tree->AddAdl(arg1, name, lags);
2783 
2784   // Declare parameters here so that parameters can be initialized after the model block
2785   for (auto i : lags)
2786     declare_parameter(name + "_lag_" + to_string(i));
2787 
2788   return id;
2789 }
2790 
2791 expr_t
add_log(expr_t arg1)2792 ParsingDriver::add_log(expr_t arg1)
2793 {
2794   return data_tree->AddLog(arg1);
2795 }
2796 
2797 expr_t
add_log10(expr_t arg1)2798 ParsingDriver::add_log10(expr_t arg1)
2799 {
2800   return data_tree->AddLog10(arg1);
2801 }
2802 
2803 expr_t
add_cos(expr_t arg1)2804 ParsingDriver::add_cos(expr_t arg1)
2805 {
2806   return data_tree->AddCos(arg1);
2807 }
2808 
2809 expr_t
add_sin(expr_t arg1)2810 ParsingDriver::add_sin(expr_t arg1)
2811 {
2812   return data_tree->AddSin(arg1);
2813 }
2814 
2815 expr_t
add_tan(expr_t arg1)2816 ParsingDriver::add_tan(expr_t arg1)
2817 {
2818   return data_tree->AddTan(arg1);
2819 }
2820 
2821 expr_t
add_acos(expr_t arg1)2822 ParsingDriver::add_acos(expr_t arg1)
2823 {
2824   return data_tree->AddAcos(arg1);
2825 }
2826 
2827 expr_t
add_asin(expr_t arg1)2828 ParsingDriver::add_asin(expr_t arg1)
2829 {
2830   return data_tree->AddAsin(arg1);
2831 }
2832 
2833 expr_t
add_atan(expr_t arg1)2834 ParsingDriver::add_atan(expr_t arg1)
2835 {
2836   return data_tree->AddAtan(arg1);
2837 }
2838 
2839 expr_t
add_cosh(expr_t arg1)2840 ParsingDriver::add_cosh(expr_t arg1)
2841 {
2842   return data_tree->AddCosh(arg1);
2843 }
2844 
2845 expr_t
add_sinh(expr_t arg1)2846 ParsingDriver::add_sinh(expr_t arg1)
2847 {
2848   return data_tree->AddSinh(arg1);
2849 }
2850 
2851 expr_t
add_tanh(expr_t arg1)2852 ParsingDriver::add_tanh(expr_t arg1)
2853 {
2854   return data_tree->AddTanh(arg1);
2855 }
2856 
2857 expr_t
add_acosh(expr_t arg1)2858 ParsingDriver::add_acosh(expr_t arg1)
2859 {
2860   return data_tree->AddAcosh(arg1);
2861 }
2862 
2863 expr_t
add_asinh(expr_t arg1)2864 ParsingDriver::add_asinh(expr_t arg1)
2865 {
2866   return data_tree->AddAsinh(arg1);
2867 }
2868 
2869 expr_t
add_atanh(expr_t arg1)2870 ParsingDriver::add_atanh(expr_t arg1)
2871 {
2872   return data_tree->AddAtanh(arg1);
2873 }
2874 
2875 expr_t
add_sqrt(expr_t arg1)2876 ParsingDriver::add_sqrt(expr_t arg1)
2877 {
2878   return data_tree->AddSqrt(arg1);
2879 }
2880 
2881 expr_t
add_cbrt(expr_t arg1)2882 ParsingDriver::add_cbrt(expr_t arg1)
2883 {
2884   return data_tree->AddCbrt(arg1);
2885 }
2886 
2887 expr_t
add_abs(expr_t arg1)2888 ParsingDriver::add_abs(expr_t arg1)
2889 {
2890   return data_tree->AddAbs(arg1);
2891 }
2892 
2893 expr_t
add_sign(expr_t arg1)2894 ParsingDriver::add_sign(expr_t arg1)
2895 {
2896   return data_tree->AddSign(arg1);
2897 }
2898 
2899 expr_t
add_max(expr_t arg1,expr_t arg2)2900 ParsingDriver::add_max(expr_t arg1, expr_t arg2)
2901 {
2902   return data_tree->AddMax(arg1, arg2);
2903 }
2904 
2905 expr_t
add_min(expr_t arg1,expr_t arg2)2906 ParsingDriver::add_min(expr_t arg1, expr_t arg2)
2907 {
2908   return data_tree->AddMin(arg1, arg2);
2909 }
2910 
2911 expr_t
add_normcdf(expr_t arg1,expr_t arg2,expr_t arg3)2912 ParsingDriver::add_normcdf(expr_t arg1, expr_t arg2, expr_t arg3)
2913 {
2914   return data_tree->AddNormcdf(arg1, arg2, arg3);
2915 }
2916 
2917 expr_t
add_normcdf(expr_t arg)2918 ParsingDriver::add_normcdf(expr_t arg)
2919 {
2920   return add_normcdf(arg, data_tree->Zero, data_tree->One);
2921 }
2922 
2923 expr_t
add_normpdf(expr_t arg1,expr_t arg2,expr_t arg3)2924 ParsingDriver::add_normpdf(expr_t arg1, expr_t arg2, expr_t arg3)
2925 {
2926   return data_tree->AddNormpdf(arg1, arg2, arg3);
2927 }
2928 
2929 expr_t
add_normpdf(expr_t arg)2930 ParsingDriver::add_normpdf(expr_t arg)
2931 {
2932   return add_normpdf(arg, data_tree->Zero, data_tree->One);
2933 }
2934 
2935 expr_t
add_erf(expr_t arg1)2936 ParsingDriver::add_erf(expr_t arg1)
2937 {
2938   return data_tree->AddErf(arg1);
2939 }
2940 
2941 expr_t
add_steady_state(expr_t arg1)2942 ParsingDriver::add_steady_state(expr_t arg1)
2943 {
2944   // Forbid exogenous variables, see dynare#825
2945   set<int> r;
2946   arg1->collectVariables(SymbolType::exogenous, r);
2947   if (r.size() > 0)
2948     error("Exogenous variables are not allowed in the context of the STEADY_STATE() operator.");
2949   arg1->collectVariables(SymbolType::exogenousDet, r);
2950   if (r.size() > 0)
2951     error("Exogenous deterministic variables are not allowed in the context of the STEADY_STATE() operator.");
2952 
2953   return data_tree->AddSteadyState(arg1);
2954 }
2955 
2956 void
external_function_option(const string & name_option,const string & opt)2957 ParsingDriver::external_function_option(const string &name_option, const string &opt)
2958 {
2959   if (name_option == "name")
2960     {
2961       if (opt.empty())
2962         error("An argument must be passed to the 'name' option of the external_function() statement.");
2963       declare_symbol(opt, SymbolType::externalFunction, "", {});
2964       current_external_function_id = mod_file->symbol_table.getID(opt);
2965     }
2966   else if (name_option == "first_deriv_provided")
2967     {
2968       if (opt.empty())
2969         current_external_function_options.firstDerivSymbID = ExternalFunctionsTable::IDSetButNoNameProvided;
2970       else
2971         {
2972           declare_symbol(opt, SymbolType::externalFunction, "", {});
2973           current_external_function_options.firstDerivSymbID = mod_file->symbol_table.getID(opt);
2974         }
2975     }
2976   else if (name_option == "second_deriv_provided")
2977     {
2978       if (opt.empty())
2979         current_external_function_options.secondDerivSymbID = ExternalFunctionsTable::IDSetButNoNameProvided;
2980       else
2981         {
2982           declare_symbol(opt, SymbolType::externalFunction, "", {});
2983           current_external_function_options.secondDerivSymbID = mod_file->symbol_table.getID(opt);
2984         }
2985     }
2986   else if (name_option == "nargs")
2987     current_external_function_options.nargs = stoi(opt);
2988   else
2989     error("Unexpected error in ParsingDriver::external_function_option(): Please inform Dynare Team.");
2990 }
2991 
2992 void
external_function()2993 ParsingDriver::external_function()
2994 {
2995   if (current_external_function_id == ExternalFunctionsTable::IDNotSet)
2996     error("The 'name' option must be passed to external_function().");
2997 
2998   if (current_external_function_options.secondDerivSymbID >= 0
2999       && current_external_function_options.firstDerivSymbID == ExternalFunctionsTable::IDNotSet)
3000     error("If the second derivative is provided to the external_function command, the first derivative must also be provided.");
3001 
3002   if (current_external_function_options.secondDerivSymbID == ExternalFunctionsTable::IDSetButNoNameProvided
3003       && current_external_function_options.firstDerivSymbID != ExternalFunctionsTable::IDSetButNoNameProvided)
3004     error("If the second derivative is provided in the top-level function, the first derivative must also be provided in that function.");
3005 
3006   mod_file->external_functions_table.addExternalFunction(current_external_function_id, current_external_function_options, true);
3007   reset_current_external_function_options();
3008 }
3009 
3010 void
push_external_function_arg_vector_onto_stack()3011 ParsingDriver::push_external_function_arg_vector_onto_stack()
3012 {
3013   vector<expr_t> emptyvec;
3014   stack_external_function_args.push(emptyvec);
3015 }
3016 
3017 void
add_external_function_arg(expr_t arg)3018 ParsingDriver::add_external_function_arg(expr_t arg)
3019 {
3020   stack_external_function_args.top().push_back(arg);
3021 }
3022 
3023 pair<bool, double>
is_there_one_integer_argument() const3024 ParsingDriver::is_there_one_integer_argument() const
3025 {
3026   if (stack_external_function_args.top().size() != 1)
3027     return { false, 0 };
3028 
3029   auto numNode = dynamic_cast<NumConstNode *>(stack_external_function_args.top().front());
3030   auto unaryNode = dynamic_cast<UnaryOpNode *>(stack_external_function_args.top().front());
3031 
3032   if (!numNode && !unaryNode)
3033     return { false, 0 };
3034 
3035   eval_context_t ectmp;
3036   double model_var_arg;
3037   if (!unaryNode)
3038     {
3039       try
3040         {
3041           model_var_arg = numNode->eval(ectmp);
3042         }
3043       catch (ExprNode::EvalException &e)
3044         {
3045           return { false, 0 };
3046         }
3047     }
3048   else
3049     if (unaryNode->op_code != UnaryOpcode::uminus)
3050       return { false, 0 };
3051     else
3052       {
3053         try
3054           {
3055             model_var_arg = unaryNode->eval(ectmp);
3056           }
3057         catch (ExprNode::EvalException &e)
3058           {
3059             return { false, 0 };
3060           }
3061       }
3062 
3063   if (model_var_arg != floor(model_var_arg))
3064     return { false, 0 };
3065   return { true, model_var_arg };
3066 }
3067 
3068 expr_t
add_model_var_or_external_function(const string & function_name,bool in_model_block)3069 ParsingDriver::add_model_var_or_external_function(const string &function_name, bool in_model_block)
3070 {
3071   expr_t nid;
3072   if (mod_file->symbol_table.exists(function_name))
3073     if (mod_file->symbol_table.getType(function_name) != SymbolType::externalFunction)
3074       if (!in_model_block && !parsing_epilogue && !parsing_pac_model)
3075         {
3076           if (stack_external_function_args.top().size() > 0)
3077             error(string("Symbol ") + function_name + string(" cannot take arguments."));
3078           else
3079             return add_expression_variable(function_name);
3080         }
3081       else
3082         { // e.g. model_var(lag) => ADD MODEL VARIABLE WITH LEAD (NumConstNode)/LAG (UnaryOpNode)
3083           if (undeclared_model_vars.find(function_name) != undeclared_model_vars.end())
3084             undeclared_model_variable_error("Unknown symbol: " + function_name, function_name);
3085 
3086           pair<bool, double> rv = is_there_one_integer_argument();
3087           if (!rv.first)
3088             model_error("Symbol " + function_name
3089                         +" is being treated as if it were a function (i.e., takes an argument that is not an integer).", "");
3090 
3091           nid = add_model_variable(mod_file->symbol_table.getID(function_name), static_cast<int>(rv.second));
3092           stack_external_function_args.pop();
3093           return nid;
3094         }
3095     else
3096       { // e.g. this function has already been referenced (either ad hoc or through the external_function() statement
3097         // => check that the information matches previously declared info
3098         int symb_id = mod_file->symbol_table.getID(function_name);
3099         if (!mod_file->external_functions_table.exists(symb_id))
3100           error("Using a derivative of an external function (" + function_name + ") in the model block is currently not allowed.");
3101 
3102         if (in_model_block || parsing_epilogue)
3103           if (mod_file->external_functions_table.getNargs(symb_id) == ExternalFunctionsTable::IDNotSet)
3104             error("Before using " + function_name
3105                   +"() in the model block, you must first declare it via the external_function() statement");
3106           else if (static_cast<int>(stack_external_function_args.top().size()) != mod_file->external_functions_table.getNargs(symb_id))
3107             error("The number of arguments passed to " + function_name
3108                   +"() does not match those of a previous call or declaration of this function.");
3109       }
3110   else
3111     { //First time encountering this external function i.e., not previously declared or encountered
3112       if (parsing_epilogue)
3113         error("Variable " + function_name + " used in the epilogue block but was not declared.");
3114 
3115       if (in_model_block)
3116         {
3117           // Continue processing, noting that it was not declared
3118           // Processing will end at the end of the model block if nostrict was not passed
3119           undeclared_model_vars.insert(function_name);
3120           undeclared_model_variable_error("Unknown symbol: " + function_name, function_name);
3121 
3122           pair<bool, double> rv = is_there_one_integer_argument();
3123           if (rv.first)
3124             {
3125               // assume it's a lead/lagged variable
3126               declare_exogenous(function_name);
3127               return add_model_variable(mod_file->symbol_table.getID(function_name), static_cast<int>(rv.second));
3128             }
3129           else
3130             error("To use an external function (" + function_name
3131                   +") within the model block, you must first declare it via the external_function() statement.");
3132         }
3133       declare_symbol(function_name, SymbolType::externalFunction, "", {});
3134       current_external_function_options.nargs = stack_external_function_args.top().size();
3135       mod_file->external_functions_table.addExternalFunction(mod_file->symbol_table.getID(function_name),
3136                                                              current_external_function_options, in_model_block);
3137       reset_current_external_function_options();
3138     }
3139 
3140   //By this point, we're sure that this function exists in the External Functions Table and is not a mod var
3141   int symb_id = mod_file->symbol_table.getID(function_name);
3142   nid = data_tree->AddExternalFunction(symb_id, stack_external_function_args.top());
3143   stack_external_function_args.pop();
3144   return nid;
3145 }
3146 
3147 void
add_native(const string & s)3148 ParsingDriver::add_native(const string &s)
3149 {
3150   mod_file->addStatement(make_unique<NativeStatement>(s));
3151 }
3152 
3153 void
add_native_remove_charset(string str,const string & token)3154 ParsingDriver::add_native_remove_charset(string str, const string &token)
3155 {
3156   size_t found = str.find(token);
3157 
3158   assert(found != string::npos);
3159   str.resize(found);
3160   add_native(str);
3161 }
3162 
3163 void
add_verbatim(const string & s)3164 ParsingDriver::add_verbatim(const string &s)
3165 {
3166   mod_file->addStatement(make_unique<VerbatimStatement>(s));
3167 }
3168 
3169 void
add_verbatim_remove_charset(string str,const string & token)3170 ParsingDriver::add_verbatim_remove_charset(string str, const string &token)
3171 {
3172   size_t found = str.find(token);
3173 
3174   assert(found != string::npos);
3175   str.resize(found);
3176   add_verbatim(str);
3177 }
3178 
3179 void
begin_steady_state_model()3180 ParsingDriver::begin_steady_state_model()
3181 {
3182   set_current_data_tree(&mod_file->steady_state_model);
3183 }
3184 
3185 void
add_steady_state_model_equal(const string & varname,expr_t expr)3186 ParsingDriver::add_steady_state_model_equal(const string &varname, expr_t expr)
3187 {
3188   int id;
3189   try
3190     {
3191       id = mod_file->symbol_table.getID(varname);
3192     }
3193   catch (SymbolTable::UnknownSymbolNameException &e)
3194     {
3195       // Unknown symbol, declare it as a ModFileLocalVariable
3196       id = mod_file->symbol_table.addSymbol(varname, SymbolType::modFileLocalVariable);
3197     }
3198 
3199   SymbolType type = mod_file->symbol_table.getType(id);
3200   if (type != SymbolType::endogenous && type != SymbolType::modFileLocalVariable && type != SymbolType::parameter)
3201     error(varname + " has incorrect type");
3202 
3203   mod_file->steady_state_model.addDefinition(id, expr);
3204 }
3205 
3206 void
add_steady_state_model_equal_multiple(expr_t expr)3207 ParsingDriver::add_steady_state_model_equal_multiple(expr_t expr)
3208 {
3209   const vector<string> &symbs = symbol_list.get_symbols();
3210   vector<int> ids;
3211 
3212   for (const auto &symb : symbs)
3213     {
3214       int id;
3215       try
3216         {
3217           id = mod_file->symbol_table.getID(symb);
3218         }
3219       catch (SymbolTable::UnknownSymbolNameException &e)
3220         {
3221           // Unknown symbol, declare it as a ModFileLocalVariable
3222           id = mod_file->symbol_table.addSymbol(symb, SymbolType::modFileLocalVariable);
3223         }
3224       SymbolType type = mod_file->symbol_table.getType(id);
3225       if (type != SymbolType::endogenous && type != SymbolType::modFileLocalVariable && type != SymbolType::parameter)
3226         error(symb + " has incorrect type");
3227       ids.push_back(id);
3228     }
3229 
3230   mod_file->steady_state_model.addMultipleDefinitions(ids, expr);
3231 
3232   symbol_list.clear();
3233 }
3234 
3235 void
add_graph_format(const string & name)3236 ParsingDriver::add_graph_format(const string &name)
3237 {
3238   graph_formats.addSymbol(name);
3239 }
3240 
3241 void
process_graph_format_option()3242 ParsingDriver::process_graph_format_option()
3243 {
3244   options_list.symbol_list_options["graph_format"] = graph_formats;
3245   graph_formats.clear();
3246 }
3247 
3248 void
initial_condition_decomp_process_graph_format_option()3249 ParsingDriver::initial_condition_decomp_process_graph_format_option()
3250 {
3251   options_list.symbol_list_options["initial_condition_decomp.graph_format"] = graph_formats;
3252   graph_formats.clear();
3253 }
3254 
3255 void
plot_shock_decomp_process_graph_format_option()3256 ParsingDriver::plot_shock_decomp_process_graph_format_option()
3257 {
3258   options_list.symbol_list_options["plot_shock_decomp.graph_format"] = graph_formats;
3259   graph_formats.clear();
3260 }
3261 
3262 void
model_diagnostics()3263 ParsingDriver::model_diagnostics()
3264 {
3265   mod_file->addStatement(make_unique<ModelDiagnosticsStatement>());
3266 }
3267 
3268 void
add_parallel_local_file(string filename)3269 ParsingDriver::add_parallel_local_file(string filename)
3270 {
3271   mod_file->parallel_local_files.push_back(move(filename));
3272 }
3273 
3274 void
add_moment_calibration_item(const string & endo1,const string & endo2,string lags,const pair<expr_t,expr_t> & range)3275 ParsingDriver::add_moment_calibration_item(const string &endo1, const string &endo2, string lags, const pair<expr_t, expr_t> &range)
3276 {
3277   MomentCalibration::Constraint c;
3278 
3279   check_symbol_is_endogenous(endo1);
3280   c.endo1 = mod_file->symbol_table.getID(endo1);
3281 
3282   check_symbol_is_endogenous(endo2);
3283   c.endo2 = mod_file->symbol_table.getID(endo2);
3284 
3285   c.lags = move(lags);
3286 
3287   c.lower_bound = range.first;
3288   c.upper_bound = range.second;
3289 
3290   moment_calibration_constraints.push_back(c);
3291 }
3292 
3293 void
end_moment_calibration()3294 ParsingDriver::end_moment_calibration()
3295 {
3296   mod_file->addStatement(make_unique<MomentCalibration>(moment_calibration_constraints,
3297                                                         mod_file->symbol_table));
3298   moment_calibration_constraints.clear();
3299 }
3300 
3301 void
add_irf_calibration_item(const string & endo,string periods,const string & exo,const pair<expr_t,expr_t> & range)3302 ParsingDriver::add_irf_calibration_item(const string &endo, string periods, const string &exo, const pair<expr_t, expr_t> &range)
3303 {
3304   IrfCalibration::Constraint c;
3305 
3306   check_symbol_is_endogenous(endo);
3307   c.endo = mod_file->symbol_table.getID(endo);
3308 
3309   c.periods = move(periods);
3310 
3311   check_symbol_existence(exo);
3312   c.exo = mod_file->symbol_table.getID(exo);
3313   if (mod_file->symbol_table.getType(exo) != SymbolType::exogenous)
3314     error("Variable " + endo + " is not an exogenous.");
3315 
3316   c.lower_bound = range.first;
3317   c.upper_bound = range.second;
3318 
3319   irf_calibration_constraints.push_back(c);
3320 }
3321 
3322 void
end_irf_calibration()3323 ParsingDriver::end_irf_calibration()
3324 {
3325   mod_file->addStatement(make_unique<IrfCalibration>(irf_calibration_constraints,
3326                                                      mod_file->symbol_table,
3327                                                      options_list));
3328   irf_calibration_constraints.clear();
3329 }
3330 
3331 void
smoother2histval()3332 ParsingDriver::smoother2histval()
3333 {
3334   mod_file->addStatement(make_unique<Smoother2histvalStatement>(options_list));
3335   options_list.clear();
3336 }
3337 
3338 void
histval_file(const string & filename)3339 ParsingDriver::histval_file(const string &filename)
3340 {
3341   mod_file->addStatement(make_unique<HistvalFileStatement>(filename));
3342 }
3343 
3344 void
perfect_foresight_setup()3345 ParsingDriver::perfect_foresight_setup()
3346 {
3347   mod_file->addStatement(make_unique<PerfectForesightSetupStatement>(options_list));
3348   options_list.clear();
3349 }
3350 
3351 void
perfect_foresight_solver()3352 ParsingDriver::perfect_foresight_solver()
3353 {
3354   mod_file->addStatement(make_unique<PerfectForesightSolverStatement>(options_list));
3355   options_list.clear();
3356 }
3357 
3358 void
gmm_estimation()3359 ParsingDriver::gmm_estimation()
3360 {
3361   mod_file->addStatement(make_unique<GMMEstimationStatement>(symbol_list, options_list));
3362   symbol_list.clear();
3363   options_list.clear();
3364 }
3365 
3366 void
smm_estimation()3367 ParsingDriver::smm_estimation()
3368 {
3369   mod_file->addStatement(make_unique<SMMEstimationStatement>(symbol_list, options_list));
3370   symbol_list.clear();
3371   options_list.clear();
3372 }
3373 
3374 void
prior_posterior_function(bool prior_func)3375 ParsingDriver::prior_posterior_function(bool prior_func)
3376 {
3377   mod_file->addStatement(make_unique<PriorPosteriorFunctionStatement>(static_cast<bool>(prior_func), options_list));
3378   options_list.clear();
3379 }
3380 
3381 void
add_ramsey_constraints_statement()3382 ParsingDriver::add_ramsey_constraints_statement()
3383 {
3384   mod_file->addStatement(make_unique<RamseyConstraintsStatement>(mod_file->symbol_table, ramsey_constraints));
3385   ramsey_constraints.clear();
3386 }
3387 
3388 void
ramsey_constraint_add_less(const string & name,const expr_t rhs)3389 ParsingDriver::ramsey_constraint_add_less(const string &name, const expr_t rhs)
3390 {
3391   add_ramsey_constraint(name, BinaryOpcode::less, rhs);
3392 }
3393 
3394 void
ramsey_constraint_add_greater(const string & name,const expr_t rhs)3395 ParsingDriver::ramsey_constraint_add_greater(const string &name, const expr_t rhs)
3396 {
3397   add_ramsey_constraint(name, BinaryOpcode::greater, rhs);
3398 }
3399 
3400 void
ramsey_constraint_add_less_equal(const string & name,const expr_t rhs)3401 ParsingDriver::ramsey_constraint_add_less_equal(const string &name, const expr_t rhs)
3402 {
3403   add_ramsey_constraint(name, BinaryOpcode::lessEqual, rhs);
3404 }
3405 
3406 void
ramsey_constraint_add_greater_equal(const string & name,const expr_t rhs)3407 ParsingDriver::ramsey_constraint_add_greater_equal(const string &name, const expr_t rhs)
3408 {
3409   add_ramsey_constraint(name, BinaryOpcode::greaterEqual, rhs);
3410 }
3411 
3412 void
add_ramsey_constraint(const string & name,BinaryOpcode op_code,const expr_t rhs)3413 ParsingDriver::add_ramsey_constraint(const string &name, BinaryOpcode op_code, const expr_t rhs)
3414 {
3415   check_symbol_is_endogenous(name);
3416   int symb_id = mod_file->symbol_table.getID(name);
3417 
3418   RamseyConstraintsStatement::Constraint C;
3419   C.endo = symb_id;
3420   C.code = op_code;
3421   C.expression = rhs;
3422   ramsey_constraints.push_back(C);
3423 }
3424 
3425 void
add_shock_group_element(string name)3426 ParsingDriver::add_shock_group_element(string name)
3427 {
3428   check_symbol_existence(name);
3429   int symb_id = mod_file->symbol_table.getID(name);
3430   SymbolType type = mod_file->symbol_table.getType(symb_id);
3431 
3432   if (type != SymbolType::exogenous)
3433     error("shock_groups: " + name + " should be an exogenous variable");
3434 
3435   shock_group.push_back(move(name));
3436 }
3437 
3438 void
add_shock_group(string name)3439 ParsingDriver::add_shock_group(string name)
3440 {
3441   ShockGroupsStatement::Group G;
3442   G.name = move(name);
3443   G.list = shock_group;
3444   shock_groups.push_back(G);
3445 
3446   shock_group.clear();
3447 }
3448 
3449 void
end_shock_groups(const string & name)3450 ParsingDriver::end_shock_groups(const string &name)
3451 {
3452   mod_file->addStatement(make_unique<ShockGroupsStatement>(shock_groups, name));
3453   shock_groups.clear();
3454 }
3455 
3456 void
add_init2shocks(const string & endo_name,const string & exo_name)3457 ParsingDriver::add_init2shocks(const string &endo_name, const string &exo_name)
3458 {
3459   check_symbol_existence(endo_name);
3460   check_symbol_existence(exo_name);
3461   int symb_id_endo = mod_file->symbol_table.getID(endo_name);
3462   if (mod_file->symbol_table.getType(symb_id_endo) != SymbolType::endogenous)
3463     error("init2shocks: " + endo_name + " should be an endogenous variable");
3464 
3465   int symb_id_exo = mod_file->symbol_table.getID(exo_name);
3466   if (mod_file->symbol_table.getType(symb_id_exo) != SymbolType::exogenous)
3467     error("init2shocks: " + exo_name + " should be an exogenous variable");
3468 
3469   init2shocks.emplace_back(symb_id_endo, symb_id_exo);
3470 }
3471 
3472 void
end_init2shocks(const string & name)3473 ParsingDriver::end_init2shocks(const string &name)
3474 {
3475   mod_file->addStatement(make_unique<Init2shocksStatement>(init2shocks, name, mod_file->symbol_table));
3476   init2shocks.clear();
3477 }
3478 
3479 void
var_expectation_model()3480 ParsingDriver::var_expectation_model()
3481 {
3482   auto it = options_list.string_options.find("variable");
3483   if (it == options_list.string_options.end() && !var_expectation_model_expression)
3484     error("You must pass either the 'variable' or the 'expression' option to the var_expectation_model statement.");
3485   if (it != options_list.string_options.end())
3486     {
3487       if (var_expectation_model_expression)
3488         error("You can't pass both the 'variable' or the 'expression' options to the var_expectation_model statement.");
3489       var_expectation_model_expression = data_tree->AddVariable(mod_file->symbol_table.getID(it->second));
3490     }
3491 
3492   it = options_list.string_options.find("auxiliary_model_name");
3493   if (it == options_list.string_options.end())
3494     error("You must pass the auxiliary_model_name option to the var_expectation_model statement.");
3495   auto var_model_name = it->second;
3496 
3497   it = options_list.string_options.find("model_name");
3498   if (it == options_list.string_options.end())
3499     error("You must pass the model_name option to the var_expectation_model statement.");
3500   auto model_name = it->second;
3501 
3502   it = options_list.num_options.find("horizon");
3503   if (it == options_list.num_options.end())
3504     error("You must pass the horizon option to the var_expectation_model statement.");
3505   auto horizon = it->second;
3506 
3507   if (var_expectation_model_discount)
3508     {
3509       VariableNode *var;
3510       if (!dynamic_cast<NumConstNode *>(var_expectation_model_discount)
3511           && !((var = dynamic_cast<VariableNode *>(var_expectation_model_discount))
3512                && var->get_type() == SymbolType::parameter))
3513         error("The discount factor must be a constant expression or a parameter");
3514     }
3515   else
3516     var_expectation_model_discount = data_tree->One;
3517 
3518   mod_file->addStatement(make_unique<VarExpectationModelStatement>(model_name, var_expectation_model_expression,
3519                                                                    var_model_name, horizon,
3520                                                                    var_expectation_model_discount, mod_file->symbol_table));
3521 
3522   options_list.clear();
3523   var_expectation_model_discount = nullptr;
3524   var_expectation_model_expression = nullptr;
3525 }
3526