//
//	File:		    tag.h
//  Version:    ASTL 1.1
//	Copyright:	Vincent LE MAOUT
//	Date:		    Fri Oct 30 13:32:07 MET 1998
//	Descrition:	ASTL 1.1 tag traits definition + default tag type empty_tag
//              Default behavior is handled by tag_traits template
//              Tag traits must provide means to :
//               - read and write to a BINARY stream
//                 static void read(istream &binary_stream, Tag &t) 
//                 static void write(ostream &binary_stream, const Tag &t)
//                 default : use basic binary read and write iostreams methods
//             
//               - clean the tag 
//                 static void clean(Tag &t)
//                 default : set the tag to default-constructed tag
//
//               - compute the union t of two tags x and y
//                 static void tag_union(const Tag &x, const Tag &y, Tag &t)
//                 default : do nothing
//
//               - compute the intersection t of two tags x and y
//                 static void tag_intersection(const Tag &x, const Tag &y, Tag &t)
//                 default : do nothing
//
//               - compute the mapping from a set of tags [first, last) to a tag t
//                 for determinization
//                 template <class InputIterator>
//                 static void tag_determinize(InputIterator first, InputIterator last, Tag &t)
//                 default : do nothing
//

#ifndef ASTL_TAG_TRAITS
#define ASTL_TAG_TRAITS

#include <iostream>
#include <cursors/cursor.h>

#ifndef WIN32
#include <type_traits.h>
#else
using namespace std;
#endif  // WIN32

template <class Tag>
class tag_traits
{
public:
  static void read(istream &binary_stream, Tag &t) {
    binary_stream.read(&t, sizeof(Tag));
  }

  static void write(ostream &binary_stream, const Tag &t) {
    binary_stream.write(&t, sizeof(Tag));
  }

  static void clean(Tag &t) {
    t = Tag();
  }

  template <class InputIterator>
  static void tag_determinize(InputIterator first, InputIterator last, Tag &t) 
  { }

  static void tag_union(const Tag &x, const Tag &y, Tag &t)
  { }

  static void tag_intersection(const Tag &x, const Tag &y, Tag &t)
  { }
};

// Default tag for automaton classes:
struct empty_tag
{ };

bool operator == (const empty_tag&, const empty_tag&) {
  return (true);
}

bool operator < (const empty_tag&, const empty_tag&) {
  return (false);
}

ostream& operator << (ostream &out, const empty_tag&) {
	return (out);
}

// Specialized tag traits for type empty_tag 
// Defines tag_traits<empty_tag>

class tag_traits<empty_tag>
{
public:
  static void read(istream &, empty_tag &) 
  {  }

  static void write(ostream &, const empty_tag &)
  {  }
  
  static void clean(empty_tag &)
  {  }
  
  template <class InputIterator>
  static void tag_determinize(InputIterator, InputIterator, empty_tag &)
  {  }
  
  static void tag_union(const empty_tag &, const empty_tag &, empty_tag &)
  {  }
  
  static void tag_intersection(const empty_tag &, const empty_tag &, empty_tag &)
  {  }
};

typedef empty_tag default_tag;

//
// Algorithm    : tag
// Version      : ASTL 1.1
// Description  : return the tag associated to a word
// Input        : a dfa, a range on a word
// Output       : (true, Tag) if the word is found, (false, Tag()) otherwise
// Precondition : InputIterator::value_type == DFA::Alphabet,
//

template <class DFA, class InputIterator>
pair<bool, typename DFA::Tag> tag(const DFA &dfa, InputIterator start, InputIterator finish)
{
  typename DFA::Tag default_constructed;
  if (dfa.initial() == dfa.null_state)
    return make_pair(false, default_constructed);
  forward_cursor<DFA> cursor(dfa, dfa.initial());
  for(; start != finish && cursor.forward(*start); ++start);
  if (start == finish && cursor.src_final())
    return make_pair(true, cursor.src_tag());
  else
    return make_pair(false, default_constructed);
}

#ifndef WIN32
// Specialized type_traits for empty_tag
struct __type_traits<empty_tag>
{
  typedef __true_type has_trivial_default_constructor;
  typedef __true_type has_trivial_copy_constructor;
  typedef __true_type has_trivial_assignment_operator;
  typedef __true_type has_trivial_destructor;
  typedef __true_type is_POD_type;
};
#endif // WIN32

#endif // ASTL_TAG_TRAITS







