dynare/parser.src/Expression.cc

273 lines
8.0 KiB
C++

/*! \file
\version 1.0
\date 04/09/2004
\par This file implements the Expression class methodes.
*/
//------------------------------------------------------------------------------
#include <stack>
using namespace std;
//------------------------------------------------------------------------------
#include "Expression.h"
//------------------------------------------------------------------------------
ostringstream Expression::output;
//------------------------------------------------------------------------------
Expression::Expression()
{
// Empty
}
//------------------------------------------------------------------------------
Expression::~Expression()
{
// Empty
}
//------------------------------------------------------------------------------
int Expression::AddToken(int id1,Type type1,int id2,Type type2,int op_code)
{
Token token;
// Making token structure
token.id1 = id1;
token.type1 = type1;
token.id2 = id2;
token.type2 = type2;
token.op_code = op_code;
token.op_name = operator_table.str(op_code);
// Inserting token into expression_list
expression_list.push_back(token);
return expression_list.size() -1;
}
//------------------------------------------------------------------------------
int Expression::AddToken(int id1,Type type1,int op_code)
{
Token token;
// Making token structure
token.id1 = id1;
token.type1 = type1;
token.id2 = -1;
token.type2 = eUNDEF;
token.op_code = op_code;
token.op_name = operator_table.str(op_code);;
// Inserting token into expression_list
expression_list.push_back(token);
return expression_list.size() -1;
}
//------------------------------------------------------------------------------
int Expression::AddToken(int id1,Type type1, string ufunction)
{
Token token;
// Making token structure
token.id1 = id1;
token.type1 = type1;
token.id2 = -1;
token.type2 = eUNDEF;
token.op_code = NAME;
token.op_name = ufunction;
// Inserting token into expression_list
expression_list.push_back(token);
return expression_list.size() -1;
}
//------------------------------------------------------------------------------
void Expression::set(void)
{
// Stack of temporary tokens
stack <int, vector<Token> > stack_token;
// Dtack of temporary expressions
stack <int, vector<string> > stack_expression;
// Temporary output
ostringstream exp;
// temporary variables for saving arguments and name oparator
string argument1, argument2, op_name;
// Define type for type operator (binary or unary)
enum OperatorType
{
unary,
binary
};
OperatorType op_type;
int current_op, last_op;
// Clearing output string
output.str("");
// Starting from the end of list
stack_token.push(expression_list.back());
// Main loop :
// Repeat for last token from the stack
// (1) if argument is temporary result, and not yet followed,
// set it as followed (flag) and push corresponding token
// on the token stack
// (2) argument followed, or final argument
// (2.1) if argument is followed
// - set argument1 (or argument2) by last expression on
// expression tack
// - pop last expression from expression stack
// (2.2) if final argument
// set argument1 (or argument2) by final argument
// (3) set op_name by last token from the token stack
// (3) pop last token from the token stack
// (4) write temporary expression (using argument1, argument2
// and op_name) and push it on the expression stack
// (5)
while (stack_token.size() > 0)
{
// First argument is a temporary result,
// pushing token on token stack and setting that argument to be followed
if ((stack_token.top().type1 == eTempResult) &&
(stack_token.top().followed1 == false))
{
stack_token.top().followed1 = true;
stack_token.push(expression_list[stack_token.top().id1]);
}
// Second argument is a temporary result,
// pushing token on stack and setting that argument to be followed
else if ((stack_token.top().type2 == eTempResult) &&
(stack_token.top().followed2 == false))
{
stack_token.top().followed2 = true;
stack_token.push(expression_list[stack_token.top().id2]);
}
// Writing expression
else
{
// Final token, no argment followed
if ((stack_token.top().followed1 == false) &&
(stack_token.top().followed2 == false))
{
argument1 = getArgument(stack_token.top().type1,stack_token.top().id1);
current_op = stack_token.top().op_code;
// Testing if unary or binary token
if (stack_token.top().id2 >= 0)
{
argument2 = getArgument(stack_token.top().type2,stack_token.top().id2);
op_type = binary;
}
else
{
op_type = unary;
}
}
// Both arguments are followed, writing stacked expressions
else if ((stack_token.top().followed1 == true) &&
(stack_token.top().followed2 == true))
{
// Testing if unary or binary token
if (stack_token.top().id2 >= 0)
{
argument2 = stack_expression.top();
stack_expression.pop();
op_type = binary;
}
else
{
op_type = unary;
}
argument1 = stack_expression.top();
current_op = stack_token.top().op_code;
stack_expression.pop();
}
// Only argument 1 is followed, combining expressions
else if (stack_token.top().followed1 == true)
{
argument1 = stack_expression.top();
current_op = stack_token.top().op_code;
stack_expression.pop();
// Testing if unary or binary token
if (stack_token.top().id2 >= 0)
{
argument2 = getArgument(stack_token.top().type2,stack_token.top().id2);
op_type = binary;
}
else
{
op_type = unary;
}
}
// Only argument 2 is followed, combining experssions
else if (stack_token.top().followed2 == true)
{
argument1 = getArgument(stack_token.top().type1,stack_token.top().id1);
argument2 = stack_expression.top();
stack_expression.pop();
current_op = stack_token.top().op_code;
op_type = binary;
}
op_name = stack_token.top().op_name;
exp.str("");
stack_token.pop();
// Saving last operator for the followed argument
if (stack_token.size() > 0)
{
last_op = stack_token.top().op_code;
}
else
{
last_op = current_op;
}
if (op_type == binary)
{
// Comma operator, no parentheses
// parentheses are writing with function operator
if (current_op == COMMA)
{
exp << argument1 << op_name << argument2 ;
}
else
{
exp << "(" << argument1 << op_name << argument2 << ")";
}
}
else
{
// Case of functions
if (operator_table.isfunction(current_op) == true)
exp << op_name << "(" << argument1 << ")";
else
exp << "(" << op_name << argument1 << ")";
}
stack_expression.push(exp.str());
}
}
output << stack_expression.top();
expression_list.clear();
}
//------------------------------------------------------------------------------
string Expression::getArgument(Type type,int id)
{
ostringstream argument;
if (type == eExogenous)
{
argument << "oo_.exo_steady_state"<< "(" << id+1 << ")";
}
else if (type == eExogenousDet)
{
argument << "exedet_" << "(" << id+1 << ")";
}
else if (type == eEndogenous)
{
argument << "oo_.steady_state" << "(" << id+1 << ")";
}
else if (type == eParameter)
{
argument << "M_.params" << "(" << id+1 << ")";
}
else if (type == eNumericalConstant)
{
argument << NumericalConstants::get(id);
}
return argument.str();
}
//------------------------------------------------------------------------------
string Expression::get(void)
{
return output.str();
}
//------------------------------------------------------------------------------
void Expression::clear(void)
{
expression_list.clear();
}
//------------------------------------------------------------------------------