// file: $isip/class/asr/JSGFParser/jp_03.cc
// version: $Id: jp_07.cc 10499 2006-03-15 21:43:17Z may $
//

// isip include files
//
#include "JSGFParser.h"

// method: setRuleTables
//
// arguments: none
//
// return: a boolean value indicating status
//
// This method check through the whole grammar picking up each rule
// definition and set it into appropriate class-protected rule table
//
boolean JSGFParser::setRuleTables() {

  long index = 0;
  while (index < token_vect_d.length()) {

    JSGFToken t = token_vect_d(index);

    // look for operator= token to split a rule definition 
    //
    if (t.operator_d(0).eq(L"=")) {

      // get the previous two tokens
      //
      JSGFToken rule_name, rule_type;
      rule_name = token_vect_d(index - 1);
      rule_type = token_vect_d(index - 2);
      
      // move to the first token after the operator=
      //
      index++;
      t = token_vect_d(index);
      
      // split out the rule expansion part
      //
      Vector<JSGFToken> rule_exp;
      while (!t.operator_d(0).eq(L";")) {

	// setting the location of terminal Token in corresponding Rule
	//
	if (t.getTokenType() == JSGFToken::TERMINAL ||
	    t.getTokenType() == JSGFToken::QUOTED_TOKEN) {
	  t.term_rule_name_d.assign(rule_name.rulename_d);
	  t.term_col_d = rule_exp.length();
	}	
	rule_exp.concat(t);
	index++;
	t = token_vect_d(index);
      }

      // create a pair of rule name and rule expansion
      //
      Pair< JSGFToken, Vector<JSGFToken> > pair;
      pair.assign(rule_name, rule_exp);
	
      // make sure the rule has never been defined before
      //
      if (ruleNotDefined(rule_name)) {

	// insert the rule into the public rule table if the rule is defined
	// with a public keyword
	//
	if (rule_type.getTokenType() == JSGFToken::KEYWORD) {
	  public_rule_table_d.concat(pair);
	}      
	// else the rule is private and need to be inserted into
	// the private rule table
	//
	else {
	  private_rule_table_d.concat(pair);
	}
      }
    } // end: if (t.operator_d[0).eq(L"="))

    // move to the next token
    //
    index++;
  } // end: while (index < token_vect_d.length())

  // make sure at least one public rule is defined
  //
  if (public_rule_table_d.length() == 0) {
    return Error::handle(name(), L"no public rule defined",
			 Error::TEST, __FILE__, __LINE__);
  }
  
////////////////////////////////////////////////////////////////////////
  //Console::put(L"\n\n\n>>>>>>>>>>>>>>>>>>public table>>>>>>>>>>>>>>>>>>>>>>>>");
  for ( long i=0; i < public_rule_table_d.length(); i++) {

     JSGFToken t_1;
     Vector<JSGFToken> t_2;
     t_1 = public_rule_table_d(i).first();
     t_2 = public_rule_table_d(i).second();
     //t_1.printToken();
     //Console::put(L"------------------------------");
     for ( long j=0; j< t_2.length(); j++) {

       JSGFToken ttt(t_2(j));
       //ttt.printToken();
     }
     //Console::put(L"*********one pair*******************************");
   }

  //Console::put(L">>>>>>>>>>>>>>>>>>>>>private table>>>>>>>>>>>>>>>>>>>>>>>>");
  for ( long i=0; i < private_rule_table_d.length(); i++) {

     JSGFToken t_1;
     Vector<JSGFToken> t_2;
     t_1 = private_rule_table_d(i).first();
     t_2 = private_rule_table_d(i).second();
     //t_1.printToken();
     //Console::put(L"------------------------------");
     for ( long j=0; j< t_2.length(); j++) {

       JSGFToken ttt(t_2(j));
       //ttt.printToken();
     }
     //Console::put(L"*********one pair*******************************");
   } 
///////////////////////////////////////////////////////////////
  
  // exit gracefully
  //
  return true;
}

// method: ruleNotDefined
//
// arguments: JSGFToken& rulename_a: (input) a rulename token
//                             to be checked in the rule tables
//
// return: a boolean value indicating status
//
// This method check through the rule tables to verify if the given
// rulename has been listed, that is, if the given rule has been defined 
//
boolean JSGFParser::ruleNotDefined(JSGFToken& rulename_a) {

  // check public rule table
  //
  for (long i = 0; i < public_rule_table_d.length(); i++) {

    JSGFToken t = public_rule_table_d(i).first();

    // error if the rulename is already defined in the table
    //
    if (rulename_a.rulename_d.eq(t.rulename_d)) {

      rulename_a.printToken();
      return Error::handle(name(),
			   L"the rule cannot be defined more than once",
			   Error::TEST, __FILE__, __LINE__);
    }
  }

  // check private rule table
  //
  for (long i = 0; i < private_rule_table_d.length(); i++) {

    JSGFToken t = private_rule_table_d(i).first();

    // error if the rulename is already defined in the table
    //
    if (rulename_a.rulename_d.eq(t.rulename_d)) {

      rulename_a.printToken();
      return Error::handle(name(),
			   L"a rule cannot be defined more than once",
			   Error::TEST, __FILE__, __LINE__);
    }
  } 

  // exit gracefully
  //
  return true;
}

// method: getPublicRuleNames
//
// arguments: none
//
// return: a boolean value indicating status
//
// This method get all the public rule names in current parser
//
boolean JSGFParser::getPublicRuleNames(Vector<JSGFToken>& public_tokens_a) {

  // clear the vector
  //
  public_tokens_a.clear();
  
  for ( long i=0; i < public_rule_table_d.length(); i++) {

    // put the token into the output vector
    //
    public_tokens_a.concat(public_rule_table_d(i).first());
  } 
  
  // exit gracefully
  //
  return true;
}

// method: getPublicRuleNames
//
// arguments: none
//
// return: a boolean value indicating status
//
// This method get all the public rule names in current parser
//
boolean JSGFParser::getPublicRuleNames(Vector<String>& public_tokens_a) {

  // clear the vector
  //
  public_tokens_a.clear();
  
  for ( long i=0; i < public_rule_table_d.length(); i++) {

    // get a token from the table
    //
    JSGFToken temp_token = public_rule_table_d(i).first();
    
    // get the string from the token
    //
    public_tokens_a.concat(temp_token.rulename_d);
  } 
  
  // exit gracefully
  //
  return true;
}


