// file: $isip/class/asr/JSGFToken/jt_04.cc
//
// implementation file for Token class
//
// isip include files
//
#include "JSGFToken.h"
#include <Console.h>

//-------------------------------------------------------------------
//
// class-specified public methods
//
//--------------------------------------------------------------------

// method: setToken
//
boolean JSGFToken::setToken(const String& arg_a) {

  // token type is 0 for header
  //
  if (isHeader(arg_a)) {
    token_type_d = HEADER;
    header_d = arg_a;
  }

  // token type is 1 for keyword
  //
  else if (isKeyword(arg_a)) {
    token_type_d = KEYWORD;
    keyword_d = arg_a;
  }
    
  // token type is 2 for grammar name
  //
  else if (isGrammarName(arg_a)) {

    token_type_d = GRAMMAR_NAME;

    // set the leading "grammar" as keyword
    //
    arg_a.substr(keyword_d, 0, 7);

    // looking for the first character after the keyword
    //
    long start = arg_a.firstNotSpace(7);
    long end = arg_a.lastNotSpace(arg_a.length() - 2);
    
    // set grammar name
    //
    arg_a.substr(grammar_name_d, start, end - start + 1);

    // set the ending sign as operator 
    //
    operator_d(0).assign(L";");
  }

  // token type is 3 for import grammar
  //
  else if(isImportGrammar(arg_a)) {

    token_type_d = IMPORT_GRAMMAR_NAME;

    // set the leading "import" as keyword
    //
    arg_a.substr(keyword_d, 0, 6);

    // get the imported graammar name
    //
    long len = arg_a.length();
    long start = arg_a.firstNotSpace(6);		      
    long end = arg_a.lastNotSpace(len - 2);

    // set the string in the <> brackets as the import grammar name
    //
    arg_a.substr(import_grammar_d, start + 1, end - start - 1);
    
    // set the ending sign as operator 
    //
    operator_d(0) = L"<";
    operator_d(1) = L">";
  }
  
  // token type is 4 for rulename
  //
  else if(isRulename(arg_a)) {
    token_type_d = RULE_NAME;
    operator_d(0) = L"<";
    operator_d(1) = L">";
    arg_a.substr(rulename_d, 1, arg_a.length() - 2);
  }

  // token type is 5 for terminal
  //
  else if(isTerminal(arg_a)) {
    token_type_d = TERMINAL;
    terminal_d.assign(arg_a);
  }

  // token type is 6 for tag
  //
  else if(isTag(arg_a)) {
    token_type_d = TAG;
    operator_d(0) = L"{";
    operator_d(1) = L"}";
    arg_a.substr(tag_d, 1, arg_a.length() - 2);
  }

  // token type is 7 for quoted token
  //
  else if(isQuotedToken(arg_a)) {
    token_type_d = QUOTED_TOKEN;
    operator_d(0) = L"\"";
    operator_d(1) = L"\"";
    arg_a.substr(terminal_d, 1, arg_a.length() - 2);
  }

  // token type is 8 for weight
  //
  else if(isWeight(arg_a)) {
    token_type_d = WEIGHT;
    operator_d(0) = L"/";
    operator_d(1) = L"/";

    // set the weight number as weight_d data
    //
    String tmp;
    arg_a.substr(tmp, 1, arg_a.length() - 2);

    // cast string to double
    //
    Float weight;
    weight.assign(tmp);
    weight_d = weight;
  }

  // token type is 9 for operator
  //
  else if(isOperator(arg_a)) {
    token_type_d = OPERATOR;
    operator_d(0) = arg_a;
  }

  // exception: input string cannot be accepted as a legal token
  //
  else {
    return false;
  }
  
  // gracefully exit
  //
  return true;
}


// method: setVertexIndex
//
boolean JSGFToken::setVertexIndex(const long vertex_index_a) {

  vertex_index_d = vertex_index_a;

  // gracefully exit
  //
  return true; 
}

// method: setRuleName
//
boolean JSGFToken::setTermRuleName(const String& rule_name_a) {

  term_rule_name_d.assign(rule_name_a);

  // gracefully exit
  //
  return true; 
}


// method: setMarker
//
boolean JSGFToken::setMarker(const String& marker_a,
			     const JSGFToken& name_a) {
  // token type is 10 for marker
  //
  token_type_d = MARKER;
  operator_d(0) = marker_a;
  rulename_d.assign(name_a.rulename_d);

  // gracefully exit
  //
  return true; 
}

// method: printToken
//
boolean JSGFToken::printToken() {
  // header
  //
  if (token_type_d == HEADER) {
    Console::put(header_d);
  }
  // grammar name
  //
  else if (token_type_d == GRAMMAR_NAME) {
    String output(keyword_d);
    output.concat(L" ");
    output.concat(grammar_name_d);
    Console::put(output);
  }
  // import grammar
  //
  else if (token_type_d == IMPORT_GRAMMAR_NAME) {
    String output(keyword_d);
    output.concat(L" ");
    output.concat(operator_d(0));
    output.concat(import_grammar_d);
    output.concat(operator_d(1));
    Console::put(output);
  }
  // keyword for public rulename
  //
  else if (token_type_d == KEYWORD) {
    Console::put(keyword_d);
  }
  // rulename
  //
  else if (token_type_d == RULE_NAME) {
    String output(operator_d(0));
    output.concat(rulename_d);
    output.concat(operator_d(1));
    Console::put(output);
  }
  // terminal 
  //
  else if (token_type_d == TERMINAL) {
    Console::put(terminal_d);
  }
  // tag
  //
  else if (token_type_d == TAG) {
    String output(operator_d(0));
    output.concat(tag_d);
    output.concat(operator_d(1));
    Console::put(output);
  }
  // quoted token
  //
  else if (token_type_d == QUOTED_TOKEN) {
    String output(operator_d(0));
    output.concat(terminal_d);
    output.concat(operator_d(1));
    Console::put(output);
  }
  // weight
  //
  else if (token_type_d == WEIGHT) {
    Float weight(weight_d);
    String output(operator_d(0));
    output.concat(weight);
    output.concat(operator_d(1));
    Console::put(output);
  }
  // operator
  //
  else if (token_type_d == OPERATOR) {
    Console::put(operator_d(0));
  }
  // marker
  //
  else if (token_type_d == MARKER) {
    String output(operator_d(0));
    output.concat(L" <");
    output.concat(rulename_d);
    output.concat(L">");
    Console::put(output);
  }

  // exit gracefully
  //
  return true;
}

// method: setCoordinate
// set coordinate for terminal token in DiGraph
//
boolean JSGFToken::setCoordinate(long row_a, long col_a) {
  term_row_d = row_a;
  term_col_d = col_a;
  
  // gracefully exit
  //
  return true;
}

// method: setTerminalWeight
//
// arguments: JSGFToken& arg_a: (input) a JSGF weight token 
//
// return: a boolean value indicating status
//
// set a weight value of input weight token to the given terminal,
// quoted token, or grouping operator( or [ 
//
boolean JSGFToken::setTerminalWeight(JSGFToken& arg_a) {
  
  // pick up the input weight value and set it to this token
  //
  weight_d = arg_a.weight_d;
  
  // set weight flag to indicate a weight value has been assigned
  //
  weighted_terminal_d = true;

  // gracefully exit
  //
  return true;
}
