ParsingDriver.cc 96.6 KB
Newer Older
1
/*
2
 * Copyright (C) 2003-2018 Dynare Team
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 *
 * This file is part of Dynare.
 *
 * Dynare is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Dynare is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <fstream>
#include <iostream>
22
#include <cassert>
Sébastien Villemot's avatar
Sébastien Villemot committed
23
#include <sstream>
24
#include <cmath>
25
26
27

#include "ParsingDriver.hh"
#include "Statement.hh"
28
#include "ExprNode.hh"
29
#include "WarningConsolidation.hh"
30
31

bool
32
ParsingDriver::symbol_exists_and_is_not_modfile_local_or_external_function(const string &s)
33
34
35
36
{
  if (!mod_file->symbol_table.exists(s))
    return false;

37
38
  SymbolType type = mod_file->symbol_table.getType(s);

39
  return (type != SymbolType::modFileLocalVariable && type != SymbolType::externalFunction);
40
41
}

42
43
44
void
ParsingDriver::check_symbol_existence_in_model_block(const string &name)
{
45
46
47
  if (!mod_file->symbol_table.exists(name)
      || undeclared_model_vars.find(name) != undeclared_model_vars.end())
    undeclared_model_variable_error("Unknown symbol: " + name, name);
48
49
}

50
51
52
53
void
ParsingDriver::check_symbol_existence(const string &name)
{
  if (!mod_file->symbol_table.exists(name))
Stéphane Adjemian's avatar
Stéphane Adjemian committed
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
58
ParsingDriver::check_symbol_is_parameter(const string &name)
59
{
60
61
  check_symbol_existence(name);
  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
67
68
69
70
void
ParsingDriver::set_current_data_tree(DataTree *data_tree_arg)
{
  data_tree = data_tree_arg;
  model_tree = dynamic_cast<ModelTree *>(data_tree_arg);
71
  dynamic_model = dynamic_cast<DynamicModel *>(data_tree_arg);
72
73
74
75
76
77
78
79
}

void
ParsingDriver::reset_data_tree()
{
  set_current_data_tree(&mod_file->expressions_tree);
}

80
81
82
void
ParsingDriver::reset_current_external_function_options()
{
83
84
85
86
  current_external_function_options.nargs = ExternalFunctionsTable::defaultNargs;
  current_external_function_options.firstDerivSymbID = ExternalFunctionsTable::IDNotSet;
  current_external_function_options.secondDerivSymbID = ExternalFunctionsTable::IDNotSet;
  current_external_function_id = ExternalFunctionsTable::IDNotSet;
87
88
}

Sébastien Villemot's avatar
Sébastien Villemot committed
89
unique_ptr<ModFile>
90
ParsingDriver::parse(istream &in, bool debug)
91
{
Sébastien Villemot's avatar
Sébastien Villemot committed
92
  mod_file = make_unique<ModFile>(warnings);
93

sebastien's avatar
sebastien committed
94
  symbol_list.clear();
95
96

  reset_data_tree();
97
  estim_params.init(*data_tree);
98
  osr_params.init(*data_tree);
99
  reset_current_external_function_options();
100

Sébastien Villemot's avatar
Sébastien Villemot committed
101
  lexer = make_unique<DynareFlex>(&in);
102
  lexer->set_debug(debug);
103
104

  Dynare::parser parser(*this);
105
  parser.set_debug_level(debug);
106
107
  parser.parse();

Sébastien Villemot's avatar
Sébastien Villemot committed
108
  return move(mod_file);
109
110
111
112
113
}

void
ParsingDriver::error(const Dynare::parser::location_type &l, const string &m)
{
114
115
116
117
118
119
120
121
122
123
124
125
126
127
  create_error_string(l, m, cerr);
  exit(EXIT_FAILURE);
}

void
ParsingDriver::error(const string &m)
{
  error(location, m);
}

void
ParsingDriver::create_error_string(const Dynare::parser::location_type &l, const string &m, ostream &stream)
{
  stream << "ERROR: " << *l.begin.filename << ": line " << l.begin.line;
128
129
  if (l.begin.line == l.end.line)
    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
140
ParsingDriver::create_error_string(const Dynare::parser::location_type &l, const string &m, const string &var)
141
{
142
143
  ostringstream stream;
  create_error_string(l, m, stream);
144
  model_errors.emplace_back(var, stream.str());
145
146
147
148
149
150
}

void
ParsingDriver::model_error(const string &m, const string &var)
{
  create_error_string(location, m, var);
151
152
}

153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
void
ParsingDriver::undeclared_model_variable_error(const string &m, const string &var)
{
  ostringstream stream;
  if (!nostrict)
    {
      stream << "ERROR: " << *location.begin.filename << ": line " << location.begin.line;
      if (location.begin.line == location.end.line)
        if (location.begin.column == location.end.column - 1)
          stream << ", col " << location.begin.column;
        else
          stream << ", cols " << location.begin.column << "-" << location.end.column - 1;
      else
        stream << ", col " << location.begin.column << " -"
               << " line " << location.end.line << ", col " << location.end.column - 1;
      stream << ": ";
    }
  stream << m;
  if (nostrict)
    stream << " automatically declared exogenous.";
173
  undeclared_model_variable_errors.emplace_back(var, stream.str());
174
175
}

176
177
178
void
ParsingDriver::warning(const string &m)
{
179
  warnings << "WARNING: " << location << ": " << m << endl;
180
181
182
}

void
183
ParsingDriver::declare_symbol(const string &name, SymbolType type, const string &tex_name, const vector<pair<string, string>> &partition_value)
184
185
186
{
  try
    {
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
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
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
214
215
216
      add_in_symbol_list(name);
      return;
    }

217
  declare_symbol(name, SymbolType::endogenousVAR, "", {});
218
219
220
  add_in_symbol_list(name);
}

221
void
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
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
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
240
ParsingDriver::declare_statement_local_variable(const string &name)
241
{
242
243
  if (mod_file->symbol_table.exists(name))
    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
249
ParsingDriver::declare_optimal_policy_discount_factor_parameter(expr_t exprnode)
250
{
251
252
  declare_parameter("optimal_policy_discount_factor");
  init_param("optimal_policy_discount_factor", exprnode);
253
254
}

255
256
257
258
259
260
261
void
ParsingDriver::begin_trend()
{
  set_current_data_tree(&mod_file->dynamic_model);
}

void
262
ParsingDriver::declare_trend_var(bool log_trend, const string &name, const string &tex_name)
263
{
264
265
  declare_symbol(name, log_trend ? SymbolType::logTrend : SymbolType::trend, tex_name, {});
  declared_trend_vars.push_back(mod_file->symbol_table.getID(name));
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
}

void
ParsingDriver::end_trend_var(expr_t growth_factor)
{
  try
    {
      dynamic_model->addTrendVariables(declared_trend_vars, growth_factor);
    }
  catch (DataTree::TrendException &e)
    {
      error("Trend variable " + e.name + " was declared twice.");
    }
  declared_trend_vars.clear();
  reset_data_tree();
}

283
void
284
ParsingDriver::add_predetermined_variable(const string &name)
285
{
286
287
288
  check_symbol_is_endogenous(name);
  int symb_id = mod_file->symbol_table.getID(name);
  mod_file->symbol_table.markPredetermined(symb_id);
289
290
}

291
void
292
ParsingDriver::add_equation_tags(string key, string value)
293
{
294
  eq_tags.emplace_back(key, value);
295

296
297
  transform(key.begin(), key.end(), key.begin(), ::tolower);
  if (key.compare("endogenous") == 0)
298
    declare_or_change_type(SymbolType::endogenous, value);
299
300
}

301
expr_t
302
ParsingDriver::add_non_negative_constant(const string &constant)
303
{
304
  return data_tree->AddNonNegativeConstant(constant);
305
306
}

307
expr_t
308
309
310
311
312
ParsingDriver::add_nan_constant()
{
  return data_tree->NaN;
}

313
expr_t
314
315
316
317
318
ParsingDriver::add_inf_constant()
{
  return data_tree->Infinity;
}

319
expr_t
320
ParsingDriver::add_model_variable(const string &name)
321
{
322
  check_symbol_existence_in_model_block(name);
323
324
325
  int symb_id;
  try
    {
326
      symb_id = mod_file->symbol_table.getID(name);
327
328
329
    }
  catch (SymbolTable::UnknownSymbolNameException &e)
    {
330
331
      // Declare variable as exogenous to continue parsing
      // processing will end at end of model block if nostrict option was not passed
332
333
334
      declare_exogenous(name);
      undeclared_model_vars.insert(name);
      symb_id = mod_file->symbol_table.getID(name);
335
    }
336
  return add_model_variable(symb_id, 0);
337
338
}

339
expr_t
340
ParsingDriver::declare_or_change_type(SymbolType new_type, const string &name)
341
342
343
344
{
  int symb_id;
  try
    {
345
      symb_id = mod_file->symbol_table.getID(name);
346
347
348
      mod_file->symbol_table.changeType(symb_id, new_type);

      // remove error messages
349
      undeclared_model_vars.erase(name);
350
      for (auto it = undeclared_model_variable_errors.begin();
351
           it != undeclared_model_variable_errors.end();)
352
        if (it->first == name)
353
          it = undeclared_model_variable_errors.erase(it);
354
355
356
357
358
359
360
        else
          it++;
    }
  catch (SymbolTable::UnknownSymbolNameException &e)
    {
      switch (new_type)
        {
361
        case SymbolType::endogenous:
362
          declare_endogenous(name);
363
          break;
364
        case SymbolType::exogenous:
365
          declare_exogenous(name);
366
          break;
367
        case SymbolType::parameter:
368
          declare_parameter(name);
369
370
371
372
          break;
        default:
          error("Type not yet supported");
        }
373
      symb_id = mod_file->symbol_table.getID(name);
374
375
376
377
378
    }
  return add_model_variable(symb_id, 0);

}

379
expr_t
380
ParsingDriver::add_model_variable(int symb_id, int lag)
381
{
382
383
  assert(symb_id >= 0);
  SymbolType type = mod_file->symbol_table.getType(symb_id);
384

385
  if (type == SymbolType::modFileLocalVariable)
386
387
    error("Variable " + mod_file->symbol_table.getName(symb_id) +
          " not allowed inside model declaration. Its scope is only outside model.");
388

389
  if (type == SymbolType::externalFunction)
390
391
    error("Symbol " + mod_file->symbol_table.getName(symb_id) +
          " is a function name external to Dynare. It cannot be used like a variable without input argument inside model.");
sebastien's avatar
sebastien committed
392

393
  if (type == SymbolType::modelLocalVariable && lag != 0)
394
    error("Model local variable " + mod_file->symbol_table.getName(symb_id) + " cannot be given a lead or a lag.");
sebastien's avatar
sebastien committed
395

396
  if (dynamic_cast<StaticModel *>(model_tree) != nullptr && lag != 0)
397
398
    error("Leads and lags on variables are forbidden in 'planner_objective'.");

399
  if (dynamic_cast<StaticModel *>(model_tree) != nullptr && type == SymbolType::modelLocalVariable)
400
401
    error("Model local variable " + mod_file->symbol_table.getName(symb_id) + " cannot be used in 'planner_objective'.");

sebastien's avatar
sebastien committed
402
  // It makes sense to allow a lead/lag on parameters: during steady state calibration, endogenous and parameters can be swapped
403
  return model_tree->AddVariable(symb_id, lag);
404
405
}

406
expr_t
407
ParsingDriver::add_expression_variable(const string &name)
408
{
Houtan Bastani's avatar
Houtan Bastani committed
409
410
411
  if (parsing_epilogue && !mod_file->symbol_table.exists(name))
    error("Variable " + name + " used in the epilogue block but was not declared.");

412
  // If symbol doesn't exist, then declare it as a mod file local variable
413
414
  if (!mod_file->symbol_table.exists(name))
    mod_file->symbol_table.addSymbol(name, SymbolType::modFileLocalVariable);
415

416
  // This check must come after the previous one!
417
418
  if (mod_file->symbol_table.getType(name) == SymbolType::modelLocalVariable)
    error("Variable " + name + " not allowed outside model declaration. Its scope is only inside model.");
419

420
421
422
  if (mod_file->symbol_table.getType(name) == SymbolType::trend
      || mod_file->symbol_table.getType(name) == SymbolType::logTrend)
    error("Variable " + name + " not allowed outside model declaration, because it is a trend variable.");
423

424
425
  if (mod_file->symbol_table.getType(name) == SymbolType::externalFunction)
    error("Symbol '" + name + "' is the name of a MATLAB/Octave function, and cannot be used as a variable.");
426

427
428
  int symb_id = mod_file->symbol_table.getID(name);
  return data_tree->AddVariable(symb_id);
429
430
}

431
void
432
ParsingDriver::declare_nonstationary_var(const string &name, const string &tex_name, const vector<pair<string, string>> &partition_value)
433
{
434
  declare_endogenous(name, tex_name, partition_value);
435

436
  declared_nonstationary_vars.push_back(mod_file->symbol_table.getID(name));
437
438
439
440
  mod_file->nonstationary_variables = true;
}

void
441
ParsingDriver::end_nonstationary_var(bool log_deflator, expr_t deflator)
442
443
444
{
  try
    {
445
      dynamic_model->addNonstationaryVariables(declared_nonstationary_vars, log_deflator, deflator);
446
447
448
449
450
    }
  catch (DataTree::TrendException &e)
    {
      error("Variable " + e.name + " was listed more than once as following a trend.");
    }
451

452
  set<int> r;
453
  deflator->collectVariables(SymbolType::endogenous, r);
454
455
  for (int it : r)
    if (dynamic_model->isNonstationary(it))
456
457
      error("The deflator contains a non-stationary endogenous variable. This is not allowed. Please use only stationary endogenous and/or {log_}trend_vars.");

458
459
460
461
  declared_nonstationary_vars.clear();
  reset_data_tree();
}

462
463
464
465
466
467
468
void
ParsingDriver::begin_VAR_restrictions()
{
  clear_VAR_storage();
}

void
469
ParsingDriver::end_VAR_restrictions(const string &var_model_name)
470
{
471
472
473
474
475
476
477
478
  mod_file->addStatement(make_unique<VarRestrictionsStatement>(var_model_name,
                                                               var_map,
                                                               exclusion_restrictions,
                                                               equation_restrictions,
                                                               crossequation_restrictions,
                                                               covariance_number_restriction,
                                                               covariance_pair_restriction,
                                                               mod_file->symbol_table));
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
  clear_VAR_storage();
}

void
ParsingDriver::clear_VAR_storage()
{
  exclusion_restriction.clear();
  exclusion_restrictions.clear();
  symbol_list.clear();
  var_restriction_eq_or_crosseq.clear();
  equation_restrictions.clear();
  crossequation_restrictions.clear();
  covariance_number_restriction.clear();
  covariance_pair_restriction.clear();
}

void
496
ParsingDriver::add_VAR_exclusion_restriction(const string &lagstr)
497
{
498
  int lag = stoi(lagstr);
499
  auto it = exclusion_restrictions.find(lag);
500
501
502
503
504
505
506
507
508
509
510
  if (it == exclusion_restrictions.end())
    exclusion_restrictions[lag] = exclusion_restriction;
  else
    for (map<int, SymbolList>::const_iterator it1 = exclusion_restriction.begin();
         it1 != exclusion_restriction.end(); it1++)
      it->second[it1->first] = it1->second;

  exclusion_restriction.clear();
}

void
511
ParsingDriver::add_VAR_restriction_coeff(const string &name1, const string &name2, const string &lagstr)
512
{
513
514
515
  int symb_id1 = mod_file->symbol_table.getID(name1);
  int symb_id2 = name2.empty() ? -1 : mod_file->symbol_table.getID(name2);
  int lag = stoi(lagstr);
516

517
  var_restriction_coeff = { symb_id1, { symb_id2, lag } };
518
519
520
521
522
}

void
ParsingDriver::add_VAR_restriction_eq_or_crosseq(expr_t expr)
{
523
  var_restriction_eq_or_crosseq.emplace_back(var_restriction_coeff, expr);
524
525
526
}

void
527
ParsingDriver::add_VAR_restriction_equation_or_crossequation(const string &numberstr)
528
529
{
  assert(var_restriction_eq_or_crosseq.size() > 0 && var_restriction_eq_or_crosseq.size() < 3);
530
  double number = stod(numberstr);
531
  if (var_restriction_eq_or_crosseq.size() == 1)
532
    var_restriction_equation_or_crossequation = { { var_restriction_eq_or_crosseq[0], { { -1, { -1, -1 } }, nullptr } }, number };
533
  else
534
    var_restriction_equation_or_crossequation = { { var_restriction_eq_or_crosseq[0], var_restriction_eq_or_crosseq[1] }, number };
535
536
537
538
539
540
541
542
  var_restriction_eq_or_crosseq.clear();
}

void
ParsingDriver::multiply_arg2_by_neg_one()
{
  assert(var_restriction_eq_or_crosseq.size() == 2);
  expr_t exprtm1 = add_times(var_restriction_eq_or_crosseq[1].second,
543
                             add_uminus(add_non_negative_constant("-1")));
544
  var_restriction_eq_or_crosseq[1] = { var_restriction_eq_or_crosseq[1].first, exprtm1 };
545
546
547
}

void
548
ParsingDriver::add_VAR_restriction_equation_or_crossequation_final(const string &name)
549
{
550
  if (!name.empty())
551
    {
552
      int symb_id = mod_file->symbol_table.getID(name);
553
      equation_restrictions[symb_id] = var_restriction_equation_or_crossequation;
554
    }
555
556
  else
    crossequation_restrictions.push_back(var_restriction_equation_or_crossequation);
557
558
559
}

void
560
ParsingDriver::add_VAR_restriction_exclusion_equation(const string &name)
561
{
562
  int symb_id = mod_file->symbol_table.getID(name);
563
564
565
566
567
  exclusion_restriction[symb_id] = symbol_list;
  symbol_list.clear();
}

void
568
ParsingDriver::add_VAR_covariance_number_restriction(const string &name1, const string &name2, const string &valuestr)
569
{
570
571
572
  int symb_id1 = mod_file->symbol_table.getID(name1);
  int symb_id2 = mod_file->symbol_table.getID(name2);
  double value = stod(valuestr);
573
  covariance_number_restriction[{ symb_id1, symb_id2 }] = value;
574
575
576
}

void
577
ParsingDriver::add_VAR_covariance_pair_restriction(const string &name11, const string &name12, const string &name21, const string &name22)
578
{
579
580
581
582
  int symb_id11 = mod_file->symbol_table.getID(name11);
  int symb_id12 = mod_file->symbol_table.getID(name12);
  int symb_id21 = mod_file->symbol_table.getID(name21);
  int symb_id22 = mod_file->symbol_table.getID(name22);
583
  covariance_pair_restriction[{ symb_id11, symb_id12 }] = { symb_id21, symb_id22 };
584
585
}

586
void
587
ParsingDriver::run_var_estimation()
588
{
589
  mod_file->addStatement(make_unique<VarEstimationStatement>(options_list));
590
591
}

592
void
593
ParsingDriver::periods(const string &periods)
594
{
595
  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.");
596

597
  int periods_val = stoi(periods);
598
  mod_file->addStatement(make_unique<PeriodsStatement>(periods_val));
599
600
601
}

void
602
ParsingDriver::dsample(const string &arg1)
603
{
604
  int arg1_val = stoi(arg1);
605
  mod_file->addStatement(make_unique<DsampleStatement>(arg1_val));
606
607
608
}

void
609
ParsingDriver::dsample(const string &arg1, const string &arg2)
610
{
611
612
  int arg1_val = stoi(arg1);
  int arg2_val = stoi(arg2);
613
  mod_file->addStatement(make_unique<DsampleStatement>(arg1_val, arg2_val));
614
615
616
}

void
617
ParsingDriver::init_param(const string &name, expr_t rhs)
618
{
619
  check_symbol_is_parameter(name);
620
  int symb_id = mod_file->symbol_table.getID(name);
621
  mod_file->addStatement(make_unique<InitParamStatement>(symb_id, rhs, mod_file->symbol_table));
622
623
624
}

void
625
ParsingDriver::init_val(const string &name, expr_t rhs)
626
{
627
  if (nostrict)
628
    if (!mod_file->symbol_table.exists(name))
629
      {
630
        warning("discarding '" + name + "' as it was not recognized in the initval or endval statement");
631
632
633
        return;
      }

634
  check_symbol_is_endogenous_or_exogenous(name);
635
  int symb_id = mod_file->symbol_table.getID(name);
636
  init_values.emplace_back(symb_id, rhs);
637
638
639
}

void
640
ParsingDriver::initval_file(const string &filename)
641
{
642
  mod_file->addStatement(make_unique<InitvalFileStatement>(filename));
643
644
645
}

void
646
ParsingDriver::hist_val(const string &name, const string &lag, expr_t rhs)
647
{
648
  if (nostrict)
649
    if (!mod_file->symbol_table.exists(name))
650
      {
Sébastien Villemot's avatar
Sébastien Villemot committed
651
        warning("discarding '" + name + "' as it was not recognized in the histval block");
652
653
        return;
      }
654

655
  check_symbol_is_endogenous_or_exogenous(name);
656
  int symb_id = mod_file->symbol_table.getID(name);
657

658
  int ilag = stoi(lag);
659
  if (ilag > 0)
660
    error("histval: the lag on " + name + " should be less than or equal to 0");
661

sebastien's avatar
sebastien committed
662
  pair<int, int> key(symb_id, ilag);
663
664

  if (hist_values.find(key) != hist_values.end())
665
    error("hist_val: (" + name + ", " + lag + ") declared twice");
666
667
668
669
670

  hist_values[key] = rhs;
}

void
671
ParsingDriver::homotopy_val(const string &name, expr_t val1, expr_t val2)
672
{
673
674
  check_symbol_existence(name);
  int symb_id = mod_file->symbol_table.getID(name);
sebastien's avatar
sebastien committed
675
  SymbolType type = mod_file->symbol_table.getType(symb_id);
676

677
678
679
  if (type != SymbolType::parameter
      && type != SymbolType::exogenous
      && type != SymbolType::exogenousDet)
680
    error("homotopy_val: " + name + " should be a parameter or exogenous variable");
681

682
  homotopy_values.emplace_back(symb_id, val1, val2);
683
684
}

685
686
687
void
ParsingDriver::end_generate_irfs()
{
688
  mod_file->addStatement(make_unique<GenerateIRFsStatement>(options_list, generate_irf_names, generate_irf_elements));
689

690
691
692
693
694
695
  generate_irf_elements.clear();
  generate_irf_names.clear();
  options_list.clear();
}

void
696
ParsingDriver::add_generate_irfs_element(string name)
697
{
698
699
  for (const auto &it : generate_irf_names)
    if (it == name)
700
      error("Names in the generate_irfs block must be unique but you entered '"
701
            + name + "' more than once.");
702

703
  generate_irf_names.push_back(move(name));
704
705
706
707
708
709
  generate_irf_elements.push_back(generate_irf_exos);

  generate_irf_exos.clear();
}

void
710
ParsingDriver::add_generate_irfs_exog_element(string exo, const string &value)
711
712
{
  check_symbol_is_exogenous(exo);
713
714
  if (generate_irf_exos.find(exo) != generate_irf_exos.end())
    error("You have set the exogenous variable " + exo + " twice.");
715

716
  generate_irf_exos[move(exo)] = stod(value);
717
718
}

719
720
721
void
ParsingDriver::forecast()
{
722
  mod_file->addStatement(make_unique<ForecastStatement>(symbol_list, options_list));
723
724
725
726
  symbol_list.clear();
  options_list.clear();
}

727
728
729
void
ParsingDriver::use_dll()
{
730
  mod_file->use_dll = true;
731
732
733
}

void
734
ParsingDriver::block()
735
{
736
  mod_file->block = true;
737
738
}

739
740
741
742
743
744
void
ParsingDriver::linear_decomposition()
{
  mod_file->linear_decomposition = true;
}

745
746
747
748
749
750
void
ParsingDriver::no_static()
{
  mod_file->no_static = true;
}

751
void
752
ParsingDriver::byte_code()
753
{
754
  mod_file->byte_code = true;
755
756
}

757
void
758
ParsingDriver::differentiate_forward_vars_all()
759
760
761
762
{
  mod_file->differentiate_forward_vars = true;
}

763
764
765
766
767
768
769
void
ParsingDriver::differentiate_forward_vars_some()
{
  mod_file->differentiate_forward_vars = true;
  mod_file->differentiate_forward_vars_subset = symbol_list.get_symbols();
  for (vector<string>::const_iterator it = mod_file->differentiate_forward_vars_subset.begin();
       it != mod_file->differentiate_forward_vars_subset.end(); ++it)
770
    check_symbol_is_endogenous(*it);
771
772
773
  symbol_list.clear();
}

774
void
775
ParsingDriver::cutoff(const string &value)
776
{
777
  double val = stod(value);
778
  mod_file->dynamic_model.cutoff = val;
779
  mod_file->static_model.cutoff = val;
780
781
782
}

void
783
ParsingDriver::mfs(const string &value)
784
{
785
  int val = stoi(value);
786
  mod_file->dynamic_model.mfs = val;
787
  mod_file->static_model.mfs = val;
788
789
}

790
void
791
ParsingDriver::end_initval(bool all_values_required)
792
{
793
  mod_file->addStatement(make_unique<InitValStatement>(init_values, mod_file->symbol_table, all_values_required));
sebastien's avatar
sebastien committed
794
  init_values.clear();
795
796
797
}

void
798
ParsingDriver::end_endval(bool all_values_required)
799
{
800
  mod_file->addStatement(make_unique<EndValStatement>(init_values, mod_file->symbol_table, all_values_required));
sebastien's avatar
sebastien committed
801
  init_values.clear();
802
803
804
}

void
805
ParsingDriver::end_histval(bool all_values_required)
806
{
807
  mod_file->addStatement(make_unique<HistValStatement>(hist_values, mod_file->symbol_table, all_values_required));
808
809
810
811
812
813
  hist_values.clear();
}

void
ParsingDriver::end_homotopy()
{
814
  mod_file->addStatement(make_unique<HomotopyStatement>(homotopy_values, mod_file->symbol_table));
815
816
817
  homotopy_values.clear();
}

Houtan Bastani's avatar
Houtan Bastani committed
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
void
ParsingDriver::begin_epilogue()
{
  parsing_epilogue = true;
  set_current_data_tree(&mod_file->epilogue);
}

void
ParsingDriver::end_epilogue()
{
  parsing_epilogue = false;
  reset_data_tree();
}

void
833
ParsingDriver::add_epilogue_equal(const string &name, expr_t expr)
Houtan Bastani's avatar
Houtan Bastani committed
834
{
835
836
  declare_symbol(name, SymbolType::epilogue, "", {});
  mod_file->epilogue.addDefinition(mod_file->symbol_table.getID(name), expr);
Houtan Bastani's avatar
Houtan Bastani committed
837
838
}

839
840
841
void
ParsingDriver::begin_model()
{
sebastien's avatar
sebastien committed
842
  set_current_data_tree(&mod_file->dynamic_model);
843
844
}

845
846
847
void
ParsingDriver::end_model()
{
848
  bool exit_after_write = false;
849
  if (model_errors.size() > 0)
850
    for (vector<pair<string, string>>::const_iterator it = model_errors.begin();
851
852
853
854
855
856
         it != model_errors.end(); it++)
      {
        if (it->first == "")
          exit_after_write = true;
        cerr << it->second;
      }
857

858
  if (undeclared_model_variable_errors.size() > 0)
859
    for (vector<pair<string, string>>::const_iterator it = undeclared_model_variable_errors.begin();
860
861
862
863
864
865
866
         it != undeclared_model_variable_errors.end(); it++)
      if (nostrict)
        warning(it->second);
      else
        {
          exit_after_write = true;
          cerr << it->second << endl;
867
        }
868
869
870
871

  if (exit_after_write)
    exit(EXIT_FAILURE);

872
873
874
  reset_data_tree();
}

875
void
876
ParsingDriver::end_shocks(bool overwrite)
877
{
878
879
  mod_file->addStatement(make_unique<ShocksStatement>(overwrite, det_shocks, var_shocks, std_shocks,
                                                      covar_shocks, corr_shocks, mod_file->symbol_table));
880
881
882
883
884
885
886
887
  det_shocks.clear();
  var_shocks.clear();
  std_shocks.clear();
  covar_shocks.clear();
  corr_shocks.clear();
}

void
888
ParsingDriver::end_mshocks(bool overwrite)
889
{
890
  mod_file->addStatement(make_unique<MShocksStatement>(overwrite, det_shocks, mod_file->symbol_table));
891
892
893
894
  det_shocks.clear();
}

void
895
ParsingDriver::add_det_shock(const string &var, bool conditional_forecast)
896
{
897
  if (conditional_forecast)
898
    check_symbol_is_endogenous(var);
899
  else
900
901
902
    check_symbol_is_exogenous(var);

  int symb_id = mod_file->symbol_table.getID(var);
903

Sébastien Villemot's avatar
Sébastien Villemot committed
904
  if (det_shocks.find(symb_id) != det_shocks.end())
905
    error("shocks/conditional_forecast_paths: variable " + var + " declared twice");
906
907

  if (det_shocks_periods.size() != det_shocks_values.size())