<!--  // Hide this just in case this file is read as HTML

// STACK.JS
// Requires arraycopy() from misc.js
//
// isStack(obj): takes an object and returns true if it is a stack
//
// Stack object
// **********************************
// clear(): empties the stack
// isEmpty(): returns true if stack is empty
// peek(): returns the top item without changing the stack
// pop(): pops an item from the stack
// push(item): pushes item on to the stack
// pushArray(array): pushes everything in the array on to the stack
// pushStack(stack): pushes everything in stack on to this stack
// size(): returns the number of elements in the stack
// copyStack(): returns a deep copy of the stack
// toString(): displays the size of the stack
// Stack(): default stack object constructor
// Stack(stackObj): copy constructor
// **********************************

function isStack(obj)
{
	// Returns true if obj is a stack
	return (obj.constructor == Stack)
}

function clear()
{
	// empties the stack
	// actually it only resets the pointer
	// it leaves the data
	this.sp = -1;
}

function isEmpty()
{
	// returns true if the stack is empty
	return (this.sp < 0 ? true : false);
}

function peek()
{
	// returns the top item without changing the stack

	if (this.isEmpty())
		return null;      // stack is empty

	return (this.data[this.sp]);
}

function pop()
{
	// returns the popped item from the stack

	if (this.isEmpty())
		return null;      // stack is empty

	// return data and decrement pointer
	return (this.data[this.sp--]);
}

function push(item)
{
	// pushes item on to top of stack
	// Returns the stack

	// increment the stack pointer and then
	// store the item on to the top of the stack
	this.data[++this.sp] = item;

	return(this);
}

function pushArray(array)
{
	// push all items in array on to the stack
	// pushes it in reverse order so that the first item of the
	// array will become the top of the stack

	for (var i = array.length - 1; i >= 0; i--)
	{
		this.push(array[i]);
	}

	return (this);
}

function pushStack(stack)
{
	// pushes all elements in stack on to this stack
	// pushes elements in the order that elements were pushed on to stack
	// Returns the this object

	for (var i = 0; i <= stack.sp; i++)
	{
		this.push(stack.data[i]);
	}

	return(this);
}

function stackSize()
{
	return(this.sp + 1);
}

function copyStack()
{
	// returns a deep copy of the stack
	// "deep" copy meaning that if any stack is found on the
	// stack, a copy of that stack is made also

	var newStack = new Stack();

	// copy the entire stack array of data
	for (var i = 0; i <= this.sp; i++)
	{
		// if the element is a stack, we make a copy of it
		// otherwise we just copy it
		if (isStack(this.data[i]))
			newStack.data[i] = this.data[i].copyStack();
		else
			newStack.data[i] = this.data[i];	// simple copy
	}

	newStack.sp = this.sp;	// set the stack pointer

	return (newStack);
}

function stackToString()
{
	// return the size of the stack
	return ("Stack size: " + (this.sp + 1));
}

function Stack(stackObj)
{
	// Constructor of stack object

	// The optional first argument if given is copied to initialize
	// the current stack

	if (arguments.length > 0)
	{
		// Copy constructor
		
		return (stackObj.copyStack());
	}
	else
	{
		// default empty stack

		// initialize class members
		this.sp = -1;                 // stack pointer
		this.data = new Array();      // stack data

		// Define the class methods
		this.clear = clear;
		this.isEmpty = isEmpty;
		this.peek = peek;
		this.pop = pop;
		this.push = push;
		this.pushArray = pushArray;
		this.pushStack = pushStack;
		this.size = stackSize;
		this.copyStack = copyStack;
		this.toString = stackToString;

		return (this);
	}
}

// Stop hiding -->

