Commit 059bb76e authored by sebastien's avatar sebastien
Browse files

v4 parser:

* refactored SymbolTable class
* added a uniform interface for emitting warnings


git-svn-id: https://www.dynare.org/svn/dynare/dynare_v4@1494 ac1d8469-bf42-47a9-8791-bf33cf982152
parent a3184c32
......@@ -35,12 +35,6 @@ DataTree::AddNumConstant(const string &value)
NodeID
DataTree::AddVariable(const string &name, int lag)
{
if (!symbol_table.Exist(name))
{
cerr << "Unknown symbol: " << name << endl;
exit(-1);
}
int symb_id = symbol_table.getID(name);
Type type = symbol_table.getType(name);
......@@ -382,12 +376,6 @@ DataTree::AddEqual(NodeID iArg1, NodeID iArg2)
void
DataTree::AddLocalParameter(const string &name, NodeID value) throw (LocalParameterException)
{
if (!symbol_table.Exist(name))
{
cerr << "Unknown symbol: " << name << endl;
exit(-1);
}
int id = symbol_table.getID(name);
// Throw an exception if symbol already declared
......@@ -401,12 +389,6 @@ DataTree::AddLocalParameter(const string &name, NodeID value) throw (LocalParame
NodeID
DataTree::AddUnknownFunction(const string &function_name, const vector<NodeID> &arguments)
{
if (!symbol_table.Exist(function_name))
{
cerr << "Unknown symbol: " << function_name << endl;
exit(-1);
}
if (symbol_table.getType(function_name) != eUnknownFunction)
{
cerr << "Symbol " << function_name << " is not a function name!";
......
......@@ -12,7 +12,7 @@ ParsingDriver::~ParsingDriver()
bool
ParsingDriver::symbol_exists_and_is_not_modfile_local_variable(const char *s)
{
if (!mod_file->symbol_table.Exist(s))
if (!mod_file->symbol_table.exists(s))
return false;
return(mod_file->symbol_table.getType(s) != eModFileLocalVariable);
......@@ -21,7 +21,7 @@ ParsingDriver::symbol_exists_and_is_not_modfile_local_variable(const char *s)
void
ParsingDriver::check_symbol_existence(const string &name)
{
if (!mod_file->symbol_table.Exist(name))
if (!mod_file->symbol_table.exists(name))
error("Unknown symbol: " + name);
}
......@@ -43,8 +43,6 @@ ParsingDriver::parse(const string &f)
{
mod_file = new ModFile();
mod_file->symbol_table.error = error;
tmp_symbol_table = new TmpSymbolTable(mod_file->symbol_table);
reset_data_tree();
......@@ -64,7 +62,7 @@ ParsingDriver::parse(const string &f)
void
ParsingDriver::error(const yy::parser::location_type &l, const string &m)
{
cerr << l << ": " << m << endl;
cerr << "ERROR: " << l << ": " << m << endl;
exit(-1);
}
......@@ -72,40 +70,58 @@ void
ParsingDriver::error(const string &m)
{
extern int yylineno;
cerr << file << ":" << yylineno << ": " << m << endl;
cerr << "ERROR: " << file << ":" << yylineno << ": " << m << endl;
exit(-1);
}
void
ParsingDriver::declare_endogenous(string *name, string *tex_name)
ParsingDriver::warning(const string &m)
{
extern int yylineno;
cerr << "WARNING: " << file << ":" << yylineno << ": " << m << endl;
}
void
ParsingDriver::declare_symbol(string *name, Type type, string *tex_name)
{
mod_file->symbol_table.AddSymbolDeclar(*name, eEndogenous, *tex_name);
try
{
mod_file->symbol_table.addSymbol(*name, type, *tex_name);
}
catch(SymbolTable::AlreadyDeclaredException &e)
{
if (e.same_type)
warning("Symbol " + *name + " declared twice.");
else
error("Symbol " + *name + " declared twice with different types!");
}
delete name;
delete tex_name;
}
void
ParsingDriver::declare_endogenous(string *name, string *tex_name)
{
declare_symbol(name, eEndogenous, tex_name);
}
void
ParsingDriver::declare_exogenous(string *name, string *tex_name)
{
mod_file->symbol_table.AddSymbolDeclar(*name, eExogenous, *tex_name);
delete name;
delete tex_name;
declare_symbol(name, eExogenous, tex_name);
}
void
ParsingDriver::declare_exogenous_det(string *name, string *tex_name)
{
mod_file->symbol_table.AddSymbolDeclar(*name, eExogenousDet, *tex_name);
delete name;
delete tex_name;
declare_symbol(name, eExogenousDet, tex_name);
}
void
ParsingDriver::declare_parameter(string *name, string *tex_name)
{
mod_file->symbol_table.AddSymbolDeclar(*name, eParameter, *tex_name);
delete name;
delete tex_name;
declare_symbol(name, eParameter, tex_name);
}
NodeID
......@@ -149,10 +165,11 @@ ParsingDriver::add_model_variable(string *name, string *olag)
if ((type == eExogenous) && lag != 0)
{
cout << "Warning: exogenous variable "
<< *name
<< " has lag " << lag << endl;
ostringstream ost;
ost << "Exogenous variable " << *name << " has lag " << lag;
warning(ost.str());
}
NodeID id = model_tree->AddVariable(*name, lag);
if ((type == eEndogenous) && (model_tree->mode == eSparseDLLMode || model_tree->mode == eSparseMode))
......@@ -167,8 +184,8 @@ NodeID
ParsingDriver::add_expression_variable(string *name)
{
// If symbol doesn't exist, then declare it as a mod file local variable
if (!mod_file->symbol_table.Exist(*name))
mod_file->symbol_table.AddSymbolDeclar(*name, eModFileLocalVariable, *name);
if (!mod_file->symbol_table.exists(*name))
mod_file->symbol_table.addSymbol(*name, eModFileLocalVariable);
NodeID id = data_tree->AddVariable(*name);
......@@ -1047,15 +1064,16 @@ ParsingDriver::add_model_equal_with_zero_rhs(NodeID arg)
void
ParsingDriver::declare_and_init_model_local_variable(string *name, NodeID rhs)
{
mod_file->symbol_table.AddSymbolDeclar(*name, eModelLocalVariable, *name);
try
{
model_tree->AddLocalParameter(*name, rhs);
mod_file->symbol_table.addSymbol(*name, eModelLocalVariable);
}
catch(DataTree::LocalParameterException &e)
catch(SymbolTable::AlreadyDeclaredException &e)
{
error("Local parameter " + e.name + " declared twice");
error("Local model variable " + *name + " declared twice.");
}
model_tree->AddLocalParameter(*name, rhs);
delete name;
}
......@@ -1254,13 +1272,13 @@ ParsingDriver::add_unknown_function_arg(NodeID arg)
NodeID
ParsingDriver::add_unknown_function(string *function_name)
{
if (mod_file->symbol_table.Exist(*function_name))
if (mod_file->symbol_table.exists(*function_name))
{
if (mod_file->symbol_table.getType(*function_name) != eUnknownFunction)
error("Symbol " + *function_name + " is not a function name.");
}
else
mod_file->symbol_table.AddSymbolDeclar(*function_name, eUnknownFunction, *function_name);
mod_file->symbol_table.addSymbol(*function_name, eUnknownFunction);
NodeID id = data_tree->AddUnknownFunction(*function_name, unknown_function_args);
unknown_function_args.clear();
......
/*! \file
\version 1.0
\date 04/09/2004
\par This file implements the SymbolTable class methodes.
*/
#include <iostream>
#include <algorithm>
#include <sstream>
#include "SymbolTable.hh"
#include "Interface.hh"
using namespace std;
SymbolTable::SymbolTable() : endo_nbr(0), exo_nbr(0), exo_det_nbr(0), parameter_nbr(0),
model_local_variable_nbr(0), modfile_local_variable_nbr(0),
recur_nbr(0), unknown_function_nbr(0)
{
name_table.resize(20);
tex_name_table.resize(20);
}
int SymbolTable::AddSymbol(string name,Type type, string tex_name)
void
SymbolTable::addSymbol(const string &name, Type type, const string &tex_name) throw (AlreadyDeclaredException)
{
symboltable[name].type = type;
name_table[(int) type].push_back(name);
tex_name_table[(int) type].push_back(tex_name);
if (exists(name))
if (symbol_table[name].first == type)
throw AlreadyDeclaredException(name, true);
else
throw AlreadyDeclaredException(name, false);
int id;
switch (type)
{
case eExogenous:
symboltable[name].id = exo_nbr;
return exo_nbr++;
id = exo_nbr++;
break;
case eExogenousDet:
symboltable[name].id = exo_det_nbr;
return exo_det_nbr++;
id = exo_det_nbr++;
break;
case eEndogenous:
symboltable[name].id = endo_nbr;
return endo_nbr++;
id = endo_nbr++;
break;
case eParameter:
symboltable[name].id = parameter_nbr;
return parameter_nbr++;
id = parameter_nbr++;
break;
case eRecursiveVariable:
symboltable[name].id = recur_nbr;
return recur_nbr++;
id = recur_nbr++;
break;
case eModelLocalVariable:
symboltable[name].id = model_local_variable_nbr;
return model_local_variable_nbr++;
id = model_local_variable_nbr++;
break;
case eModFileLocalVariable:
symboltable[name].id = modfile_local_variable_nbr;
return modfile_local_variable_nbr++;
id = modfile_local_variable_nbr++;
break;
case eUnknownFunction:
symboltable[name].id = unknown_function_nbr;
return unknown_function_nbr++;
id = unknown_function_nbr++;
break;
}
// should never happen
return -1;
}
int SymbolTable::AddSymbolDeclar(string name,Type type, string tex_name)
{
//Testing if the symbol exist in the map
if ( !Exist(name) )
{
//The symbol dosn't exist, adding it
return AddSymbol(name,type, tex_name);
}
else
{
//The symbol exists, testing its type
if (symboltable[name].type == type)
{
cout << "Warning : symbol " << name << " declared more than once.\n";
return getID(name);
}
else
{
string msg = "symbol " + name + " declared more than once with different types.";
(* error) (msg.c_str());
return -1;
}
}
}
void SymbolTable::AddSymbolRange(string name,int nbr,Type type, string tex_name)
{
}
void SymbolTable::ResetType(string name,Type new_type)
{
symboltable[name].type = new_type;
symbol_type symbol(type, id);
symbol_table[name] = symbol;
name_table[symbol] = name;
tex_name_table[symbol] = tex_name;
}
void
......@@ -97,60 +60,60 @@ SymbolTable::writeOutput(ostream &output) const
{
if (exo_nbr > 0)
{
output << "M_.exo_names = '" << getNameByID(eExogenous, 0) << "';\n";
output << "M_.exo_names_tex = '" << getTexNameByID(eExogenous, 0) << "';\n";
output << "M_.exo_names = '" << getNameByID(eExogenous, 0) << "';" << endl;
output << "M_.exo_names_tex = '" << getTeXNameByID(eExogenous, 0) << "';" << endl;
for (int id = 1; id < exo_nbr; id++)
{
output << "M_.exo_names = " + interfaces::strvcat("M_.exo_names","'"+getNameByID(eExogenous, id)+"'") + ";\n";
output << "M_.exo_names_tex = " + interfaces::strvcat("M_.exo_names_tex","'"+getTexNameByID(eExogenous, id)+"'") + ";\n";
output << "M_.exo_names = " << interfaces::strvcat("M_.exo_names","'"+getNameByID(eExogenous, id)+"'") << ";" << endl;
output << "M_.exo_names_tex = " << interfaces::strvcat("M_.exo_names_tex","'"+getTeXNameByID(eExogenous, id)+"'") << ";" << endl;
}
}
if (exo_det_nbr > 0)
{
output << "lgxdet_ = '" << getNameByID(eExogenousDet, 0) << "';\n";
output << "lgxdet_tex_ = '" << getTexNameByID(eExogenousDet, 0) << "';\n";
output << "lgxdet_ = '" << getNameByID(eExogenousDet, 0) << "';" << endl;
output << "lgxdet_tex_ = '" << getTeXNameByID(eExogenousDet, 0) << "';" << endl;
for (int id = 1; id < exo_det_nbr; id++)
{
output << "lgxdet_ = " + interfaces::strvcat("lgxdet_","'"+getNameByID(eExogenousDet, id)+"'") + ";\n";
output << "lgxdet_tex_ = " + interfaces::strvcat("lgxdet_tex_","'"+getTexNameByID(eExogenousDet, id)+"'") + ";\n";
output << "lgxdet_ = " << interfaces::strvcat("lgxdet_","'"+getNameByID(eExogenousDet, id)+"'") << ";" << endl;
output << "lgxdet_tex_ = " << interfaces::strvcat("lgxdet_tex_","'"+getTeXNameByID(eExogenousDet, id)+"'") << ";" << endl;
}
}
if (endo_nbr > 0)
{
output << "M_.endo_names = '" << getNameByID(eEndogenous, 0) << "';\n";
output << "M_.endo_names_tex = '" << getTexNameByID(eEndogenous, 0) << "';\n";
output << "M_.endo_names = '" << getNameByID(eEndogenous, 0) << "';" << endl;
output << "M_.endo_names_tex = '" << getTeXNameByID(eEndogenous, 0) << "';" << endl;
for (int id = 1; id < endo_nbr; id++)
{
output << "M_.endo_names = " + interfaces::strvcat("M_.endo_names","'"+getNameByID(eEndogenous, id)+"'") + ";\n";
output << "M_.endo_names_tex = " + interfaces::strvcat("M_.endo_names_tex","'"+getTexNameByID(eEndogenous, id)+"'") + ";\n";
output << "M_.endo_names = " << interfaces::strvcat("M_.endo_names","'"+getNameByID(eEndogenous, id)+"'") << ";" << endl;
output << "M_.endo_names_tex = " << interfaces::strvcat("M_.endo_names_tex","'"+getTeXNameByID(eEndogenous, id)+"'") << ";" << endl;
}
}
if (recur_nbr > 0)
{
output << "M_.recur_names = '" << getNameByID(eRecursiveVariable, 0) << "';\n";
output << "M_.recur_names_tex = '" << getTexNameByID(eRecursiveVariable, 0) << "';\n";
output << "M_.recur_names = '" << getNameByID(eRecursiveVariable, 0) << "';" << endl;
output << "M_.recur_names_tex = '" << getTeXNameByID(eRecursiveVariable, 0) << "';" << endl;
for (int id = 1; id < recur_nbr; id++)
{
output << "M_.recur_names = " + interfaces::strvcat("M_.recur_names","'"+getNameByID(eRecursiveVariable, id)+"'") + ";\n";
output << "M_.recur_names_tex = " + interfaces::strvcat("M_.recur_names_tex","'"+getTexNameByID(eRecursiveVariable, id)+"'") + ";\n";
output << "M_.recur_names = " << interfaces::strvcat("M_.recur_names","'"+getNameByID(eRecursiveVariable, id)+"'") << ";" << endl;
output << "M_.recur_names_tex = " << interfaces::strvcat("M_.recur_names_tex","'"+getTeXNameByID(eRecursiveVariable, id)+"'") << ";" << endl;
}
}
if (parameter_nbr > 0)
{
output << "M_.param_names = '" << getNameByID(eParameter, 0) << "';\n";
output << "M_.param_names_tex = '" << getTexNameByID(eParameter, 0) << "';\n";
output << "M_.param_names = '" << getNameByID(eParameter, 0) << "';" << endl;
output << "M_.param_names_tex = '" << getTeXNameByID(eParameter, 0) << "';" << endl;
for (int id = 1; id < parameter_nbr; id++)
{
output << "M_.param_names = " + interfaces::strvcat("M_.param_names","'"+getNameByID(eParameter, id)+"'") + ";\n";
output << "M_.param_names_tex = " + interfaces::strvcat("M_.param_names_tex","'"+getTexNameByID(eParameter, id)+"'") + ";\n";
output << "M_.param_names = " << interfaces::strvcat("M_.param_names","'"+getNameByID(eParameter, id)+"'") << ";" << endl;
output << "M_.param_names_tex = " << interfaces::strvcat("M_.param_names_tex","'"+getTeXNameByID(eParameter, id)+"'") << ";" << endl;
}
}
output << "M_.exo_det_nbr = " << exo_det_nbr << ";\n";
output << "M_.exo_nbr = " << exo_nbr << ";\n";
output << "M_.Sigma_e = zeros(" << exo_nbr
<< ", " << exo_nbr << ");\n";
output << "M_.endo_nbr = " << endo_nbr << ";\n";
output << "M_.recur_nbr = " << recur_nbr << ";\n";
output << "M_.param_nbr = " << parameter_nbr << ";\n";
output << "M_.exo_det_nbr = " << exo_det_nbr << ";" << endl
<< "M_.exo_nbr = " << exo_nbr << ";" << endl
<< "M_.endo_nbr = " << endo_nbr << ";" << endl
<< "M_.recur_nbr = " << recur_nbr << ";" << endl
<< "M_.param_nbr = " << parameter_nbr << ";" << endl;
output << "M_.Sigma_e = zeros(" << exo_nbr << ", " << exo_nbr << ");" << endl;
}
......@@ -17,12 +17,6 @@ VariableTable::VariableTable(const SymbolTable &symbol_table_arg) :
int
VariableTable::AddVariable(const string &iName, int iLag)
{
// Testing if symbol exists
if (!symbol_table.Exist(iName))
{
cerr << "Unknown symbol: " << iName << endl;
exit(-1);
}
// Testing if variable exists in VariableTable
int lVariableID = getID(iName,iLag);
if (lVariableID != -1)
......
......@@ -10,7 +10,7 @@ using namespace std;
#include <fstream>
#include "SymbolTableTypes.hh"
#include "SymbolTable.hh"
#include "CodeInterpreter.hh"
class DataTree;
......
#ifndef MODELNORMALIZATION
#define MODELNORMALIZATION
#include "SymbolTableTypes.hh"
#include "SymbolTable.hh"
#include "CodeInterpreter.hh"
......
......@@ -42,6 +42,9 @@ private:
//! Checks that a given symbol exists, and stops with an error message if it doesn't
void check_symbol_existence(const string &name);
//! Helper to add a symbol declaration
void declare_symbol(string *name, Type type, string *tex_name);
//! Creates option "optim_opt" in OptionsList if it doesn't exist, else add a comma, and adds the option name
void optim_options_helper(const string &name);
......@@ -139,15 +142,8 @@ public:
void error(const yy::parser::location_type &l, const string &m);
//! Error handler without location
void error(const string &m);
//! Static error handler
/*! To be removed in the future. */
static void error(const char *m)
{
extern int yylineno;
cerr << "Error at line " << yylineno << ": " << m << endl;
exit(-1);
}
//! Warning handler
void warning(const string &m);
//! Check if a given symbol exists in the parsing context, and is not a mod file local variable
bool symbol_exists_and_is_not_modfile_local_variable(const char *s);
......@@ -161,13 +157,13 @@ public:
void init_compiler(int compiler_type);
//! Sets the FILENAME for the initial value in initval
void init_val_filename(string *filename);
//! Declares an endogenous variable by adding it to SymbolTable
//! Declares an endogenous variable
void declare_endogenous(string *name, string *tex_name = new string);
//! Declares an exogenous variable by adding it to SymbolTable
//! Declares an exogenous variable
void declare_exogenous(string *name, string *tex_name = new string);
//! Declares an exogenous deterministic variable by adding it to SymbolTable
//! Declares an exogenous deterministic variable
void declare_exogenous_det(string *name, string *tex_name = new string);
//! Declares a parameter by adding it to SymbolTable
//! Declares a parameter
void declare_parameter(string *name, string *tex_name = new string);
//! Declares and initializes a local parameter
void declare_and_init_model_local_variable(string *name, NodeID rhs);
......
#ifndef _SYMBOLTABLE_HH
#define _SYMBOLTABLE_HH
//------------------------------------------------------------------------------
/*! \file
\version 1.0
\date 12/01/2003
\par This file defines the SymbolTable class .
*/
//------------------------------------------------------------------------------
using namespace std;
#include <map>
......@@ -15,125 +9,154 @@ using namespace std;
#include <ostream>
#include <iostream>
#include "SymbolTableTypes.hh"
//! Enumeration of possible symbol types
/*! Be careful not to change the order of the enumeration, it matters for VariableTable (at least up to eParameter) */
enum Type
{
eEndogenous = 0, //!< Endogenous
eExogenous = 1, //!< Exogenous
eExogenousDet = 2, //!< Exogenous deterministic
eRecursiveVariable = 3, //!< Recursive variable (reserved for future use)
eParameter = 4, //!< Parameter
eModelLocalVariable = 10, //!< Local variable whose scope is model (pound expression)
eModFileLocalVariable = 11, //!< Local variable whose scope is mod file (model excluded)
eUnknownFunction = 12 //!< Function unknown to the preprocessor
};
//! Stores the symbol table
/*!
\class SymbolTable
\brief This class keeps track of symbols
A symbol is given by its name, and is internally represented by a pair (type, id).
There is a distinct sequence of ids for each type, so two symbol of different types can have the same id.
Also manages a TeX name for each symbol, which by default is an empty string.
*/
class SymbolTable
{
private:
/*! Adds symbol into symbol table
\param name a string.
\param type a Type struct.
\param tex_name a string for the TeX name.
\par Description
- warning if symbol is already set with same type
- error if symbol is already set with different type
- set Name and Type
- increase corresponding counter in ModelParameters class
*/
int AddSymbol(std::string name, Type type, std::string tex_name);
/*! Symbol table map */
std::map<std::string, Symbol, std::less<std::string> > symboltable;
//! Typedef for const iterator on symboltable map
typedef std::map<std::string, Symbol, std::less<std::string> >::const_iterator symboltable_const_iterator;
/*! Symbol name table indexed by type and ID */
std::vector< std::vector<std::string> > name_table;
std::vector< std::vector<std::string> > tex_name_table;
/*! Changes type of a symbol */
void ResetType(std::string name, Type new_type);
public :
/*! Constructor */
//! A symbol is represented by a pair (type, id)
typedef pair<Type, int> symbol_type;
//! Type for map: symbol_name -> (type, id)
typedef map<string, symbol_type> symbol_table_type;
//! Maps strings to pairs (type,id)
symbol_table_type symbol_table;
//! Type for map: (type, id) -> symbol_name
typedef map<symbol_type, string> inv_symbol_table_type;
//! Maps pairs (type, id) to names
inv_symbol_table_type name_table;
//! Maps pairs (type, id) to TeX names
inv_symbol_table_type tex_name_table;
public:
SymbolTable();
//! Thrown when trying to access an unknown symbol (by name)
class UnknownSymbolNameException
{
public:
//! Symbol name
string name;
UnknownSymbolNameException(const string &name_arg) : name(name_arg) {}
};
//! Thrown when trying to access an unknown symbol (by type+id pair)
class UnknownSymbolIDException
{
public:
//! Symbol type
Type type;