/* Copyright (c) 2000 by Kevin Forchione. All Rights Reserved. */
/*
* TADS LIBRARY EXTENSION
* STACK.T
* version 1.0
*
* stack.t implements a dynamically created FIFO or LIFO stack and a
* Vector class that can be used for list manipulation.
*
*----------------------------------------------------------------------
* REQUIREMENTS
*
* + HTML TADS 2.2.6 or later
*
*----------------------------------------------------------------------
* IMPORTANT LIBRARY INTERFACE AND MODIFICATION
*
* None.
*
*----------------------------------------------------------------------
* COPYRIGHT NOTICE
*
* You may modify and use this file in any way you want, provided that
* if you redistribute modified copies of this file in source form, the
* copies must include the original copyright notice (including this
* paragraph), and must be clearly marked as modified from the original
* version.
*
*------------------------------------------------------------------------------
* REVISION HISTORY
*
* 08-Mar-00: Creation.
*/
#define __STACK_MODULE_
#pragma C+
/*
* Stack: object
*
* This implements a FIFO (First-In-First-Out) or LIFO
* (Last-In-First-Out) stack that can be used for pushing and popping.
* The Stack will automatically create a Vector class object, which it
* uses for keeping track of pushed objects.
*
* To use a stack simply create it dynamically. The Stack default is
* LIFO. If you wish it to behave as a FIFO stack simply set its isLIFO
* attribute to nil.
*
* local stack = new Stack;
* stack.isLIFO = nil;
*
* You can push items onto the stack with the stack's push method:
*
* stack.push(item);
*
* and pop items off the stack using its pop method:
*
* item = stack.pop;
*
* When the stack is no longer needed you can delete it with the delete
* statement. The stack will automatically clean-up the Vector class
* object that it dynamically created.
*/
class Stack: object
isLIFO = true
vector = nil // pointer to dynamically-created Vector class obj
/*
* Push an item onto the stack. All items are pushed to the top of
* the stack.
*/
push(item) = {
self.vector.addElement(item);
}
/*
* Push an item to the bottom of the stack.
*/
pushB(item) = {
self.vector.addElementToHead(item);
}
/*
* Pop an item off the stack. If stack.isLIFO then it pops the
* item from the top of the stack; otherwise it pops the item from
* the bottom of the stack.
*/
pop = {
local item;
if (self.isLIFO)
{
item = self.vector.elementAt(self.vector.getSize);
self.vector.removeElementAt(self.vector.getSize);
}
else
{
item = self.vector.elementAt(1);
self.vector.removeElementAt(1);
}
return item;
}
/*
* Returns a boolean indicating whether the stack is empty or not.
*/
isEmpty = {
return self.vector.isEmpty;
}
/*
* Returns the size of the stack.
*/
getSize = {
return self.vector.getSize;
}
construct = {self.vector = new Vector;}
destruct = {delete self.vector;}
;
/*
* Vector: object
*
* The Vector class can be used to manipulate lists.
*/
class Vector: object
list = []
/*
* Add an element to the tail of the list.
*/
addElement(item) = {
self.list += item;
}
/*
* Add an element to the head of the list.
*/
addElementToHead(item) = {
local newlist = [];
newlist += item;
newlist += self.list;
self.list = newlist;
}
/*
* Add item to the list at pos n. If n > list.getSize the list
* is padded with nil values to a length of n-1 before adding item.
*/
addElementAt(item, n) = {
local newlist = [], l1 = [], l2 = [];
if (n > self.getSize) self.padVector(n-1);
newlist += self.sublist(1, n-1);
newlist += item;
newlist += self.sublist(n, self.getSize);
self.list = newlist;
}
/*
* Pad the list with nil elements to the length of n.
*/
padVector(n) = {
local i, len;
len = self.getSize + 1;
for (i = len; i <= n; ++i)
self.list += nil;
}
/*
* Left pad the list with nil elements to the length of n.
*/
lpadVector(n) = {
local i, len, newlist = [];
len = n - self.getSize;
for (i = 1; i <= len; ++i)
newlist += nil;
newlist += self.list;
self.list = newlist;
}
/*
* Remove the element at pos n in the list.
*/
removeElementAt(n) = {
local i, len, newlist = [];
len = self.getSize;
for (i = 1; i <= len; ++i)
{
if (i != n)
newlist += self.list[i];
}
self.list = newlist;
}
/*
* Remove the first occurrence (from left to right) of item from
* the list.
*/
removeFirstOccurrence(item) = {
local n = self.posFirstOccurrence(item);
if (0 < n && n <= self.getSize)
self.removeElementAt(n);
}
/*
* Remove the last occurrence (from left to right) of item from
* the list.
*/
removeLastOccurrence(item) = {
local n = self.posLastOccurrence(item);
if (0 < n && n <= self.getSize)
self.removeElementAt(n);
}
/*
* Remove all occurrences of item from the list.
*/
removeAllOccurrence(item) = {
self.list -= [item];
}
elementAt(n) = {
if (0 < n && n <= self.getSize)
return self.list[n];
else return nil;
}
/*
* Return the pos n for the first occurrence (from left to right) of
* item in the list.
*/
posFirstOccurrence(item) = {
local f = find(self.list, item);
if (f) return f;
return 0;
}
/*
* Return the pos n for the last occurrence (from left to right) of
* item in the list.
*/
posLastOccurrence(item) = {
local i, len;
for (i = length(self.list); i > 0; --i)
{
if (self.list[i] == item)
return i;
}
return 0;
}
/*
* Return a list of elements that are positions in the list for
* all occurrences of item.
*/
posAllOccurrence(item) = {
local i, len, newlist = [];
len = length(self.list);
for (i = 1; i <= len; ++i)
{
if (self.list[i] == item)
newlist += [i];
}
return newlist;
}
/*
* Return a count of all occurrences of item in the list.
*/
countOccurrence(item) = {
local n = self.posAllOccurrence(item);
return length(n);
}
/*
* Return a sublist of list, starting from pos for a length len
* (if provided). if len is not provided then it is the length of
* the remainder of the list. If len is greater than the length
* of the list then the sublist contains the remainder of the list.
* If pos is greater than the length of the list then an empty list
* is returned.
*/
sublist(pos, ...) = {
local i, len, newlist = [];
if (argcount > 1) len = getarg(2);
if (len == nil) len = self.getSize - pos + 1;
for (i = pos; i <= pos + len - 1; ++i)
{
if (self.getSize >= i)
newlist += self.list[i];
else break;
}
return newlist;
}
/*
* Returns the length of the list.
*/
getSize = {return length(self.list);}
/*
* Returns a boolean indicating whether the list is empty or not.
*/
isEmpty = {
if (self.getSize)
return nil;
else return true;
}
construct = {}
destruct = {}
;