package java_cup.runtime;
import java.util.Stack;
/**
* This class implements a temporary or "virtual" parse stack that replaces the
* top portion of the actual parse stack (the part that has been changed by some
* set of operations) while maintaining its original contents. This data
* structure is used when the parse needs to "parse ahead" to determine if a
* given error recovery attempt will allow the parse to continue far enough to
* consider it successful. Once success or failure of parse ahead is determined
* the system then reverts to the original parse stack (which has not actually
* been modified). Since parse ahead does not execute actions, only parse state
* is maintained on the virtual stack, not full Symbol objects.
*
* @see java_cup.runtime.lr_parser
* @version last updated: 7/3/96
* @author Frank Flannery
*/
@SuppressWarnings (
{ "all" } )
public class virtual_parse_stack
{
/*-----------------------------------------------------------*/
/*--- Constructor(s) ----------------------------------------*/
/*-----------------------------------------------------------*/
/** Constructor to build a virtual stack out of a real stack. */
public virtual_parse_stack ( Stack shadowing_stack )
throws java.lang.Exception
{
/* sanity check */
if ( shadowing_stack == null )
throw new Exception (
"Internal parser error: attempt to create null virtual stack" );
/* set up our internals */
real_stack = shadowing_stack;
vstack = new Stack ();
real_next = 0;
/* get one element onto the virtual portion of the stack */
get_from_real ();
}
/*-----------------------------------------------------------*/
/*--- (Access to) Instance Variables ------------------------*/
/*-----------------------------------------------------------*/
/**
* The real stack that we shadow. This is accessed when we move off the bottom
* of the virtual portion of the stack, but is always left unmodified.
*/
protected Stack real_stack;
/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
/**
* Top of stack indicator for where we leave off in the real stack. This is
* measured from top of stack, so 0 would indicate that no elements have been
* "moved" from the real to virtual stack.
*/
protected int real_next;
/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
/**
* The virtual top portion of the stack. This stack contains Integer objects
* with state numbers. This stack shadows the top portion of the real stack
* within the area that has been modified (via operations on the virtual
* stack). When this portion of the stack becomes empty we transfer elements
* from the underlying stack onto this stack.
*/
protected Stack vstack;
/*-----------------------------------------------------------*/
/*--- General Methods ---------------------------------------*/
/*-----------------------------------------------------------*/
/**
* Transfer an element from the real to the virtual stack. This assumes that
* the virtual stack is currently empty.
*/
protected void get_from_real ()
{
Symbol stack_sym;
/* don't transfer if the real stack is empty */
if ( real_next >= real_stack.size () )
return;
/* get a copy of the first Symbol we have not transfered */
stack_sym = ( Symbol ) real_stack.elementAt ( real_stack.size () - 1
- real_next );
/* record the transfer */
real_next++ ;
/* put the state number from the Symbol onto the virtual stack */
vstack.push ( new Integer ( stack_sym.parse_state ) );
}
/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
/** Indicate whether the stack is empty. */
public boolean empty ()
{
/*
* if vstack is empty then we were unable to transfer onto it and the whole
* thing is empty.
*/
return vstack.empty ();
}
/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
/** Return value on the top of the stack (without popping it). */
public int top () throws java.lang.Exception
{
if ( vstack.empty () )
throw new Exception (
"Internal parser error: top() called on empty virtual stack" );
return ( ( Integer ) vstack.peek () ).intValue ();
}
/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
/** Pop the stack. */
public void pop () throws java.lang.Exception
{
if ( vstack.empty () )
throw new Exception (
"Internal parser error: pop from empty virtual stack" );
/* pop it */
vstack.pop ();
/* if we are now empty transfer an element (if there is one) */
if ( vstack.empty () )
get_from_real ();
}
/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
/** Push a state number onto the stack. */
public void push ( int state_num )
{
vstack.push ( new Integer ( state_num ) );
}
/*-----------------------------------------------------------*/
}