Commit 0c16f528 authored by sebastien's avatar sebastien
Browse files

v4 parser:

* reshaped DataTree/ModelTree using a more object-oriented approach
* improved expression sharing algorithm (temporary terms in output files), resulting in smaller output files for big models
* optimized performance (both in computing time and memory consumption)
* bugfix: the expressions stored in local parameters of models (pound expressions) are now derived
* bugfix: cosh(0) = 1
* removed some useless parentheses in output


git-svn-id: https://www.dynare.org/svn/dynare/dynare_v4@1148 ac1d8469-bf42-47a9-8791-bf33cf982152
parent 7417d180
/*! \file
\version 1.0
\date 04/09/2004
\par This file implements the DataTree class methodes.
*/
//------------------------------------------------------------------------------
#include <iostream> #include <iostream>
#include <string>
#include <vector>
#include <map>
using namespace std;
#include <time.h>
//------------------------------------------------------------------------------
#include "DynareBison.hh"
#include "VariableTable.hh"
#include "NumericalConstants.hh"
#include "DataTree.hh" #include "DataTree.hh"
DataTree::DataTree(SymbolTable &symbol_table_arg) : DataTree::DataTree(SymbolTable &symbol_table_arg, NumericalConstants &num_constants_arg) :
symbol_table(symbol_table_arg), symbol_table(symbol_table_arg),
num_constants(num_constants_arg),
variable_table(symbol_table_arg), variable_table(symbol_table_arg),
NoOpCode(-1), NullID(NULL) offset(1)
{ {
offset = 1; Zero = AddNumConstant("0.0");
current_order = 0; One = AddNumConstant("1.0");
Zero = new MetaToken(reinterpret_cast <NodeID> (0), eNumericalConstant, NULL, -1); MinusOne = AddUMinus(One);
Zero->op_name = ""; }
Zero->reference_count.resize(current_order+1,2);
Zero->idx = 0;
mModelTree.push_back(Zero);
mIndexOfTokens[*Zero]=Zero;
One = new MetaToken(reinterpret_cast <NodeID> (1), eNumericalConstant, NULL, -1); One->op_name = "";
One->op_name = "";
One->reference_count.resize(current_order+1,1);
One->idx = 1;
mModelTree.push_back(One);
mIndexOfTokens[*One]=One;
MinusOne = new MetaToken(One, eTempResult, NULL, token::UMINUS);
MinusOne->op_name = OperatorTable::str(token::UMINUS);
MinusOne->reference_count.resize(current_order+1,1);
MinusOne->idx = 2;
mModelTree.push_back(MinusOne);
mIndexOfTokens[*MinusOne]=MinusOne;
// Pushing "0=0" into mModelTree
ZeroEqZero = new MetaToken(Zero, eTempResult, Zero, token::EQUAL);
ZeroEqZero->op_name = OperatorTable::str(token::EQUAL);
ZeroEqZero->reference_count.resize(current_order+1,1);
ZeroEqZero->idx = 3;
mModelTree.push_back(ZeroEqZero);
mIndexOfTokens[*ZeroEqZero]=ZeroEqZero;
// Initialise global node counter
nodeCounter = 4;
BeginModel = mModelTree.end();
BeginModel--;
}
//------------------------------------------------------------------------------
DataTree::~DataTree() DataTree::~DataTree()
{ {
for (TreeIterator it = mModelTree.begin(); it != mModelTree.end(); it++) for (node_list_type::iterator it = node_list.begin(); it != node_list.end(); it++)
delete *it;
}
NodeID
DataTree::AddNumConstant(const string &value)
{
int id = num_constants.AddConstant(value);
num_const_node_map_type::iterator it = num_const_node_map.find(id);
if (it != num_const_node_map.end())
return it->second;
else
return new NumConstNode(*this, id);
}
NodeID
DataTree::AddVariable(const string &name, int lag)
{
if (!symbol_table.Exist(name))
{
cerr << "Unknown symbol: " << name << endl;
exit(-1);
}
symbol_table.SetReferenced(name);
Type type = symbol_table.getType(name);
int id;
if (type == eEndogenous
|| type == eExogenousDet
|| type == eExogenous
|| type == eRecursiveVariable)
id = variable_table.AddVariable(name, lag);
else
id = symbol_table.getID(name);
variable_node_map_type::iterator it = variable_node_map.find(make_pair(id, type));
if (it != variable_node_map.end())
return it->second;
else
return new VariableNode(*this, id, type);
}
NodeID
DataTree::AddPlus(NodeID iArg1, NodeID iArg2)
{
if (iArg1 != Zero && iArg2 != Zero)
{
// Simplify x+(-y) in x-y
UnaryOpNode *uarg2 = dynamic_cast<UnaryOpNode *>(iArg2);
if (uarg2 != NULL && uarg2->op_code == oUminus)
return AddMinus(iArg1, uarg2->arg);
// To treat commutativity of "+"
// Nodes iArg1 and iArg2 are sorted by index
if (iArg1->idx > iArg2->idx)
{
NodeID tmp = iArg1;
iArg1 = iArg2;
iArg2 = tmp;
}
return AddBinaryOp(iArg1, oPlus, iArg2);
}
else if (iArg1 != Zero)
return iArg1;
else if (iArg2 != Zero)
return iArg2;
else
return Zero;
}
NodeID
DataTree::AddMinus(NodeID iArg1, NodeID iArg2)
{
if (iArg1 != Zero && iArg2 != Zero)
return AddBinaryOp(iArg1, oMinus, iArg2);
else if (iArg1 != Zero)
return iArg1;
else if (iArg2 != Zero)
return AddUMinus(iArg2);
else
return Zero;
}
NodeID
DataTree::AddUMinus(NodeID iArg1)
{
if (iArg1 != Zero)
{
// Simplify -(-x) in x
UnaryOpNode *uarg = dynamic_cast<UnaryOpNode *>(iArg1);
if (uarg != NULL && uarg->op_code == oUminus)
return uarg->arg;
return AddUnaryOp(oUminus, iArg1);
}
else
return Zero;
}
NodeID
DataTree::AddTimes(NodeID iArg1, NodeID iArg2)
{
if (iArg1 == MinusOne)
return AddUMinus(iArg2);
else if (iArg2 == MinusOne)
return AddUMinus(iArg1);
else if (iArg1 != Zero && iArg1 != One && iArg2 != Zero && iArg2 != One)
{
// To treat commutativity of "*"
// Nodes iArg1 and iArg2 are sorted by index
if (iArg1->idx > iArg2->idx)
{
NodeID tmp = iArg1;
iArg1 = iArg2;
iArg2 = tmp;
}
return AddBinaryOp(iArg1, oTimes, iArg2);
}
else if (iArg1 != Zero && iArg1 != One && iArg2 == One)
return iArg1;
else if (iArg2 != Zero && iArg2 != One && iArg1 == One)
return iArg2;
else if (iArg2 == One && iArg1 == One)
return One;
else
return Zero;
}
NodeID
DataTree::AddDivide(NodeID iArg1, NodeID iArg2)
{
if (iArg1 != Zero && iArg2 != Zero && iArg2 != One)
return AddBinaryOp(iArg1, oDivide, iArg2);
else if (iArg2 == One)
return iArg1;
else if (iArg1 == Zero && iArg2 != Zero)
return Zero;
else
{ {
if (*it != NullID) delete *it; cerr << "Division by zero!" << endl;
exit(-1);
} }
} }
NodeID
DataTree::AddPower(NodeID iArg1, NodeID iArg2)
{
if (iArg1 != Zero && iArg2 != Zero && iArg2 != One)
return AddBinaryOp(iArg1, oPower, iArg2);
else if (iArg2 == One)
return iArg1;
else if (iArg2 == Zero)
return One;
else
return Zero;
}
NodeID
DataTree::AddExp(NodeID iArg1)
{
if (iArg1 != Zero)
return AddUnaryOp(oExp, iArg1);
else
return One;
}
NodeID
DataTree::AddLog(NodeID iArg1)
{
if (iArg1 != Zero && iArg1 != One)
return AddUnaryOp(oLog, iArg1);
else if (iArg1 == One)
return Zero;
else
{
cerr << "log(0) isn't available" << endl;
exit(-1);
}
}
NodeID DataTree::AddLog10(NodeID iArg1)
{
if (iArg1 != Zero && iArg1 != One)
return AddUnaryOp(oLog10, iArg1);
else if (iArg1 == One)
return Zero;
else
{
cerr << "log10(0) isn't available" << endl;
exit(-1);
}
}
NodeID
DataTree::AddCos(NodeID iArg1)
{
if (iArg1 != Zero)
return AddUnaryOp(oCos, iArg1);
else
return One;
}
NodeID
DataTree::AddSin(NodeID iArg1)
{
if (iArg1 != Zero)
return AddUnaryOp(oSin, iArg1);
else
return Zero;
}
NodeID
DataTree::AddTan(NodeID iArg1)
{
if (iArg1 != Zero)
return AddUnaryOp(oTan, iArg1);
else
return Zero;
}
NodeID
DataTree::AddACos(NodeID iArg1)
{
if (iArg1 != One)
return AddUnaryOp(oAcos, iArg1);
else
return Zero;
}
NodeID
DataTree::AddASin(NodeID iArg1)
{
if (iArg1 != Zero)
return AddUnaryOp(oAsin, iArg1);
else
return Zero;
}
NodeID
DataTree::AddATan(NodeID iArg1)
{
if (iArg1 != Zero)
return AddUnaryOp(oAtan, iArg1);
else
return Zero;
}
NodeID
DataTree::AddCosH(NodeID iArg1)
{
if (iArg1 != Zero)
return AddUnaryOp(oCosh, iArg1);
else
return One;
}
NodeID
DataTree::AddSinH(NodeID iArg1)
{
if (iArg1 != Zero)
return AddUnaryOp(oSinh, iArg1);
else
return Zero;
}
NodeID
DataTree::AddTanH(NodeID iArg1)
{
if (iArg1 != Zero)
return AddUnaryOp(oTanh, iArg1);
else
return Zero;
}
NodeID
DataTree::AddACosH(NodeID iArg1)
{
if (iArg1 != One)
return AddUnaryOp(oAcosh, iArg1);
else
return Zero;
}
NodeID
DataTree::AddASinH(NodeID iArg1)
{
if (iArg1 != Zero)
return AddUnaryOp(oAsinh, iArg1);
else
return Zero;
}
NodeID
DataTree::AddATanH(NodeID iArg1)
{
if (iArg1 != Zero)
return AddUnaryOp(oAtanh, iArg1);
else
return Zero;
}
NodeID
DataTree::AddSqRt(NodeID iArg1)
{
if (iArg1 != Zero)
return AddUnaryOp(oSqrt, iArg1);
else
return Zero;
}
NodeID
DataTree::AddEqual(NodeID iArg1, NodeID iArg2)
{
return AddBinaryOp(iArg1, oEqual, iArg2);
}
void
DataTree::AddLocalParameter(const string &name, NodeID value) throw (LocalParameterException)
{
int id = symbol_table.getID(name);
// Throw an exception if symbol already declared
map<int, NodeID>::iterator it = local_parameters_table.find(id);
if (it != local_parameters_table.end())
throw LocalParameterException(name);
local_parameters_table[id] = value;
}
...@@ -8,7 +8,7 @@ using namespace std; ...@@ -8,7 +8,7 @@ using namespace std;
class ParsingDriver; class ParsingDriver;
#include "SymbolTableTypes.hh" #include "SymbolTableTypes.hh"
#include "ModelTypes.hh" #include "ExprNode.hh"
//! Type for semantic value of non-derivable expressions //! Type for semantic value of non-derivable expressions
typedef pair<int, Type> ExpObj; typedef pair<int, Type> ExpObj;
...@@ -74,9 +74,6 @@ typedef pair<int, Type> ExpObj; ...@@ -74,9 +74,6 @@ typedef pair<int, Type> ExpObj;
%left UMINUS %left UMINUS
%nonassoc POWER %nonassoc POWER
%token EXP LOG LOG10 SIN COS TAN ASIN ACOS ATAN SINH COSH TANH ASINH ACOSH ATANH SQRT %token EXP LOG LOG10 SIN COS TAN ASIN ACOS ATAN SINH COSH TANH ASINH ACOSH ATANH SQRT
/* isn't parsed from the *.mod file, but used to distinguish EQUAL in equation and EQUAL in assignment in operation codes
*/
%token ASSIGN
%type <exp_val> expression comma_expression %type <exp_val> expression comma_expression
%type <model_val> equation hand_side model_var %type <model_val> equation hand_side model_var
......
This diff is collapsed.
...@@ -50,7 +50,8 @@ COMMON_OBJ=\ ...@@ -50,7 +50,8 @@ COMMON_OBJ=\
ParsingDriver.o\ ParsingDriver.o\
DataTree.o \ DataTree.o \
ModFile.o \ ModFile.o \
Statement.o Statement.o \
ExprNode.o
MATLAB_OBJ = InterfaceMatlab.o MATLAB_OBJ = InterfaceMatlab.o
......
#include <iostream>
#include <fstream>
#include "ModFile.hh" #include "ModFile.hh"
#include "Interface.hh" #include "Interface.hh"
...@@ -56,7 +59,7 @@ ModFile::computingPass() ...@@ -56,7 +59,7 @@ ModFile::computingPass()
} }
void void
ModFile::writeOutputFiles(const string &basename, bool clear_all) ModFile::writeOutputFiles(const string &basename, bool clear_all) const
{ {
ofstream mOutputFile; ofstream mOutputFile;
...@@ -135,7 +138,7 @@ ModFile::writeOutputFiles(const string &basename, bool clear_all) ...@@ -135,7 +138,7 @@ ModFile::writeOutputFiles(const string &basename, bool clear_all)
model_tree.writeDynamicFile(basename); model_tree.writeDynamicFile(basename);
// Print statements // Print statements
for(vector<Statement *>::iterator it = statements.begin(); for(vector<Statement *>::const_iterator it = statements.begin();
it != statements.end(); it++) it != statements.end(); it++)
(*it)->writeOutput(mOutputFile, basename); (*it)->writeOutput(mOutputFile, basename);
......
This diff is collapsed.
...@@ -42,7 +42,6 @@ ParsingDriver::parse(const string &f) ...@@ -42,7 +42,6 @@ ParsingDriver::parse(const string &f)
{ {
mod_file = new ModFile(); mod_file = new ModFile();
mod_file->model_tree.error = error;
mod_file->symbol_table.error = error; mod_file->symbol_table.error = error;
expression.setNumericalConstants(&mod_file->num_constants); expression.setNumericalConstants(&mod_file->num_constants);
...@@ -118,16 +117,16 @@ ParsingDriver::add_expression_constant(string *constant) ...@@ -118,16 +117,16 @@ ParsingDriver::add_expression_constant(string *constant)
NodeID NodeID
ParsingDriver::add_model_constant(string *constant) ParsingDriver::add_model_constant(string *constant)
{ {
int id = mod_file->num_constants.AddConstant(*constant); NodeID id = model_tree->AddNumConstant(*constant);
delete constant; delete constant;
return model_tree->AddTerminal((NodeID) id, eNumericalConstant); return id;
} }
NodeID NodeID
ParsingDriver::add_model_variable(string *name) ParsingDriver::add_model_variable(string *name)
{ {
check_symbol_existence(*name); check_symbol_existence(*name);
NodeID id = model_tree->AddTerminal(*name); NodeID id = model_tree->AddVariable(*name);
delete name; delete name;
return id; return id;
} }
...@@ -145,7 +144,7 @@ ParsingDriver::add_model_variable(string *name, string *olag) ...@@ -145,7 +144,7 @@ ParsingDriver::add_model_variable(string *name, string *olag)
<< *name << *name
<< " has lag " << lag << endl; << " has lag " << lag << endl;
} }
NodeID id = model_tree->AddTerminal(*name, lag); NodeID id = model_tree->AddVariable(*name, lag);
delete name; delete name;
delete olag; delete olag;
return id; return id;
...@@ -920,8 +919,8 @@ void ...@@ -920,8 +919,8 @@ void
ParsingDriver::end_planner_objective(NodeID expr) ParsingDriver::end_planner_objective(NodeID expr)
{ {
// Add equation corresponding to expression // Add equation corresponding to expression
model_tree->AddEqual(expr, model_tree->Zero); NodeID eq = model_tree->AddEqual(expr, model_tree->Zero);
model_tree->eq_nbr++; model_tree->addEquation(eq);
mod_file->addStatement(new PlannerObjectiveStatement(model_tree)); mod_file->addStatement(new PlannerObjectiveStatement(model_tree));
} }
...@@ -938,7 +937,7 @@ NodeID ...@@ -938,7 +937,7 @@ NodeID
ParsingDriver::add_model_equal(NodeID arg1, NodeID arg2) ParsingDriver::add_model_equal(NodeID arg1, NodeID arg2)
{ {
NodeID id = model_tree->AddEqual(arg1, arg2); NodeID id = model_tree->AddEqual(arg1, arg2);
model_tree->eq_nbr++; model_tree->addEquation(id);
return id; return id;
} }
...@@ -952,8 +951,14 @@ void ...@@ -952,8 +951,14 @@ void
ParsingDriver::declare_and_init_local_parameter(string *name, NodeID rhs) ParsingDriver::declare_and_init_local_parameter(string *name, NodeID rhs)
{ {
mod_file->symbol_table.AddSymbolDeclar(*name, eLocalParameter, *name); mod_file->symbol_table.AddSymbolDeclar(*name, eLocalParameter, *name);
NodeID id = model_tree->AddTerminal(*name); try
model_tree->AddAssign(id, rhs); {
model_tree->AddLocalParameter(*name, rhs);
}
catch(DataTree::LocalParameterException &e)
{
error("Local parameter " + e.name + " declared twice");
}
delete name; delete name;
} }
......
...@@ -100,7 +100,7 @@ Reference SymbolTable::isReferenced(const std::string &name) const ...@@ -100,7 +100,7 @@ Reference SymbolTable::isReferenced(const std::string &name) const
} }
void void
SymbolTable::writeOutput(ostream &output) SymbolTable::writeOutput(ostream &output) const
{ {
if (exo_nbr > 0) if (exo_nbr > 0)
{ {
......
This diff is collapsed.
#ifndef _EXPR_NODE_HH
#define _EXPR_NODE_HH