// file: $isip/class/pr/LanguageModelABNF/LanguageModelABNF.h
// version: $Id: LanguageModelABNF.h 10511 2006-03-17 17:01:48Z may $
//

// make sure definitions are only made once
//
#ifndef ISIP_LANGUAGEMODELABNF
#define ISIP_LANGUAGEMODELABNF

// isip include files
//
#ifndef ISIP_DIGRAPH
#include <DiGraph.h>
#endif

#ifndef ISIP_LANGUAGE_MODEL_BASE
#include <LanguageModelBase.h>
#endif

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

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

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

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

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

#ifndef ISIP_PRODUCTIONRULE
#include <ProductionRule.h>
#endif

#ifndef ISIP_PRODUCTIONRULETOKENTYPE
#include <ProductionRuleTokenType.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

typedef Vector<Pair<SearchSymbol, Float> > WeightedSymbols;


// LanguageModelABNF: a class used for converting ABNF productions into a set
// of BNF Productions. This class reads in ABNF productions from
// LanguageModelXML. The weights that are passed from the LanguageModelXML
// are preserved even after conversion. A Vector<Vector<Vector<
// ProductionRules>>> is passed to LanguageModelABNF,
// which takes one production at a time and removes the meta symbols. 
//
class LanguageModelABNF : public LanguageModelBase {

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

  //------------------------------------
  //
  // i/o related constants
  //
  //------------------------------------
  
  static const String DEF_PARAM;
  static const long DEF_LEVEL;
  static const String PARAM_ABNF;
  static const long DEF_TAG;
    
  //-------------------------------------
  //
  // default values and arguments
  //
  //-------------------------------------
  
  // define the default attribute values
  //
  static const float DEF_WEIGHT;
  
  //-------------------------------------
  //
  // error codes
  //
  //-------------------------------------
  
  static const long ERR = 100800;
  static const long ERR_CTXT_INV_SYM = 100801;
  static const long ERR_RULE_EMPTY = 100802;

  //--------------------------------------
  //
  // protected data
  //
  //-------------------------------------- 
protected:

  // search direction
  //
  enum DIRECTION {RIGHT=0, LEFT};
  
  // rulemodel name
  //
  RuleModel abnf_model_d;

  // holds count for non-conflicting variable names
  //
  long count_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;
  
  // method: destructor
  //
  // ~LanguageModelABNF() { }

  // method: default constructor
  //
  LanguageModelABNF();

  // 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 rm_d.sofSize();
  }
  
  // method: assign
  //
  boolean assign(const LanguageModelABNF& lmabnf_a); 
  
  // method: operator=
  //
  boolean operator=(const LanguageModelABNF& lmabnf_a);
  
  // method: eq
  //
  boolean eq(const LanguageModelABNF& lmabnf_a) const;
  
  // method: operator==
  //
  boolean operator==(const LanguageModelABNF& lmabnf_a) const;
  
  // method: clear
  //
  boolean clear(Integral::CMODE ctype);
  
  //---------------------------------------------------------------------------
  //
  // class-specific public methods required by interface contract
  // defined in LanguageModelBase.h
  //
  //---------------------------------------------------------------------------

  // LanguageModelBase required methods
  //
  boolean assign(const LanguageModelBase& arg);
  boolean eq(const LanguageModelBase& arg) const;

  // method: className
  //
  const String& className() const {
    return CLASS_NAME;
  }
  
  // method: retrieve equivalent BNF production rules
  //
  RuleModel getRuleModel();
  
  // method: pass in equivalent BNF production rules
  //
  boolean setRuleModel(const RuleModel& model_a) {
    return (rm_d.assign(model_a) && abnf_model_d.assign(model_a));
  }

  // method: retrieve equivalent ABNF production rules
  //
  RuleModel getABNFRuleModel() {
    return abnf_model_d;
  }
  
  // method: pass in equivalent ABNF production rules
  //
  boolean setABNFRuleModel(const RuleModel& model_a) {
    return abnf_model_d.assign(model_a);
  }
       
  //---------------------------------------------------------------------------
  //
  // class-specific protected methods
  //
  //---------------------------------------------------------------------------
protected:
  
  //---------------------------------------------------------------------------
  //
  // ABNF to BNF conversion methods
  //
  //---------------------------------------------------------------------------

  // method: getRightSymbols
  //
  WeightedSymbols findRightSymbols(ProductionRuleSet& rules,
				  long index, long nest_level,
				  long position, Float weight);
  
  // method: getLeftSymbols
  //
  Vector<SearchSymbol> findLeftSymbols(ProductionRuleSet& rules,
				      long index, long nest_level,
				      long position);

  // method: buildNormBNFRules
  //  
  boolean buildNormBNFRules(Vector<SearchSymbol> left_symbols,
			    WeightedSymbols right_symbols,
			    ProductionRuleSet& bnf_rules);

  // method: findEndOfNestLevel
  //
  long findEndOfNestLevel(ProductionRule current_rule, long index,
			  DIRECTION dir);

  // method: findToken
  //  
  long findToken(ProductionRule current_rule, long index,
		 ProductionRuleTokenType::TYPE token, DIRECTION dir);

  // method: restoreSymbols
  //  
  boolean restoreSymbols(ProductionRuleSet& rules,
			 Vector<Pair<SearchSymbol, SearchSymbol> > chart);    

  // method: createStartRules
  //
  boolean createStartRules(RuleModel abnf_rules,
			   ProductionRuleSet& bnf_rules, long level_index,
			   long graph_index);
  
};

#endif
