// file: $isip/class/search/StackSearch/ssrch_12.cc
// version: $Id: ssrch_12.cc 9144 2003-05-16 21:59:27Z jelinek $
//

// isip include files
//
#include "StackSearch.h"

// method: generateRightContexts
//
// arguments:
//  DoubleLinkedList<Context>& context_list: (output) generated contexts
//  Context* initial_context: (input) starting context
//  long depth: (input) depth of the context to be generated
//
// return: logical error status
//
// generates a list of contexts expanded from the starting context to
// right into the context depth
//
boolean StackSearch::generateRightContexts(
                                  DoubleLinkedList<Context>& context_list_a,
				  Context* initial_context_a,
				  long depth_a) {

  context_list_a.insertLast(initial_context_a);

  // generate new context lists into the depth of depth_a
  //
  for (long i = 0; i < depth_a; i++) {
    
    // all new contexts will be added at the end of the list so we set
    // the mark to tell us when to stop propagating
    //
    context_list_a.gotoLast();
    context_list_a.setMark();
    context_list_a.gotoFirst();
    
    // propagate all contexts in the list
    //
    boolean end_loop = context_list_a.length() < 1;
    while (!end_loop) {
    
      end_loop = context_list_a.isMarkedElement();

      // get the current context from the list
      //
      Context* curr_context;
      context_list_a.removeFirst(curr_context);
      
      // get the last vertex of the current context
      //
      GraphVertex<SearchNode>* curr_vertex =
	curr_context->getLastVertex();
      
      // if it is NULL vertex, throw an error and exit
      //
      if (curr_vertex == (GraphVertex<SearchNode>*)NULL) {
	return Error::handle(name(), L"generateRightContexts - from NULL!",
			     Error::ARG, __FILE__, __LINE__);
      }
      
      if (!curr_vertex->isTerm()) {
	
	// loop over arcs of the last vertex if it is not terminal vertex
	//
	for (boolean more_arcs = curr_vertex->gotoFirst();
	     more_arcs;
	     more_arcs = curr_vertex->gotoNext()) {
	  
	  // get the next vertex and shift context
	  //
	  GraphVertex<SearchNode>* next_vert =
	                           curr_vertex->getCurr()->getVertex();
	  Context* new_context = context_pool_d.
	    shiftAndAllocate(curr_context, next_vert);

	  // add new context to the list
	  //
	  context_list_a.insertLast(new_context);
	  
	} // end of loop over all arcs of the last vertex
	
      } // end of if not terminal
      
      // if the last vertex of the current context is terminal, simply
      // shift context
      //
      else {

	Context* new_context = context_pool_d.
	  shiftAndAllocate(curr_context, curr_vertex);
	context_list_a.insertLast(new_context);

      } // end of else terminal vertex
      
      context_list_a.gotoFirst();
      
    } // end of the loop over contexts list
    
  } // end of for depths loop

  //exit gracefully
  //
  return true;
}
