/* symbol.h */

#ifndef SYMBOL__H
#define SYMBOL__H

#include "data.h"
#include <LEDA/basic.h>
#include <LEDA/dictionary.h>
#include <LEDA/list.h>
#include "symbol_tdefs.h"

class dc_symbol : public dc_data {
private:
  dc_symbol_tag val;
  dc_svec_tag etype;
  int rank;

public:
  dc_symbol( void );
  dc_symbol( dc_symbol_tag, dc_svec_tag = undef_svec );
  dc_symbol( cstring, cstring );
  
  /* inherited functions */
  const dc_type type( void ) const { return Symbol_t; }
  string type_string( void ) const; /* of form (<type>|"<nil>") "symbol" */
  void get_xtype( xtype &xt ) const { 
    xt.T = xt.subT = Symbol_t; xt.inf.svec = etype; }

  ostream &display( ostream &stream = cout ){ return display_c( stream ); }
  ostream &display_c( ostream &stream = cout ) const;
  friend ostream &operator<<( ostream &stream, const dc_symbol &S ) {
    return S.display_c( stream );
  }
  
  /* functions to access val */
  dc_symbol_tag get( void ) const { return val; }
  dc_svec_tag get_type( void ) const { return etype; }
  int get_rank( void ) const { return rank; } /* 0 if no type */
  void set( const dc_symbol & ); /* most efficient */
  bool set( dc_symbol_tag ); /* true on failure */
  bool set( dc_symbol_tag, dc_svec_tag );
  bool set( cstring, cstring );

  dc_label *duplicate( dc_node *parent ) const;
};

struct dc_symbol_block{ 
private:
  dictionary<string, dc_symbol_tag> symbol_dict;
  dictionary<dc_symbol_tag, string> symbol_rdict;
  
  dictionary<string, dic_item> svec_dict; /* item into svec_map */
  dictionary<dc_svec_tag, list<dc_symbol_tag> *> svec_map;
  dictionary<dc_svec_tag, string> svec_rdict;
public:
  ~dc_symbol_block( void );

  dc_symbol_tag define_symbol( cstring );
  dc_symbol_tag lookup_symbol( cstring ) const;
  
  dc_svec_tag define_svec( cstring );
  dc_svec_tag lookup_svec( cstring ) const;
  
  bool add_symbol( cstring symbol, cstring type );
  bool add_symbol( dc_symbol_tag, dc_svec_tag );

  string svec_string( dc_svec_tag ) const;

  friend bool dc_symbol::set( dc_symbol_tag );
  friend bool dc_symbol::set( dc_symbol_tag, dc_svec_tag );
  friend bool dc_symbol::set( cstring, cstring );
  friend bool dc_symbol::type_string( void ) const;
  friend bool dc_symbol::display_c( ostream & = cout ) const;
};

extern dc_symbol_block sb;

#endif
