-------------------------------------------------------------------------------
-- (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 Command_Line_Options;
with SPARK_Ada_Integer_Text_IO;
with Sparklalr_Common;
with Sparklalr_Memory;
with Sparklalr_Memory.Dump;
with Sparklalr_Parser;
with Symbols_Dump;

package body Ees_Sym
--# own State is Ees_Max,
--#              Essentials,
--#              Exp_Symbol_Count;
is

   type Ess_Sym_Set is array (Sparklalr_Common.Sym_Range) of Boolean;

   type Ees_T is record
      Start_Index, T_Like_Count, Nt_Count : Integer;
      Entry_Symbol                        : Sparklalr_Common.Sym_Range;
      Expected_Ess_Symbols                : Ess_Sym_Set;
      Other_State                         : Boolean;
      Base_State                          : Sparklalr_Common.State_Range;
   end record;

   type Ess_Sym_Tab is array (Sparklalr_Common.State_Range) of Ees_T;

   Essentials                : Ess_Sym_Tab;
   Ees_Max, Exp_Symbol_Count : Integer;

   -- Local procedures/functions
   procedure Non_Empty_Expected (Ees_Set : in     Ess_Sym_Set;
                                 Result  :    out Boolean)
   --# derives Result from Ees_Set;
   is
      C         : Integer;
      Searching : Boolean;
   begin
      Searching := True;
      C         := -1;
      while Searching and then (C <= Sparklalr_Common.Max_Sym) loop
         Searching := not Ees_Set (C);
         C         := C + 1;
      end loop;
      Result := not Searching;
   end Non_Empty_Expected;
   -- End local procedures/functions

   procedure Gen_Essentials
   --# global in     Sparklalr_Memory.Stat_No;
   --#        in     Sparklalr_Parser.State;
   --#        in     Symbols_Dump.State;
   --#        in out Sparklalr_Memory.Dump.State;
   --#           out Ees_Max;
   --#           out Essentials;
   --#           out Exp_Symbol_Count;
   --# derives Ees_Max,
   --#         Essentials                  from Sparklalr_Memory.Dump.State,
   --#                                          Sparklalr_Memory.Stat_No,
   --#                                          Sparklalr_Parser.State,
   --#                                          Symbols_Dump.State &
   --#         Exp_Symbol_Count            from  &
   --#         Sparklalr_Memory.Dump.State from *,
   --#                                          Sparklalr_Memory.Stat_No,
   --#                                          Symbols_Dump.State;
   is

      Count, Ees_Start_Index : Sparklalr_Common.State_Range;
      S, T                   : Sparklalr_Memory.Dump.Pt_Memory;
      Temp_Ees               : Ees_T;
      Insert_State           : Sparklalr_Common.State_Range;

      procedure Gen_Ees
        (Current_State : in     Sparklalr_Common.State_Range;
         S, T          : in     Sparklalr_Memory.Dump.Pt_Memory;
         Ees_Ent       : in out Ees_T)
      --# global in     Sparklalr_Parser.State;
      --#        in     Symbols_Dump.State;
      --#        in out Sparklalr_Memory.Dump.State;
      --# derives Ees_Ent                     from *,
      --#                                          Current_State,
      --#                                          S,
      --#                                          Sparklalr_Memory.Dump.State,
      --#                                          Sparklalr_Parser.State,
      --#                                          Symbols_Dump.State,
      --#                                          T &
      --#         Sparklalr_Memory.Dump.State from *,
      --#                                          Symbols_Dump.State;
      is
         P, Q           : Sparklalr_Memory.Dump.Pt_Memory;
         C              : Integer;
         Dot_Out        : Boolean;
         Entry_Sym_Done : Boolean;
         S_Tmp          : Sparklalr_Memory.Dump.Pt_Memory;
      begin
         S_Tmp := S;
         Sparklalr_Memory.Dump.Gen_Terminal_Like;
         Ees_Ent.T_Like_Count         := 0;
         Ees_Ent.Nt_Count             := 0;
         Ees_Ent.Expected_Ess_Symbols := Ess_Sym_Set'(others => False);
         Entry_Sym_Done               := False;
         while (S_Tmp /= T) and then (S_Tmp /= Sparklalr_Memory.Dump.Null_Pt_Memory) loop
            Q := Sparklalr_Memory.Dump.Get_Dot (Sparklalr_Memory.Dump.Get_Item (S_Tmp));
            P := Sparklalr_Memory.Dump.Prodstart (Q);
            if (Sparklalr_Memory.Dump.Get_Next (P) /= Q)
              or else (Sparklalr_Memory.Dump.Get_Contents (Sparklalr_Memory.Dump.Get_Next (P)) = Sparklalr_Common.Nt_Base + 2) then
               Dot_Out := False;
               while (Sparklalr_Memory.Dump.Get_Contents (P) > 0) and then (not Dot_Out) loop
                  if Sparklalr_Memory.Dump.Get_Next (P) = Q then
                     Dot_Out := True;
                     C       := Sparklalr_Memory.Dump.Get_Contents (P);
                     if not Entry_Sym_Done then
                        Entry_Sym_Done       := True;
                        Ees_Ent.Entry_Symbol := C;
                     end if;
                  end if;
                  P := Sparklalr_Memory.Dump.Get_Next (P);
               end loop;
               if Dot_Out and then (not Sparklalr_Parser.Get_Reduce_State (Current_State)) then
                  C := Sparklalr_Memory.Dump.Get_Contents (Q);
                  if C > 0 then
                     if not Sparklalr_Memory.Dump.Get_Terminal_Like (C) and then not Ees_Ent.Expected_Ess_Symbols (C) then
                        Ees_Ent.Expected_Ess_Symbols (C) := True;
                        Ees_Ent.Nt_Count                 := Ees_Ent.Nt_Count + 1;
                     else
                        if Sparklalr_Memory.Dump.Get_Terminal_Like (C) and then not Ees_Ent.Expected_Ess_Symbols (C) then
                           Ees_Ent.Expected_Ess_Symbols (C) := True;
                           Ees_Ent.T_Like_Count             := Ees_Ent.T_Like_Count + 1;
                        end if;
                     end if;
                  end if;
               end if;
            end if;
            S_Tmp := Sparklalr_Memory.Dump.Get_Next (S_Tmp);
         end loop;
      end Gen_Ees;

      procedure Insert_Ees
        (Curr_State   : in     Sparklalr_Common.State_Range;
         In_Ees       : in     Ees_T;
         Insert_State :    out Sparklalr_Common.State_Range)
      --# global in out Essentials;
      --# derives Essentials,
      --#         Insert_State from Curr_State,
      --#                           Essentials,
      --#                           In_Ees;
      is
         S, C                 : Integer;
         Searching, Equal_Ees : Boolean;
      begin
         Searching    := True;
         Insert_State := 0;
         S            := 1;
         while Searching and then (S < Curr_State) loop
            if (In_Ees.T_Like_Count = Essentials (S).T_Like_Count) and then (In_Ees.Nt_Count = Essentials (S).Nt_Count) then
               C         := -1;
               Equal_Ees := True;
               while Equal_Ees and then (C <= Sparklalr_Common.Max_Sym) loop
                  if In_Ees.Expected_Ess_Symbols (C) /= Essentials (S).Expected_Ess_Symbols (C) then
                     Equal_Ees := False;
                  else
                     C := C + 1;
                  end if;
               end loop;
               if Equal_Ees then
                  Essentials (S).Other_State := True;
                  Insert_State               := S;
                  Searching                  := False;
               else
                  S := S + 1;
               end if;
            else
               S := S + 1;
            end if;
         end loop;
      end Insert_Ees;

   begin
      Essentials       :=
        Ess_Sym_Tab'
        (others => Ees_T'(Start_Index          => 0,
                          T_Like_Count         => 0,
                          Nt_Count             => 0,
                          Entry_Symbol         => -1,
                          Expected_Ess_Symbols => Ess_Sym_Set'(others => False),
                          Other_State          => False,
                          Base_State           => 0));
      Exp_Symbol_Count := 0;
      Ees_Max          := 0;
      Ees_Start_Index  := 1;
      Temp_Ees         :=
        Ees_T'
        (Start_Index          => 0,
         T_Like_Count         => 0,
         Nt_Count             => 0,
         Entry_Symbol         => -1,
         Expected_Ess_Symbols => Ess_Sym_Set'(others => False),
         Other_State          => False,
         Base_State           => 0);
      for I in Integer range 1 .. Sparklalr_Memory.Get_Stat_No loop
         S := Sparklalr_Memory.Dump.Get_State (I);
         T := Sparklalr_Memory.Dump.Get_State (I + 1);
         Gen_Ees (I, S, T, Temp_Ees);
         Insert_Ees (I, Temp_Ees, Insert_State);
         if Insert_State = 0 then
            Temp_Ees.Start_Index := Ees_Start_Index;
            Temp_Ees.Base_State  := 0;
            Count                := Temp_Ees.T_Like_Count + Temp_Ees.Nt_Count;
            Ees_Start_Index      := Ees_Start_Index + Count;
            if Count > Ees_Max then
               Ees_Max := Count;
            end if;
         else
            Temp_Ees.Start_Index := Essentials (Insert_State).Start_Index;
            Temp_Ees.Base_State  := Insert_State;
         end if;
         Temp_Ees.Other_State := False;
         Essentials (I)       := Temp_Ees;
      end loop;
   end Gen_Essentials;

   procedure Out_Essentials
   --# global in     Essentials;
   --#        in     Sparklalr_Memory.Stat_No;
   --#        in out Exp_Symbol_Count;
   --# derives Exp_Symbol_Count from *,
   --#                               Essentials,
   --#                               Sparklalr_Memory.Stat_No;
   is

      Result_Non_Empty_Expected : Boolean;

      procedure Out_Ees (Ees_Set : in Ess_Sym_Set)
      --# global in out Exp_Symbol_Count;
      --# derives Exp_Symbol_Count from *,
      --#                               Ees_Set;
      is
      begin
         for C in Sparklalr_Common.Sym_Range loop
            if C <= Sparklalr_Common.Nt_Base then
               if Ees_Set (C) then
                  Exp_Symbol_Count := Exp_Symbol_Count + 1;
               end if;
            end if;
         end loop;
         for C in Sparklalr_Common.Sym_Range loop
            if C > Sparklalr_Common.Nt_Base then
               if Ees_Set (C) then
                  Exp_Symbol_Count := Exp_Symbol_Count + 1;
               end if;
            end if;
         end loop;
      end Out_Ees;

   begin
      for I in Integer range 1 .. Sparklalr_Memory.Get_Stat_No loop
         Non_Empty_Expected (Essentials (I).Expected_Ess_Symbols, Result_Non_Empty_Expected);
         if (Essentials (I).Base_State = 0) and then Result_Non_Empty_Expected then
            Out_Ees (Essentials (I).Expected_Ess_Symbols);
         end if;
      end loop;
   end Out_Essentials;

   procedure Sp_Exp_Out (F : in out SPARK.Ada.Text_IO.File_Type)
   --# global in     Command_Line_Options.State;
   --#        in     Ees_Max;
   --#        in     Essentials;
   --#        in     Exp_Symbol_Count;
   --#        in     Sparklalr_Memory.Stat_No;
   --#        in     Symbols_Dump.State;
   --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
   --# derives F                                     from *,
   --#                                                    Command_Line_Options.State,
   --#                                                    Ees_Max,
   --#                                                    Essentials,
   --#                                                    Exp_Symbol_Count,
   --#                                                    Sparklalr_Memory.Stat_No,
   --#                                                    Symbols_Dump.State &
   --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
   --#                                                    Essentials,
   --#                                                    Sparklalr_Memory.Stat_No,
   --#                                                    Symbols_Dump.State;
   is

      Comma_Required            : Boolean;
      No_Exp_Sym_P2, Ees_Max_P2 : Integer;
      Result_Non_Empty_Expected : Boolean;

      procedure Out_Ees (F       : in out SPARK.Ada.Text_IO.File_Type;
                         Ees_Set : in     Ess_Sym_Set;
                         ST      : in     Sparklalr_Common.State_Range)
      --# global in     Essentials;
      --#        in     Symbols_Dump.State;
      --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
      --# derives F                                     from *,
      --#                                                    Ees_Set,
      --#                                                    Essentials,
      --#                                                    ST,
      --#                                                    Symbols_Dump.State &
      --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
      --#                                                    Ees_Set,
      --#                                                    Symbols_Dump.State;
      is
         Index          : Integer;
         Posn           : Integer;
         Comma_Required : Boolean;
      begin
         Comma_Required := False;
         Posn           := 10;
         Index          := Essentials (ST).Start_Index;
         for C in Sparklalr_Common.Sym_Range loop
            if C <= Sparklalr_Common.Nt_Base then
               if Ees_Set (C) then
                  if Comma_Required then
                     SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                                      Item => ",");
                     SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                                         Item  => Index,
                                                         Width => 5,
                                                         Base  => 10);
                     SPARK.Ada.Text_IO.Put_File (File => F,
                                                 Item => " =>");
                  else
                     Comma_Required := True;
                  end if;
                  Symbols_Dump.Print_String_Sym (F, Sparklalr_Common.Sp_Symbol_Str, C, Posn, 10, False);
                  Index := Index + 1;
               end if;
            end if;
         end loop;
         for C in Sparklalr_Common.Sym_Range loop
            if C > Sparklalr_Common.Nt_Base then
               if Ees_Set (C) then
                  if Comma_Required then
                     SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                                      Item => ",");
                     SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                                         Item  => Index,
                                                         Width => 5,
                                                         Base  => 10);
                     SPARK.Ada.Text_IO.Put_File (File => F,
                                                 Item => " =>");
                  else
                     Comma_Required := True;
                  end if;
                  Symbols_Dump.Print_String_Sym (F, Sparklalr_Common.Sp_Symbol_Str, C, Posn, 10, False);
                  Index := Index + 1;
               end if;
            end if;
         end loop;
      end Out_Ees;

   begin -- Sp_Exp_Out
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "with SP_Productions;");
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "with SP_Symbols;");
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "use type SP_Productions.SP_State;");
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "--# inherit SP_Productions,");
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "--#         SP_Symbols;");
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "package SP_Expected_Symbols is");
      SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                       Spacing => 1);
      SPARK.Ada.Text_IO.Put_File (File => F,
                                  Item => "   Max_Ess_Symbol : constant Natural := ");
      SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                          Item  => Ees_Max,
                                          Width => 1,
                                          Base  => 10);
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => ";");
      SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                       Spacing => 1);
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "   type SP_Ess_Sym_Range is range 0 .. Max_Ess_Symbol;");
      SPARK.Ada.Text_IO.Put_Line_File
        (File => F,
         Item => "   type SP_Exp_Sym_List is array (SP_Ess_Sym_Range) of SP_Symbols.SP_Symbol;");
      SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                       Spacing => 1);
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "   procedure Get_Expected_Symbols");
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "     (Error_State         : in     SP_Productions.SP_State;");
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "      No_Of_Terminals     :    out SP_Ess_Sym_Range;");
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "      Terminal_List       :    out SP_Exp_Sym_List;");
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "      No_Of_Non_Terminals :    out SP_Ess_Sym_Range;");
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "      Non_Terminal_List   :    out SP_Exp_Sym_List);");
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "   --# derives Non_Terminal_List,");
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "   --#         No_Of_Non_Terminals,");
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "   --#         No_Of_Terminals,");
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "   --#         Terminal_List       from Error_State;");
      SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                       Spacing => 1);
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "end SP_Expected_Symbols;");
      SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                       Spacing => 1);
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "package body SP_Expected_Symbols is");
      SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                       Spacing => 1);
      SPARK.Ada.Text_IO.Put_File (File => F,
                                  Item => "   No_Of_Exp_Symbols : constant Natural := ");
      SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                          Item  => Exp_Symbol_Count,
                                          Width => 1,
                                          Base  => 10);
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => ";");
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "   type Exp_Sym_Range is range 1 .. No_Of_Exp_Symbols;");
      SPARK.Ada.Text_IO.Put_Line_File
        (File => F,
         Item => "   type Exp_Symbol_List is array (Exp_Sym_Range) of SP_Symbols.SP_Symbol;");
      SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                       Spacing => 1);
      if Command_Line_Options.Get_Self_Pack then
         No_Exp_Sym_P2 := 0;
         while 2 ** No_Exp_Sym_P2 <= Exp_Symbol_Count loop
            No_Exp_Sym_P2 := No_Exp_Sym_P2 + 1;
         end loop;
         Ees_Max_P2 := 0;
         while 2 ** Ees_Max_P2 <= Ees_Max loop
            Ees_Max_P2 := Ees_Max_P2 + 1;
         end loop;
         SPARK.Ada.Text_IO.Put_File (File => F,
                                     Item => "   type Ess_Symbol_Entry is range 0 .. 2**");
         SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                             Item  => No_Exp_Sym_P2 + 2 * Ees_Max_P2,
                                             Width => 1,
                                             Base  => 10);
         SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                          Item => "-1;");
         SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                          Spacing => 1);
         SPARK.Ada.Text_IO.Put_File (File => F,
                                     Item => "   Index_Lim       : constant Ess_Symbol_Entry := 2**");
         SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                             Item  => No_Exp_Sym_P2,
                                             Width => 1,
                                             Base  => 10);
         SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                          Item => ";");
         SPARK.Ada.Text_IO.Put_File (File => F,
                                     Item => "   Term_Lim        : constant Ess_Symbol_Entry := 2**");
         SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                             Item  => Ees_Max_P2,
                                             Width => 1,
                                             Base  => 10);
         SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                          Item => ";");
         SPARK.Ada.Text_IO.Put_File (File => F,
                                     Item => "   Non_Term_Lim    : constant Ess_Symbol_Entry := 2**");
         SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                             Item  => 2 * Ees_Max_P2,
                                             Width => 1,
                                             Base  => 10);
         SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                          Item => ";");
         SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                          Item => "   Index           : constant Ess_Symbol_Entry := 1;");
         SPARK.Ada.Text_IO.Put_Line_File
           (File => F,
            Item => "   N_Terminals     : constant Ess_Symbol_Entry := Index * Index_Lim;");
         SPARK.Ada.Text_IO.Put_Line_File
           (File => F,
            Item => "   N_Non_Terminals : constant Ess_Symbol_Entry := N_Terminals * Term_Lim;");
      else
         SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                          Item => "   type Ess_Symbol_Entry is record");
         SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                          Item => "      Index                                : Exp_Sym_Range;");
         SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                          Item => "      No_Of_Terminals, No_Of_Non_Terminals : SP_Ess_Sym_Range;");
         SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                          Item => "   end record;");
      end if;
      SPARK.Ada.Text_IO.Put_File (File => F,
                                  Item => "   type Exp_Ess_Symbols is array (SP_Productions.Valid_States) of");
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => " Ess_Symbol_Entry;");
      SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                       Spacing => 1);
      Comma_Required := False;
      SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                       Spacing => 1);
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "   Essential_Symbols : constant Exp_Symbol_List := Exp_Symbol_List'(");
      for I in Integer range 1 .. Sparklalr_Memory.Get_Stat_No loop
         Non_Empty_Expected (Essentials (I).Expected_Ess_Symbols, Result_Non_Empty_Expected);
         if (Essentials (I).Base_State = 0) and then Result_Non_Empty_Expected then
            if Comma_Required then
               SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                                Item => ",");
            end if;
            Comma_Required := True;
            if Essentials (I).Other_State then
               for J in Integer range I + 1 .. Sparklalr_Memory.Get_Stat_No loop
                  if Essentials (J).Base_State = I then
                     SPARK.Ada.Text_IO.Put_File (File => F,
                                                 Item => "--");
                     SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                                         Item  => J,
                                                         Width => 5,
                                                         Base  => 10);
                     SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                                      Spacing => 1);
                  end if;
               end loop;
            end if;
            SPARK.Ada.Text_IO.Put_File (File => F,
                                        Item => "--");
            SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                                Item  => I,
                                                Width => 5,
                                                Base  => 10);
            SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                             Spacing => 1);
            SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                                Item  => Essentials (I).Start_Index,
                                                Width => 5,
                                                Base  => 10);
            SPARK.Ada.Text_IO.Put_File (File => F,
                                        Item => " =>");
            Out_Ees (F, Essentials (I).Expected_Ess_Symbols, I);
         end if;
      end loop;
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => ");");
      SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                       Spacing => 1);
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "   Expected_Symbols : constant Exp_Ess_Symbols := Exp_Ess_Symbols'(");
      if Command_Line_Options.Get_Self_Pack then
         for I in Integer range 1 .. Sparklalr_Memory.Get_Stat_No loop
            SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                                Item  => I,
                                                Width => 5,
                                                Base  => 10);
            SPARK.Ada.Text_IO.Put_File (File => F,
                                        Item => " => (Index * ");
            SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                                Item  => Essentials (I).Start_Index,
                                                Width => 1,
                                                Base  => 10);
            SPARK.Ada.Text_IO.Put_File (File => F,
                                        Item => " + ");
            SPARK.Ada.Text_IO.Put_File (File => F,
                                        Item => "N_Terminals * ");
            SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                                Item  => Essentials (I).T_Like_Count,
                                                Width => 1,
                                                Base  => 10);
            SPARK.Ada.Text_IO.Put_File (File => F,
                                        Item => ") + ");
            SPARK.Ada.Text_IO.Put_File (File => F,
                                        Item => "N_Non_Terminals * ");
            SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                                Item  => Essentials (I).Nt_Count,
                                                Width => 1,
                                                Base  => 10);
            if I < Sparklalr_Memory.Get_Stat_No then
               SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                                Item => ",");
            else
               SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                                Item => ");");
            end if;
         end loop;
      else
         for I in Integer range 1 .. Sparklalr_Memory.Get_Stat_No loop
            SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                                Item  => I,
                                                Width => 5,
                                                Base  => 10);
            SPARK.Ada.Text_IO.Put_File (File => F,
                                        Item => " => Ess_Symbol_Entry'(");
            SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                                Item  => Essentials (I).Start_Index,
                                                Width => 4,
                                                Base  => 10);
            SPARK.Ada.Text_IO.Put_File (File => F,
                                        Item => ", ");
            SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                                Item  => Essentials (I).T_Like_Count,
                                                Width => 1,
                                                Base  => 10);
            SPARK.Ada.Text_IO.Put_File (File => F,
                                        Item => ", ");
            SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                                Item  => Essentials (I).Nt_Count,
                                                Width => 1,
                                                Base  => 10);
            SPARK.Ada.Text_IO.Put_Character_File (File => F,
                                                  Item => ')');
            if I < Sparklalr_Memory.Get_Stat_No then
               SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                                Item => ",");
            else
               SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                                Item => ");");
            end if;
         end loop;
      end if;
      SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                       Spacing => 1);
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "   procedure Get_Expected_Symbols");
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "     (Error_State         : in     SP_Productions.SP_State;");
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "      No_Of_Terminals     :    out SP_Ess_Sym_Range;");
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "      Terminal_List       :    out SP_Exp_Sym_List;");
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "      No_Of_Non_Terminals :    out SP_Ess_Sym_Range;");
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "      Non_Terminal_List   :    out SP_Exp_Sym_List)");
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "      is separate;");
      SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                       Spacing => 1);
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "end SP_Expected_Symbols;");
   end Sp_Exp_Out;

end Ees_Sym;
