// file: $isip/class/pr/LanguageModelJSGF/LanguageModelJSGF.h
//

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

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

#ifndef ISIP_JSGF_PARSER
#include <JSGFParser.h>
#endif

// forward class definitions
//

// LanguageModelJSGF: Used for language models in JSGF (JAVA Speech Grammar Format) Format.
//
class LanguageModelJSGF : public LanguageModelBase {

  //---------------------------------------------------------------------------
  //
  // public constants
  //
  //---------------------------------------------------------------------------
public:

  // define the class name
  //
  static const String CLASS_NAME;

  //--------------------------------------------------------------
  //
  // other important constants
  //
  //--------------------------------------------------------------

  static const SearchSymbol START_SYMBOL;
  static const SearchSymbol TERM_SYMBOL;

  static const long DEF_LEVEL = -1;
  
  //----------------------------------------
  //
  // i/o related constants
  //
  //----------------------------------------  
  
  static const String DEF_PARAM;
  static const String PARAM_GRAMMARS;

  static const String TOP_GRAMMAR_NAME;

  // jsgf comments
  //
  static const String COMMENT_GRAMMAR_NAME;
  static const String COMMENT_TERM_SYMBOL;
  static const String COMMENT_START_SYMBOL;
  static const String COMMENT_RESERVED_GRAMMAR;
  static const String COMMENT_SYMBOLS;
  static const String COMMENT_RULES;
  static const String COMMENT_CONTEXT_RULE;

  // other JSGF standard syntax constants
  //
  static const String PARAM_JSGF_START_SYMBOL;
  static const String PARAM_JSGF_TERM_SYMBOL;
  static const String START_SYMBOL_REFERENCE;
  static const String TERM_SYMBOL_REFERENCE;
  static const String OPERATOR_OPENPARENS;
  static const String OPERATOR_CLOSEPARENS;
  static const String OPERATOR_OPENANGLEBRACKET;
  static const String OPERATOR_CLOSEANGLEBRACKET;
  static const String OPERATOR_FWDSLASH;
  static const String OPERATOR_EQUALS;
  static const String OPERATOR_ALTERNATION;
  static const String OPERATOR_SEMICOLON;

  // open/close operator constants
  //
  static const long OPERATOR_OPEN_POS;
  static const long OPERATOR_CLOSE_POS;

  // other i/o constants
  //
  static const String KEYWORD_PUBLIC;
  static const String KEYWORD_GRAMMAR;
  static const String GRAMMAR_DEF_BASE;
  static const String PARAM_UNDERSCORE;
  static const String PARAM_JSGF_VERSION;
  static const String CONTEXT_LABEL_PREFIX;
  static const String RULE_NAME_BASE;
  
  //----------------------------------------
  //
  // default values and arguments
  //
  //----------------------------------------

  //----------------------------------------
  //
  // error codes
  //
  //----------------------------------------  

  static const long ERR = 100102;
  
  //---------------------------------------------------------------------------
  //
  // protected data
  //
  //---------------------------------------------------------------------------
protected:

  // debug level
  //
  // debug_level_d inherited from LanguageModelBase

  // hierarchical digraph to store symbol table and symbol types
  //
  HierarchicalDigraph hg_d;

  // abnf rule model object
  //
  RuleModel abnf_model_d;

  // vector to store grammars
  //
  Vector< Vector < Vector<JSGFToken> > > grammars_d;
  
  // memory manager
  //
  static MemoryManager mgr_d;

  // isip standard jsgf start symbol
  //
  SearchSymbol start_symbol_d;

  // isip standard jsgf term symbol
  //
  SearchSymbol term_symbol_d;  

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

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

  // method: diagnose
  //
  static boolean diagnose(Integral::DEBUG debug_level);
  
  // debug methods
  //
  boolean debug(const unichar* msg) const;
  
  // method: destructor
  //
  ~LanguageModelJSGF() { }

  // method: default constructor
  //
  LanguageModelJSGF() { }

  // method: copy constructor
  //
  LanguageModelJSGF(const LanguageModelJSGF& arg) {
    assign(arg);
  }

  // assign methods
  //
  boolean assign(const LanguageModelJSGF& arg) {
    return rm_d.assign(arg.rm_d);
  }

  // i/o methods
  //
  // method: sofSize
  //
  long sofSize() const {
    return rm_d.sofSize();
  }

  // method: read
  //
  boolean read(Sof& sof, long tag, const String& cname = CLASS_NAME);

  // method: write
  //
  boolean write(Sof& sof, long tag, const String& cname = CLASS_NAME) const;


  // method: readData
  //
  boolean readData(Sof& sof, const String& pname = DEF_PARAM,
		   long size = SofParser::FULL_OBJECT,
		   boolean param = true, boolean nested = false);

  // method: writeData
  //
  boolean writeData(Sof& sof, const String& pname = DEF_PARAM) const;

  // other memory managements methods
  //
  boolean clear(Integral::CMODE cmode = Integral::DEF_CMODE) {
    return rm_d.clear();
  }
      
  // equality methods
  //
  boolean eq(const LanguageModelJSGF& arg) const {
    return rm_d.eq(arg.rm_d);
  }

  //---------------------------------------------------------------------------
  //
  // 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;
  
  //--------------------------------------------------------
  //
  // load and store methods
  //
  //--------------------------------------------------------

  //--------------------------------------------------------
  //
  // other methods
  //
  //--------------------------------------------------------  

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

  // method: getRuleModel
  //
  RuleModel getRuleModel();

  // method: getRuleModel
  //
  RuleModel getABNFRuleModel();
  
  // method: setRuleModel
  //
  boolean setRuleModel(const RuleModel& rm_a);

  // method: setABNFRuleModel
  //
  boolean setABNFRuleModel(const RuleModel& rm_a) {
    return rm_d.assign(rm_a);
  }

  // method: getJSGFGrammars
  //
  Vector< Vector < Vector<JSGFToken> > > getJSGFGrammars() {

    return grammars_d;
  }

  // method: setJSGF Grammars
  //
  boolean setJSGFGrammars(Vector< Vector < Vector<JSGFToken> > > grammars_a) {

    return grammars_d.assign(grammars_a);
  }
  
  //---------------------------------------------------------------------------
  //
  // private methods
  //
  //---------------------------------------------------------------------------
private:  

  // method: writeGrammars
  //
  boolean writeGrammars(Sof& sof, long level,
			HierarchicalDigraph& h_digraph) const;

  // method: writeSymbolType
  //
  boolean writeSymbolType(Sof& sof, long level, const String& pname,
			  Vector<SearchSymbol> symbol_list) const;

  // method: writeContextMapping
  //
  boolean writeContextMapping(Sof& sof, long level,
			      HierarchicalDigraph& h_digraph) const;
  
  // method: digraphToJSGF
  //
  String digraphToJSGF(DiGraph<SearchNode>& graph,
			SearchSymbol grammar_name) const;

  // method: readSymbolTypes
  //
  boolean readSymbolType(Sof& sof, long level, const String& pname,
			 Vector<SearchSymbol>& symbol_list_a,
			 SofParser& parser);
  
  // method: readGrammars
  //
  boolean readGrammars(Sof& sof, const String& pname, long level,
		       boolean use_context,
		       Vector<SearchSymbol>* symbol_table,
		       SofParser& parser);
  
  // method: readJSGF
  //
  boolean readJSGF(Sof& sof, String grammar, Vector<String>& sub_symbol_list,
		   DiGraph<String>& sub_graph, String& sub_graph_name,
		   Vector<JSGFToken>& jsgf_graph);

  // method: readContextMapping
  //
  boolean readContextMapping(Sof& sof, const String& pname, long level,
			     SofParser&parser);
  
  // method: alignGraphs
  //
  boolean alignGraphs(Vector<Vector<JSGFToken> >& token_vector,
		      Vector<SearchSymbol>& symbol_table,
		      Vector<String>& graph_name_list);
  
  // method: convertGraph
  //
  boolean convertGraph(DiGraph<String>& symbol_graph,
		       DiGraph<SearchNode>& node_graph, long& num_symbols,
		       long level);
  
  // method: convertJSGFtoABNF
  //
  ProductionRuleSet convertJSGFtoABNF(Vector<JSGFToken> grammar);

  // method: convertBNFtoJSFF
  //
  Vector<JSGFToken> convertBNFtoJSGF(ProductionRuleSet rules);
  
  // method: findRule
  //
  ProductionRule findRule(String ruleref, ProductionRuleSet rules);

  // method: convertTokensToString
  //
  boolean convertTokensToString(Vector<JSGFToken> token_grammar, String& string_grammar) const;
	
};

// end of include file
// 
#endif
