
/*MA****************************************************************/
/*                                                                 */
/*     File: symbol-table.h                                        */
/*   Author: Helmut Schmid                                         */
/*  Purpose:                                                       */
/*  Created: Thu Jan  2 14:55:10 2003                              */
/* Modified: Wed Jan 14 16:56:46 2009 (schmid)                     */
/*                                                                 */
/*ME****************************************************************/

#include <limits.h>
#include <string.h>

#ifdef SGIext

#include <ext/hash_map>
using __gnu_cxx::hash_map;
using __gnu_cxx::hash;

#else

#include <hash_map>
using std::hash_map;
using std::hash;

#endif

typedef unsigned int SymNum;
const size_t MaxSymNum = UINT_MAX;


/*****************  class SymbolTable  *****************************/

class SymbolTable {

private:

  struct eqstr {
    bool operator()(const char* s1, const char* s2) const {
      return strcmp(s1, s2) == 0;
    }
  };

  typedef hash_map<const char*, SymNum, hash<const char*>, eqstr> SymbolMap;

  SymbolMap ST;
  vector<char*> SN;

public:
  ~SymbolTable() {
    for( size_t i=0; i<SN.size(); i++ )
      free(SN[i]);
  }

  SymNum number( const char *s ) {
    SymbolMap::iterator it=ST.find(s);
    if (it != ST.end())
      return it->second;

    // insert the new symbol into the tables
    char *r = strdup(s);
    size_t n = SN.size();
    if (n > MaxSymNum)
      throw("too many grammar symbols!");
    SN.push_back(r);
    ST[r] = (SymNum)n;
    return (SymNum)n;
  }

  const char *name( SymNum n ) {
    if (n < SN.size())
      return SN[n];
    return NULL;
  }

  typedef SymbolMap::iterator iterator;

  iterator find( const char *s ) { return ST.find(s); }
  iterator begin() { return ST.begin(); }
  iterator end()   { return ST.end(); }
  size_t   size()  { return ST.size(); }
};

