[comp.lang.eiffel] EIFFEL CODE

marcap@hercule.cs.concordia.ca (PAWLOWSKY) (02/08/90)

This file consists of two classes.  The first is a deferred class which
defines the routines needed, and the second is a class which implements
pattern matching for a FIXED_LIST.


deferred class PATTERN_MATCHER [T]
  -- This class will find patterns based on Current.
  -- The reciever should inherit from this class.
  -- 
  -- These routines are made to find patterns in 1 dimensional collections.

  -- Marc Andrew Pawlowsky
  -- 1683063
  -- Concordia University
  -- Dept. Computer Science
  -- Montreal, Quebec
  -- Canada
  

  -- CLOSED:  08 AUG 89

  -- BUGS:
  --   Might not work with characters, due to bug in Eiffel 2.1.  Known
  --   fix is to inherit STD_FILES.  (Why this works is unkown.)

export
  do_not_care, wild_card, find

feature

  i_th(i:INTEGER):T is
	-- the i-th member of the collection
    require
      i_positive: i > 0
    deferred
    end; -- i_th

  count:INTEGER is
	-- the number of members in the collection
    deferred
    ensure
      Result >= 0
    end; -- count

  do_not_care: T;
	-- Skip 1 position when this is occurs

  wild_card:  T;
	-- Skip as many positions as needed when this occurs
        -- This may be 1 or more positions.

  find(match:LIST[T], i:INTEGER):INTEGER  is
	-- Return the index of where Current cound be found in match
        -- Start the search at the i-th position of match
	--
	-- Return 0 if Current does not occur in match
        --
        -- test between elements is done with Equal
    require
      i_positive: i > 0;
    local
      matches: BOOLEAN;
    do
      -- try finding match for every position >= i
      from
        matches := false;
        Result := i;
      variant
        match.count - Result + 1
      until
        matches or (Result > (match.count - Current.count + 1))
      loop        
        matches := Current.find2(match, 1, Result);
        Result := Result + 1;
      end; -- loop
      
      if not matches then
        Result := 0;
      else
        Result := Result - 1;
      end;

    ensure
      Result >= 0;
    end; -- find


  find2(match:LIST[T], start:INTEGER, i:INTEGER):BOOLEAN is
	-- Return whether Current[start,Current.length] starts at the i-th position
        -- in match

	-- test between elements is done with Equal
    require
      start_positive: start > 0;
      i_positive: i > 0;
    local
      j: INTEGER;
    do
      if start > Current.count then
        Result := true;
        -- all items have been matched
     else
       if (Current.count - start) > (match.count - i) then
          -- there are more things to match then there are places
	  Result := false;
        else
          if Current.i_th(start) = (do_not_care) then
            -- go to next position 
            Result := Current.find2(match, start+1, i+1);
          else
            if Current.i_th(start) = (wild_card) then
              -- try matching for each position > i
              from
	        Result := false;
	        j := i + 1;
	      variant
	        match.count - j + 1
	      until
		Result or (j > match.count)
	      loop
		Result := Current.find2(match, start+1, j);
		j := j + 1;
	      end; -- loop
            else
              -- the normal members
              if Current.i_th(start) = (match.i_th(i)) then
                Result := Current.find2(match, start+1, i+1);
              else
	        Result := false;
              end; -- if
            end; -- if
          end; -- if
        end; -- if
      end; -- if
    end; -- find2

end  -- PATTERN_MATCHER 
--
--  MODIFICATION HISTORY
--
--  03 FEB 90 -- updated obsolete features from Eiffel 2.1 to 2.2



class PATTERN_FIXED_LIST[T]
  -- A fixed-list that can be searched for patterns with wild cards.

  -- Marc Andrew Pawlowsky
  -- 1683063
  -- Concordia University
  -- Dept. Computer Science
  -- Montreal, Quebec
  -- Canada
  
  -- CLOSED:  08 AUG 89
 
export
  do_not_care, wild_card, find, 
  count, empty, position, offright, offleft, isfirst, 
  islast, value, i_th, first, last, change_value, change_i_th,
  swap, start, finish, forth, back, go, search, mark, return,
  index_of, present, duplicate, wipe_out,
  put_i_th

inherit 
  PATTERN_MATCHER[T] define count;
  FIXED_LIST[T] rename i_th as j_th, nb_elements as number_of_elements
                

feature

  Create(n:INTEGER, do_not_care_value, wild_card_value:T) is
	-- Allocate list with n elements
    require
      at_least_one: n >= 1
    do
      do_not_care := do_not_care_value;
      wild_card := wild_card_value;
      array_create(1, n);
    end; -- Create

  -- work arounds to allow the proper functions to come from FIXED_LIST

  i_th(i:INTEGER):T is
	-- value of the i-th element
    require
      index_large_enough: i>= 1;
      index_small_enough: i <= count;
    do
      Result := Current.j_th(i);
    end; -- i_th


end -- PATTERN_FIXED_LIST
--
--  MODIFICATION HISTORY
--
--  03 FEB 90 -- updated obsolete features from Eiffel 2.1 to 2.2