/*
 * 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_MATCHER_ALGORITHM
#define ASTL_MATCHER_ALGORITHM

#include <utility>   // pair<>

// Returns a past-the-end iterator on the shortest matching subsequence of [first, last). 
// If none is found, first is returned.

// Category:       Algorithms
// Component Type: Function
// Prototype:
// template <class ForwardIterator, class Cursor>
// ForwardIterator first_match(ForwardIterator first, ForwardIterator last, Cursor c)
//
// Description:   first_match looks for the shortest subsequence of [first, last) starting
//                at first and recognized by the DFA accessed through the cursor c.
// Return value:  first_match returns a past-the-end iterator on the matching subsequence. 
//                If none is found, first is returned which means that either no final state
//                has been reached during the traversal or a transition was undefined.
// Definition:    matcher.h
// Requirements on types: 
//                - ForwardIterator is a model of forward iterator
//                - Cursor is a model of plain cursor
//                - forward iterator value type must be convertible to Cursor::Alphabet
// Preconditions: c must have a non singular value, however c might point to the sink state.
// Complexity:    at most (last - first) calls to the transition function Cursor::forward
// Notes:         this algorithm ignores the empty word.
// Bugs and limitations:
// See also: longest_match, match_count

template <class ForwardIterator, class Cursor>
ForwardIterator first_match(ForwardIterator first, ForwardIterator last, Cursor c)
{
  if (c.sink()) return first;
  ForwardIterator start = first;
  for(; first != last && c.forward(*first); ++first)
    if (c.src_final()) return ++first;
  return start;  // no match found
}

// Category:       Algorithms
// Component Type: Function
// Prototype:
// template <class ForwardIterator, class Cursor>
// ForwardIterator longest_match(ForwardIterator first, ForwardIterator last, Cursor c)
//
// Description:   longest_match looks for the longest subsequence of [first, last) starting
//                at first and recognized by the DFA accessed through the cursor c.
// Return value:  longest_match returns a past-the-end iterator on the matching subsequence. 
//                If none is found, first is returned which means that either no final state
//                has been reached during the traversal or an undefined transition has been
//                accessed before reaching any final state.
// Definition:    matcher.h
// Requirements on types: 
//                - ForwardIterator is a model of forward iterator
//                - Cursor is a model of plain cursor
//                - forward iterator value type must be convertible to Cursor::Alphabet
// Preconditions: c must have a non singular value, however c might point to the sink state.
// Complexity:    at most (last - first) calls to the transition function Cursor::forward
// Notes:         this algorithm ignores the empty word.
// See also: longest_match, match_count

template <class ForwardIterator, class Cursor>
ForwardIterator longest_match(ForwardIterator first, ForwardIterator last, Cursor c)
{
  if (c.sink()) return first;
  ForwardIterator last_match_position = first;
  while(first != last && c.forward(*first)) {
    ++first;
    if (c.src_final()) last_match_position = first;
  }
  return last_match_position;
}

// Category:       Algorithms
// Component Type: Function
// Prototype:
// template <class InputIterator, class Cursor>
// unsigned int match_count(InputIterator first, InputIterator last, Cursor c)
//
// Description:
// Return value:
// Definition:
// Requirements on types:
// Preconditions:
// Complexity:
// Example:
// Notes:         this algorithm ignores the empty word.    
// Bugs and limitations:
// See also: first_match, longest_match

template <class InputIterator, class Cursor>
unsigned int match_count(InputIterator first, InputIterator last, Cursor c)
{
  if (c.sink()) return 0;
  unsigned int r = 0;
  for(; first != last && c.forward(*first); ++first)
    if (c.src_final()) ++r;
  return r;
}

#endif

