/*
 * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */


package com.sun.java_cup.internal.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     com.sun.java_cup.internal.runtime.lr_parser
 * @author  Frank Flannery
 */

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));
    }

  /*-----------------------------------------------------------*/

}
