SymbolTable.cc 8.85 KB
Newer Older
sebastien's avatar
sebastien committed
1
/*
sebastien's avatar
sebastien committed
2
 * Copyright (C) 2003-2009 Dynare Team
sebastien's avatar
sebastien committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 *
 * This file is part of Dynare.
 *
 * Dynare is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Dynare is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
 */

20
#include <algorithm>
21
#include <sstream>
sebastien's avatar
sebastien committed
22
#include <iostream>
23

24
#include "SymbolTable.hh"
25

sebastien's avatar
sebastien committed
26
SymbolTable::SymbolTable() : frozen(false), size(0)
27
28
29
{
}

sebastien's avatar
sebastien committed
30
int
sebastien's avatar
sebastien committed
31
SymbolTable::addSymbol(const string &name, SymbolType type, const string &tex_name) throw (AlreadyDeclaredException, FrozenException)
32
{
sebastien's avatar
sebastien committed
33
34
35
  if (frozen)
    throw FrozenException();

sebastien's avatar
sebastien committed
36
  if (exists(name))
37
    {
sebastien's avatar
sebastien committed
38
      if (type_table[getID(name)] == type)
39
40
41
42
        throw AlreadyDeclaredException(name, true);
      else
        throw AlreadyDeclaredException(name, false);
    }
sebastien's avatar
sebastien committed
43

sebastien's avatar
sebastien committed
44
45
46
47
48
49
  int id = size++;

  symbol_table[name] = id;
  type_table.push_back(type);
  name_table.push_back(name);
  tex_name_table.push_back(tex_name);
sebastien's avatar
sebastien committed
50
51

  return id;
sebastien's avatar
sebastien committed
52
53
}

sebastien's avatar
sebastien committed
54
int
55
56
57
58
59
60
61
62
63
64
SymbolTable::addSymbol(const string &name, SymbolType type) throw (AlreadyDeclaredException, FrozenException)
{
  // Construct "tex_name" by prepending an antislash to all underscores in "name"
  string tex_name = name;
  size_t pos = 0;
  while((pos = tex_name.find('_', pos)) != string::npos)
    {
      tex_name.insert(pos, "\\");
      pos += 2;
    }
sebastien's avatar
sebastien committed
65
  return addSymbol(name, type, tex_name);
66
67
}

sebastien's avatar
sebastien committed
68
69
70
71
72
void
SymbolTable::freeze() throw (FrozenException)
{
  if (frozen)
    throw FrozenException();
73

sebastien's avatar
sebastien committed
74
75
76
  frozen = true;

  for(int i = 0; i < size; i++)
77
    {
sebastien's avatar
sebastien committed
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
      int tsi;
      switch(getType(i))
        {
        case eEndogenous:
          tsi = endo_ids.size();
          endo_ids.push_back(i);
          break;
        case eExogenous:
          tsi = exo_ids.size();
          exo_ids.push_back(i);
          break;
        case eExogenousDet:
          tsi = exo_det_ids.size();
          exo_det_ids.push_back(i);
          break;
        case eParameter:
          tsi = param_ids.size();
          param_ids.push_back(i);
          break;
        default:
          tsi = -1;
          break;
        }
      type_specific_ids.push_back(tsi);
    }
}

void
SymbolTable::changeType(int id, SymbolType newtype) throw (UnknownSymbolIDException, FrozenException)
{
  if (frozen)
    throw FrozenException();

  if (id < 0 || id >= size)
    throw UnknownSymbolIDException(id);

  type_table[id] = newtype;
}

int
SymbolTable::getID(SymbolType type, int tsid) const throw (UnknownTypeSpecificIDException, NotYetFrozenException)
{
  if (!frozen)
    throw NotYetFrozenException();

  switch(type)
    {
    case eEndogenous:
      if (tsid < 0 || tsid >= (int) endo_ids.size())
        throw UnknownTypeSpecificIDException(tsid, type);
      else
        return endo_ids[tsid];
130
    case eExogenous:
sebastien's avatar
sebastien committed
131
132
133
134
      if (tsid < 0 || tsid >= (int) exo_ids.size())
        throw UnknownTypeSpecificIDException(tsid, type);
      else
        return exo_ids[tsid];
135
    case eExogenousDet:
sebastien's avatar
sebastien committed
136
137
138
139
      if (tsid < 0 || tsid >= (int) exo_det_ids.size())
        throw UnknownTypeSpecificIDException(tsid, type);
      else
        return exo_det_ids[tsid];
140
    case eParameter:
sebastien's avatar
sebastien committed
141
142
143
144
145
146
      if (tsid < 0 || tsid >= (int) param_ids.size())
        throw UnknownTypeSpecificIDException(tsid, type);
      else
        return param_ids[tsid];
    default:
      throw UnknownTypeSpecificIDException(tsid, type);
147
148
149
    }
}

sebastien's avatar
sebastien committed
150
void
sebastien's avatar
sebastien committed
151
SymbolTable::writeOutput(ostream &output) const throw (NotYetFrozenException)
152
{
sebastien's avatar
sebastien committed
153
154
155
156
  if (!frozen)
    throw NotYetFrozenException();

  if (exo_nbr() > 0)
157
    {
sebastien's avatar
sebastien committed
158
159
160
      output << "M_.exo_names = '" << getName(exo_ids[0]) << "';" << endl;
      output << "M_.exo_names_tex = '" << getTeXName(exo_ids[0]) << "';" << endl;
      for (int id = 1; id < exo_nbr(); id++)
161
        {
sebastien's avatar
sebastien committed
162
163
          output << "M_.exo_names = strvcat(M_.exo_names, '" << getName(exo_ids[id]) << "');" << endl
                 << "M_.exo_names_tex = strvcat(M_.exo_names_tex, '" << getTeXName(exo_ids[id]) << "');" << endl;
164
165
        }
    }
sebastien's avatar
sebastien committed
166
  if (exo_det_nbr() > 0)
167
    {
sebastien's avatar
sebastien committed
168
169
170
      output << "M_.exo_det_names = '" << getName(exo_det_ids[0]) << "';" << endl;
      output << "M_.exo_det_names_tex = '" << getTeXName(exo_det_ids[0]) << "';" << endl;
      for (int id = 1; id < exo_det_nbr(); id++)
171
        {
sebastien's avatar
sebastien committed
172
173
          output << "M_.exo_det_names = strvcat(M_.exo_det_names, '" << getName(exo_det_ids[id]) << "');" << endl
                 << "M_.exo_det_names_tex = strvcat(M_.exo_det_names_tex, '" << getTeXName(exo_det_ids[id]) << "');" << endl;
174
175
        }
    }
sebastien's avatar
sebastien committed
176
  if (endo_nbr() > 0)
177
    {
sebastien's avatar
sebastien committed
178
179
180
      output << "M_.endo_names = '" << getName(endo_ids[0]) << "';" << endl;
      output << "M_.endo_names_tex = '" << getTeXName(endo_ids[0]) << "';" << endl;
      for (int id = 1; id < endo_nbr(); id++)
181
        {
sebastien's avatar
sebastien committed
182
183
          output << "M_.endo_names = strvcat(M_.endo_names, '" << getName(endo_ids[id]) << "');" << endl
                 << "M_.endo_names_tex = strvcat(M_.endo_names_tex, '" << getTeXName(endo_ids[id]) << "');" << endl;
184
185
        }
    }
sebastien's avatar
sebastien committed
186
  if (param_nbr() > 0)
187
    {
sebastien's avatar
sebastien committed
188
189
190
      output << "M_.param_names = '" << getName(param_ids[0]) << "';" << endl;
      output << "M_.param_names_tex = '" << getTeXName(param_ids[0]) << "';" << endl;
      for (int id = 1; id < param_nbr(); id++)
191
        {
sebastien's avatar
sebastien committed
192
193
          output << "M_.param_names = strvcat(M_.param_names, '" << getName(param_ids[id]) << "');" << endl
                 << "M_.param_names_tex = strvcat(M_.param_names_tex, '" << getTeXName(param_ids[id]) << "');" << endl;
194
195
196
        }
    }

sebastien's avatar
sebastien committed
197
198
199
200
  output << "M_.exo_det_nbr = " << exo_det_nbr() << ";" << endl
         << "M_.exo_nbr = " << exo_nbr() << ";" << endl
         << "M_.endo_nbr = " << endo_nbr() << ";" << endl
         << "M_.param_nbr = " << param_nbr() << ";" << endl;
sebastien's avatar
sebastien committed
201

sebastien's avatar
sebastien committed
202
  output << "M_.Sigma_e = zeros(" << exo_nbr() << ", " << exo_nbr() << ");" << endl;
sebastien's avatar
sebastien committed
203
204
205
206
207
208
209
210

  // Write the auxiliary variable table
  for(int i = 0; i < (int) aux_vars.size(); i++)
    {
      output << "M_.aux_vars(" << i+1 << ").endo_index = " << getTypeSpecificID(aux_vars[i].symb_id)+1 << ";" << endl
             << "M_.aux_vars(" << i+1 << ").type = " << aux_vars[i].type << ";" << endl;
      switch(aux_vars[i].type)
        {
211
        case avEndoLead:
sebastien's avatar
sebastien committed
212
          break;
213
214
215
        case avEndoLag:
        case avExoLead:
        case avExoLag:
sebastien's avatar
sebastien committed
216
217
218
219
220
221
222
223
          output << "M_.aux_vars(" << i+1 << ").orig_endo_index = " << getTypeSpecificID(aux_vars[i].orig_symb_id)+1 << ";" << endl
                 << "M_.aux_vars(" << i+1 << ").orig_lag = " << aux_vars[i].orig_lag << ";" << endl;
          break;
        }
    }
}

int
224
SymbolTable::addEndoLeadAuxiliaryVar(int index) throw (FrozenException)
sebastien's avatar
sebastien committed
225
226
{
  ostringstream varname;
227
  varname << "AUX_ENDO_LEAD_" << index;
sebastien's avatar
sebastien committed
228
229
230
231
232
233
234
235
236
237
238
239
240
  int symb_id;
  try
    {
      symb_id = addSymbol(varname.str(), eEndogenous);
    }
  catch(AlreadyDeclaredException &e)
    {
      cerr << "ERROR: you should rename your variable called " << varname.str() << ", this name is internally used by Dynare" << endl;
      exit(EXIT_FAILURE);
    }

  AuxVarInfo avi;
  avi.symb_id = symb_id;
241
  avi.type = avEndoLead;
sebastien's avatar
sebastien committed
242
243
244
245
246
247
  aux_vars.push_back(avi);

  return symb_id;
}

int
248
SymbolTable::addLeadLagAuxiliaryVarInternal(aux_var_t type, int orig_symb_id, int orig_lag) throw (FrozenException)
sebastien's avatar
sebastien committed
249
250
{
  ostringstream varname;
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
  switch(type)
    {
    case avEndoLag:
      varname << "AUX_ENDO_LAG_" << orig_symb_id << "_" << -orig_lag;
      break;
    case avExoLead:
      varname << "AUX_EXO_LEAD_" << orig_symb_id << "_" << orig_lag;
      break;
    case avExoLag:
      varname << "AUX_EXO_LAG_" << orig_symb_id << "_" << -orig_lag;
      break;
    default:
      cerr << "Impossible case!" << endl;
      exit(EXIT_FAILURE);
    }

sebastien's avatar
sebastien committed
267
268
269
270
271
272
273
274
275
276
277
278
279
  int symb_id;
  try
    {
      symb_id = addSymbol(varname.str(), eEndogenous);
    }
  catch(AlreadyDeclaredException &e)
    {
      cerr << "ERROR: you should rename your variable called " << varname.str() << ", this name is internally used by Dynare" << endl;
      exit(EXIT_FAILURE);
    }

  AuxVarInfo avi;
  avi.symb_id = symb_id;
280
  avi.type = type;
sebastien's avatar
sebastien committed
281
282
283
284
285
  avi.orig_symb_id = orig_symb_id;
  avi.orig_lag = orig_lag;
  aux_vars.push_back(avi);

  return symb_id;
286
}
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304

int
SymbolTable::addEndoLagAuxiliaryVar(int orig_symb_id, int orig_lag) throw (FrozenException)
{
  return addLeadLagAuxiliaryVarInternal(avEndoLag, orig_symb_id, orig_lag);
}

int
SymbolTable::addExoLeadAuxiliaryVar(int orig_symb_id, int orig_lag) throw (FrozenException)
{
  return addLeadLagAuxiliaryVarInternal(avExoLead, orig_symb_id, orig_lag);
}

int
SymbolTable::addExoLagAuxiliaryVar(int orig_symb_id, int orig_lag) throw (FrozenException)
{
  return addLeadLagAuxiliaryVarInternal(avExoLag, orig_symb_id, orig_lag);
}