10.2. A more elaborate example

Consider the following routine, which tries to read a boolean value from a string:
get_bool(file_name:STR):BOOL is
   f:FILE := FILE::open_for_read(file_name);
   if f.error then
      raise #FILE_OPEN_EXC(file_name);
   end;
   s:STR := f.str;  -- Read the file into a string
   f.close;         -- Close the file
   res:BOOL;
   bool ::= "";
   i:INT := 0;
   loop
      until!(~(s[i].is_alpha) or (s[i].is_space) or i >= s.size);
      bool := bool + s[i];
      i := i + 1;
   end;
   case bool
   when "true","t","True","T","TRUE" then
      return true;
   when "false","f","False","F","FALSE" then
      return false;
   else
      raise #PARSE_BAD_BOOL_EXC(s);
   end;
end;

In the above routine there are two possible errors - either the file could not be opened or it does not contain a valid boolean. The two cases can be distinguised at the point when the exception is caught
protect
   file_name:STR; ... set to a value
   b:BOOL := get_bool(s);
when FILE_OPEN_EXC then
   #ERR + "Could not open:" + exception.file_name + "\n";
when PARSE_BAD_BOOL_EXC then
   #ERR + "Error in reading boolean:" + exception.str + "\n";
end;

The classes that implement these exceptions can be fairly simple
class FILE_OPEN_EXC is
   readonly attr str:STR:
   create(file_name:STR):SAME is
      res ::= new;
      res.str := file_name;
      return res;
   end;
end;

The other exception class is very similar.