/*
 * ASTL - the Automaton Standard Template Library.
 * C++ generic components for Finite State Machine handling.
 * Copyright (C) 2000 Vincent Le Maout (vlemaout@lexiquest.fr).
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */


#ifndef ASTL_CLASS_DFA_DEFAULT
#define ASTL_CLASS_DFA_DEFAULT

#include <astl.h> 

template <class DFA>
class DFA_default : public DFA_concept
{
protected :
  DFA      dfa;

public:
  typedef typename DFA::Sigma          Sigma;
  typedef typename DFA::Alphabet       Alphabet;
  typedef typename DFA::State          State;
  typedef typename DFA::Tag            Tag;
  //  typedef typename DFA::Edges          Edges;
  typedef typename DFA::const_iterator const_iterator;
  
  State&   null_state;
  Alphabet default_letter;   

  DFA_default(const Alphabet &def_letter, unsigned long n = 0)
    : dfa(n), null_state(dfa.null_state), default_letter(def_letter)
  { }

  // For edges class, one has to redefine method find to take in account the
  // default transition (brute force):
  class Edges : public DFA::Edges
  {
  protected:
    Alphabet default_letter;
  public:
    typedef typename DFA::Edges super;

    Edges(const typename DFA::Edges &x, const Alphabet &def_letter)
      : super(x), default_letter(def_letter)
      { }

    typename DFA::Edges::const_iterator find(const Alphabet &x) {
      typename DFA::Edges::const_iterator tmp = super::find(x);
      if (tmp == super::end())
	return super::find(default_letter);
      return tmp;
    }
  };

  State new_state() {
    return (dfa.new_state());
  }

  template <class OutputIterator>
  OutputIterator new_state(unsigned long how_many, OutputIterator x) {
    return (dfa.new_state(how_many, x));
  }

  void del_state(State s) {
    dfa.del_state(s);
  }

  void set_trans(State from, const Alphabet &a, State to) {
    ///   cout << "dfa_default::set_trans(" << from << ", " << a << ", " << to << ")" << endl;
    dfa.set_trans(from, a, to);
  }

  void del_trans(State s, const Alphabet &a) {
    dfa.del_trans(s, a);
  }

  void change_trans(State s, const Alphabet &a, State new_aim) {
    dfa.change_trans(s, a, new_aim);
  }

  void copy_state(State from, State to) {
    dfa.copy_state(from, to);
  }

  State duplicate_state(State s) {
    return (dfa.duplicate_state(s));
  }

  Tag&           tag(State s) {
    return (dfa.tag(s));
  }

  const Tag& tag(State s) const {
    return (dfa.tag(s));
  }

  State delta1(State s, const Alphabet &a) const {
    State aim;
    return (((aim = dfa.delta1(s, a)) == null_state) ? 
	    dfa.delta1(s, default_letter) : aim);
  }

  // No use of default transitions:
  State delta0(State s, const Alphabet &a) const {
    return (dfa.delta1(s, a));
  }

  Edges delta2(State s) const {
    return (Edges(dfa.delta2(s), default_letter));
  }

  State initial() const {
    return (dfa.initial());
  }
  
  void initial(State s) {
    dfa.initial(s);
  }

  unsigned long  state_count() const {
    return (dfa.state_count());
  }

  unsigned long  trans_count() const {
    return (dfa.trans_count());
  }

  const_iterator begin() const {
    return (dfa.begin());
  }

  const_iterator end() const {
    return (dfa.end());
  }

  class bool_reference
  {
    DFA &dfa;
    State s;

  public:
    bool_reference(DFA &_dfa, State q)
      : dfa(_dfa), s(q)
    { }
    
    operator bool() const {
      return (dfa.final(s));
    }

    template <class T>
    bool_reference operator = (T t) {
      dfa.final(s) = t;
      return (*this);
    }

    template <class T>
    bool operator == (T t) const { 
      return (dfa.final(s) == t);
    }
  };
		   
  bool final(State s) const {
    return (dfa.final(s));
  }

  char& final(State s) {
    return dfa.final(s);
  }

};  

#endif // ASTL_CLASS_DFA_DEFAULT




