unit LexiconClass;

interface

 const
  STATE_JUSTRESET = 0;
  STATE_NOTJUSTRESET = 1;

 type
  POLexicon = ^OLexicon;
  OLexicon = Object
   Constructor Create;
   Function    SetFileLexicon(const fn: String): Boolean;
   Function    SetFilePrefix(const fn: String): Boolean;
   Function    SetFileSuffix(const fn: String): Boolean;

   Procedure   PrefixActive(const newmode: Boolean);
   Procedure   SuffixActive(const newmode: Boolean);

   Function    GetNextWord(var nextword: String): Boolean;

   Procedure   Reset;
   Destructor  Destroy;

  public
   lexposition      :LongInt;
   lexmax           :LongInt;

  private
   fn_lexicon,
   fn_prefix,
   fn_suffix        :String;

   fh_lexicon,
   fh_prefix,
   fh_suffix        :TextFile;

   is_open_lexicon,
   is_open_prefix,
   is_open_suffix,
   is_prefix_active,
   is_suffix_active :Boolean;

   curr_lexiconword,
   curr_prefixword,
   curr_suffixword  :String;

   istate           :Byte;
  end;

implementation
Uses SysUtils;

Constructor OLexicon.Create;
begin
 fn_lexicon:='';
 fn_prefix:='';
 fn_suffix:='';
 is_prefix_active:=false;
 is_suffix_active:=false;
 is_open_lexicon:=false;
 is_open_prefix:=false;
 is_open_suffix:=false;
 curr_lexiconword:='';
 curr_prefixword:='';
 curr_suffixword:='';
 istate:=0;
 lexposition:=0;
 lexmax:=0;
end;

Function  OLexicon.SetFileLexicon(const fn: String): Boolean;
begin
 if FileExists(fn) then
 begin
  fn_lexicon:=fn;
  result:=true;
 end else begin
  fn_lexicon:='';
  result:=false;
 end;
end;

Function  OLexicon.SetFilePrefix(const fn: String): Boolean;
begin
 if FileExists(fn) then
 begin
  fn_prefix:=fn;
  result:=true;
 end else begin
  fn_prefix:='';
  result:=false;
 end;
end;

Function  OLexicon.SetFileSuffix(const fn: String): Boolean;
begin
 if FileExists(fn) then
 begin
  fn_suffix:=fn;
  result:=true;
 end else begin
  fn_suffix:='';
  result:=false;
 end;
end;

Procedure OLexicon.PrefixActive(const newmode: Boolean);
begin
 is_prefix_active:=newmode;
end;

Procedure OLexicon.SuffixActive(const newmode: Boolean);
begin
 is_suffix_active:=newmode;
end;

Function    OLexicon.GetNextWord(var nextword: String): Boolean;
begin
 if (not is_open_lexicon) then
 begin
  result:=false;
  exit;
 end;

 result:=true;

 if is_prefix_active and is_suffix_active then { both active }
 begin

  if istate=STATE_JUSTRESET then { always with a lexicon word }
  begin
   readln(fh_lexicon,curr_lexiconword);
   istate:=STATE_NOTJUSTRESET;
  end;

  if eof(fh_suffix) then
  begin

   if eof(fh_prefix) then
   begin

    if eof(fh_lexicon) then { the end }
    begin
     result:=false;
     exit;
    end;

    system.reset(fh_prefix);
    readln(fh_lexicon,curr_lexiconword);
    Inc(lexposition,length(curr_lexiconword)+2); { progress }
   end; { eof-of-prefix }

   system.reset(fh_suffix);
   readln(fh_prefix,curr_prefixword);
  end; { eof-of-suffix }

  readln(fh_suffix,curr_suffixword);
  nextword:=curr_prefixword+curr_lexiconword+curr_suffixword;

 end else if is_prefix_active then             { prefix active }
 begin
  if eof(fh_prefix) then
  begin
   if eof(fh_lexicon) then { the end }
   begin
    result:=false;
    exit;
   end;
   system.reset(fh_prefix);
   readln(fh_lexicon,curr_lexiconword);
   Inc(lexposition,length(curr_lexiconword)+2); { progress }
  end;

  if istate=STATE_JUSTRESET then { always with a lexicon word }
  begin
   readln(fh_lexicon,curr_lexiconword);
   istate:=STATE_NOTJUSTRESET;
  end;

  readln(fh_prefix,curr_prefixword);
  nextword:=curr_prefixword+curr_lexiconword;
 end else if is_suffix_active then             { suffix active }
 begin
  if eof(fh_suffix) then
  begin
   if eof(fh_lexicon) then { the end }
   begin
    result:=false;
    exit;
   end;
   system.reset(fh_suffix);
   readln(fh_lexicon,curr_lexiconword);
   Inc(lexposition,length(curr_lexiconword)+2); { progress }
  end;

  if istate=STATE_JUSTRESET then { always with a lexicon word }
  begin
   readln(fh_lexicon,curr_lexiconword);
   istate:=STATE_NOTJUSTRESET;
  end;

  readln(fh_suffix,curr_suffixword);
  nextword:=curr_lexiconword+curr_suffixword;
 end else                                      { only lexicon active }
 begin
  if eof(fh_lexicon) then { the end }
  begin
   result:=false;
   exit;
  end;
  readln(fh_lexicon,curr_lexiconword);
  Inc(lexposition,length(curr_lexiconword)+2); { progress }
  nextword:=curr_lexiconword;
 end;

end;

Procedure   OLexicon.Reset;
var
 F             :File;
begin
 if is_open_lexicon then system.reset(fh_lexicon) else
 begin
  assign(f,fn_lexicon);
  system.reset(f,1);
  lexmax:=filesize(f);
  close(f);
  assign(fh_lexicon,fn_lexicon);
  system.reset(fh_lexicon);
  is_open_lexicon:=true;
  istate:=STATE_JUSTRESET;
  lexposition:=0;
 end;
 if is_open_prefix then system.reset(fh_prefix) else if is_prefix_active then
 begin
  assign(fh_prefix,fn_prefix);
  system.reset(fh_prefix);
  is_open_prefix:=true;
  istate:=STATE_JUSTRESET;
 end;
 if is_open_suffix then system.reset(fh_suffix) else if is_suffix_active then
 begin
  assign(fh_suffix,fn_suffix);
  system.reset(fh_suffix);
  is_open_suffix:=true;
  istate:=STATE_JUSTRESET;
 end;
end;

Destructor  OLexicon.Destroy;
begin
 if is_open_lexicon then
 begin
  close(fh_lexicon);
  is_open_lexicon:=false;
 end;

 if is_open_prefix then
 begin
  close(fh_prefix);
  is_open_prefix:=false;
 end;

 if is_open_suffix then
 begin
  close(fh_suffix);
  is_open_suffix:=false;
 end;
end;


end.

