UNIT StackAry;

(*
      Library of Stack Array routines.

      by: Ilya Shlyakhter
*)

                              INTERFACE

   CONST MaxStackSize = 100;


   TYPE  StackDataType = Char;
         StackIndexType = 0..MaxStackSize;
         StackArray = ARRAY [1..MaxStackSize] OF StackDataType;

         StackType = RECORD
                        StackData: StackArray;
                        StackTop: StackIndexType
                     END;  (* StackType *)

   PROCEDURE InitStack (VAR Stack: StackType);

   FUNCTION Empty (VAR Stack: StackType): Boolean;
   FUNCTION GetStackSize (VAR Stack: StackType): StackIndexType;

   PROCEDURE Push (VAR Stack: StackType; 
                   NewData: StackDataType;
                   VAR Error: Boolean);

   PROCEDURE Pop (VAR Stack: StackType; 
                  VAR TopElement: StackDataType;
                  VAR Error: Boolean);

   PROCEDURE Peek (VAR Stack: StackType; 
                   VAR TopElement: StackDataType;
                   VAR Error: Boolean);


                            IMPLEMENTATION

   PROCEDURE InitStack (VAR Stack: StackType);

   (*
      Clears a given stack (Stack), preparing it to receive elements.
   *)

      VAR I: StackIndexType;

      BEGIN  (* InitStack *)
         Stack.StackTop := 0
      END;   (* InitStack *)


   FUNCTION Empty (VAR Stack: StackType): Boolean;

   (*
      Returns TRUE if there are no elements of the stack (Stack), FALSE otherwise.
   *)

      BEGIN  (* Empty *)
         Empty := (Stack.StackTop = 0)
      END;   (* Empty *)

   FUNCTION GetStackSize (VAR Stack: StackType): StackIndexType;

   (*
      Returns the number of elements on a given stack (Stack).  Returns 0
      if Stack is empty.
   *)

      BEGIN  (* GetStackSize *)
         GetStackSize := Stack.StackTop
      END;   (* GetStackSize *)

   PROCEDURE Push (VAR Stack: StackType; 
                   NewData: StackDataType;
                   VAR Error: Boolean);

   (*
      Puts the element (NewData) onto the stack (Stack).  If the stack is full,
      leaves the stack intact and returns an error (sets Error to True).
   *)

      BEGIN  (* Push *)
         IF Stack.StackTop < MaxStackSize THEN
            BEGIN  (* there is more space on the stack *)
               Stack.StackTop := Stack.StackTop + 1;
               Stack.StackData [Stack.StackTop] := NewData;
               Error := False;
            END    (* there is more space on the stack *)
               ELSE
                  Error := True  (* stack full *)
      END;   (* Push *)


   PROCEDURE Pop (VAR Stack: StackType; 
                  VAR TopElement: StackDataType;
                  VAR Error: Boolean);

   (*
      Retrievs an element (TopElements) from the stack (Stack).  If the stack
      is empty, returns an error (sets Error to True).
   *)

      BEGIN  (* Pop *)
         IF Stack.StackTop > 0 THEN
            BEGIN  (* there is at least 1 element on the stack *)
               TopElement := Stack.StackData [Stack.StackTop];
               Stack.StackTop := Stack.StackTop - 1;
               Error := False
            END    (* there is at least 1 element on the stack *)
               ELSE
                  Error := True   (* stack empty *)
      END;   (* Pop *)

   PROCEDURE Peek (VAR Stack: StackType; 
                   VAR TopElement: StackDataType;
                   VAR Error: Boolean);

   (*
      Returns an element (TopElement) at the top of the stack (Stack), but
      does NOT remove it from the stack, so the next call to Push will
      return this element.  This allows the program to "look ahead" before
      retrieving the next data item.  If the stack is empty, returns an error
      (sets Error to True).
   *)

      BEGIN  (* Peek *)
         IF Stack.StackTop > 0 THEN
            BEGIN  (* there is at least 1 element on the stack *)
               TopElement := Stack.StackData [Stack.StackTop];
               Error := False
            END    (* there is at least 1 element on the stack *)
               ELSE
                  Error := True   (* stack empty *)
      END;   (* Peek *)

   END.  (* of Unit StackAry *)







