/* gnu/regexp/RETokenRepeated.java
   Copyright (C) 2006 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath 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
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package gnu.java.util.regex;

import gnu.java.lang.CPStringBuilder;

import java.util.ArrayDeque;
import java.util.Deque;

final class RETokenRepeated extends REToken
{
  private REToken token;
  private int min, max;
  private boolean stingy;
  private boolean possessive;
  private int tokenFixedLength;

    RETokenRepeated (int subIndex, REToken token, int min, int max)
  {
    super (subIndex);
    this.token = token;
    this.min = min;
    this.max = max;
    if (token.returnsFixedLengthMatches ())
      {
	tokenFixedLength = token.getMaximumLength ();
      }
    else
      {
	tokenFixedLength = -1;
      }
  }

    /** Sets the minimal matching mode to true. */
  void makeStingy ()
  {
    stingy = true;
  }

    /** Queries if this token has minimal matching enabled. */
  boolean isStingy ()
  {
    return stingy;
  }

    /** Sets possessive matching mode to true. */
  void makePossessive ()
  {
    possessive = true;
  }

    /** Queries if this token has possessive matching enabled. */
  boolean isPossessive ()
  {
    return possessive;
  }

    /**
     * The minimum length of a repeated token is the minimum length
     * of the token multiplied by the minimum number of times it must
     * match.
     */
  int getMinimumLength ()
  {
    return (min * token.getMinimumLength ());
  }

  int getMaximumLength ()
  {
    if (max == Integer.MAX_VALUE)
      return Integer.MAX_VALUE;
    int tmax = token.getMaximumLength ();
    if (tmax == Integer.MAX_VALUE)
      return tmax;
    return (max * tmax);
  }

  // The comment "MUST make a clone" below means that some tests
  // failed without doing clone(),

  private static class DoablesFinder
  {
    private REToken tk;
    private CharIndexed input;
    private REMatch rematch;
    private boolean findFirst;

    private DoablesFinder (REToken tk, CharIndexed input, REMatch mymatch)
    {
      this.tk = tk;
      this.input = input;
      this.rematch = (REMatch) mymatch.clone ();	// MUST make a clone
      this.rematch.backtrackStack = new BacktrackStack ();
      findFirst = true;
    }

    private REMatch find ()
    {
      int origin = rematch.index;
      REMatch rem;
      if (findFirst)
	{
	  rem = tk.findMatch (input, rematch);
	  findFirst = false;
	}
      else
	{
	  while (true)
	    {
	      if (rematch.backtrackStack.empty ())
		{
		  rem = null;
		  break;
		}
	      BacktrackStack.Backtrack bt = rematch.backtrackStack.pop ();
	      rem = bt.token.backtrack (bt.input, bt.match, bt.param);
	      if (rem != null)
		break;
	    }
	}
      if (rem == null)
	return null;
      if (rem.index == origin)
	rem.empty = true;
      rematch = rem;
      return (REMatch) rem.clone ();	// MUST make a clone.
    }

    boolean noMore ()
    {
      return rematch.backtrackStack.empty ();
    }
  }

  REMatch findMatch (CharIndexed input, REMatch mymatch)
  {
    if (tokenFixedLength >= 0)
      return findMatchFixedLength (input, mymatch);
    BacktrackStack stack = new BacktrackStack ();
    stack.push (new StackedInfo (input, 0, mymatch, null, null));
    return findMatch (stack);
  }

  REMatch backtrack (CharIndexed input, REMatch mymatch, Object param)
  {
    if (tokenFixedLength >= 0)
      return backtrackFixedLength (input, mymatch, param);
    return findMatch ((BacktrackStack) param);
  }

  private static class StackedInfo extends BacktrackStack.Backtrack
  {
    int numRepeats;
    int[] visited;
    DoablesFinder finder;
      StackedInfo (CharIndexed input, int numRepeats, REMatch match,
		   int[]visited, DoablesFinder finder)
    {
      super (null, input, match, null);
      this.numRepeats = numRepeats;
      this.visited = visited;
      this.finder = finder;
    }
  }

  private static class FindMatchControl
  {
    DoablesFinder finder;
      FindMatchControl (DoablesFinder finder)
    {
      this.finder = finder;
    }
  }

  private REMatch findMatch (BacktrackStack stack)
  {
    return findMatch (stack, new ArrayDeque < FindMatchControl > ());
  }

  private REMatch findMatch (BacktrackStack stack,
			     Deque < FindMatchControl > controlStack)
  {
    REMatch result = null;
    StackedInfo si = null;
    CharIndexed input = null;
    int numRepeats = 0;
    REMatch mymatch = null;
    int[] visited = null;
    DoablesFinder finder = null;

    // Avoid using recursive calls because a match can be very long.

    // This is the first entry point of this method.
    // If you want to call this method recursively and you need the
    // result returned, save necessary information in a FindMatchControl
    // object and push it to controlStack, then continue from this point.
    // You can check the result after exiting MAIN_LOOP.
  MAIN_LOOP0:
    while (true)
      {

	// This is the second entry point of this method.
	// If you want to call this method recursively but you do not need the
	// result returned, just continue from this point.
      MAIN_LOOP:
	while (true)
	  {

	    if (stack.empty ())
	      break MAIN_LOOP;
	    si = (StackedInfo) (stack.peek ());
	    input = si.input;
	    numRepeats = si.numRepeats;
	    mymatch = si.match;
	    visited = si.visited;
	    finder = si.finder;

	    if (mymatch.backtrackStack == null)
	      mymatch.backtrackStack = new BacktrackStack ();

	    if (numRepeats >= max)
	      {
		stack.pop ();
		REMatch m1 = matchRest (input, mymatch);
		if (m1 != null)
		  {
		    if (!stack.empty ())
		      {
			m1.backtrackStack.push (new BacktrackStack.
						Backtrack (this, input,
							   mymatch, stack));
		      }
		    result = m1;
		    break MAIN_LOOP;
		  }
		if (stingy)
		  {
		    continue MAIN_LOOP;
		  }
		break MAIN_LOOP;
	      }

	    if (finder == null)
	      {
		finder = new DoablesFinder (token, input, mymatch);
		si.finder = finder;
	      }

	    if (numRepeats < min)
	      {
		while (true)
		  {
		    REMatch doable = finder.find ();
		    if (doable == null)
		      {
			if (stack.empty ())
			  return null;
			stack.pop ();
			continue MAIN_LOOP;
		      }
		    if (finder.noMore ())
		      stack.pop ();
		    int newNumRepeats = (doable.empty ? min : numRepeats + 1);
		    stack.
		      push (new
			    StackedInfo (input, newNumRepeats, doable,
					 visited, null));
		    continue MAIN_LOOP;
		  }
	      }

	    if (visited == null)
	      visited = initVisited ();

	    if (stingy)
	      {
		REMatch nextMatch = finder.find ();
		if (nextMatch != null && !nextMatch.empty)
		  {
		    stack.
		      push (new
			    StackedInfo (input, numRepeats + 1, nextMatch,
					 visited, null));
		  }
		else
		  {
		    stack.pop ();
		  }
		REMatch m1 = matchRest (input, mymatch);
		if (m1 != null)
		  {
		    if (!stack.empty ())
		      {
			m1.backtrackStack.push (new BacktrackStack.
						Backtrack (this, input,
							   mymatch, stack));
		      }
		    result = m1;
		    break MAIN_LOOP;
		  }
		else
		  {
		    continue MAIN_LOOP;
		  }
	      }

	    visited = addVisited (mymatch.index, visited);

	    TryAnotherResult taresult =
	      tryAnother (stack, input, mymatch, numRepeats, finder, visited);
	    visited = taresult.visited;
	    switch (taresult.status)
	      {
	      case TryAnotherResult.TRY_FURTHER:
		controlStack.push (new FindMatchControl (finder));
		continue MAIN_LOOP0;
	      case TryAnotherResult.RESULT_FOUND:
		result = taresult.result;
		break MAIN_LOOP;
	      }

	    if (!stack.empty ())
	      {
		stack.pop ();
	      }
	    if (possessive)
	      {
		stack.clear ();
	      }
	    REMatch m1 = matchRest (input, mymatch);
	    if (m1 != null)
	      {
		if (!stack.empty ())
		  {
		    m1.backtrackStack.push (new BacktrackStack.
					    Backtrack (this, input, mymatch,
						       stack));
		  }
		result = m1;
		break MAIN_LOOP;
	      }

	  }			// MAIN_LOOP

	if (controlStack.isEmpty ())
	  return result;
	FindMatchControl control = controlStack.pop ();
	if (possessive)
	  {
	    return result;
	  }
	if (result != null)
	  {
	    result.backtrackStack.push (new BacktrackStack.
					Backtrack (this, input, mymatch,
						   stack));
	    return result;
	  }

	finder = control.finder;

	TryAnotherResult taresult =
	  tryAnother (stack, input, mymatch, numRepeats, finder, visited);
	visited = taresult.visited;
	switch (taresult.status)
	  {
	  case TryAnotherResult.TRY_FURTHER:
	    controlStack.push (new FindMatchControl (finder));
	    continue MAIN_LOOP0;
	  case TryAnotherResult.RESULT_FOUND:
	    return taresult.result;
	  }
	continue MAIN_LOOP0;

      }				// MAIN_LOOP0
  }

  private static class TryAnotherResult
  {
    REMatch result;
    int status;
    static final int RESULT_FOUND = 1;
    static final int TRY_FURTHER = 2;
    static final int NOTHING_FOUND = 3;
    int[] visited;
  }

  private TryAnotherResult tryAnother (BacktrackStack stack,
				       CharIndexed input, REMatch mymatch,
				       int numRepeats, DoablesFinder finder,
				       int[]visited)
  {

    TryAnotherResult taresult = new TryAnotherResult ();
    taresult.visited = visited;

  DO_THIS:
    {

      boolean emptyMatchFound = false;

    DO_ONE_DOABLE:
      while (true)
	{

	  REMatch doable = finder.find ();
	  if (doable == null)
	    {
	      break DO_THIS;
	    }
	  if (doable.empty)
	    emptyMatchFound = true;

	  if (!emptyMatchFound)
	    {
	      int n = doable.index;
	      if (visitedContains (n, visited))
		{
		  continue DO_ONE_DOABLE;
		}
	      visited = addVisited (n, visited);
	      stack.
		push (new
		      StackedInfo (input, numRepeats + 1, doable, visited,
				   null));
	      taresult.visited = visited;
	      taresult.status = TryAnotherResult.TRY_FURTHER;
	      return taresult;
	    }
	  else
	    {
	      REMatch m1 = matchRest (input, doable);
	      if (possessive)
		{
		  taresult.result = m1;
		  taresult.status = TryAnotherResult.RESULT_FOUND;
		  return taresult;
		}
	      if (m1 != null)
		{
		  if (!stack.empty ())
		    {
		      m1.backtrackStack.push (new BacktrackStack.
					      Backtrack (this, input, mymatch,
							 stack));
		    }
		  taresult.result = m1;
		  taresult.status = TryAnotherResult.RESULT_FOUND;
		  return taresult;
		}
	    }

	}			// DO_ONE_DOABLE

    }				// DO_THIS

    taresult.status = TryAnotherResult.NOTHING_FOUND;
    return taresult;

  }

  boolean match (CharIndexed input, REMatch mymatch)
  {
    setHitEnd (input, mymatch);
    REMatch m1 = findMatch (input, mymatch);
    if (m1 != null)
      {
	mymatch.assignFrom (m1);
	return true;
      }
    return false;
  }

  // Array visited is an array of character positions we have already
  // visited. visited[0] is used to store the effective length of the
  // array.
  private static int[] initVisited ()
  {
    int[] visited = new int[32];
    visited[0] = 0;
    return visited;
  }

  private static boolean visitedContains (int n, int[]visited)
  {
    // Experience tells that for a small array like this,
    // simple linear search is faster than binary search.
    for (int i = 1; i < visited[0]; i++)
      {
	if (n == visited[i])
	  return true;
      }
    return false;
  }

  private static int[] addVisited (int n, int[]visited)
  {
    if (visitedContains (n, visited))
      return visited;
    if (visited[0] >= visited.length - 1)
      {
	int[] newvisited = new int[visited.length + 32];
	System.arraycopy (visited, 0, newvisited, 0, visited.length);
	visited = newvisited;
      }
    visited[0]++;
    visited[visited[0]] = n;
    return visited;
  }

  private REMatch matchRest (CharIndexed input, final REMatch newMatch)
  {
    if (next (input, newMatch))
      {
	return newMatch;
      }
    return null;
  }

  private REMatch findMatchFixedLength (CharIndexed input, REMatch mymatch)
  {
    if (mymatch.backtrackStack == null)
      mymatch.backtrackStack = new BacktrackStack ();
    int numRepeats =
      token.findFixedLengthMatches (input, (REMatch) mymatch.clone (), max);
    if (numRepeats == Integer.MAX_VALUE)
      numRepeats = min;
    int count = numRepeats - min + 1;
    if (count <= 0)
      return null;
    int index = 0;
    if (!stingy)
      index = mymatch.index + (tokenFixedLength * numRepeats);
    else
      index = mymatch.index + (tokenFixedLength * min);
    return findMatchFixedLength (input, mymatch, index, count);
  }

  private REMatch backtrackFixedLength (CharIndexed input, REMatch mymatch,
					Object param)
  {
    int[] params = (int[]) param;
    int index = params[0];
    int count = params[1];
    return findMatchFixedLength (input, mymatch, index, count);
  }

  private REMatch findMatchFixedLength (CharIndexed input, REMatch mymatch,
					int index, int count)
  {
    REMatch tryMatch = (REMatch) mymatch.clone ();
    while (true)
      {
	tryMatch.index = index;
	REMatch m = matchRest (input, tryMatch);
	count--;
	if (stingy)
	  index += tokenFixedLength;
	else
	  index -= tokenFixedLength;
	if (possessive)
	  return m;
	if (m != null)
	  {
	    if (count > 0)
	      {
		m.backtrackStack.push (new BacktrackStack.
				       Backtrack (this, input, mymatch,
						  new int[]
						  {
						  index, count}));
	      }
	    return m;
	  }
	if (count <= 0)
	  return null;
      }
  }

  void dump (CPStringBuilder os)
  {
    os.append ("(?:");
    token.dumpAll (os);
    os.append (')');
    if ((max == Integer.MAX_VALUE) && (min <= 1))
      os.append ((min == 0) ? '*' : '+');
    else if ((min == 0) && (max == 1))
      os.append ('?');
    else
      {
	os.append ('{').append (min);
	if (max > min)
	  {
	    os.append (',');
	    if (max != Integer.MAX_VALUE)
	      os.append (max);
	  }
	os.append ('}');
      }
    if (stingy)
      os.append ('?');
  }
}
