#ifndef _TTransi_h
#define _TTransi_h
//---------------------------------------------------------------------------
#include <iostream>

using namespace std;
//---------------------------------------------------------------------------

//! The template for a transition with input and output symbols stored internally.
/*!
    A state is identified with the set of its outgoing transitions.
    The state index is the index of the first transition for it.
    A state with no outgoing transition is represented as an empty transition.
*/
template<class I, class Ipass, class O, class Opass>
class TTrans_i
{
public:
//private:
//! Input symbol
  I i;
//! Output symbol
  O o;

public:

//! state is final
  static const unsigned char BITf=0x01;
//! transition list is continued
  static const unsigned char BITc=0x02;
//! no transition
  static const unsigned char BITe=0x04;
//! epsilon input
  static const unsigned char BITepsi=0x08;
//! default input
  static const unsigned char BITdefi=0x10;
//! epsilon output
  static const unsigned char BITepso=0x20;
//! default output
  static const unsigned char BITdefo=0x40;

//! Flags
  unsigned char flags;

//! The index of the next state
  long nxt;

//! Input symbol.
//! \return The input symbol of the transition.
  Ipass in() const { return i; }

//! Output symbol.
//! \return The output symbol of the transition.
  Opass out() const { return o; }

//! Set the input symbol.
//! \param in input symbol
  void in(Ipass in) { i=in; }

//! Set the output symbol.
//! \param out output symbol
  void out(Opass out) { o=out; }

//! remark Is this needed?
  I& iref() { return i; }

//! remark Is this needed?
  O& oref() { return o; }

//! Test whether an input symbol is accepted.
//! \remark Simplified. Should rely on a test function provided by the user.
  bool accepts(Ipass in) { return defi() || in==i; }

//! Next state.
//! \return Destination state of the transition.
  long next() const { return nxt; };

//! Set the next state.
//! \param t destination state of the transition
  void next(long t) { nxt=t; };

//! Is the state final?
//! \return \c true if the state is final, false otherwise.
  bool final() const { return flags&BITf; };

//! Set the \b final flag.
//! \param b \c true if the state is final, \c false otherwise.
  void final(bool b) { if(b) flags|=BITf; else flags&=~BITf; };

//! Is the transition list continued?
//! \return \c true if the transition is not the last transition for the state,
//! \c false otherwise.
  bool continued() const { return flags&BITc; };

//! Set the \b continuation flag.
//! \param b \c true if the transition is not the last one for the state, \c false otherwise.
  void continued(bool b) { if(b) flags|=BITc; else flags&=~BITc; };

//! Is the transition empty?
//! \return \c true if the transition is empty (represents a state with no outgoing transitions),
//! \c false otherwise.
  bool empty() const { return flags&BITe; };

//! Set the \b empty flag.
//! \param b \c true if the transition is empty, \c false otherwise.
  void empty(bool b) { if(b) flags|=BITe; else flags&=~BITe; };

  bool epsi() const { return flags&BITepsi; };
  void epsi(bool b) { if(b) flags|=BITepsi; else flags&=~BITepsi; };

  bool defi() const { return flags&BITdefi; };
  void defi(bool b) { if(b) flags|=BITdefi; else flags&=~BITdefi; };

  bool epso() const { return flags&BITepso; };
  void epso(bool b) { if(b) flags|=BITepso; else flags&=~BITepso; };

  bool defo() const { return flags&BITdefo; };
  void defo(bool b) { if(b) flags|=BITdefo; else flags&=~BITdefo; };

  void geti(istream&);
  void geto(istream&);

//  friend ostream& operator<<(ostream& os, const TTrans_i<I,Ipass,O,Opass>& t);

};

//---------------------------------------------------------------------------

template<char>
void getsym(istream& is, char& c)
{
  is >> c;
  if(c=='\\')
    {
      is.get(c);
      switch(c)
      {
        case 'n':c='\n';break;
        case 't':c='\t';break;
      }
    }
}

template<class T>
void getsym(istream& is, T& s)
{ is >> s; }

//---------------------------------------------------------------------------

template<class I, class Ipass, class O, class Opass>
void TTrans_i<I,Ipass,O,Opass>::geti(istream& is)
{ getsym<I>(is,iref()); };

template<class I, class Ipass, class O, class Opass>
void TTrans_i<I,Ipass,O,Opass>::geto(istream& is)
{ getsym<I>(is,oref()); };

//---------------------------------------------------------------------------
/*
template<class I, class Ipass, class O, class Opass>
ostream& operator<<(ostream& os, const TTrans_i<I,Ipass,O,Opass>& t)
{
  os << (t.final() ? '+' : '-');
  os << ' ';

  if(!t.empty())
  {
    if(t.defi())
      os << (t.epsi() ? '~' : '@');
    else
      switch(t.in())
      {
        case ' ': os << "\\ "; break;
        case '\n': os << "\\n"; break;
        case '\t': os << "\\t"; break;
        default:   os << t.in();
      }

    os << '/';

    if(t.defo())
      os << (t.epso() ? '~' : '@');
    else
      switch(t.out())
      {
        case ' ': os << "\\ "; break;
        case '\n': os << "\\n"; break;
        case '\t': os << "\\t"; break;
        default:   os << t.out();
      }

    os << ' ' << t.next();
  }

  os << '\n';

  if(!t.continued())
    os << '\n';

  return os;
}
*/

//---------------------------------------------------------------------------
#endif

