diff --git a/src/DynareBison.yy b/src/DynareBison.yy
index 2c501b5a64f68bba56ba87380ad04cb95a2a685b..0048713fee0cd4b1d92544178aefba2946b285a7 100644
--- a/src/DynareBison.yy
+++ b/src/DynareBison.yy
@@ -39,6 +39,7 @@
 
 #include "CommonEnums.hh"
 #include "ExprNode.hh"
+#include "Shocks.hh"
 
 class ParsingDriver;
 }
@@ -244,7 +245,8 @@ str_tolower(string s)
 %type <vector<map<string, string>>> tag_pair_list_for_selection
 %type <map<string, string>> tag_pair_list
 %type <tuple<string,string,string,string>> prior_eq_opt options_eq_opt
-%type <vector<pair<int, int>>> period_list
+%type <AbstractShocksStatement::period_range_t> period_range
+%type <vector<AbstractShocksStatement::period_range_t>> period_list
 %type <vector<expr_t>> matched_moments_list value_list ramsey_constraints_list
 %type <tuple<string, BinaryOpNode*, BinaryOpNode*, expr_t, expr_t>> occbin_constraints_regime
 %type <vector<tuple<string, BinaryOpNode*, BinaryOpNode*, expr_t, expr_t>>> occbin_constraints_regimes_list
@@ -1401,48 +1403,38 @@ mshock_list : mshock_list det_shock_elem
             | det_shock_elem
             ;
 
-period_list : period_list COMMA INT_NUMBER
-              {
-                $$ = $1;
-                int p = stoi($3);
-                $$.emplace_back(p, p);
-              }
-            | period_list INT_NUMBER
-              {
-                $$ = $1;
-                int p = stoi($2);
-                $$.emplace_back(p, p);
-              }
-            | period_list COMMA INT_NUMBER ':' INT_NUMBER
+period_list : period_range
+              { $$ = { $1 }; }
+            | period_list period_range
               {
                 $$ = $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");
-                $$.emplace_back(p1, p2);
+                $$.emplace_back($2);
               }
-            | period_list INT_NUMBER ':' INT_NUMBER
+            | period_list COMMA period_range
               {
                 $$ = $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");
-                $$.emplace_back(p1, p2);
-              }
-            | INT_NUMBER ':' INT_NUMBER
-              {
-                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
-              {
-                int p = stoi($1);
-                $$ = {{p, p}};
+                $$.emplace_back($3);
               }
             ;
 
+period_range : INT_NUMBER
+               {
+                 int p = stoi($1);
+                 $$.emplace<pair<int, int>>(p, p);
+               }
+             | INT_NUMBER ':' INT_NUMBER
+               {
+                 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");
+                 $$.emplace<pair<int, int>>(p1, p2);
+               }
+             | date_expr
+               { $$.emplace<pair<string, string>>($1, $1); }
+             | date_expr ':' date_expr
+               { $$.emplace<pair<string, string>>($1, $3); }
+             ;
+
 value_list : value_list COMMA '(' expression ')'
              {
                $$ = $1;
@@ -3627,7 +3619,15 @@ matched_irfs_elem : matched_irfs_elem_var_varexo
                       vector<tuple<int, int, expr_t, expr_t>> v;
                       v.reserve($3.size());
                       for (size_t i {0}; i < $3.size(); i++)
-                        v.emplace_back($3[i].first, $3[i].second, $5.first[i], $5.second[i]);
+                        try
+                          {
+                            auto [p1, p2] = get<pair<int, int>>($3[i]);
+                            v.emplace_back(p1, p2, $5.first[i], $5.second[i]);
+                          }
+                        catch (bad_variant_access&)
+                          {
+                            driver.error("matched_irfs: dates are not allowed in the 'periods' keyword");
+                          }
                       $$ = {$1, v};
                     }
                   ;
diff --git a/src/DynareFlex.ll b/src/DynareFlex.ll
index 15023c8a6eb7bbf26701cadbd513e1b52e1536ae..e10dcf31c180fbf2b47758ce0a651381ea8e2739 100644
--- a/src/DynareFlex.ll
+++ b/src/DynareFlex.ll
@@ -256,11 +256,12 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|[sh][12])
 <INITIAL>prior_function {BEGIN DYNARE_STATEMENT; return token::PRIOR_FUNCTION;}
 <INITIAL>posterior_function {BEGIN DYNARE_STATEMENT; return token::POSTERIOR_FUNCTION;}
 
- /* Inside  of a Dynare statement */
-<DYNARE_STATEMENT>{DATE} {
+<DYNARE_STATEMENT,DYNARE_BLOCK>{DATE} {
   yylval->emplace<string>(yytext);
   return token::DATE;
 }
+
+ /* Inside a Dynare statement */
 <DYNARE_STATEMENT>file                  {return token::FILE;}
 <DYNARE_STATEMENT>datafile 		{return token::DATAFILE;}
 <DYNARE_STATEMENT>dirname       {return token::DIRNAME;}
diff --git a/src/ParsingDriver.cc b/src/ParsingDriver.cc
index 5afacaf79dfc6978378b96ded4b9ec9e6a286ca9..8852d3198b0de272ec571bb76ea4965ddbf7c24e 100644
--- a/src/ParsingDriver.cc
+++ b/src/ParsingDriver.cc
@@ -948,6 +948,11 @@ ParsingDriver::end_mshocks(bool overwrite, bool relative_to_initval)
 void
 ParsingDriver::end_shocks_surprise(bool overwrite)
 {
+  if (ranges::any_of(views::values(det_shocks), [](auto& v) {
+        return ranges::any_of(views::keys(v),
+                              [](auto& p) { return !holds_alternative<pair<int, int>>(p); });
+      }))
+    error("shocks(surprise): dates are not allowed in the 'periods' keyword");
   mod_file->addStatement(
       make_unique<ShocksSurpriseStatement>(overwrite, move(det_shocks), mod_file->symbol_table));
   det_shocks.clear();
@@ -970,35 +975,41 @@ ParsingDriver::end_shocks_learnt_in(const string& learnt_in_period, bool overwri
     }
   for (auto& storage : {det_shocks, learnt_shocks_add, learnt_shocks_multiply})
     for (auto& [symb_id, vals] : storage)
-      for (auto [period1, period2, expr] : vals)
-        if (period1 < learnt_in_period_int)
-          error("shocks: for variable " + mod_file->symbol_table.getName(symb_id)
-                + ", shock period (" + to_string(period1)
-                + ") is earlier than the period in which the shock is learnt (" + learnt_in_period
-                + ")");
+      for (const auto& [period_range, expr] : vals)
+        if (holds_alternative<pair<int, int>>(period_range))
+          if (int period1 = get<pair<int, int>>(period_range).first; period1 < learnt_in_period_int)
+            error("shocks: for variable " + mod_file->symbol_table.getName(symb_id)
+                  + ", shock period (" + to_string(period1)
+                  + ") is earlier than the period in which the shock is learnt (" + learnt_in_period
+                  + ")");
 
   // Aggregate the three types of shocks
   ShocksLearntInStatement::learnt_shocks_t learnt_shocks;
   for (const auto& [id, v] : det_shocks)
     {
-      vector<tuple<ShocksLearntInStatement::LearntShockType, int, int, expr_t>> v2;
-      for (auto [period1, period2, value] : v)
-        v2.emplace_back(ShocksLearntInStatement::LearntShockType::level, period1, period2, value);
+      vector<tuple<ShocksLearntInStatement::LearntShockType,
+                   AbstractShocksStatement::period_range_t, expr_t>>
+          v2;
+      for (const auto& [period_range, value] : v)
+        v2.emplace_back(ShocksLearntInStatement::LearntShockType::level, period_range, value);
       learnt_shocks[id] = v2;
     }
   for (const auto& [id, v] : learnt_shocks_add)
     {
-      vector<tuple<ShocksLearntInStatement::LearntShockType, int, int, expr_t>> v2;
-      for (auto [period1, period2, value] : v)
-        v2.emplace_back(ShocksLearntInStatement::LearntShockType::add, period1, period2, value);
+      vector<tuple<ShocksLearntInStatement::LearntShockType,
+                   AbstractShocksStatement::period_range_t, expr_t>>
+          v2;
+      for (const auto& [period_range, value] : v)
+        v2.emplace_back(ShocksLearntInStatement::LearntShockType::add, period_range, value);
       learnt_shocks[id] = v2;
     }
   for (const auto& [id, v] : learnt_shocks_multiply)
     {
-      vector<tuple<ShocksLearntInStatement::LearntShockType, int, int, expr_t>> v2;
-      for (auto [period1, period2, value] : v)
-        v2.emplace_back(ShocksLearntInStatement::LearntShockType::multiply, period1, period2,
-                        value);
+      vector<tuple<ShocksLearntInStatement::LearntShockType,
+                   AbstractShocksStatement::period_range_t, expr_t>>
+          v2;
+      for (const auto& [period_range, value] : v)
+        v2.emplace_back(ShocksLearntInStatement::LearntShockType::multiply, period_range, value);
       learnt_shocks[id] = v2;
     }
 
@@ -1023,12 +1034,13 @@ ParsingDriver::end_mshocks_learnt_in(const string& learnt_in_period, bool overwr
     }
 
   for (auto& [symb_id, vals] : det_shocks)
-    for (auto [period1, period2, expr] : vals)
-      if (period1 < learnt_in_period_int)
-        error("mshocks: for variable " + mod_file->symbol_table.getName(symb_id)
-              + ", shock period (" + to_string(period1)
-              + ") is earlier than the period in which the shock is learnt (" + learnt_in_period
-              + ")");
+    for (const auto& [period_range, expr] : vals)
+      if (holds_alternative<pair<int, int>>(period_range))
+        if (int period1 = get<pair<int, int>>(period_range).first; period1 < learnt_in_period_int)
+          error("mshocks: for variable " + mod_file->symbol_table.getName(symb_id)
+                + ", shock period (" + to_string(period1)
+                + ") is earlier than the period in which the shock is learnt (" + learnt_in_period
+                + ")");
 
   ShocksLearntInStatement::learnt_shocks_t learnt_shocks;
   const auto type {relative_to_initval
@@ -1036,9 +1048,11 @@ ParsingDriver::end_mshocks_learnt_in(const string& learnt_in_period, bool overwr
                        : ShocksLearntInStatement::LearntShockType::multiplySteadyState};
   for (const auto& [id, v] : det_shocks)
     {
-      vector<tuple<ShocksLearntInStatement::LearntShockType, int, int, expr_t>> v2;
-      for (auto [period1, period2, value] : v)
-        v2.emplace_back(type, period1, period2, value);
+      vector<tuple<ShocksLearntInStatement::LearntShockType,
+                   AbstractShocksStatement::period_range_t, expr_t>>
+          v2;
+      for (const auto& [period_range, value] : v)
+        v2.emplace_back(type, period_range, value);
       learnt_shocks[id] = v2;
     }
 
@@ -1062,7 +1076,8 @@ ParsingDriver::end_heteroskedastic_shocks(bool overwrite)
 }
 
 void
-ParsingDriver::add_det_shock(const string& var, const vector<pair<int, int>>& periods,
+ParsingDriver::add_det_shock(const string& var,
+                             const vector<AbstractShocksStatement::period_range_t>& periods,
                              const vector<expr_t>& values, DetShockType type)
 {
   switch (type)
@@ -1090,10 +1105,10 @@ ParsingDriver::add_det_shock(const string& var, const vector<pair<int, int>>& pe
     error("shocks/conditional_forecast_paths: variable " + var
           + ": number of periods is different from number of shock values");
 
-  vector<tuple<int, int, expr_t>> v;
+  vector<pair<AbstractShocksStatement::period_range_t, expr_t>> v;
 
   for (size_t i = 0; i < periods.size(); i++)
-    v.emplace_back(periods[i].first, periods[i].second, values[i]);
+    v.emplace_back(periods[i], values[i]);
 
   switch (type)
     {
@@ -1111,11 +1126,15 @@ ParsingDriver::add_det_shock(const string& var, const vector<pair<int, int>>& pe
 }
 
 void
-ParsingDriver::add_heteroskedastic_shock(const string& var, const vector<pair<int, int>>& periods,
-                                         const vector<expr_t>& values, bool scales)
+ParsingDriver::add_heteroskedastic_shock(
+    const string& var, const vector<AbstractShocksStatement::period_range_t>& periods,
+    const vector<expr_t>& values, bool scales)
 {
   check_symbol_is_exogenous(var, false);
 
+  if (ranges::any_of(periods, [](auto& p) { return !holds_alternative<pair<int, int>>(p); }))
+    error("heteroskedastic_shocks: dates are not allowed in the 'periods' keyword");
+
   int symb_id = mod_file->symbol_table.getID(var);
 
   if ((!scales && heteroskedastic_shocks_values.contains(symb_id))
@@ -1128,7 +1147,10 @@ ParsingDriver::add_heteroskedastic_shock(const string& var, const vector<pair<in
 
   vector<tuple<int, int, expr_t>> v;
   for (size_t i = 0; i < periods.size(); i++)
-    v.emplace_back(periods[i].first, periods[i].second, values[i]);
+    {
+      auto [period1, period2] = get<pair<int, int>>(periods[i]);
+      v.emplace_back(period1, period2, values[i]);
+    }
 
   if (scales)
     heteroskedastic_shocks_scales[symb_id] = v;
@@ -2629,6 +2651,11 @@ ParsingDriver::plot_conditional_forecast(const optional<string>& periods,
 void
 ParsingDriver::conditional_forecast_paths()
 {
+  if (ranges::any_of(views::values(det_shocks), [](auto& v) {
+        return ranges::any_of(views::keys(v),
+                              [](auto& p) { return !holds_alternative<pair<int, int>>(p); });
+      }))
+    error("conditional_forecast_paths: dates are not allowed in the 'periods' keyword");
   mod_file->addStatement(
       make_unique<ConditionalForecastPathsStatement>(move(det_shocks), mod_file->symbol_table));
   det_shocks.clear();
diff --git a/src/ParsingDriver.hh b/src/ParsingDriver.hh
index 132dee5834ba62b581abff2c6aab59e4d47e07ec..fffa1a39f95ab5ea191a2d3e78371352559efe11 100644
--- a/src/ParsingDriver.hh
+++ b/src/ParsingDriver.hh
@@ -481,10 +481,12 @@ public:
     multiply, // for “multiply” in “shocks(learnt_in)”
     conditional_forecast
   };
-  void add_det_shock(const string& var, const vector<pair<int, int>>& periods,
+  void add_det_shock(const string& var,
+                     const vector<AbstractShocksStatement::period_range_t>& periods,
                      const vector<expr_t>& values, DetShockType type);
   //! Adds a heteroskedastic shock (either values or scales)
-  void add_heteroskedastic_shock(const string& var, const vector<pair<int, int>>& periods,
+  void add_heteroskedastic_shock(const string& var,
+                                 const vector<AbstractShocksStatement::period_range_t>& periods,
                                  const vector<expr_t>& values, bool scales);
   //! Adds a std error shock
   void add_stderr_shock(const string& var, expr_t value);
diff --git a/src/Shocks.cc b/src/Shocks.cc
index 1bb84966ed9cb548303efd3e49377d4e805f00bc..644b2b06178ef6fdf071b63a51dc4f60c22a0a55 100644
--- a/src/Shocks.cc
+++ b/src/Shocks.cc
@@ -19,11 +19,32 @@
 
 #include <cassert>
 #include <cstdlib>
+#include <functional>
 #include <iostream>
 #include <utility>
 
 #include "Shocks.hh"
 
+static auto print_matlab_period_range = []<class T>(ostream& output, const T& arg) {
+  if constexpr (is_same_v<T, pair<int, int>>)
+    output << arg.first << ":" << arg.second;
+  else if constexpr (is_same_v<T, pair<string, string>>)
+    output << "(" << arg.first << "):(" << arg.second << ")";
+  else
+    static_assert(always_false_v<T>, "Non-exhaustive visitor!");
+};
+
+static auto print_json_period_range = []<class T>(ostream& output, const T& arg) {
+  if constexpr (is_same_v<T, pair<int, int>>)
+    output << R"("period1": )" << arg.first << ", "
+           << R"("period2": )" << arg.second;
+  else if constexpr (is_same_v<T, pair<string, string>>)
+    output << R"("period1": ")" << arg.first << R"(", )"
+           << R"("period2": ")" << arg.second << '"';
+  else
+    static_assert(always_false_v<T>, "Non-exhaustive visitor!");
+};
+
 AbstractShocksStatement::AbstractShocksStatement(bool overwrite_arg, ShockType type_arg,
                                                  det_shocks_t det_shocks_arg,
                                                  const SymbolTable& symbol_table_arg) :
@@ -39,12 +60,14 @@ AbstractShocksStatement::writeDetShocks(ostream& output) const
 {
   for (const auto& [id, shock_vec] : det_shocks)
     for (bool exo_det = (symbol_table.getType(id) == SymbolType::exogenousDet);
-         const auto& [period1, period2, value] : shock_vec)
+         const auto& [period_range, value] : shock_vec)
       {
         output << "M_.det_shocks = [ M_.det_shocks;" << endl
                << boolalpha << "struct('exo_det'," << exo_det << ",'exo_id',"
                << symbol_table.getTypeSpecificID(id) + 1 << ",'type','" << typeToString(type) << "'"
-               << ",'periods'," << period1 << ":" << period2 << ",'value',";
+               << ",'periods',";
+        visit(bind(print_matlab_period_range, ref(output), placeholders::_1), period_range);
+        output << ",'value',";
         value->writeOutput(output);
         output << ") ];" << endl;
       }
@@ -60,13 +83,13 @@ AbstractShocksStatement::writeJsonDetShocks(ostream& output) const
         output << ", ";
       output << R"({"var": ")" << symbol_table.getName(id) << R"(", )"
              << R"("values": [)";
-      for (bool printed_something2 {false}; const auto& [period1, period2, value] : shock_vec)
+      for (bool printed_something2 {false}; const auto& [period_range, value] : shock_vec)
         {
           if (exchange(printed_something2, true))
             output << ", ";
-          output << R"({"period1": )" << period1 << ", "
-                 << R"("period2": )" << period2 << ", "
-                 << R"("value": ")";
+          output << "{";
+          visit(bind(print_json_period_range, ref(output), placeholders::_1), period_range);
+          output << R"(, "value": ")";
           value->writeJsonOutput(output, {}, {});
           output << R"("})";
         }
@@ -461,8 +484,9 @@ ShocksSurpriseStatement::writeOutput(ostream& output, [[maybe_unused]] const str
   else
     output << "M_.surprise_shocks = [ M_.surprise_shocks;" << endl;
   for (const auto& [id, shock_vec] : surprise_shocks)
-    for (const auto& [period1, period2, value] : shock_vec)
+    for (const auto& [period_range, value] : shock_vec)
       {
+        auto [period1, period2] = get<pair<int, int>>(period_range);
         output << "struct('exo_id'," << symbol_table.getTypeSpecificID(id) + 1 << ",'periods',"
                << period1 << ":" << period2 << ",'value',";
         value->writeOutput(output);
@@ -483,8 +507,9 @@ ShocksSurpriseStatement::writeJsonOutput(ostream& output) const
         output << ", ";
       output << R"({"var": ")" << symbol_table.getName(id) << R"(", )"
              << R"("values": [)";
-      for (bool printed_something2 {false}; const auto& [period1, period2, value] : shock_vec)
+      for (bool printed_something2 {false}; const auto& [period_range, value] : shock_vec)
         {
+          auto [period1, period2] = get<pair<int, int>>(period_range);
           if (exchange(printed_something2, true))
             output << ", ";
           output << R"({"period1": )" << period1 << ", "
@@ -546,11 +571,12 @@ ShocksLearntInStatement::writeOutput(ostream& output, [[maybe_unused]] const str
 
   output << "M_.learnt_shocks = [ M_.learnt_shocks;" << endl;
   for (const auto& [id, shock_vec] : learnt_shocks)
-    for (const auto& [type, period1, period2, value] : shock_vec)
+    for (const auto& [type, period_range, value] : shock_vec)
       {
         output << "struct('learnt_in'," << learnt_in_period << ",'exo_id',"
-               << symbol_table.getTypeSpecificID(id) + 1 << ",'periods'," << period1 << ":"
-               << period2 << ",'type','" << typeToString(type) << "'"
+               << symbol_table.getTypeSpecificID(id) + 1 << ",'periods',";
+        visit(bind(print_matlab_period_range, ref(output), placeholders::_1), period_range);
+        output << ",'type','" << typeToString(type) << "'"
                << ",'value',";
         value->writeOutput(output);
         output << ");" << endl;
@@ -570,13 +596,13 @@ ShocksLearntInStatement::writeJsonOutput(ostream& output) const
         output << ", ";
       output << R"({"var": ")" << symbol_table.getName(id) << R"(", )"
              << R"("values": [)";
-      for (bool printed_something2 {false}; const auto& [type, period1, period2, value] : shock_vec)
+      for (bool printed_something2 {false}; const auto& [type, period_range, value] : shock_vec)
         {
           if (exchange(printed_something2, true))
             output << ", ";
-          output << R"({"period1": )" << period1 << ", "
-                 << R"("period2": )" << period2 << ", "
-                 << R"("type": ")" << typeToString(type) << R"(", )"
+          output << "{";
+          visit(bind(print_json_period_range, ref(output), placeholders::_1), period_range);
+          output << R"(, "type": ")" << typeToString(type) << R"(", )"
                  << R"("value": ")";
           value->writeJsonOutput(output, {}, {});
           output << R"("})";
@@ -805,9 +831,12 @@ ConditionalForecastPathsStatement::computePathLength(
 {
   int length {0};
   for (const auto& [ignore, elems] : paths)
-    for (auto& [period1, period2, value] : elems)
-      // Period1 < Period2, as enforced in ParsingDriver::add_period()
-      length = max(length, period2);
+    for (auto& [period_range, value] : elems)
+      {
+        auto [period1, period2] = get<pair<int, int>>(period_range);
+        // Period1 < Period2, as enforced in ParsingDriver::add_period()
+        length = max(length, period2);
+      }
   return length;
 }
 
@@ -827,13 +856,16 @@ ConditionalForecastPathsStatement::writeOutput(ostream& output,
       else
         output << "constrained_vars_ = [constrained_vars_; "
                << symbol_table.getTypeSpecificID(id) + 1 << "];" << endl;
-      for (const auto& [period1, period2, value] : elems)
-        for (int j = period1; j <= period2; j++)
-          {
-            output << "constrained_paths_(" << k << "," << j << ")=";
-            value->writeOutput(output);
-            output << ";" << endl;
-          }
+      for (const auto& [period_range, value] : elems)
+        {
+          auto [period1, period2] = get<pair<int, int>>(period_range);
+          for (int j = period1; j <= period2; j++)
+            {
+              output << "constrained_paths_(" << k << "," << j << ")=";
+              value->writeOutput(output);
+              output << ";" << endl;
+            }
+        }
       k++;
     }
 }
@@ -849,13 +881,13 @@ ConditionalForecastPathsStatement::writeJsonOutput(ostream& output) const
         output << ", ";
       output << R"({"var": ")" << symbol_table.getName(id) << R"(", )"
              << R"("values": [)";
-      for (bool printed_something2 {false}; const auto& [period1, period2, value] : elems)
+      for (bool printed_something2 {false}; const auto& [period_range, value] : elems)
         {
           if (exchange(printed_something2, true))
             output << ", ";
-          output << R"({"period1": )" << period1 << ", "
-                 << R"("period2": )" << period2 << ", "
-                 << R"("value": ")";
+          output << "{";
+          visit(bind(print_json_period_range, ref(output), placeholders::_1), period_range);
+          output << R"(, "value": ")";
           value->writeJsonOutput(output, {}, {});
           output << R"("})";
         }
diff --git a/src/Shocks.hh b/src/Shocks.hh
index a92ef73327219b04b0e8e44611ae247bfceed07d..2f8d335e38eadef5d20c43f125d8299a729d09d0 100644
--- a/src/Shocks.hh
+++ b/src/Shocks.hh
@@ -22,6 +22,7 @@
 
 #include <map>
 #include <string>
+#include <variant>
 #include <vector>
 
 #include "ExprNode.hh"
@@ -34,8 +35,10 @@ using namespace std;
 class AbstractShocksStatement : public Statement
 {
 public:
-  // The tuple is (period1, period2, value)
-  using det_shocks_t = map<int, vector<tuple<int, int, expr_t>>>;
+  // A period range is either two indices (1-based), or two dates (from dseries)
+  using period_range_t = variant<pair<int, int>, pair<string, string>>;
+  // The pair is (period range, value)
+  using det_shocks_t = map<int, vector<pair<period_range_t, expr_t>>>;
   enum class ShockType
   {
     level, // The value is the level of the exogenous (“values” statement in “shocks”)
@@ -140,8 +143,9 @@ public:
                                // state as anticipated in the same informational period (“values”
                                // statement in “mshocks(learnt_in=…, relative_to_initval)”)
   };
-  // The tuple is (type, period1, period2, value)
-  using learnt_shocks_t = map<int, vector<tuple<LearntShockType, int, int, expr_t>>>;
+  // The tuple is (type, period range, value)
+  using learnt_shocks_t
+      = map<int, vector<tuple<LearntShockType, AbstractShocksStatement::period_range_t, expr_t>>>;
   const learnt_shocks_t learnt_shocks;
 
 private:
diff --git a/src/Statement.hh b/src/Statement.hh
index e542e7999c46c12a1c024714aca6688d04f96c52..6716f8d5320d585e82627fb9c63d5cd5dafd84a5 100644
--- a/src/Statement.hh
+++ b/src/Statement.hh
@@ -30,6 +30,10 @@
 #include "SymbolList.hh"
 #include "WarningConsolidation.hh"
 
+// Helper constant for visitors
+template<class>
+inline constexpr bool always_false_v {false};
+
 struct ModFileStructure
 {
   //! Whether check is present
@@ -333,9 +337,6 @@ public:
 private:
   map<string, OptionValue> options;
   void writeOutputCommon(ostream& output, const string& option_group) const;
-  // Helper constant for visitors
-  template<class>
-  static constexpr bool always_false_v {false};
 };
 
 #endif