3.9 The raise Statement

[ Table of Contents ] Prev ] Chapter Overview ] Next ] [ Glossary/Index ]

The previous section suggests that for a proper understanding of exceptions, one has to learn how to declare, raise  and handle them. This section contains an example package that declares two user-defined exceptions, includes raise statements in the normal executable parts of two nested procedures that raise the exceptions, and also includes appropriate exception handlers in those same procedures. A raise statement is a simple statement.

General Form

raise Exception_Name;

Robust Generic Stack Example

In this example we improve upon the generic stack package of the previous chapter. We make the generic stack more robust by declaring, raising and handling exceptions called Stack_Full and Stack_Empty. Thus, if the client tries to Push onto a full stack or Pop from an empty one, the program takes an alternate path and displays an appropriate message, rather than allowing the  program to crash (because Stack.Index would go out of range).

The right side of this diagram depicts a generic ADT package called Robust_Stack, whose body contains the declaration of two exceptions called Stack_Full and Stack_Empty. The test procedure on the left declares a subtype of String, a generic instance of Robust_Stack called SS4, and a stack object called S4.

Im3-10.gif (7039 bytes)

Note the five-sided graphic symbol used to represent the declaration of one or more exceptions.

Source Code Listing

------------------------- Robust_Stack ---------------------------
--  This generic package provides a template that can be the basis 
--  for stacks with different sizes and which store items of 
--  different types. It is also robust, in that it handles 
--  exceptions raised when the client tries to Push onto a full  
--  stack or Pop from an empty one. 
------------------------------------------------------------------
generic
  Size : Positive;  
  type Item_Type is private;
package Robust_Stack is
    
  type Stack_Type is private;
  procedure Push(Stack : in out Stack_Type;
                 Item  : in Item_Type);
  procedure Pop (Stack : in out Stack_Type;
                 Item  : out Item_Type);
private
    
  type Space_Type is array (1..Size) of Item_Type;
  type Stack_Type is record
    Index : Integer range 0..Size := 0;
    Space : Space_Type;
  end record;
               
end Robust_Stack;
------------------------------------------------------------------
with Ada.Text_IO;
use  Ada.Text_IO;
package body Robust_Stack is

  Stack_Full, Stack_Empty : exception;       -- declare exceptions
  ------------------------------------------
  procedure Push(Stack : in out Stack_Type;
                 Item  : in Item_Type) is
  begin
    if Stack.Index = Size then
      raise Stack_Full;                      -- raise exception 
    end if;
    Stack.Index := Stack.Index + 1;
    Stack.Space(Stack.Index) := Item;
  exception
    when Stack_Full =>                       -- handle exception
      Put_Line("Stack is full. Can't Push.");  
  end Push;                   
  -------------------------------------------                   
  procedure Pop (Stack : in out Stack_Type;
                 Item  : out Item_Type) is
  begin
    if Stack.Index = 0 then
      raise Stack_Empty;                     -- raise exception
    end if;
    Item := Stack.Space(Stack.Index);
    Stack.Index := Stack.Index - 1;
  exception
    when Stack_Empty =>                      -- handle exception
      Put_Line("Stack is empty. Can't Pop.");    
  end Pop;                   
  -------------------------------------------                     
end Robust_Stack;
------------------------------------------------------------------  
----------------------- Test_Robust_Stack ------------------------
--  This test procedure tries one too many Pushes, which raises 
--  the Stack_Full exception, then tries one too many Pops which 
--  raises the Stack_Empty exception. 
------------------------------------------------------------------
with Ada.Text_IO;
use  Ada.Text_IO;
with Robust_Stack;
procedure Test_Robust_Stack is          
  
  subtype String_4 is String(1..4);
  Str4 : String_4;
  package SS4 is new Robust_Stack
          (Size => 4, Item_Type => String_4);
  S4 : SS4.Stack_Type;
    
begin
    Put_Line("Testing Robust stack");
    New_Line;
    
    Put_Line("Pushing Adam"); SS4.Push(S4,"Adam"); 
    Put_Line("Pushing Bill"); SS4.Push(S4,"Bill"); 
    Put_Line("Pushing Carl"); SS4.Push(S4,"Carl"); 
    Put_Line("Pushing Dave"); SS4.Push(S4,"Dave"); 
    Put_Line("Pushing Eric"); SS4.Push(S4,"Eric");
    
    New_Line; 
                                               
    for I in 1..5 loop
      SS4.Pop(S4, Str4);
      Put_Line(Str4);
    end loop;
    
end Test_Robust_Stack;
------------------------------------------------------------------

The above program produces the following output:

     Testing robust stack

     Pushing Adam
     Pushing Bill
     Pushing Carl
     Pushing Dave
     Pushing Eric
     Stack is full. Can't Push.

     Dave
     Carl
     Bill
     Adam
     Stack is empty. Can't Pop.
     Adam

Note that we did not use blocks to enclose the exception handlers in this case, because we are happy to have control passed back to the test procedure following the occurrence of an exception.

Related Topics

2.11 Generic Units 3.8 Exception Handling
A.2 Simple and Compound Statements

[ Back to top of pagePrev ] Next ]