-------------------------------------------------------------------------------
-- (C) Altran Praxis Limited
-------------------------------------------------------------------------------
--
-- The SPARK toolset is free software; you can redistribute it and/or modify it
-- under terms of the GNU General Public License as published by the Free
-- Software Foundation; either version 3, or (at your option) any later
-- version. The SPARK toolset is distributed in the hope that it will be
-- useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
-- Public License for more details. You should have received a copy of the GNU
-- General Public License distributed with the SPARK toolset; see file
-- COPYING3. If not, go to http://www.gnu.org/licenses for a complete copy of
-- the license.
--
--=============================================================================

with SystemErrors;

package body LexTokenLists is

   function Prefix_Unit (Poss_Prefix, Prefixed : Lists) return Boolean is
      Result : Boolean;
   begin
      if Poss_Prefix.Length <= Prefixed.Length then
         Result := True;
         for I in Positions range 1 .. Poss_Prefix.Length loop
            Result := Result
              and then LexTokenManager.Lex_String_Case_Insensitive_Compare
              (Lex_Str1 => Poss_Prefix.Content (I),
               Lex_Str2 => Prefixed.Content (I)) =
              LexTokenManager.Str_Eq;
            exit when not Result;
         end loop;
      else
         Result := False;
      end if;
      return Result;
   end Prefix_Unit;

   function Eq_Unit (First_Item, Second : Lists) return Boolean is
      Result : Boolean;
   begin
      if First_Item.Length = Second.Length then
         Result := True;
         for I in Positions range 1 .. First_Item.Length loop
            Result := Result
              and then LexTokenManager.Lex_String_Case_Insensitive_Compare
              (Lex_Str1 => First_Item.Content (I),
               Lex_Str2 => Second.Content (I)) =
              LexTokenManager.Str_Eq;
            exit when not Result;
         end loop;
      else
         Result := False;
      end if;
      return Result;
   end Eq_Unit;

   procedure Append (List : in out Lists;
                     Item : in     LexTokenManager.Lex_String) is
   begin
      if List.Length = ExaminerConstants.Lex_Token_Lists_Max_Length then
         SystemErrors.Fatal_Error (Sys_Err => SystemErrors.Unit_Nesting_Too_Deep,
                                   Msg     => "in LexTokenLists");
      end if;

      List.Length                := List.Length + 1;
      List.Content (List.Length) := Item;
   end Append;

   procedure Print_List (File : in SPARK_IO.File_Type;
                         List : in Lists) is
   begin
      for I in Positions range 1 .. List.Length loop
         E_Strings.Put_String (File  => File,
                               E_Str => LexTokenManager.Lex_String_To_String (Lex_Str => List.Content (I)));
         if I < List.Length then
            SPARK_IO.Put_Char (File => File,
                               Item => '.');
         end if;
      end loop;
   end Print_List;

   function Token_List_To_String (Token_List : Lists) return E_Strings.T is
      Full_Str, E_Str : E_Strings.T;
   begin
      if Token_List.Length > 0 then
         Full_Str := LexTokenManager.Lex_String_To_String (Lex_Str => Token_List.Content (1));
         for I in Positions range 2 .. Token_List.Length loop
            E_Str := LexTokenManager.Lex_String_To_String (Lex_Str => Token_List.Content (I));
            E_Strings.Append_String (E_Str => Full_Str,
                                     Str   => ".");
            E_Strings.Append_Examiner_String (E_Str1 => Full_Str,
                                              E_Str2 => E_Str);
         end loop;
      else
         Full_Str := E_Strings.Empty_String;
      end if;
      return Full_Str;
   end Token_List_To_String;

   function Get_Length (List : Lists) return Lengths is
   begin
      return List.Length;
   end Get_Length;

   function Get_Element (List : Lists;
                         Pos  : Positions) return LexTokenManager.Lex_String is
      Result : LexTokenManager.Lex_String := LexTokenManager.Null_String;
   begin
      if Pos <= List.Length then
         Result := List.Content (Pos);
      end if;
      return Result;
   end Get_Element;

   procedure Pop (List : in out Lists;
                  Item :    out LexTokenManager.Lex_String) is
   begin
      if List.Length > 0 then
         Item                       := List.Content (List.Length);
         List.Content (List.Length) := LexTokenManager.Null_String;
         List.Length                := List.Length - 1;
      else
         Item := LexTokenManager.Null_String;
      end if;
   end Pop;

end LexTokenLists;
