From e552bfc4b398903e634b1952b00b42b017b091d5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Villemot?= <sebastien@dynare.org>
Date: Wed, 26 May 2021 17:00:07 +0200
Subject: [PATCH] Refactor parsing of deterministic shocks

This will simplify the implementation of heteroskedastic_shocks.
---
 src/DynareBison.yy   | 79 +++++++++++++++++++++++++++++++++++---------
 src/ParsingDriver.cc | 51 ++++------------------------
 src/ParsingDriver.hh |  6 +---
 3 files changed, 71 insertions(+), 65 deletions(-)

diff --git a/src/DynareBison.yy b/src/DynareBison.yy
index e73d9861..180d3e67 100644
--- a/src/DynareBison.yy
+++ b/src/DynareBison.yy
@@ -199,7 +199,8 @@ class ParsingDriver;
 %type <pair<string,string>> named_var_elem subsamples_eq_opt integer_range_w_inf
 %type <vector<pair<string,string>>> named_var named_var_1
 %type <tuple<string,string,string,string>> prior_eq_opt options_eq_opt
-%type <vector<expr_t>> matched_moments_list
+%type <vector<pair<int, int>>> period_list
+%type <vector<expr_t>> matched_moments_list value_list
 %%
 
 %start statement_list;
@@ -1038,7 +1039,7 @@ shock_elem : det_shock_elem
            ;
 
 det_shock_elem : VAR symbol ';' PERIODS period_list ';' VALUES value_list ';'
-                 { driver.add_det_shock($2, false); }
+                 { driver.add_det_shock($2, $5, $8, false); }
                ;
 
 svar_identification : SVAR_IDENTIFICATION {driver.begin_svar_identification();} ';' svar_identification_list END ';'
@@ -1137,33 +1138,81 @@ mshock_list : mshock_list det_shock_elem
             ;
 
 period_list : period_list COMMA INT_NUMBER
-              { driver.add_period($3); }
+              {
+                $$ = $1;
+                int p = stoi($3);
+                $$.push_back({ p, p });
+              }
             | period_list INT_NUMBER
-              { driver.add_period($2); }
+              {
+                $$ = $1;
+                int p = stoi($2);
+                $$.push_back({ p, p });
+              }
             | period_list COMMA INT_NUMBER ':' INT_NUMBER
-              { driver.add_period($3, $5); }
+              {
+                $$ = $1;
+                int p1 = stoi($3), p2 = stoi($5);
+                if (p1 > p2)
+                  driver.error("Can't have first period index greater than second index in range specification");
+                $$.push_back({ p1, p2 });
+              }
             | period_list INT_NUMBER ':' INT_NUMBER
-              { driver.add_period($2, $4); }
+              {
+                $$ = $1;
+                int p1 = stoi($2), p2 = stoi($4);
+                if (p1 > p2)
+                  driver.error("Can't have first period index greater than second index in range specification");
+                $$.push_back({ p1, p2 });
+              }
             | INT_NUMBER ':' INT_NUMBER
-              { driver.add_period($1, $3); }
+              {
+                int p1 = stoi($1), p2 = stoi($3);
+                if (p1 > p2)
+                  driver.error("Can't have first period index greater than second index in range specification");
+                $$ = { { p1, p2 } };
+              }
             | INT_NUMBER
-              { driver.add_period($1); }
+              {
+                int p = stoi($1);
+                $$ = { { p, p } };
+              }
             ;
 
 sigma_e : SIGMA_E EQUAL '[' triangular_matrix ']' ';' { driver.do_sigma_e(); };
 
 value_list : value_list COMMA '(' expression ')'
-             { driver.add_value($4); }
+             {
+               $$ = $1;
+               $$.push_back($4);
+             }
            | value_list '(' expression ')'
-             { driver.add_value($3); }
+             {
+               $$ = $1;
+               $$.push_back($3);
+             }
            | '(' expression ')'
-             { driver.add_value($2); }
+             { $$ = { $2 }; }
            | value_list COMMA signed_number
-             { driver.add_value($3); }
+             {
+               $$ = $1;
+               $$.push_back($3.at(0) == '-' ?
+                            driver.add_uminus(driver.add_non_negative_constant($3.substr(1))) :
+                            driver.add_non_negative_constant($3));
+             }
            | value_list signed_number
-             { driver.add_value($2); }
+             {
+               $$ = $1;
+               $$.push_back($2.at(0) == '-' ?
+                            driver.add_uminus(driver.add_non_negative_constant($2.substr(1))) :
+                            driver.add_non_negative_constant($2));
+             }
            | signed_number
-             { driver.add_value($1); }
+             {
+               $$ = { $1.at(0) == '-' ?
+                      driver.add_uminus(driver.add_non_negative_constant($1.substr(1))) :
+                      driver.add_non_negative_constant($1) };
+             }
            ;
 
 triangular_matrix : triangular_matrix ';' triangular_row
@@ -2898,7 +2947,7 @@ conditional_forecast_paths_shock_list : conditional_forecast_paths_shock_elem
                                       ;
 
 conditional_forecast_paths_shock_elem : VAR symbol ';' PERIODS period_list ';' VALUES value_list ';'
-                                        { driver.add_det_shock($2, true); }
+                                        { driver.add_det_shock($2, $5, $8, true); }
                                       ;
 
 steady_state_model : STEADY_STATE_MODEL ';' { driver.begin_steady_state_model(); }
diff --git a/src/ParsingDriver.cc b/src/ParsingDriver.cc
index 4945bb47..05a0c6ec 100644
--- a/src/ParsingDriver.cc
+++ b/src/ParsingDriver.cc
@@ -810,7 +810,7 @@ ParsingDriver::end_mshocks(bool overwrite)
 }
 
 void
-ParsingDriver::add_det_shock(const string &var, bool conditional_forecast)
+ParsingDriver::add_det_shock(const string &var, const vector<pair<int, int>> &periods, const vector<expr_t> &values, bool conditional_forecast)
 {
   if (conditional_forecast)
     check_symbol_is_endogenous(var);
@@ -822,24 +822,21 @@ ParsingDriver::add_det_shock(const string &var, bool conditional_forecast)
   if (det_shocks.find(symb_id) != det_shocks.end())
     error("shocks/conditional_forecast_paths: variable " + var + " declared twice");
 
-  if (det_shocks_periods.size() != det_shocks_values.size())
+  if (periods.size() != values.size())
     error("shocks/conditional_forecast_paths: variable " + var + ": number of periods is different from number of shock values");
 
   vector<ShocksStatement::DetShockElement> v;
 
-  for (size_t i = 0; i < det_shocks_periods.size(); i++)
+  for (size_t i = 0; i < periods.size(); i++)
     {
       ShocksStatement::DetShockElement dse;
-      dse.period1 = det_shocks_periods[i].first;
-      dse.period2 = det_shocks_periods[i].second;
-      dse.value = det_shocks_values[i];
+      dse.period1 = periods[i].first;
+      dse.period2 = periods[i].second;
+      dse.value = values[i];
       v.push_back(dse);
     }
 
   det_shocks[symb_id] = v;
-
-  det_shocks_periods.clear();
-  det_shocks_values.clear();
 }
 
 void
@@ -936,42 +933,6 @@ ParsingDriver::add_correl_shock(const string &var1, const string &var2, expr_t v
   corr_shocks[key] = value;
 }
 
-void
-ParsingDriver::add_period(const string &p1, const string &p2)
-{
-  int p1_val = stoi(p1);
-  int p2_val = stoi(p2);
-  if (p1_val > p2_val)
-    error("shocks/conditional_forecast_paths: can't have first period index greater than second index in range specification");
-  det_shocks_periods.emplace_back(p1_val, p2_val);
-}
-
-void
-ParsingDriver::add_period(const string &p1)
-{
-  int p1_val = stoi(p1);
-  det_shocks_periods.emplace_back(p1_val, p1_val);
-}
-
-void
-ParsingDriver::add_value(expr_t value)
-{
-  det_shocks_values.push_back(value);
-}
-
-void
-ParsingDriver::add_value(const string &v)
-{
-  expr_t id;
-
-  if (v.at(0) == '-')
-    id = data_tree->AddUMinus(data_tree->AddNonNegativeConstant(v.substr(1, string::npos)));
-  else
-    id = data_tree->AddNonNegativeConstant(v);
-
-  det_shocks_values.push_back(id);
-}
-
 void
 ParsingDriver::begin_svar_identification()
 {
diff --git a/src/ParsingDriver.hh b/src/ParsingDriver.hh
index 0811f3bc..bbb3d8e5 100644
--- a/src/ParsingDriver.hh
+++ b/src/ParsingDriver.hh
@@ -151,10 +151,6 @@ private:
   OptimWeightsStatement::covar_weights_t covar_weights;
   //! Temporary storage for deterministic shocks
   ShocksStatement::det_shocks_t det_shocks;
-  //! Temporary storage for periods of deterministic shocks
-  vector<pair<int, int>> det_shocks_periods;
-  //! Temporary storage for values of deterministic shocks
-  vector<expr_t> det_shocks_values;
   //! Temporary storage for variances of shocks
   ShocksStatement::var_and_std_shocks_t var_shocks;
   //! Temporary storage for standard errors of shocks
@@ -439,7 +435,7 @@ public:
   //! Writes a mshocks statement
   void end_mshocks(bool overwrite);
   //! Adds a deterministic shock or a path element inside a conditional_forecast_paths block
-  void add_det_shock(const string &var, bool conditional_forecast);
+  void add_det_shock(const string &var, const vector<pair<int, int>> &periods, const vector<expr_t> &values, bool conditional_forecast);
   //! Adds a std error shock
   void add_stderr_shock(const string &var, expr_t value);
   //! Adds a variance shock
-- 
GitLab