// file: JSGFToken.h
//
// make sure definitions are only made once
//
#ifndef ISIP_JSGF_TOKEN
#define ISIP_JSGF_TOKEN

// isip include files
//
#ifndef ISIP_CHAR
#include <Char.h>
#endif

#ifndef ISIP_STRING
#include <String.h>
#endif

#ifndef ISIP_FLOAT
#include <Float.h>
#endif

#ifndef ISIP_LONG
#include <Long.h>
#endif

#ifndef ISIP_VECTOR
#include <Vector.h>
#endif

// Token: a class to store a tokenized component of JSGF grammar
//
class JSGFToken {  

  //--------------------------------------------------------
  //
  // public constants
  //
  //--------------------------------------------------------
public:
  
  // define the class name
  //
  static const String CLASS_NAME;

  // constants: i/o related constants
  //
  static const long DEF_TOKEN_TYPE;
  static const String DEF_HEADER;
  static const String DEF_KEYWORD;
  static const String DEF_GRAMMAR_NAME;
  static const String DEF_IMPORT_GRAMMAR;
  static const String DEF_RULENAME;
  static const String DEF_TERMINAL;
  static const String DEF_OPERATOR;
  static const String DEF_TAG;
  static const String DEF_TERM_RULE_NAME;
  static const float DEF_WEIGHT;
  static const long DEF_TERM_ROW;
  static const long DEF_TERM_COL;
  static const long DEF_VERTEX_INDEX;
  static const boolean DEF_IS_HEAD_GROUP;
  static const boolean DEF_WEIGHTED_TERMINAL;
  static const long DEF_OPERATOR_SIZE;
  
  //----------------------------------------
  //
  // error codes
  //
  //----------------------------------------  

  static const long ERR = (long)50200;
  
  //-------------------------------------------------------------
  //
  // protected data
  //
  //-------------------------------------------------------------
public:
  
  enum TYPE {HEADER = 0, KEYWORD, GRAMMAR_NAME, IMPORT_GRAMMAR_NAME, RULE_NAME,
	     TERMINAL, TAG, QUOTED_TOKEN, WEIGHT, OPERATOR, MARKER,
	     DEF_TYPE = HEADER};

  // numeric value identifying the token's type
  // 0: header
  // 1: keyword
  // 2: grammar name
  // 3: import grammar name
  // 4: rule name
  // 5: terminal
  // 6: tag
  // 7: quoted token
  // 8: weight
  // 9: operator
  // 10: parser-defined marker
  //
  TYPE token_type_d;

  // self-identifying header
  //
  String header_d;

  // keyword (public)
  //
  String keyword_d;

  // grammar name
  //
  String grammar_name_d;

  // import grammar
  //
  String import_grammar_d;  

  // refernce to a rule in surrounding <>
  //
  String rulename_d;     

  // a speakable terminal token
  //
  String terminal_d;

  // operators
  //
  Vector<String> operator_d;     

  // tag string surrounded by {}
  //
  String tag_d;
  
  // weight of the token
  //
  float weight_d;

  // term_row: the index of the queue containing this terminal (row)
  //
  long term_row_d;

  // term_rule_name: the name of the rule containing this terminal (row)
  //
  String term_rule_name_d;

  // term_col: the index of this terminal in the queue (column)
  //
  long term_col_d;

  // vertex_index: the index of this terminal in the symbol vertex list
  //
  long vertex_index_d;
  
  // is_head_group: flag to determine if the token is optional group
  //
  boolean is_head_group_d;
  
  // weight flag indicating if a weight is assigned to the token
  //
  boolean weighted_terminal_d;
  
  // static memory manager
  //
  static MemoryManager mgr_d;

  //--------------------------------------------------------
  //
  // required public methods
  //
  //--------------------------------------------------------
public:

  // method: name
  //
  static const String& name() {
    return CLASS_NAME;
  }

  // method: diagnose
  //
  static boolean diagnose(Integral::DEBUG level_a);

  // method: debug
  //
  boolean debug(const unichar* msg_a) const;

  // method: destructor
  //
  ~JSGFToken() {};

  // method: constructor
  //
  JSGFToken();

  // method: assign
  //
  boolean assign(const JSGFToken& arg_a);

  // method: operator=
  //
  JSGFToken& operator=(const JSGFToken& arg_a) {
    assign(arg_a);
    return *this;
  }
  
  // method: eq
  //
  boolean eq(const JSGFToken& arg_a) const;

  // method: operator==
  //
  boolean operator==(const JSGFToken& arg_a) {
    return eq(arg_a);
  }

  // method: read
  //
  boolean read(Sof& sof, long tag, const String& cname = CLASS_NAME) {
    return Error::handle(name(), L"read", Error::NOT_IMPLEM, __FILE__,
			 __LINE__);
  }

  // method: write
  //
  boolean write(Sof& sof, long tag, const String& cname = CLASS_NAME) const {
    return Error::handle(name(), L"write", Error::NOT_IMPLEM, __FILE__,
			 __LINE__);
  }
  
  // method: new
  //
  static void* operator new(size_t size) {
    return mgr_d.get();
  }

  // method: new[]
  //
  static void* operator new[](size_t size) {
    return mgr_d.getBlock(size);
  }

  // method: delete
  //
  static void operator delete(void* ptr) {
    mgr_d.release(ptr);
  }

  // method: delete[]
  //
  static void operator delete[](void* ptr) {
    mgr_d.releaseBlock(ptr);
  }

  // method: setGrowSize
  //
  static boolean setGrowSize(long grow_size) {
    return mgr_d.setGrow(grow_size);
  }
  
  // method: clear
  //
  boolean clear(Integral::CMODE ctype_a = Integral::RELEASE);
  
  //--------------------------------------------------------
  //
  // class-specified public methods
  //
  //--------------------------------------------------------
public:
  
  //--------------------------------------------------------
  //
  // get/set methods
  //
  //--------------------------------------------------------

  // method: setOperator
  //
  
  // method: get
  //
  
  // method: setHeader
  //
  boolean setHeader(String header_a) {
    return header_d.assign(header_a);
  }

  // method: getHeader
  //
  String getHeader() {
    return header_d;
  }

  // method: setKeyword
  //
  boolean setKeyword(String keyword_a) {
    return keyword_d.assign(keyword_a);
  }
  
  // method: get
  //
  String getKeyword() {
    return keyword_d;
  }
  
  // method: setGrammarName
  //
  boolean setGrammarName(String grammar_name_a) {
    return grammar_name_d.assign(grammar_name_a);
  }
  
  // method: getGrammarName
  //
  String getGrammarName() {
    return grammar_name_d;
  }
  
  // method: setImportGrammar
  //
  boolean setImportGrammar(String import_grammar_a) {
    return import_grammar_d.assign(import_grammar_a);
  }

  // method: getImportGrammar
  //
  String getImportGrammar() {
    return import_grammar_d;
  }

  // method: setRuleName
  //
  boolean setRuleName(String rule_name_a) {
    return rulename_d.assign(rule_name_a);
  }

  // method: getRuleName
  //
  String getRuleName() {
    return rulename_d;
  }

  // method: setTag
  //
  boolean setTag(String tag_a) {
    return tag_d.assign(tag_a);
  }
  
  // method: getTag
  //
  String getTag() {
    return tag_d;
  }

  // method: setWeight
  //
  boolean setWeight(float weight_a) {
    weight_d = weight_a;
    return true;
  }

  // method: getWeight
  //
  float getWeight() {
    return weight_d;
  }
  
  // method: setToken
  //
  boolean setToken(const String& arg_a);
  
  // method: setVertexIndex
  //
  boolean setVertexIndex(const long vertex_index_a);
  
  // method: setTermRuleName
  //
  boolean setTermRuleName(const String& rule_name_a);
  
  // method: setMarker
  //
  boolean setMarker(const String& marker_a, const JSGFToken& name_a);

  // method: printToken
  //
  boolean printToken();

  // method: getTerminal
  //
  String getTerminal() {
    return terminal_d;
  }

  // method: set
  //
  boolean setTerminal(String terminal_a) {
    return terminal_d.assign(terminal_a);
  }

  // method: getTokenType
  //
  TYPE getTokenType() {
    return token_type_d;
  }

  // method: setTokenType
  //
  boolean setTokenType(TYPE token_type_a) {
    token_type_d=token_type_a;
    return true;
  }
  
  // method: setCoordinate
  //
  boolean setCoordinate(long row_a, long col_a);

  // method: setTerminalWeight
  //
  boolean setTerminalWeight(JSGFToken& arg_a);
    
  //--------------------------------------------------------
  //
  // private methods
  //
  //--------------------------------------------------------
private:
  
  // method: isHeader
  //
  boolean isHeader(const String& arg_a);

  // method: isKeyword
  //
  boolean isKeyword(const String& arg_a);

  // method: isGrammarName
  //
  boolean isGrammarName(const String& arg_a);

  // method: isImportGrammar
  //
  boolean isImportGrammar(const String& arg_a);
  
  // method: isRulename
  //
  boolean isRulename(const String& arg_a);     

  // method: isTerminal
  //
  boolean isTerminal(const String& arg_a);

  // method: isOperator
  //
  boolean isOperator(const String& arg_a);     

  // method: isTag
  //
  boolean isTag(const String& arg_a);  

  // method: isQuotedToken
  //
  boolean isQuotedToken(const String& arg_a);

  // method: isWeight
  //
  boolean isWeight(const String& arg_a);
};

// end of file
//
#endif
