Compare commits

...

32 Commits
master ... 5.x

Author SHA1 Message Date
Sébastien Villemot 5d0ad3f666
include_eqs/exclude_eqs: fix equation number in error message 2021-12-13 16:47:35 +01:00
Sébastien Villemot f44155d43a
Fix logic of include_eqs in the presence of [static]/[dynamic] equations
In a model with [static]/[dynamic] equations, if the user was using include_eqs
with a list of equations that does *not* contain equations marked
[static]/[dynamic], then the call to ModelTree::includeExcludeEquations(…,
static_equations=true) would have an empty list of equation tags (as stored
in tag_eqns).

The right behaviour in this case is to exclude all static equations. However,
the code would exclude none, and this would disrupt the equilibrium between
[static] and [dynamic] equations (since all [dynamic] equations were excluded
by the other call to the same method).

The fix consists in removing the shortcut that returns from the method if
tag_eqns is empty.

(cherry picked from commit a73b0d911a)
2021-12-13 12:19:16 +01:00
Sébastien Villemot 4deb397d18
Bump version number 2021-12-08 14:35:47 +01:00
Johannes Pfeifer 1341963d32
occbin_write_regimes: add option to select type
(cherry picked from commit 164e2debdc)
2021-12-07 18:13:25 +01:00
Sébastien Villemot 7fff5c4c30
Occbin: use element-by-element multiply, divide and power in occbin_difference.m
This file operates on vectors.

Ref. dynare#1826

(cherry picked from commit 81abea042b)
2021-12-07 18:11:13 +01:00
Sébastien Villemot f257b96060
When looking for unused endos/exos, also search in equations marked [static]
(cherry picked from commit fe974c4c31)
2021-12-07 11:37:27 +01:00
Sébastien Villemot cac24dad7e
Substitute model-local variables in equations marked [static]
(cherry picked from commit 8d4cab6fe3)
2021-12-07 11:37:27 +01:00
Sébastien Villemot ced586febf
Symbolic detrending engine: correctly handle equations marked [static]
Incidentally, this also fixes a detrending bug in the Occbin engine (since the
latter internally generates a [static] equation).

Ref. dynare#1827

By the way, perform a small code simplification.

(cherry picked from commit 7b8fc8edb7)
2021-12-07 11:37:27 +01:00
Sébastien Villemot bdbafdc34c
No longer consider an equation of the form “x(+1) = 0” as defining x to be a constant
Fix this by restricting the detection of constant equations to those where the
variable appears without a lead or lag.

Closes: #83
(cherry picked from commit 1cc512962c)
2021-11-22 10:23:57 +01:00
Sébastien Villemot 008a0dbb9e
With nostrict, really ignore unused endogenous in initval/endval/histval
Closes: #82
(cherry picked from commit b51f122e59)
2021-11-22 10:23:57 +01:00
Sébastien Villemot 0c1a9fa916
Fix handling of undeclared variables in the planner_objective statement
Closes: #81
(cherry picked from commit 02ee077663)
2021-11-22 10:23:57 +01:00
Sébastien Villemot a2977dd07c
Macroprocessor: make the removal of “@#line” directives and extra newlines consistent across LF and CR+LF conventions
Simplify the algorithm using only regexps, and add comments.

(cherry picked from commit 1e4eadb266)
2021-11-22 10:23:57 +01:00
Sébastien Villemot 67b8ef1a19
Macroprocessor: fix line counter inside @{} constructs
There were two bugs:
– with the LF convention, newlines were counted twice
– with the CR+LF convention, they were counted four times (because the CR was
  included in yyleng, alongside the LF)

The fix consists in implementing a location_increment() method similar to the
one used for the Dynare parser. This is the most robust solution.

By the way, mark the method DynareFlex::location_increment() method static.

(cherry picked from commit 1de3476546)
2021-11-22 10:23:57 +01:00
Sébastien Villemot 8e7dd47a16
Macroprocessor: fix newlines in output when under Windows and input uses CR+LF convention
If the input .mod file uses CR+LF convention, and if the user is under Windows,
then the output of the macroprocessor (as given by the “savemacro” option) had
incorrect end of lines: those would be CR+CR+LF.

The reason is that some TextNode(s) internally created by the macroprocessor
would themselves contain CR+LF sequences, which would then be transformed into
CR+CR+LF in the output (because MinGW transforms LF into CR+LF in output
streams).

The fix consists in changing the nature of the EOL token: the parsed text is no
longer attached to it, so that the Bison file now systematically turns it into
a LF inside TextNode(s).

Closes: #80
(cherry picked from commit 487c372900)
2021-11-22 10:23:57 +01:00
Sébastien Villemot c63d08007c
Fix error message when using pac_expectation with occbin_constraints
By the way, also fix the argument name (the model is not a VAR).

(cherry picked from commit 0123326123)
2021-10-29 14:12:13 +02:00
Sébastien Villemot ff564cbc9a
PAC: add growth correction term for definition of Z₁ in the MCE case
(cherry picked from commit 5bef185370)
2021-10-25 19:18:36 +02:00
Sébastien Villemot d430f47616
Improve message for GCC installation under macOS
(cherry picked from commit 8bb8e59410)
2021-10-08 15:51:37 +02:00
Sébastien Villemot 990cee70c2
PAC: better error message in case of name conflict for the growth neutrality correction parameter
(cherry picked from commit 78e295115a)
2021-10-06 16:42:22 +02:00
Johannes Pfeifer dfed3e98ab
ramsey_model: Fix error message logic
one of the statements being present is sufficient

(cherry picked from commit b496c4ba2c)
2021-09-24 16:54:28 +02:00
Sébastien Villemot 784b2d6d40
Remove unused steady_state_growth option to pac_model
(cherry picked from commit eb006ecaeb)
2021-09-22 17:29:53 +02:00
Johannes Pfeifer 0ccb986da8
Rename mh_mode to correct mh_posterior_mode_estimation option
Closes https://git.dynare.org/Dynare/preprocessor/-/issues/60

(cherry picked from commit 8d14e18cdb)
2021-09-22 17:28:32 +02:00
Sébastien Villemot d03b74469a
ramsey_{model,policy}, discretionary_policy: check that instruments are declared endogenous
Closes: #72
(cherry picked from commit b12746190d)
2021-09-21 18:41:41 +02:00
Sébastien Villemot 37b38b46cc
Fix use_dll on macOS + Octave
Enforce GCC with mkoctfile. Otherwise Clang will be used, and it does not
accept our custom optimization flags.

Ref. dynare#1797

(cherry picked from commit 3d215020ae)
2021-09-13 16:52:27 +02:00
Sébastien Villemot b1a0ebf513
Fix bug introduced in previous commit that triggers a crash for DSGE-VAR models
(cherry picked from commit 989347f448)
2021-09-08 19:00:58 +02:00
Sébastien Villemot 79efd2ec17
estimated_params*: add a check that prevents (apparently) recursive prior definitions
Closes: #77
(cherry picked from commit cb19ece049)
2021-09-08 17:11:48 +02:00
Sébastien Villemot 04e42fa821
estimated_params_{bounds,init} now check that a parameter (or correlation) is never declared twice
This check was previously only implemented in estimated_params.

(cherry picked from commit 62ba9a434a)
2021-09-08 17:11:47 +02:00
Sébastien Villemot ce43e91b57
PAC: generate the “growth_neutrality_param_index” MATLAB field for MCE models
Previously it was only generated in the case of backward PAC models.

(cherry picked from commit 784dd4122a)
2021-09-01 11:31:08 +02:00
Sébastien Villemot d528467234
Ensure that the “discount” option of “pac_model” is a parameter
Ref. Madysson/estimation-codes#4

(cherry picked from commit 6863494db2)
2021-08-31 13:58:59 +02:00
Johannes Pfeifer 4f8713134f
method_of_moments: move to namespace
(cherry picked from commit 3f37d9692c)
2021-08-31 13:56:19 +02:00
Stéphane Adjemian (Charybdis) 2f2e02e007
Fix warning (missing option in occbin_setup).
(cherry picked from commit 79d5a2d687)
2021-08-18 15:29:06 +02:00
Stéphane Adjemian 0bbba398a1
Merge branch 'occbin_options' into 'master'
Occbin: Add missing options

See merge request Dynare/preprocessor!49
2021-08-16 12:09:37 +02:00
Sébastien Villemot 0a6b71a375
Bump version number 2021-07-23 15:40:27 +02:00
18 changed files with 415 additions and 237 deletions

View File

@ -1,6 +1,6 @@
dnl Process this file with autoconf to produce a configure script.
dnl Copyright © 2009-2019 Dynare Team
dnl Copyright © 2009-2021 Dynare Team
dnl
dnl This file is part of Dynare.
dnl
@ -18,7 +18,7 @@ dnl You should have received a copy of the GNU General Public License
dnl along with Dynare. If not, see <https://www.gnu.org/licenses/>.
AC_PREREQ([2.62])
AC_INIT([dynare-preprocessor], [4.7-unstable])
AC_INIT([dynare-preprocessor], [5.0])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_SRCDIR([src/DynareMain.cc])
AM_INIT_AUTOMAKE([1.11 -Wall -Wno-portability foreign no-dist-gzip dist-xz tar-pax])

View File

@ -20,6 +20,8 @@
#include <cassert>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <iterator>
using namespace std;
@ -335,16 +337,12 @@ PacModelStatement::PacModelStatement(string name_arg,
string aux_model_name_arg,
string discount_arg,
expr_t growth_arg,
double steady_state_growth_rate_number_arg,
int steady_state_growth_rate_symb_id_arg,
const SymbolTable &symbol_table_arg) :
name{move(name_arg)},
aux_model_name{move(aux_model_name_arg)},
discount{move(discount_arg)},
growth{growth_arg},
original_growth{growth_arg},
steady_state_growth_rate_number{steady_state_growth_rate_number_arg},
steady_state_growth_rate_symb_id{steady_state_growth_rate_symb_id_arg},
symbol_table{symbol_table_arg}
{
}
@ -386,12 +384,6 @@ PacModelStatement::writeOutput(ostream &output, const string &basename, bool min
{
output << "M_.pac." << name << ".auxiliary_model_name = '" << aux_model_name << "';" << endl
<< "M_.pac." << name << ".discount_index = " << symbol_table.getTypeSpecificID(discount) + 1 << ";" << endl;
if (steady_state_growth_rate_symb_id < 0 && steady_state_growth_rate_number > 0)
output << "M_.pac." << name << ".steady_state_growth_rate = "
<< steady_state_growth_rate_number << ";" << endl;
else if (steady_state_growth_rate_symb_id >= 0)
output << "M_.pac." << name << ".steady_state_growth_rate = "
<< symbol_table.getTypeSpecificID(steady_state_growth_rate_symb_id) + 1 << ";" << endl;
if (growth)
{
@ -676,7 +668,7 @@ RamseyConstraintsStatement::RamseyConstraintsStatement(const SymbolTable &symbol
void
RamseyConstraintsStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
{
if (!mod_file_struct.ramsey_model_present || !mod_file_struct.ramsey_policy_present)
if (!mod_file_struct.ramsey_model_present && !mod_file_struct.ramsey_policy_present)
cerr << "ramsey_constraints: can only be used with ramsey_model or ramsey_policy" << endl;
}
@ -1003,7 +995,7 @@ void
OccbinWriteRegimesStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
{
options_list.writeOutput(output, "options_.occbin");
output << "occbin.write_regimes_to_xls(oo_.occbin.regime_history, M_, options_);" << endl;
output << "occbin.write_regimes_to_xls(oo_.occbin, M_, options_);" << endl;
}
void
@ -1362,16 +1354,94 @@ DsampleStatement::writeJsonOutput(ostream &output) const
<< R"("value2": )" << val2 << "}";
}
EstimatedParamsStatement::EstimatedParamsStatement(vector<EstimationParams> estim_params_list_arg,
const SymbolTable &symbol_table_arg) :
AbstractEstimatedParamsStatement::AbstractEstimatedParamsStatement(vector<EstimationParams> estim_params_list_arg,
const SymbolTable &symbol_table_arg) :
estim_params_list{move(estim_params_list_arg)},
symbol_table{symbol_table_arg}
{
}
void
AbstractEstimatedParamsStatement::commonCheckPass() const
{
// Check that no parameter/endogenous is declared twice in the block
set<string> already_declared;
set<pair<string, string>> already_declared_corr;
for (const auto &it : estim_params_list)
{
if (it.type == 3) // Correlation
{
// Use lexical ordering for the pair of symbols
auto x = it.name < it.name2 ? make_pair(it.name, it.name2) : make_pair(it.name2, it.name);
if (already_declared_corr.find(x) == already_declared_corr.end())
already_declared_corr.insert(x);
else
{
cerr << "ERROR: in `" << blockName() << "' block, the correlation between " << it.name << " and " << it.name2 << " is declared twice." << endl;
exit(EXIT_FAILURE);
}
}
else
{
if (already_declared.find(it.name) == already_declared.end())
already_declared.insert(it.name);
else
{
cerr << "ERROR: in `" << blockName() << "' block, the symbol " << it.name << " is declared twice." << endl;
exit(EXIT_FAILURE);
}
}
}
/* Check that a parameter declared in this block is not used in expressions
associated to other parameters in the same block (see issue #77) */
// First compute the symbol IDs of parameters declared in this block
set<int> declared_params;
for (const string &name : already_declared)
if (name != "dsge_prior_weight")
declared_params.insert(symbol_table.getID(name));
// Then look for (apparently) recursive definitions
for (const auto &it : estim_params_list)
{
set<int> used_params;
it.init_val->collectVariables(SymbolType::parameter, used_params);
it.low_bound->collectVariables(SymbolType::parameter, used_params);
it.up_bound->collectVariables(SymbolType::parameter, used_params);
it.mean->collectVariables(SymbolType::parameter, used_params);
it.std->collectVariables(SymbolType::parameter, used_params);
it.p3->collectVariables(SymbolType::parameter, used_params);
it.p4->collectVariables(SymbolType::parameter, used_params);
it.jscale->collectVariables(SymbolType::parameter, used_params);
vector<int> intersect;
set_intersection(declared_params.begin(), declared_params.end(),
used_params.begin(), used_params.end(),
back_inserter(intersect));
if (intersect.size() > 0)
{
cerr << "ERROR: in `" << blockName() << "' block, the value of estimated parameter "
<< symbol_table.getName(intersect[0]) << " is used in the declaration for ";
if (it.type == 3)
cerr << "correlation between " << it.name << " and " << it.name2;
else // either a parameter, the stderr of an exo, or the measurement error of an endo
cerr << "symbol " << it.name;
cerr << ". This behaviour is undefined." << endl;
exit(EXIT_FAILURE);
}
}
}
EstimatedParamsStatement::EstimatedParamsStatement(vector<EstimationParams> estim_params_list_arg,
const SymbolTable &symbol_table_arg) :
AbstractEstimatedParamsStatement(move(estim_params_list_arg), symbol_table_arg)
{
}
void
EstimatedParamsStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
{
commonCheckPass();
for (const auto &it : estim_params_list)
{
if (it.name == "dsge_prior_weight")
@ -1394,36 +1464,6 @@ EstimatedParamsStatement::checkPass(ModFileStructure &mod_file_struct, WarningCo
}
}
// Check that no parameter/endogenous is declared twice in the block
set<string> already_declared;
set<pair<string, string>> already_declared_corr;
for (const auto &it : estim_params_list)
{
if (it.type == 3) // Correlation
{
// Use lexical ordering for the pair of symbols
auto x = it.name < it.name2 ? pair(it.name, it.name2) : pair(it.name2, it.name);
if (already_declared_corr.find(x) == already_declared_corr.end())
already_declared_corr.insert(x);
else
{
cerr << "ERROR: in `estimated_params' block, the correlation between " << it.name << " and " << it.name2 << " is declared twice." << endl;
exit(EXIT_FAILURE);
}
}
else
{
if (already_declared.find(it.name) == already_declared.end())
already_declared.insert(it.name);
else
{
cerr << "ERROR: in `estimated_params' block, the symbol " << it.name << " is declared twice." << endl;
exit(EXIT_FAILURE);
}
}
}
// Fill in mod_file_struct.estimated_parameters (related to #469)
for (const auto &it : estim_params_list)
if (it.type == 2 && it.name != "dsge_prior_weight")
@ -1537,8 +1577,7 @@ EstimatedParamsStatement::writeJsonOutput(ostream &output) const
EstimatedParamsInitStatement::EstimatedParamsInitStatement(vector<EstimationParams> estim_params_list_arg,
const SymbolTable &symbol_table_arg,
const bool use_calibration_arg) :
estim_params_list{move(estim_params_list_arg)},
symbol_table{symbol_table_arg},
AbstractEstimatedParamsStatement(move(estim_params_list_arg), symbol_table_arg),
use_calibration{use_calibration_arg}
{
}
@ -1546,6 +1585,8 @@ EstimatedParamsInitStatement::EstimatedParamsInitStatement(vector<EstimationPara
void
EstimatedParamsInitStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
{
commonCheckPass();
if (use_calibration)
mod_file_struct.estim_params_use_calib = true;
}
@ -1675,11 +1716,16 @@ EstimatedParamsInitStatement::writeJsonOutput(ostream &output) const
EstimatedParamsBoundsStatement::EstimatedParamsBoundsStatement(vector<EstimationParams> estim_params_list_arg,
const SymbolTable &symbol_table_arg) :
estim_params_list{move(estim_params_list_arg)},
symbol_table{symbol_table_arg}
AbstractEstimatedParamsStatement(move(estim_params_list_arg), symbol_table_arg)
{
}
void
EstimatedParamsBoundsStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
{
commonCheckPass();
}
void
EstimatedParamsBoundsStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
{
@ -2346,7 +2392,7 @@ PlannerObjectiveStatement::checkPass(ModFileStructure &mod_file_struct, WarningC
assert(model_tree.equation_number() == 1);
if (model_tree.exoPresentInEqs())
{
cerr << "ERROR: You cannot include exogenous variables in the planner objective. Please "
cerr << "ERROR: You cannot include exogenous variables (or variables of undeclared type) in the planner objective. Please "
<< "define an auxiliary endogenous variable like eps_aux=epsilon and use it instead "
<< "of the varexo." << endl;
exit(EXIT_FAILURE);
@ -4965,7 +5011,7 @@ MethodOfMomentsStatement::writeOutput(ostream &output, const string &basename, b
{
options_list.writeOutput(output, "options_mom_");
output << "[oo_, options_mom_, M_] = method_of_moments(bayestopt_, options_, oo_, estim_params_, M_, options_mom_);" << endl;
output << "[oo_, options_mom_, M_] = mom.run(bayestopt_, options_, oo_, estim_params_, M_, options_mom_);" << endl;
}
void

View File

@ -146,8 +146,6 @@ public:
const string name, aux_model_name, discount;
expr_t growth, original_growth;
private:
const double steady_state_growth_rate_number;
const int steady_state_growth_rate_symb_id;
const SymbolTable &symbol_table;
vector<tuple<int, int, int, double>> growth_info;
public:
@ -155,8 +153,6 @@ public:
string aux_model_name_arg,
string discount_arg,
expr_t growth_arg,
double steady_state_growth_rate_number_arg,
int steady_state_growth_rate_symb_id_arg,
const SymbolTable &symbol_table_arg);
void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) override;
void overwriteGrowth(expr_t new_growth);
@ -511,42 +507,50 @@ public:
}
};
class EstimatedParamsStatement : public Statement
class AbstractEstimatedParamsStatement : public Statement
{
private:
protected:
const vector<EstimationParams> estim_params_list;
const SymbolTable &symbol_table;
AbstractEstimatedParamsStatement(vector<EstimationParams> estim_params_list_arg,
const SymbolTable &symbol_table_arg);
virtual string blockName() const = 0;
// Part of the check pass that is common to the three estimated_params* blocks
void commonCheckPass() const;
};
class EstimatedParamsStatement : public AbstractEstimatedParamsStatement
{
public:
EstimatedParamsStatement(vector<EstimationParams> estim_params_list_arg,
const SymbolTable &symbol_table_arg);
string blockName() const override { return "estimated_params"; };
void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) override;
void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream &output) const override;
};
class EstimatedParamsInitStatement : public Statement
class EstimatedParamsInitStatement : public AbstractEstimatedParamsStatement
{
private:
const vector<EstimationParams> estim_params_list;
const SymbolTable &symbol_table;
const bool use_calibration;
public:
EstimatedParamsInitStatement(vector<EstimationParams> estim_params_list_arg,
const SymbolTable &symbol_table_arg,
const bool use_calibration_arg);
string blockName() const override { return "estimated_params_init"; };
void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) override;
void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream &output) const override;
};
class EstimatedParamsBoundsStatement : public Statement
class EstimatedParamsBoundsStatement : public AbstractEstimatedParamsStatement
{
private:
const vector<EstimationParams> estim_params_list;
const SymbolTable &symbol_table;
public:
EstimatedParamsBoundsStatement(vector<EstimationParams> estim_params_list_arg,
const SymbolTable &symbol_table_arg);
string blockName() const override { return "estimated_params_bounds"; };
void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) override;
void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream &output) const override;
};

View File

@ -114,6 +114,7 @@ DynamicModel::DynamicModel(const DynamicModel &m) :
pac_h1_indices{m.pac_h1_indices},
pac_mce_z1_symb_ids{m.pac_mce_z1_symb_ids},
pac_eqtag_and_lag{m.pac_eqtag_and_lag},
pac_growth_neutrality_params{m.pac_growth_neutrality_params},
pac_model_info{m.pac_model_info},
pac_equation_info{m.pac_equation_info}
{
@ -178,6 +179,7 @@ DynamicModel::operator=(const DynamicModel &m)
pac_mce_z1_symb_ids = m.pac_mce_z1_symb_ids;
pac_eqtag_and_lag = m.pac_eqtag_and_lag;
pac_expectation_substitution.clear();
pac_growth_neutrality_params = m.pac_growth_neutrality_params;
pac_model_info = m.pac_model_info;
pac_equation_info = m.pac_equation_info;
@ -3033,20 +3035,19 @@ DynamicModel::writeDriverOutput(ostream &output, const string &basename, bool bl
output << "];" << endl;
}
for (auto &it : pac_model_info)
for (auto &[model, growth_neutrality_param_index] : pac_growth_neutrality_params)
output << "M_.pac." << model << ".growth_neutrality_param_index = "
<< symbol_table.getTypeSpecificID(growth_neutrality_param_index) + 1 << ";" << endl;
for (auto &[model, values] : pac_model_info)
{
vector<int> lhs = get<0>(it.second);
output << "M_.pac." << it.first << ".lhs = [";
auto &[lhs, aux_model_type] = values;
output << "M_.pac." << model << ".lhs = [";
for (auto it : lhs)
output << it + 1 << " ";
output << "];" << endl;
if (int growth_param_index = get<1>(it.second);
growth_param_index >= 0)
output << "M_.pac." << it.first << ".growth_neutrality_param_index = "
<< symbol_table.getTypeSpecificID(growth_param_index) + 1 << ";" << endl;
output << "M_.pac." << it.first << ".auxiliary_model_type = '" << get<2>(it.second) << "';" << endl;
output << "M_.pac." << model << ".auxiliary_model_type = '" << aux_model_type << "';" << endl;
}
for (auto &pit : pac_equation_info)
@ -4066,7 +4067,8 @@ DynamicModel::declarePacModelConsistentExpectationEndogs(const string &name)
void
DynamicModel::addPacModelConsistentExpectationEquation(const string &name, int discount_symb_id,
const map<pair<string, string>, pair<string, int>> &eqtag_and_lag,
ExprNode::subst_table_t &diff_subst_table)
ExprNode::subst_table_t &diff_subst_table,
expr_t growth)
{
int pac_target_symb_id;
try
@ -4189,11 +4191,31 @@ DynamicModel::addPacModelConsistentExpectationEquation(const string &name, int d
AddMinus(AddTimes(A, AddMinus(const_cast<VariableNode *>(target_base_diff_node), fs)), fp));
addEquation(neweq, -1);
neqs++;
pac_expectation_substitution[{name, eqtag}] = AddVariable(mce_z1_symb_id);
/* The growth correction term is not added to the definition of Z₁
because the latter is recursive. Rather put it at the level of the
substition of pac_expectation operator. */
expr_t growth_correction = growth ? AddTimes(AddVariable(pac_growth_neutrality_params.at(name)), growth) : Zero;
pac_expectation_substitution[{name, eqtag}] = AddPlus(AddVariable(mce_z1_symb_id), growth_correction);
}
cout << "Pac Model Consistent Expectation: added " << neqs << " auxiliary variables and equations for model " << name << "." << endl;
}
void
DynamicModel::createPacGrowthNeutralityParameter(const string &pac_model_name)
{
string param_name = pac_model_name + "_pac_growth_neutrality_correction";
try
{
int param_idx = symbol_table.addSymbol(param_name, SymbolType::parameter);
pac_growth_neutrality_params[pac_model_name] = param_idx;
}
catch (SymbolTable::AlreadyDeclaredException)
{
cerr << "The parameter '" << param_name << "' conflicts with the auxiliary parameter that will be generated for the growth neutrality correction of the '" << pac_model_name << "' PAC model. Please rename that parameter." << endl;
exit(EXIT_FAILURE);
}
}
void
DynamicModel::fillPacModelInfo(const string &pac_model_name,
vector<int> lhs,
@ -4208,12 +4230,6 @@ DynamicModel::fillPacModelInfo(const string &pac_model_name,
bool stationary_vars_present = any_of(nonstationary.begin(), nonstationary.end(), logical_not<bool>());
bool nonstationary_vars_present = any_of(nonstationary.begin(), nonstationary.end(), [](bool b) { return b; }); // FIXME: use std::identity instead of an anonymous function when we upgrade to C++20
int growth_param_index = -1;
if (growth)
growth_param_index = symbol_table.addSymbol(pac_model_name
+"_pac_growth_neutrality_correction",
SymbolType::parameter);
for (auto pac_models_and_eqtags : pac_eqtag_and_lag)
{
if (pac_models_and_eqtags.first.first != pac_model_name)
@ -4276,12 +4292,15 @@ DynamicModel::fillPacModelInfo(const string &pac_model_name,
}
if (growth)
subExpr = AddPlus(subExpr,
AddTimes(AddVariable(growth_param_index), growth));
{
int growth_param_index = pac_growth_neutrality_params.at(pac_model_name);
subExpr = AddPlus(subExpr,
AddTimes(AddVariable(growth_param_index), growth));
}
pac_expectation_substitution[{pac_model_name, eqtag}] = subExpr;
}
pac_model_info[pac_model_name] = {move(lhs), growth_param_index, move(aux_model_type)};
pac_model_info[pac_model_name] = {move(lhs), move(aux_model_type)};
}
void
@ -4904,6 +4923,8 @@ DynamicModel::findUnusedEndogenous()
set<int> usedEndo, unusedEndo;
for (auto &equation : equations)
equation->collectVariables(SymbolType::endogenous, usedEndo);
for (auto &equation : static_only_equations)
equation->collectVariables(SymbolType::endogenous, usedEndo);
set<int> allEndo = symbol_table.getEndogenous();
set_difference(allEndo.begin(), allEndo.end(),
usedEndo.begin(), usedEndo.end(),
@ -4917,6 +4938,8 @@ DynamicModel::findUnusedExogenous()
set<int> usedExo, unusedExo, unobservedExo;
for (auto &equation : equations)
equation->collectVariables(SymbolType::exogenous, usedExo);
for (auto &equation : static_only_equations)
equation->collectVariables(SymbolType::exogenous, usedExo);
set<int> observedExo = symbol_table.getObservedExogenous();
set<int> allExo = symbol_table.getExogenous();
set_difference(allExo.begin(), allExo.end(),
@ -5658,6 +5681,9 @@ DynamicModel::substituteModelLocalVariables()
for (auto &equation : equations)
equation = dynamic_cast<BinaryOpNode *>(equation->substituteModelLocalVariables());
for (auto &equation : static_only_equations)
equation = dynamic_cast<BinaryOpNode *>(equation->substituteModelLocalVariables());
/* We cant clear local_variables_table at this point, because in case of
ramsey_policy, the original model is saved via DynamicModel::operator=()
before computing the FOC. But since DataTree::operator=() clones all
@ -5869,18 +5895,28 @@ DynamicModel::detrendEquations()
// We go backwards in the list of trend_vars, to deal correctly with I(2) processes
for (auto it = nonstationary_symbols_map.crbegin();
it != nonstationary_symbols_map.crend(); ++it)
for (auto &equation : equations)
{
auto substeq = dynamic_cast<BinaryOpNode *>(equation->detrend(it->first, it->second.first, it->second.second));
assert(substeq);
equation = dynamic_cast<BinaryOpNode *>(substeq);
}
{
for (auto &equation : equations)
{
equation = dynamic_cast<BinaryOpNode *>(equation->detrend(it->first, it->second.first, it->second.second));
assert(equation);
}
for (auto &equation : static_only_equations)
{
equation = dynamic_cast<BinaryOpNode *>(equation->detrend(it->first, it->second.first, it->second.second));
assert(equation);
}
}
for (auto &equation : equations)
{
auto substeq = dynamic_cast<BinaryOpNode *>(equation->removeTrendLeadLag(trend_symbols_map));
assert(substeq);
equation = dynamic_cast<BinaryOpNode *>(substeq);
equation = dynamic_cast<BinaryOpNode *>(equation->removeTrendLeadLag(trend_symbols_map));
assert(equation);
}
for (auto &equation : static_only_equations)
{
equation = dynamic_cast<BinaryOpNode *>(equation->removeTrendLeadLag(trend_symbols_map));
assert(equation);
}
}
@ -5889,9 +5925,13 @@ DynamicModel::removeTrendVariableFromEquations()
{
for (auto &equation : equations)
{
auto substeq = dynamic_cast<BinaryOpNode *>(equation->replaceTrendVar());
assert(substeq);
equation = dynamic_cast<BinaryOpNode *>(substeq);
equation = dynamic_cast<BinaryOpNode *>(equation->replaceTrendVar());
assert(equation);
}
for (auto &equation : static_only_equations)
{
equation = dynamic_cast<BinaryOpNode *>(equation->replaceTrendVar());
assert(equation);
}
}

View File

@ -134,13 +134,16 @@ private:
//! Store lag info for pac equations
//! (pac_model_name, equation_tag) -> (standardized_eqtag, lag)
map<pair<string, string>, pair<string, int>> pac_eqtag_and_lag;
// Store indices for growth neutrality parameters
// pac_model_name -> growth_param_index
map<string, int> pac_growth_neutrality_params;
//! (pac_model_name, equation_tag) -> expr_t
map<pair<string, string>, expr_t> pac_expectation_substitution;
//! Store info about pac models:
//! pac_model_name -> (lhsvars, growth_param_index, aux_model_type)
map<string, tuple<vector<int>, int, string>> pac_model_info;
//! Store info about backward PAC models:
//! pac_model_name -> (lhsvars, aux_model_type)
map<string, pair<vector<int>, string>> pac_model_info;
//! Store info about pac models specific to the equation they appear in
//! (pac_model_name, standardized_eqtag) ->
@ -414,7 +417,14 @@ public:
//! Get Pac equation parameter info
map<pair<string, string>, pair<string, int>> walkPacParameters(const string &name);
// Create the growth neutrality parameter of a given PAC model (when the
// “growth” option has been passed)
void createPacGrowthNeutralityParameter(const string &pac_model_name);
//! Add var_model info to pac_expectation nodes
// Must be called after createPacGrowthNeutralityParameter() has been called
// on the relevant models
void fillPacModelInfo(const string &pac_model_name,
vector<int> lhs,
int max_lag,
@ -572,7 +582,7 @@ public:
//! Add model consistent expectation equation for pac model
void addPacModelConsistentExpectationEquation(const string &name, int discount,
const map<pair<string, string>, pair<string, int>> &eqtag_and_lag,
ExprNode::subst_table_t &diff_subst_table);
ExprNode::subst_table_t &diff_subst_table, expr_t growth);
//! Table to undiff LHS variables for pac vector z
vector<int> getUndiffLHSForPac(const string &aux_model_name,

View File

@ -96,7 +96,7 @@ class ParsingDriver;
%token LAPLACE LIK_ALGO LIK_INIT LINEAR LINEAR_DECOMPOSITION LOAD_IDENT_FILES LOAD_MH_FILE LOAD_RESULTS_AFTER_LOAD_MH LOAD_PARAMS_AND_STEADY_STATE LOGLINEAR LOGDATA LYAPUNOV LINEAR_APPROXIMATION
%token LYAPUNOV_COMPLEX_THRESHOLD LYAPUNOV_FIXED_POINT_TOL LYAPUNOV_DOUBLING_TOL LOG_DEFLATOR LOG_TREND_VAR LOG_GROWTH_FACTOR
%token MATCHED_MOMENTS MARKOWITZ MARGINAL_DENSITY MAX MAXIT
%token MFS MH_CONF_SIG MH_DROP MH_INIT_SCALE MH_JSCALE MH_TUNE_JSCALE MH_TUNE_GUESS MH_MODE MH_NBLOCKS MH_REPLIC MH_RECOVER MH_INITIALIZE_FROM_PREVIOUS_MCMC MH_INITIALIZE_FROM_PREVIOUS_MCMC_DIRECTORY MH_INITIALIZE_FROM_PREVIOUS_MCMC_RECORD MH_INITIALIZE_FROM_PREVIOUS_MCMC_PRIOR
%token MFS MH_CONF_SIG MH_DROP MH_INIT_SCALE MH_JSCALE MH_TUNE_JSCALE MH_TUNE_GUESS MH_POSTERIOR_MODE_ESTIMATION MH_NBLOCKS MH_REPLIC MH_RECOVER MH_INITIALIZE_FROM_PREVIOUS_MCMC MH_INITIALIZE_FROM_PREVIOUS_MCMC_DIRECTORY MH_INITIALIZE_FROM_PREVIOUS_MCMC_RECORD MH_INITIALIZE_FROM_PREVIOUS_MCMC_PRIOR
%token POSTERIOR_MAX_SUBSAMPLE_DRAWS MIN MINIMAL_SOLVING_PERIODS
%token MODE_CHECK MODE_CHECK_NEIGHBOURHOOD_SIZE MODE_CHECK_SYMMETRIC_PLOTS MODE_CHECK_NUMBER_OF_POINTS MODE_COMPUTE MODE_FILE MODEL MODEL_COMPARISON MODEL_INFO MSHOCKS ABS SIGN
%token MODEL_DIAGNOSTICS MODIFIEDHARMONICMEAN MOMENTS_VARENDO CONTEMPORANEOUS_CORRELATION DIFFUSE_FILTER SUB_DRAWS TAPER_STEPS GEWEKE_INTERVAL RAFTERY_LEWIS_QRS RAFTERY_LEWIS_DIAGNOSTICS MCMC_JUMPING_COVARIANCE MOMENT_CALIBRATION
@ -120,10 +120,11 @@ class ParsingDriver;
%token STDERR STEADY STOCH_SIMUL SYLVESTER SYLVESTER_FIXED_POINT_TOL REGIMES REGIME REALTIME_SHOCK_DECOMPOSITION CONDITIONAL UNCONDITIONAL
%token TEX RAMSEY_MODEL RAMSEY_POLICY RAMSEY_CONSTRAINTS PLANNER_DISCOUNT PLANNER_DISCOUNT_LATEX_NAME
%token DISCRETIONARY_POLICY DISCRETIONARY_TOL EVALUATE_PLANNER_OBJECTIVE
%token OCCBIN_SETUP OCCBIN_SOLVER OCCBIN_WRITE_REGIMES OCCBIN_GRAPH SIMUL_MAXIT SMOOTHER_MAXIT SIMUL_PERIODS SMOOTHER_PERIODS SIMUL_CURB_RETRENCH SMOOTHER_CURB_RETRENCH SIMUL_CHECK_AHEAD_PERIODS SMOOTHER_CHECK_AHEAD_PERIODS
%token SIMUL_DEBUG SMOOTHER_DEBUG
%token OCCBIN_SETUP OCCBIN_SOLVER OCCBIN_WRITE_REGIMES OCCBIN_GRAPH SIMUL_MAXIT LIKELIHOOD_MAXIT SMOOTHER_MAXIT SIMUL_PERIODS LIKELIHOOD_PERIODS SMOOTHER_PERIODS
%token SIMUL_CURB_RETRENCH LIKELIHOOD_CURB_RETRENCH SMOOTHER_CURB_RETRENCH SIMUL_CHECK_AHEAD_PERIODS LIKELIHOOD_CHECK_AHEAD_PERIODS SMOOTHER_CHECK_AHEAD_PERIODS
%token SIMUL_DEBUG SMOOTHER_DEBUG SIMUL_PERIODIC_SOLUTION LIKELIHOOD_PERIODIC_SOLUTION SMOOTHER_PERIODIC_SOLUTION
%token LIKELIHOOD_INVERSION_FILTER SMOOTHER_INVERSION_FILTER FILTER_USE_RELEXATION
%token LIKELIHOOD_PIECEWISE_KALMAN_FILTER SMOOTHER_PIECEWISE_KALMAN_FILTER
%token LIKELIHOOD_PIECEWISE_KALMAN_FILTER SMOOTHER_PIECEWISE_KALMAN_FILTER LIKELIHOOD_MAX_KALMAN_ITERATIONS
%token <string> TEX_NAME TRUE BIND RELAX ERROR_BIND ERROR_RELAX
%token UNIFORM_PDF UNIT_ROOT_VARS USE_DLL USEAUTOCORR GSA_SAMPLE_FILE USE_UNIVARIATE_FILTERS_IF_SINGULARITY_IS_DETECTED
%token VALUES SCALES VAR VAREXO VAREXO_DET VARIABLE VAROBS VAREXOBS PREDETERMINED_VARIABLES VAR_EXPECTATION VAR_EXPECTATION_MODEL PLOT_SHOCK_DECOMPOSITION MODEL_LOCAL_VARIABLE
@ -177,7 +178,7 @@ class ParsingDriver;
%token METHOD_OF_MOMENTS MOM_METHOD
%token BARTLETT_KERNEL_LAG WEIGHTING_MATRIX WEIGHTING_MATRIX_SCALING_FACTOR ANALYTIC_STANDARD_ERRORS ANALYTIC_JACOBIAN PENALIZED_ESTIMATOR VERBOSE
%token SIMULATION_MULTIPLE MOM_SEED SEED BOUNDED_SHOCK_SUPPORT ADDITIONAL_OPTIMIZER_STEPS MOM_SE_TOLX SE_TOLX MOM_BURNIN BURNIN
%token EQTAGS STEADY_STATE_GROWTH
%token EQTAGS
%token ANALYTICAL_GIRF IRF_IN_PERCENT EMAS_GIRF EMAS_DROP EMAS_TOLF EMAS_MAX_ITER
%token NO_IDENTIFICATION_STRENGTH NO_IDENTIFICATION_REDUCEDFORM NO_IDENTIFICATION_MOMENTS
%token NO_IDENTIFICATION_MINIMAL NO_IDENTIFICATION_SPECTRUM NORMALIZE_JACOBIANS GRID_NBR
@ -428,7 +429,6 @@ pac_model_options : o_pac_name
| o_pac_aux_model_name
| o_pac_discount
| o_pac_growth
| o_pac_steady_state_growth
;
var_expectation_model : VAR_EXPECTATION_MODEL '(' var_expectation_model_options_list ')' ';'
@ -2085,7 +2085,7 @@ estimation_options : o_datafile
| o_mode_check_symmetric_plots
| o_mode_check_number_of_points
| o_prior_trunc
| o_mh_mode
| o_mh_posterior_mode_estimation
| o_mh_nblocks
| o_load_mh_file
| o_load_results_after_load_mh
@ -2470,15 +2470,23 @@ occbin_setup_option : o_occbin_simul_periods
| o_occbin_simul_maxit
| o_occbin_simul_curb_retrench
| o_occbin_simul_check_ahead_periods
| o_occbin_simul_periodic_solution
| o_occbin_simul_debug
| o_occbin_likelihood_periods
| o_occbin_likelihood_maxit
| o_occbin_likelihood_curb_retrench
| o_occbin_likelihood_check_ahead_periods
| o_occbin_likelihood_periodic_solution
| o_occbin_likelihood_max_kalman_iterations
| o_occbin_likelihood_inversion_filter
| o_occbin_likelihood_piecewise_kalman_filter
| o_occbin_smoother_inversion_filter
| o_occbin_smoother_piecewise_kalman_filter
| o_occbin_smoother_periods
| o_occbin_smoother_maxit
| o_occbin_smoother_curb_retrench
| o_occbin_smoother_check_ahead_periods
| o_occbin_smoother_periodic_solution
| o_occbin_smoother_inversion_filter
| o_occbin_smoother_piecewise_kalman_filter
| o_occbin_smoother_debug
| o_occbin_filter_use_relaxation
;
@ -2499,7 +2507,8 @@ occbin_solver_option : o_occbin_simul_periods
| o_occbin_simul_curb_retrench
| o_occbin_simul_check_ahead_periods
| o_occbin_simul_debug
;
| o_occbin_simul_periodic_solution
;
occbin_write_regimes : OCCBIN_WRITE_REGIMES ';'
{ driver.occbin_write_regimes(); }
@ -2512,6 +2521,8 @@ occbin_write_regimes_options_list : occbin_write_regimes_option COMMA occbin_wri
occbin_write_regimes_option : o_occbin_write_regimes_periods
| o_occbin_write_regimes_filename
| o_occbin_write_regimes_smoother
| o_occbin_write_regimes_simul
;
occbin_graph : OCCBIN_GRAPH ';'
@ -3399,9 +3410,6 @@ o_pac_name : MODEL_NAME EQUAL symbol { driver.option_str("pac.model_name", $3);
o_pac_aux_model_name : AUXILIARY_MODEL_NAME EQUAL symbol { driver.option_str("pac.aux_model_name", $3); };
o_pac_discount : DISCOUNT EQUAL symbol { driver.option_str("pac.discount", $3); };
o_pac_growth : GROWTH { driver.begin_pac_growth(); } EQUAL hand_side { driver.set_pac_growth($4); };
o_pac_steady_state_growth : STEADY_STATE_GROWTH EQUAL signed_number { driver.set_pac_steady_state_growth($3); }
| STEADY_STATE_GROWTH EQUAL symbol { driver.set_pac_steady_state_growth($3); }
;
o_var_name : MODEL_NAME EQUAL symbol { driver.option_str("var.model_name", $3); };
o_series : SERIES EQUAL symbol { driver.option_str("series", $3); };
o_datafile : DATAFILE EQUAL filename { driver.option_str("datafile", $3); };
@ -3549,7 +3557,7 @@ o_mode_check_neighbourhood_size : MODE_CHECK_NEIGHBOURHOOD_SIZE EQUAL signed_num
o_mode_check_number_of_points : MODE_CHECK_NUMBER_OF_POINTS EQUAL INT_NUMBER { driver.option_num("mode_check.number_of_points", $3); };
o_mode_check_symmetric_plots : MODE_CHECK_SYMMETRIC_PLOTS EQUAL INT_NUMBER { driver.option_num("mode_check.symmetric_plots", $3); };
o_prior_trunc : PRIOR_TRUNC EQUAL non_negative_number { driver.option_num("prior_trunc", $3); };
o_mh_mode : MH_MODE EQUAL INT_NUMBER { driver.option_num("mh_mode", $3); };
o_mh_posterior_mode_estimation : MH_POSTERIOR_MODE_ESTIMATION { driver.option_num("mh_posterior_mode_estimation", "true"); };
o_mh_nblocks : MH_NBLOCKS EQUAL INT_NUMBER { driver.option_num("mh_nblck", $3); };
o_load_mh_file : LOAD_MH_FILE { driver.option_num("load_mh_file", "true"); };
o_load_results_after_load_mh : LOAD_RESULTS_AFTER_LOAD_MH { driver.option_num("load_results_after_load_mh", "true"); };
@ -4033,18 +4041,26 @@ o_occbin_simul_periods : SIMUL_PERIODS EQUAL INT_NUMBER { driver.option_num("sim
o_occbin_simul_curb_retrench : SIMUL_CURB_RETRENCH { driver.option_num("simul.curb_retrench", "true"); };
o_occbin_simul_check_ahead_periods : SIMUL_CHECK_AHEAD_PERIODS EQUAL INT_NUMBER { driver.option_num("simul.check_ahead_periods", $3); };
o_occbin_simul_debug : SIMUL_DEBUG { driver.option_num("simul.debug", "true"); };
o_occbin_simul_periodic_solution : SIMUL_PERIODIC_SOLUTION { driver.option_num("simul.periodic_solution", "true"); };
// Some options to "occbin_setup"
o_occbin_likelihood_inversion_filter : LIKELIHOOD_INVERSION_FILTER { driver.option_num("likelihood.inversion_filter", "true"); };
o_occbin_likelihood_piecewise_kalman_filter : LIKELIHOOD_PIECEWISE_KALMAN_FILTER { driver.option_num("likelihood.inversion_filter", "false"); };
o_occbin_likelihood_maxit : LIKELIHOOD_MAXIT EQUAL INT_NUMBER { driver.option_num("likelihood.maxit", $3); };
o_occbin_likelihood_periods : LIKELIHOOD_PERIODS EQUAL INT_NUMBER { driver.option_num("likelihood.periods", $3); };
o_occbin_likelihood_curb_retrench : LIKELIHOOD_CURB_RETRENCH { driver.option_num("likelihood.curb_retrench", "true"); };
o_occbin_likelihood_check_ahead_periods : LIKELIHOOD_CHECK_AHEAD_PERIODS EQUAL INT_NUMBER { driver.option_num("likelihood.check_ahead_periods", $3); };
o_occbin_likelihood_periodic_solution : LIKELIHOOD_PERIODIC_SOLUTION { driver.option_num("likelihood.periodic_solution", "true"); };
o_occbin_likelihood_max_kalman_iterations : LIKELIHOOD_MAX_KALMAN_ITERATIONS EQUAL INT_NUMBER { driver.option_num("likelihood.max_number_of_iterations", $3); };
o_occbin_smoother_inversion_filter : SMOOTHER_INVERSION_FILTER { driver.option_num("smoother.inversion_filter", "true"); };
o_occbin_smoother_piecewise_kalman_filter : SMOOTHER_PIECEWISE_KALMAN_FILTER { driver.option_num("smoother.inversion_filter", "false"); };
o_occbin_filter_use_relaxation : FILTER_USE_RELEXATION { driver.option_num("filter.use_relaxation", "true"); };
o_occbin_smoother_maxit : SMOOTHER_MAXIT EQUAL INT_NUMBER { driver.option_num("smoother.maxit", $3); };
o_occbin_smoother_periods : SMOOTHER_PERIODS EQUAL INT_NUMBER { driver.option_num("smoother.periods", $3); };
o_occbin_smoother_curb_retrench : SMOOTHER_CURB_RETRENCH { driver.option_num("smoother.curb_retrench", "true"); };
o_occbin_smoother_check_ahead_periods : SMOOTHER_CHECK_AHEAD_PERIODS EQUAL INT_NUMBER { driver.option_num("smoother.check_ahead_periods", $3); };
o_occbin_smoother_debug : SMOOTHER_DEBUG { driver.option_num("smoother.debug", "true"); };
o_occbin_smoother_periodic_solution : SMOOTHER_PERIODIC_SOLUTION { driver.option_num("smoother.periodic_solution", "true"); };
o_occbin_filter_use_relaxation : FILTER_USE_RELEXATION { driver.option_num("filter.use_relaxation", "true"); };
// Some options to "occbin_write_regimes"
o_occbin_write_regimes_periods : PERIODS EQUAL vec_int
@ -4052,6 +4068,8 @@ o_occbin_write_regimes_periods : PERIODS EQUAL vec_int
| PERIODS EQUAL vec_int_number
{ driver.option_vec_int("write_regimes.periods", $3); }
o_occbin_write_regimes_filename : FILENAME EQUAL filename { driver.option_str("write_regimes.filename", $3); };
o_occbin_write_regimes_smoother : SMOOTHER { driver.option_str("write_regimes.type", "smoother"); };
o_occbin_write_regimes_simul : SIMUL { driver.option_str("write_regimes.type", "simul"); };
// Some options to "occbin_graph"
o_occbin_graph_noconstant : NOCONSTANT { driver.option_num("graph.steady_state", "false"); };

View File

@ -329,7 +329,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4])
<DYNARE_STATEMENT>mode_check_symmetric_plots {return token::MODE_CHECK_SYMMETRIC_PLOTS;}
<DYNARE_STATEMENT>mode_check_number_of_points {return token::MODE_CHECK_NUMBER_OF_POINTS;}
<DYNARE_STATEMENT>prior_trunc {return token::PRIOR_TRUNC;}
<DYNARE_STATEMENT>mh_mode {return token::MH_MODE;}
<DYNARE_STATEMENT>mh_posterior_mode_estimation {return token::MH_POSTERIOR_MODE_ESTIMATION;}
<DYNARE_STATEMENT>mh_nblocks {return token::MH_NBLOCKS;}
<DYNARE_STATEMENT>load_mh_file {return token::LOAD_MH_FILE;}
<DYNARE_STATEMENT>load_results_after_load_mh {return token::LOAD_RESULTS_AFTER_LOAD_MH;}
@ -565,16 +565,25 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4])
<DYNARE_STATEMENT>max_repeated_optimization_runs {return token::MAX_REPEATED_OPTIMIZATION_RUNS;}
<DYNARE_STATEMENT>maxit {return token::MAXIT;}
<DYNARE_STATEMENT>simul_maxit {return token::SIMUL_MAXIT;}
<DYNARE_STATEMENT>likelihood_maxit {return token::LIKELIHOOD_MAXIT;}
<DYNARE_STATEMENT>smoother_maxit {return token::SMOOTHER_MAXIT;}
<DYNARE_STATEMENT>simul_periods {return token::SIMUL_PERIODS;}
<DYNARE_STATEMENT>likelihood_periods {return token::LIKELIHOOD_PERIODS;}
<DYNARE_STATEMENT>smoother_periods {return token::SMOOTHER_PERIODS;}
<DYNARE_STATEMENT>simul_curb_retrench {return token::SIMUL_CURB_RETRENCH;}
<DYNARE_STATEMENT>likelihood_curb_retrench {return token::LIKELIHOOD_CURB_RETRENCH;}
<DYNARE_STATEMENT>smoother_curb_retrench {return token::SMOOTHER_CURB_RETRENCH;}
<DYNARE_STATEMENT>simul_check_ahead_periods {return token::SIMUL_CHECK_AHEAD_PERIODS;}
<DYNARE_STATEMENT>likelihood_check_ahead_periods {return token::LIKELIHOOD_CHECK_AHEAD_PERIODS;}
<DYNARE_STATEMENT>smoother_check_ahead_periods {return token::SMOOTHER_CHECK_AHEAD_PERIODS;}
<DYNARE_STATEMENT>simul_debug {return token::SIMUL_DEBUG;}
<DYNARE_STATEMENT>smoother_debug {return token::SMOOTHER_DEBUG;}
<DYNARE_STATEMENT>simul_periodic_solution {return token::SIMUL_PERIODIC_SOLUTION;}
<DYNARE_STATEMENT>likelihood_periodic_solution {return token::LIKELIHOOD_PERIODIC_SOLUTION;}
<DYNARE_STATEMENT>smoother_periodic_solution {return token::SMOOTHER_PERIODIC_SOLUTION;}
<DYNARE_STATEMENT>likelihood_inversion_filter {return token::LIKELIHOOD_INVERSION_FILTER;}
<DYNARE_STATEMENT>likelihood_piecewise_kalman_filter {return token::LIKELIHOOD_PIECEWISE_KALMAN_FILTER;}
<DYNARE_STATEMENT>likelihood_max_kalman_iterations {return token::LIKELIHOOD_MAX_KALMAN_ITERATIONS;}
<DYNARE_STATEMENT>smoother_inversion_filter {return token::SMOOTHER_INVERSION_FILTER;}
<DYNARE_STATEMENT>smoother_piecewise_kalman_filter {return token::SMOOTHER_PIECEWISE_KALMAN_FILTER;}
<DYNARE_STATEMENT>filter_use_relaxation {return token::FILTER_USE_RELEXATION;}
@ -924,7 +933,6 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4])
<DYNARE_BLOCK>var_expectation {return token::VAR_EXPECTATION;}
<DYNARE_BLOCK>pac_expectation {return token::PAC_EXPECTATION;}
<DYNARE_STATEMENT>discount {return token::DISCOUNT;}
<DYNARE_STATEMENT>steady_state_growth {return token::STEADY_STATE_GROWTH;}
<DYNARE_STATEMENT,DYNARE_BLOCK>varobs {return token::VAROBS;}
<DYNARE_STATEMENT,DYNARE_BLOCK>varexobs {return token::VAREXOBS;}
<DYNARE_STATEMENT,DYNARE_BLOCK>nan {return token::NAN_CONSTANT;}

View File

@ -4475,15 +4475,25 @@ BinaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
case BinaryOpcode::times:
if (isLatexOutput(output_type))
output << R"(\, )";
else if (output_type == ExprNodeOutputType::occbinDifferenceFile)
output << ".*"; // This file operates on vectors, see dynare#1826
else
output << "*";
break;
case BinaryOpcode::divide:
if (!isLatexOutput(output_type))
output << "/";
{
if (output_type == ExprNodeOutputType::occbinDifferenceFile)
output << "./"; // This file operates on vectors, see dynare#1826
else
output << "/";
}
break;
case BinaryOpcode::power:
output << "^";
if (output_type == ExprNodeOutputType::occbinDifferenceFile)
output << ".^"; // This file operates on vectors, see dynare#1826
else
output << "^";
break;
case BinaryOpcode::less:
output << "<";
@ -5469,10 +5479,13 @@ BinaryOpNode::findConstantEquations(map<VariableNode *, NumConstNode *> &table)
{
if (op_code == BinaryOpcode::equal)
{
if (dynamic_cast<VariableNode *>(arg1) && dynamic_cast<NumConstNode *>(arg2))
table[dynamic_cast<VariableNode *>(arg1)] = dynamic_cast<NumConstNode *>(arg2);
else if (dynamic_cast<VariableNode *>(arg2) && dynamic_cast<NumConstNode *>(arg1))
table[dynamic_cast<VariableNode *>(arg2)] = dynamic_cast<NumConstNode *>(arg1);
// The variable must be contemporaneous (see #83)
if (auto varg1 = dynamic_cast<VariableNode *>(arg1);
varg1 && varg1->lag == 0 && dynamic_cast<NumConstNode *>(arg2))
table[varg1] = dynamic_cast<NumConstNode *>(arg2);
else if (auto varg2 = dynamic_cast<VariableNode *>(arg2);
varg2 && varg2->lag == 0 && dynamic_cast<NumConstNode *>(arg1))
table[varg2] = dynamic_cast<NumConstNode *>(arg1);
}
}

View File

@ -50,10 +50,22 @@ macroExpandModFile(const string &filename, const string &basename, const istream
string str(macro_output.str());
if (!line_macro)
{
str = regex_replace(str, regex(R"((^|\n)\s*@#line.*)"), "");
auto compareNewline = [](char i, char j) { return i == '\n' && j == '\n'; };
str.erase(0, str.find_first_not_of('\n'));
str.erase(unique(str.begin(), str.end(), compareNewline), str.end());
/* Remove the @#line directives.
Unfortunately GCC 11 does not yet support std::regex::multiline
(despite it being in the C++17 standard), so we are forced to use
a trick to emulate the usual behaviour of the caret ^;
here, the latter only matches the beginning of file.
This also means that we are forced to remove the EOL before the
@#line, and not the one after it (matching the EOL before and the
EOL after in the same regexp does not work). */
str = regex_replace(str, regex(R"((^|\r?\n)@#line.*)"), "");
/* Remove the EOLs at the beginning of the output, the first one
being a remnant of the first @#line directive. */
str = regex_replace(str, regex(R"(^(\r?\n)+)"), "");
/* Replace sequences of several newlines by a single newline (in
both LF and CR+LF conventions). */
str = regex_replace(str, regex(R"(\n{2,})"), "\n");
str = regex_replace(str, regex(R"((\r\n){2,})"), "\r\n");
}
macro_output_file << str;
macro_output_file.close();

View File

@ -484,10 +484,14 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, bool
cerr << "Error: aux_model_name not recognized as VAR model or Trend Component model" << endl;
exit(EXIT_FAILURE);
}
if (pms->growth)
dynamic_model.createPacGrowthNeutralityParameter(pms->name);
auto eqtag_and_lag = dynamic_model.walkPacParameters(pms->name);
if (pms->aux_model_name.empty())
dynamic_model.addPacModelConsistentExpectationEquation(pms->name, symbol_table.getID(pms->discount),
eqtag_and_lag, diff_subst_table);
eqtag_and_lag, diff_subst_table,
pms->growth);
else
dynamic_model.fillPacModelInfo(pms->name, lhs, max_lag, aux_model_type,
eqtag_and_lag, nonstationary, pms->growth);

View File

@ -1566,9 +1566,6 @@ ModelTree::includeExcludeEquations(set<pair<string, string>> &eqs, bool exclude_
else
++it;
if (tag_eqns.empty())
return excluded_vars;
set<int> eqns;
if (exclude_eqs)
eqns = tag_eqns;
@ -1594,7 +1591,7 @@ ModelTree::includeExcludeEquations(set<pair<string, string>> &eqs, bool exclude_
excluded_vars.push_back(result.begin()->first);
else
{
cerr << "ERROR: Equation " << i
cerr << "ERROR: Equation " << i+1
<< " has been excluded but does not have a single variable on LHS or `endogenous` tag" << endl;
exit(EXIT_FAILURE);
}
@ -1895,6 +1892,36 @@ ModelTree::matlab_arch(const string &mexext)
}
}
#ifdef __APPLE__
string
ModelTree::findGccOnMacos()
{
const string macos_gcc_version{"11"}; // doc/manual/source/installation-and-configuration.rst
// should be updated when this is changed
char dynare_preprocessor_path[PATH_MAX];
uint32_t size = PATH_MAX;
string local_gcc_path;
if (_NSGetExecutablePath(dynare_preprocessor_path, &size) == 0)
{
string s = dynare_preprocessor_path;
local_gcc_path = s.substr(0, s.find_last_of("/")) + "/../.brew/bin/gcc-" + macos_gcc_version;
}
if (filesystem::exists(local_gcc_path))
return local_gcc_path;
else if (string global_gcc_path = "/usr/local/bin/gcc-" + macos_gcc_version;
filesystem::exists(global_gcc_path))
return global_gcc_path;
else
{
cerr << "ERROR: You must install gcc-" << macos_gcc_version
<< " on your system before using the `use_dll` option of Dynare. "
<< "If using MATLAB, you can do this via the Dynare installation package. If using Octave, you should run `brew install gcc-" << macos_gcc_version << "` in a terminal." << endl;
exit(EXIT_FAILURE);
}
}
#endif
void
ModelTree::compileMEX(const string &basename, const string &funcname, const string &mexext, const vector<filesystem::path> &src_files, const filesystem::path &matlabroot, const filesystem::path &dynareroot) const
{
@ -1915,6 +1942,22 @@ ModelTree::compileMEX(const string &basename, const string &funcname, const stri
// Octave
compiler = matlabroot / "bin" / "mkoctfile";
flags << "--mex";
#ifdef __APPLE__
/* On macOS, enforce GCC, otherwise Clang will be used, and it does not
accept our custom optimization flags (see dynare#1797) */
string gcc_path = findGccOnMacos();
if (setenv("CC", gcc_path.c_str(), 1) != 0)
{
cerr << "Can't set CC environment variable" << endl;
exit(EXIT_FAILURE);
}
// We also define CXX, because that is used for linking
if (setenv("CXX", gcc_path.c_str(), 1) != 0)
{
cerr << "Can't set CXX environment variable" << endl;
exit(EXIT_FAILURE);
}
#endif
}
else
{
@ -1941,6 +1984,9 @@ ModelTree::compileMEX(const string &basename, const string &funcname, const stri
// Put the MinGW environment shipped with Dynare in the path
auto mingwpath = dynareroot / "mingw64" / "bin";
string newpath = "PATH=" + mingwpath.string() + ';' + string{getenv("PATH")};
/* We cant use setenv() since it is not available on MinGW. Note
that putenv() seems to make a copy of the string on MinGW, contrary
to what is done on GNU/Linux and macOS. */
if (putenv(const_cast<char *>(newpath.c_str())) != 0)
{
cerr << "Can't set PATH" << endl;
@ -1950,26 +1996,7 @@ ModelTree::compileMEX(const string &basename, const string &funcname, const stri
#ifdef __APPLE__
else if (mexext == "mexmaci64")
{
// macOS
char dynare_m_path[PATH_MAX];
uint32_t size = PATH_MAX;
string gcc_relative_path;
if (_NSGetExecutablePath(dynare_m_path, &size) == 0)
{
string str = dynare_m_path;
gcc_relative_path = str.substr(0, str.find_last_of("/")) + "/../.brew/bin/gcc-11";
}
if (filesystem::exists(gcc_relative_path))
compiler = gcc_relative_path;
else if (filesystem::exists("/usr/local/bin/gcc-11"))
compiler = "/usr/local/bin/gcc-11";
else
{
cerr << "ERROR: You must install gcc-11 on your system before using the `use_dll` option of Dynare. "
<< "You can do this via the Dynare installation package." << endl;
exit(EXIT_FAILURE);
}
compiler = findGccOnMacos();
flags << " -fno-common -Wl,-twolevel_namespace -undefined error -bundle";
libs += " -lm";
}

View File

@ -398,6 +398,10 @@ private:
void copyHelper(const ModelTree &m);
//! Returns the name of the MATLAB architecture given the extension used for MEX files
static string matlab_arch(const string &mexext);
#ifdef __APPLE__
//! Finds a suitable GCC compiler on macOS
static string findGccOnMacos();
#endif
//! Compiles a MEX file
void compileMEX(const string &basename, const string &funcname, const string &mexext, const vector<filesystem::path> &src_files, const filesystem::path &matlabroot, const filesystem::path &dynareroot) const;

View File

@ -132,6 +132,9 @@ InitOrEndValStatement::writeInitValues(ostream &output) const
{
for (auto [symb_id, value] : init_values)
{
if (symbol_table.getType(symb_id) == SymbolType::unusedEndogenous) // See #82
continue;
SymbolType type = symbol_table.getType(symb_id);
int tsid = symbol_table.getTypeSpecificID(symb_id) + 1;
@ -167,9 +170,11 @@ InitOrEndValStatement::writeJsonInitValues(ostream &output) const
for (auto it = init_values.begin();
it != init_values.end(); ++it)
{
auto [symb_id, value] = *it;
if (symbol_table.getType(symb_id) == SymbolType::unusedEndogenous) // See #82
continue;
if (it != init_values.begin())
output << ", ";
auto [symb_id, value] = *it;
output << R"({"name": ")" << symbol_table.getName(symb_id) << R"(", )" << R"("value": ")";
value->writeJsonOutput(output, {}, {});
output << R"("})";
@ -363,6 +368,8 @@ HistValStatement::writeOutput(ostream &output, const string &basename, bool mini
for (const auto &[key, value] : hist_values)
{
auto [symb_id, lag] = key;
if (symbol_table.getType(symb_id) == SymbolType::unusedEndogenous) // See #82
continue;
output << "M_.histval_dseries{'" << symbol_table.getName(symb_id) << "'}(dates('" << lag << "Y'))=";
value->writeOutput(output);
@ -389,6 +396,8 @@ HistValStatement::writeJsonOutput(ostream &output) const
it != hist_values.end(); ++it)
{
auto [symb_id, lag] = it->first;
if (symbol_table.getType(symb_id) == SymbolType::unusedEndogenous) // See #82
continue;
if (it != hist_values.begin())
output << ", ";
output << R"({ "name": ")" << symbol_table.getName(symb_id) << R"(")"

View File

@ -321,8 +321,9 @@ ParsingDriver::add_model_variable(const string &name)
}
catch (SymbolTable::UnknownSymbolNameException &e)
{
// Declare variable as exogenous to continue parsing
// processing will end at end of model block if nostrict option was not passed
/* Declare variable as exogenous to continue parsing. Processing will end
at end of model block (or planner_objective statement) if nostrict
option was not passed. */
declare_exogenous(name);
undeclared_model_vars.insert(name);
symb_id = mod_file->symbol_table.getID(name);
@ -785,6 +786,7 @@ ParsingDriver::end_model()
exit_after_write = true;
cerr << it.second << endl;
}
undeclared_model_variable_errors.clear();
if (exit_after_write)
exit(EXIT_FAILURE);
@ -2022,6 +2024,21 @@ ParsingDriver::end_planner_objective(expr_t expr)
mod_file->addStatement(make_unique<PlannerObjectiveStatement>(*planner_objective));
// Handle undeclared variables (see #81)
bool exit_after_write = false;
if (undeclared_model_variable_errors.size() > 0)
for (auto &it : undeclared_model_variable_errors)
if (nostrict)
warning(it.second);
else
{
exit_after_write = true;
cerr << it.second << endl;
}
undeclared_model_variable_errors.clear();
if (exit_after_write)
exit(EXIT_FAILURE);
reset_data_tree();
}
@ -2038,6 +2055,12 @@ ParsingDriver::ramsey_model()
else if (planner_discount)
error("ramsey_model: the 'planner_discount' option cannot be used when the 'optimal_policy_discount_factor' parameter is explicitly declared.");
// Check that instruments are declared endogenous (#72)
if (auto it = options_list.symbol_list_options.find("instruments");
it != options_list.symbol_list_options.end())
for (const auto &s : it->second.getSymbols())
check_symbol_is_endogenous(s);
mod_file->addStatement(make_unique<RamseyModelStatement>(options_list));
options_list.clear();
planner_discount = nullptr;
@ -2059,6 +2082,12 @@ ParsingDriver::ramsey_policy()
else if (planner_discount)
error("ramsey_policy: the 'planner_discount' option cannot be used when the 'optimal_policy_discount_factor' parameter is explicitly declared.");
// Check that instruments are declared endogenous (#72)
if (auto it = options_list.symbol_list_options.find("instruments");
it != options_list.symbol_list_options.end())
for (const auto &s : it->second.getSymbols())
check_symbol_is_endogenous(s);
mod_file->addStatement(make_unique<RamseyPolicyStatement>(mod_file->symbol_table,
symbol_list, options_list));
options_list.clear();
@ -2114,6 +2143,12 @@ ParsingDriver::discretionary_policy()
planner_discount = data_tree->One;
init_param("optimal_policy_discount_factor", planner_discount);
// Check that instruments are declared endogenous (#72)
if (auto it = options_list.symbol_list_options.find("instruments");
it != options_list.symbol_list_options.end())
for (const auto &s : it->second.getSymbols())
check_symbol_is_endogenous(s);
mod_file->addStatement(make_unique<DiscretionaryPolicyStatement>(symbol_list, options_list));
symbol_list.clear();
options_list.clear();
@ -2562,12 +2597,12 @@ ParsingDriver::add_var_expectation(const string &model_name)
}
expr_t
ParsingDriver::add_pac_expectation(const string &var_model_name)
ParsingDriver::add_pac_expectation(const string &model_name)
{
if (data_tree == occbin_constraints_tree.get())
error("The 'var_expectation' operator is forbidden in 'occbin_constraints'.");
error("The 'pac_expectation' operator is forbidden in 'occbin_constraints'.");
return data_tree->AddPacExpectation(var_model_name);
return data_tree->AddPacExpectation(model_name);
}
void
@ -2581,8 +2616,6 @@ ParsingDriver::begin_pac_model()
{
parsing_pac_model = true;
pac_growth = nullptr;
pac_steady_state_growth_rate_number = -1;
pac_steady_state_growth_rate_symb_id = -1;
options_list.clear();
}
@ -2594,53 +2627,19 @@ ParsingDriver::pac_model()
error("You must pass the model_name option to the pac_model statement.");
auto name = it->second;
bool pac_growth_is_param = false;
if (pac_growth && dynamic_cast<VariableNode *>(pac_growth))
{
set<int> params;
pac_growth->collectVariables(SymbolType::parameter, params);
if (params.size() == 1)
pac_growth_is_param = true;
pac_growth->collectVariables(SymbolType::endogenous, params);
pac_growth->collectVariables(SymbolType::exogenous, params);
if (params.size() != 1)
pac_growth_is_param = false;
}
string aux_model_name;
it = options_list.string_options.find("pac.aux_model_name");
if (it != options_list.string_options.end())
{
aux_model_name = it->second;
if (pac_steady_state_growth_rate_number >= 0 || pac_steady_state_growth_rate_symb_id >= 0)
{
pac_steady_state_growth_rate_number = -1;
pac_steady_state_growth_rate_symb_id = -1;
warning("when aux_model_name is used in the pac_model statement, steady_state_growth is ignored");
}
}
else
if (pac_growth_is_param
&& (pac_steady_state_growth_rate_number >= 0 || pac_steady_state_growth_rate_symb_id >= 0))
warning("If growth option is constant, steady_state_growth is ignored");
else if (pac_growth && !pac_growth_is_param
&& pac_steady_state_growth_rate_number < 0
&& pac_steady_state_growth_rate_symb_id < 0)
error("The steady state growth rate of the target must be provided (steady_state_growth option) if option growth is not constant");
if (pac_steady_state_growth_rate_symb_id >= 0
&& mod_file->symbol_table.getType(pac_steady_state_growth_rate_symb_id) != SymbolType::parameter)
error("pac_model: steady_state_growth accepts either a number or a parameter");
aux_model_name = it->second;
it = options_list.string_options.find("pac.discount");
if (it == options_list.string_options.end())
error("You must pass the discount option to the pac_model statement.");
auto discount = it->second;
check_symbol_is_parameter(discount);
mod_file->addStatement(make_unique<PacModelStatement>(name, aux_model_name, discount,
pac_growth,
pac_steady_state_growth_rate_number,
pac_steady_state_growth_rate_symb_id,
mod_file->symbol_table));
parsing_pac_model = false;
}
@ -2652,21 +2651,6 @@ ParsingDriver::set_pac_growth(expr_t pac_growth_arg)
reset_data_tree();
}
void
ParsingDriver::set_pac_steady_state_growth(const string &name_or_number)
{
try
{
pac_steady_state_growth_rate_number = stod(name_or_number);
}
catch (...)
{
if (!mod_file->symbol_table.exists(name_or_number))
error("Unknown symbol used in pac_steady_state_growth option: " + name_or_number + "\n");
pac_steady_state_growth_rate_symb_id = mod_file->symbol_table.getID(name_or_number);
}
}
expr_t
ParsingDriver::add_exp(expr_t arg1)
{

View File

@ -75,7 +75,7 @@ public:
string filename;
//! Increment the location counter given a token
void location_increment(Dynare::parser::location_type *yylloc, const char *yytext);
static void location_increment(Dynare::parser::location_type *yylloc, const char *yytext);
//! Count parens in dates statement
int dates_parens_nb;
@ -257,8 +257,6 @@ private:
//! Temporary storage for growth declared in pac_model
expr_t pac_growth;
double pac_steady_state_growth_rate_number = -1;
int pac_steady_state_growth_rate_symb_id = -1;
bool nostrict;
@ -740,15 +738,13 @@ public:
//! Writes token "VAR_EXPECTATION(model_name)" to model tree
expr_t add_var_expectation(const string &model_name);
//! Writes token "PAC_EXPECTATION(model_name, discount, growth)" to model tree
expr_t add_pac_expectation(const string &var_model_name);
expr_t add_pac_expectation(const string &model_name);
//! Creates pac_model statement
void begin_pac_growth();
void begin_pac_model();
void pac_model();
//! Adds growth for pac
void set_pac_growth(expr_t pac_growth_arg);
//! Adds steady state growth for pac
void set_pac_steady_state_growth(const string &name_or_number);
//! Writes token "diff(arg1)" to model tree
expr_t add_diff(expr_t arg1);
//! Writes token "adl(arg1, lag)" to model tree

View File

@ -1,5 +1,5 @@
/*
* Copyright © 2019-2020 Dynare Team
* Copyright © 2019-2021 Dynare Team
*
* This file is part of Dynare.
*
@ -56,6 +56,7 @@ namespace macro
Tokenizer::parser::token_type lex(Tokenizer::parser::semantic_type *yylval,
Tokenizer::parser::location_type *yylloc,
macro::Driver &driver);
static void location_increment(Tokenizer::parser::location_type *yylloc, const char *yytext);
};
//! Implements the macro expansion using a Flex scanner and a Bison parser

View File

@ -1,6 +1,6 @@
// -*- C++ -*-
/*
* Copyright © 2019-2020 Dynare Team
* Copyright © 2019-2021 Dynare Team
*
* This file is part of Dynare.
*
@ -89,7 +89,8 @@ using namespace macro;
%precedence CAST
%nonassoc POWER
%token <string> NAME TEXT QUOTED_STRING NUMBER EOL
%token EOL
%token <string> NAME TEXT QUOTED_STRING NUMBER
%type <DirectivePtr> statement
%type <DirectivePtr> directive directive_one_line directive_multiline for if ifdef ifndef text eval
@ -284,7 +285,7 @@ else : else_begin EOL
text : TEXT
{ $$ = make_shared<TextNode>($1, @$); }
| EOL
{ $$ = make_shared<TextNode>($1, @$); }
{ $$ = make_shared<TextNode>("\n", @$); }
;
eval : BEGIN_EVAL expr END_EVAL

View File

@ -1,6 +1,6 @@
/* -*- C++ -*- */
/*
* Copyright © 2019 Dynare Team
* Copyright © 2019-2021 Dynare Team
*
* This file is part of Dynare.
*
@ -50,7 +50,7 @@ using token = Tokenizer::parser::token;
%{
// Increments location counter for every token read
# define YY_USER_ACTION yylloc->columns(yyleng);
#define YY_USER_ACTION location_increment(yylloc, yytext);
%}
SPC [ \t]+
@ -175,24 +175,15 @@ CONT \\\\{SPC}*
}
<expr,eval>{SPC}+ { }
<eval>{EOL}+ { yylloc->lines(yyleng); yylloc->lines(yyleng); }
<eval>{EOL}+ { }
<eval>\} { BEGIN(INITIAL); return token::END_EVAL; }
<expr,end_line>{CONT}("//".*)?{SPC}*{EOL} { yylloc->lines(1); yylloc->step(); }
<expr,end_line>{SPC}*("//".*)?{EOL} {
yylval->build<string>("\n");
yylloc->lines(1);
BEGIN(INITIAL);
return token::EOL;
}
<expr,end_line>{CONT}("//".*)?{SPC}*{EOL} { yylloc->step(); }
<expr,end_line>{SPC}*("//".*)?{EOL} { BEGIN(INITIAL); return token::EOL; }
<INITIAL>^{SPC}*@#{SPC}* { BEGIN(directive); }
<INITIAL>@\{ { BEGIN(eval); return token::BEGIN_EVAL; }
<INITIAL>{SPC}*{EOL} {
yylval->build<string>(yytext);
yylloc->lines(1);
return token::EOL;
}
<INITIAL>{EOL} { return token::EOL; }
<INITIAL><<EOF>> { yyterminate(); }
<directive,expr,eval,end_line><<EOF>> { driver.error(*yylloc, "unexpected end of file"); }
@ -202,6 +193,16 @@ CONT \\\\{SPC}*
%%
void
TokenizerFlex::location_increment(Tokenizer::parser::location_type *yylloc, const char *yytext)
{
while (*yytext != 0)
if (*yytext++ == '\n')
yylloc->lines(1);
else
yylloc->columns(1);
}
/* This implementation of TokenizerFlexLexer::yylex() is required to fill the
* vtable of the class TokenizerFlexLexer. We define the scanner's main yylex
* function via YY_DECL to reside in the TokenizerFlex class instead. */