// -*- mode: c++ -*-
//
//  Copyright(C) 2010-2011 Taro Watanabe <taro.watanabe@nict.go.jp>
//

#ifndef __CICADA__GRAMMAR_MUTABLE__HPP__
#define __CICADA__GRAMMAR_MUTABLE__HPP__ 1

// very siple mutable grammar class..

#include <string>

#include <cicada/transducer.hpp>

namespace cicada
{
  
  class GrammarMutableImpl;

  class GrammarMutable : public Transducer
  {
  private:
    typedef GrammarMutableImpl impl_type;

  public:
    // mutable grammar, use to encode rule-table generated by nicttm, moses, joshua etc.
    // 
    // [x] ||| [x,1] ... ||| [x,1] ... ||| score1 score2
    //
    // The parameter must be of form:
    // parameter = file-name:[key=value delimited by ',']*
    // where:
    // file-name: file name for the grammar, "-" for stdin
    // key,value: key, value pair... valid pairs are..
    //
    // feature0=name feature1=another-name
    //
    // for feature names. By default, we will assign rule-table-0, rule-table-1 etc.
    //
    // or, you can supply optional feature-name to each score,
    //
    // [x] ||| [x,1] ... ||| [x,1] ... ||| feature-name-1=score1 FeatureName2=score2
    // [x] ||| [v,1] ... ||| [v,1] ... ||| featurename2=score1 FeatureName3=score2
    // 
    // Here, we will have 4 features, feature-name-1, FeatuerName2, featurename2 etc.!
    //

    GrammarMutable(const int __max_span=0);
    GrammarMutable(const std::string& parameter);
    ~GrammarMutable();

    GrammarMutable(const GrammarMutable& x);
    GrammarMutable& operator=(const GrammarMutable& x);
    
  public:
    // virtual members
    transducer_ptr_type clone() const;

    bool valid_span(int first, int last, int distance) const;
    id_type root() const;
    id_type next(const id_type& node, const symbol_type& symbol) const;
    bool has_next(const id_type& node) const;
    const rule_pair_set_type& rules(const id_type& node) const;
    id_type insert(const id_type& node, const symbol_type& symbol);
    
    // mutable grammar specific members...
    void read(const std::string& parameter);
    void clear();
    size_type size() const;
    
    void insert(const std::string& pattern);
    void insert(const rule_pair_type& rule_pair);
    
    void insert(const rule_type& source, const rule_type& target)
    {
      rule_type __source(source);
      rule_type __target(target);

      cicada::sort(__source, __target);
      
      insert(rule_pair_type(rule_type::create(__source), rule_type::create(__target)));
    }
    void insert(const rule_type& source, const rule_type& target, const feature_set_type& features)
    {
      rule_type __source(source);
      rule_type __target(target);

      cicada::sort(__source, __target);
      
      insert(rule_pair_type(rule_type::create(__source), rule_type::create(__target), features));
    }
    void insert(const rule_type& source, const rule_type& target, const feature_set_type& features, const attribute_set_type& attributes)
    {
      rule_type __source(source);
      rule_type __target(target);

      cicada::sort(__source, __target);
      
      insert(rule_pair_type(rule_type::create(__source), rule_type::create(__target), features, attributes));
    }
    
    void insert(const rule_ptr_type& source, const rule_ptr_type& target)
    {
      insert(rule_pair_type(source, target));
    }
    void insert(const rule_ptr_type& source, const rule_ptr_type& target, const feature_set_type& features)
    {
      insert(rule_pair_type(source, target, features));
    }
    
    void insert(const rule_ptr_type& source, const rule_ptr_type& target, const feature_set_type& features, const attribute_set_type& attributes)
    {
      insert(rule_pair_type(source, target, features, attributes));
    }
    
  private:
    impl_type* pimpl;
  };
  
};

#endif
