// file: $isip/class/pr/ProductionRule/ProductionRule.h
// version: $Id: ProductionRule.h 10497 2006-03-15 21:40:16Z may $

#ifndef ISIP_PRODUCTIONRULE
#define ISIP_PRODUCTIONRULE

//---------------------------------------------------------------------------
//
// ISIP include files
//
//---------------------------------------------------------------------------

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

#ifndef ISIP_DOUBLE_LINKED_LIST
#include <DoubleLinkedList.h>
#endif

#ifndef ISIP_PRODUCTIONRULETOKENTYPE
#include <ProductionRuleTokenType.h>
#endif

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

#ifndef ISIP_FILENAME
#include <Filename.h>
#endif

#ifndef ISIP_FILE
#include <File.h>
#endif

#ifndef ISIP_DEBUGLEVEL
#include <DebugLevel.h>
#endif

#ifndef ISIP_TRIPLE
#include <Triple.h>
#endif

#ifndef ISIP_SOF
#include <Sof.h>
#endif

class ProductionRule {
public:  
  
  //---------------------------------------------------------------------------
  //
  // public constants
  //
  //---------------------------------------------------------------------------
public:
  
  // constant: class name
  //
  static const String CLASS_NAME;
  

  //---------------------------------------
  //
  // type related constants
  //
  //---------------------------------------  
  //
  enum TYPE {NORMAL=0, START, DEF_TYPE = NORMAL};

  // define type NameMap object
  //
  static const NameMap TYPE_MAP;

  //---------------------------------------
  //
  // file i/o constants
  //
  //---------------------------------------
  //
  static const String DEF_PARAM;
  static const String PARAM_RULE_NAME;
  static const String PARAM_RULE_TYPE;  
  static const String PARAM_RULE;  
  static const String RULE_NAME_BASE;
  static const String START_RULE_NAME;
  static const String TERM_RULE_NAME;
  static const String DEF_RULE_NAME;  
  static const long DEF_TAG;
  
  //---------------------------------------
  //
  // error codes
  //
  //---------------------------------------
  //
  
  //---------------------------------------------------------------------------
  //
  // protected data
  //
  //---------------------------------------------------------------------------

protected:
  
  // rule name
  //
  String rule_name_d;

  // rule type
  //
  TYPE rule_type_d;

  // rule list.  this contains a series of operators and tokens and weights
  //
  DoubleLinkedList< Triple<ProductionRuleTokenType, String, Float> > rule_d;
  
  // debug level
  //
  DebugLevel debug_level_d;

  //---------------------------------------------------------------------------
  //
  // required public methods
  //
  //---------------------------------------------------------------------------
public:
  
  // method: name
  //
  static const String& name() {
    return CLASS_NAME;
  } 
  
  // method: diagnose
  //
  static boolean diagnose(Integral::DEBUG level);
  
  // method: debug
  //
  boolean debug(const unichar* msg) const;
  
  // constructor
  //
  ProductionRule ();
  
  // method: read
  //
  boolean read(Sof& sof, long tag, const String& cname = CLASS_NAME);
  
  // method: readData
  //
  boolean readData(Sof& sof, const String& pname = DEF_PARAM,
		   long size = SofParser::FULL_OBJECT, boolean param = true,
		   boolean nested = false);
  
  // method: write
  //
  boolean write(Sof& sof, long tag, const String& cname = CLASS_NAME) const;
  
  // method: writeData
  //
  boolean writeData(Sof& sof, const String& pname = DEF_PARAM) const;
  
  // method: sofSize
  //
  long sofSize() const {
    return rule_d.sofSize()+rule_name_d.sofSize();
  }
  
  // method: assign
  //
  boolean assign(const ProductionRule& prdrl_a); 
  
  // method: operator=
  //
  boolean operator=(const ProductionRule& prdrl_a);
  
  // method: eq
  //
  boolean eq(const ProductionRule& prdrl_a) const;
  
  // method: operator==
  //
  boolean operator==(const ProductionRule& prdrl_a) const;
  
  // method: clear
  //
  boolean clear(Integral::CMODE ctype = Integral::DEF_CMODE);
  
  //---------------------------------------------------------------------------
  //
  // class-specific public methods
  //
  //---------------------------------------------------------------------------
public:

  long length() const;

  //----------------------------------------------------------
  //
  // traversal methods and traversal-based operations
  //
  //----------------------------------------------------------

  // method: removeCurr()
  //
  boolean removeCurr();
  
  // method: gotoFirst
  //
  boolean gotoFirst();

  // method: gotoNext
  //
  boolean gotoNext();

  // method: gotoPrev
  //
  boolean gotoPrev();

  // method: gotoPosition
  //
  boolean gotoPosition(long position);

  // method: getType
  //
  boolean setType(ProductionRuleTokenType type);

  // method: getValue
  //
  boolean setValue(String value);

  // method: getWeight
  //
  boolean setWeight(Float weight);

  // method: getType
  //
  ProductionRuleTokenType::TYPE getType();

  // method: getValue
  //
  String getValue();

  // method: getWeight
  //
  Float getWeight();

  // method: insert
  //
  boolean insert(const ProductionRuleTokenType::TYPE& type_a,
		 const String& value_a=L"", Float weight_a=0);
  
  // method: append
  //
  boolean append(const ProductionRuleTokenType::TYPE& type_a,
		 const String& value_a, Float weight_a);
  boolean append(const ProductionRuleTokenType::TYPE& type_a,
		 const String& value_a=L"");

  //----------------------------------------------------------
  //
  // get methods
  //
  //----------------------------------------------------------

  // get rule - return a string representation of the entire rule
  //
  String getRule();
  
  // get rule name
  //
  String getRuleName();

  // method: getRuleType
  //
  TYPE getRuleType() {
    return rule_type_d;
  }
  
  //----------------------------------------------------------
  //
  // set methods
  //
  //----------------------------------------------------------

  // set rule name
  //
  boolean setRuleName(const String& rule_name_a);

  // method: setDebug
  //
  boolean setDebug(Integral::DEBUG level) {
    debug_level_d = level;
    return true;
  }

  // method: setRuleType
  //
  boolean setRuleType(TYPE type_a) {
    rule_type_d = type_a;
    return true;
  }
  
  //---------------------------------------------------------------------------
  //
  // class-specific protected methods
  //
  //---------------------------------------------------------------------------
protected:

  // method: convertToString
  //
  String convertToString(Triple<ProductionRuleTokenType, String, Float>& item_a);
};

#endif
