-------------------------------------------------------------------------------
-- (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_Error;
with Sparklalr_Memory;
with Symbols_Dump;

package body Sparklalr_Goto
--# own State is Goto_Array,
--#              Goto_Count,
--#              Goto_List,
--#              Goto_List_Count,
--#              Goto_Table;
is

   Goto_Table_Size : constant := 10000;

   subtype Pt_Goto_Rec is Natural range 0 .. Goto_Table_Size;
   subtype Goto_Array_Range is Positive range 1 .. Goto_Table_Size;
   type Goto_Rec is record
      Index, Check_Index : Sparklalr_Common.State_Range;
      Entry_State        : Sparklalr_Common.State_Range;
      Go_Next            : Pt_Goto_Rec;
   end record;
   type Goto_Array_Array_T is array (Goto_Array_Range) of Goto_Rec;
   type Goto_Array_T is record
      The_Array : Goto_Array_Array_T;
      Top       : Pt_Goto_Rec;
   end record;

   type N_Term_Index_Pair is record
      Lower, Upper : Integer;
   end record;
   type N_Term_Index is array (Sparklalr_Common.Non_Term_Range) of N_Term_Index_Pair;

   type Goto_List_T is array (Sparklalr_Common.Non_Term_Range) of Pt_Goto_Rec; -- GOTO TABLE
   Goto_List       : Goto_List_T;
   Goto_List_Count : Integer;
   Goto_Count      : Integer;
   Goto_Table      : N_Term_Index;
   Goto_Array      : Goto_Array_T;

   -- Local procedures/functions
   procedure New_State_Set
     (G        : in     Pt_Goto_Rec;
      Org      : in out Integer;
      Last_Var :    out Integer;
      Next     :    out Next_T)
   --# global in out Goto_Array;
   --# derives Goto_Array,
   --#         Org        from *,
   --#                         G,
   --#                         Goto_Array &
   --#         Last_Var   from G,
   --#                         Goto_Array,
   --#                         Org &
   --#         Next       from ;
   is
   begin
      while Goto_Array.The_Array (G).Index - Org > Sparklalr_Common.Max_Set loop
         Org := (Org + Sparklalr_Common.Max_Set) + 1;
      end loop;
      while Goto_Array.The_Array (G).Index - Org < 0 loop
         Org := (Org - Sparklalr_Common.Max_Set) - 1;
      end loop;
      Last_Var                       := Goto_Array.The_Array (G).Index - Org;
      Next                           := Next_T'(others => False);
      Goto_Array.The_Array (G).Index := 0;
   end New_State_Set;

   procedure Copy (G     : in     Pt_Goto_Rec;
                   Found :    out Boolean;
                   G1    : in out Pt_Goto_Rec)
   --# global in Goto_Array;
   --# derives Found,
   --#         G1    from G,
   --#                    G1,
   --#                    Goto_Array;
   is
      Gval : Integer;
   begin
      Found := False;
      Gval  := Goto_Array.The_Array (G).Entry_State;
      G1    := Goto_Array.The_Array (G1).Go_Next;
      while (G1 /= 0) and then not Found loop
         if Goto_Array.The_Array (G1).Entry_State = Gval then
            Found := True;
         else
            G1 := Goto_Array.The_Array (G1).Go_Next;
         end if;
      end loop;
   end Copy;

   procedure Insert_State
     (G        : in     Pt_Goto_Rec;
      Org      : in     Integer;
      Last_Var : in out Integer;
      Next     : in out Next_T)
   --# global in out Goto_Array;
   --# derives Goto_Array from *,
   --#                         G &
   --#         Last_Var,
   --#         Next       from *,
   --#                         G,
   --#                         Goto_Array,
   --#                         Last_Var,
   --#                         Org;
   is
   begin
      if Goto_Array.The_Array (G).Index - Org < Last_Var then
         Next (Goto_Array.The_Array (G).Index - Org) := True;
      else
         Next (Last_Var) := True;
         Last_Var        := Goto_Array.The_Array (G).Index - Org;
      end if;
      Goto_Array.The_Array (G).Index := 0;
   end Insert_State;

   function Last_Goto (G : in Pt_Goto_Rec) return Boolean
   --# global in Goto_Array;
   is
      Result : Boolean;
      Gval   : Integer;
      G_Tmp  : Pt_Goto_Rec;
   begin
      G_Tmp  := G;
      Result := True;
      Gval   := Goto_Array.The_Array (G_Tmp).Entry_State;
      G_Tmp  := Goto_Array.The_Array (G_Tmp).Go_Next;
      while (G_Tmp /= 0) and then Result loop
         if (Goto_Array.The_Array (G_Tmp).Entry_State = Gval) or else (Goto_Array.The_Array (G_Tmp).Index = 0) then
            G_Tmp := Goto_Array.The_Array (G_Tmp).Go_Next;
         else
            Result := False;
         end if;
      end loop;
      return Result;
   end Last_Goto;

   procedure Zero_Index (G : in Pt_Goto_Rec)
   --# global in out Goto_Array;
   --# derives Goto_Array from *,
   --#                         G;
   is
      G_Tmp : Pt_Goto_Rec;
   begin
      G_Tmp := G;
      if Last_Goto (G) then
         while G_Tmp /= 0 loop
            Goto_Array.The_Array (G_Tmp).Index := 0;
            G_Tmp                              := Goto_Array.The_Array (G_Tmp).Go_Next;
         end loop;
      end if;
   end Zero_Index;
   -- End local procedures/functions

   procedure Initialise
   --# global out Goto_Array;
   --#        out Goto_Count;
   --#        out Goto_List;
   --#        out Goto_List_Count;
   --#        out Goto_Table;
   --# derives Goto_Array,
   --#         Goto_Count,
   --#         Goto_List,
   --#         Goto_List_Count,
   --#         Goto_Table      from ;
   is
   begin
      Goto_List       := Goto_List_T'(others => 0);
      Goto_List_Count := 0;
      Goto_Count      := 0;
      Goto_Table      := N_Term_Index'(others => N_Term_Index_Pair'(Lower => 0,
                                                                    Upper => 0));
      Goto_Array      :=
        Goto_Array_T'
        (The_Array => Goto_Array_Array_T'(others => Goto_Rec'(Index       => 0,
                                                              Check_Index => 0,
                                                              Entry_State => 0,
                                                              Go_Next     => 0)),
         Top       => 0);
   end Initialise;

   function Goto_Search (State_Index, Non_Term_Index : in Integer) return Integer
   -- SEARCHES GOTO TABLE
   --# global in Goto_Array;
   --#        in Goto_List;
   is
      Result_Goto_Search : Integer;
      Glist              : Pt_Goto_Rec;
      Found              : Boolean;
   begin
      Found              := False;
      Result_Goto_Search := 0;
      Glist              := Goto_List (Non_Term_Index - Sparklalr_Common.Nt_Base);
      while (Glist /= 0) and then not Found loop
         if Goto_Array.The_Array (Glist).Index = State_Index then
            Result_Goto_Search := Goto_Array.The_Array (Glist).Entry_State;
            Found              := True;
         else
            Glist := Goto_Array.The_Array (Glist).Go_Next;
         end if;
      end loop;
      return Result_Goto_Search;
   end Goto_Search;

   procedure Go_Out (I : in Integer)
   --# global in     Goto_List;
   --#        in out Goto_Array;
   --#        in out Goto_List_Count;
   --# derives Goto_Array,
   --#         Goto_List_Count from *,
   --#                              Goto_Array,
   --#                              Goto_List,
   --#                              I;
   is

      G, G1    : Pt_Goto_Rec;
      Found    : Boolean;
      Org      : Integer;
      Last_Var : Integer;
      Next     : Next_T;

      procedure New_State_Set_Nested
        (G        : in     Pt_Goto_Rec;
         Org      : in out Integer;
         Last_Var :    out Integer;
         Next     :    out Next_T)
      --# global in out Goto_Array;
      --# derives Goto_Array,
      --#         Org        from *,
      --#                         G,
      --#                         Goto_Array &
      --#         Last_Var   from G,
      --#                         Goto_Array,
      --#                         Org &
      --#         Next       from ;
      is
      begin
         while Goto_Array.The_Array (G).Check_Index - Org > Sparklalr_Common.Max_Set loop
            Org := (Org + Sparklalr_Common.Max_Set) + 1;
         end loop;
         while Goto_Array.The_Array (G).Index - Org < 0 loop
            Org := (Org - Sparklalr_Common.Max_Set) - 1;
         end loop;
         Last_Var                             := Goto_Array.The_Array (G).Check_Index - Org;
         Next                                 := Next_T'(others => False);
         Goto_Array.The_Array (G).Check_Index := 0;
      end New_State_Set_Nested;

      procedure Insert_State_Nested
        (G        : in     Pt_Goto_Rec;
         Org      : in     Integer;
         Last_Var : in out Integer;
         Next     : in out Next_T)
      --# global in out Goto_Array;
      --# derives Goto_Array from *,
      --#                         G &
      --#         Last_Var,
      --#         Next       from *,
      --#                         G,
      --#                         Goto_Array,
      --#                         Last_Var,
      --#                         Org;
      is
      begin
         if Goto_Array.The_Array (G).Check_Index - Org < Last_Var then
            Next (Goto_Array.The_Array (G).Check_Index - Org) := True;
         else
            Next (Last_Var) := True;
            Last_Var        := Goto_Array.The_Array (G).Check_Index - Org;
         end if;
         Goto_Array.The_Array (G).Check_Index := 0;
      end Insert_State_Nested;

      function Last_Goto_Nested (G : in Pt_Goto_Rec) return Boolean
      --# global in Goto_Array;
      is
         Result : Boolean;
         Gval   : Integer;
         G_Tmp  : Pt_Goto_Rec;
      begin
         G_Tmp  := G;
         Result := True;
         Gval   := Goto_Array.The_Array (G_Tmp).Entry_State;
         G_Tmp  := Goto_Array.The_Array (G_Tmp).Go_Next;
         while (G_Tmp /= 0) and then Result loop
            if (Goto_Array.The_Array (G_Tmp).Entry_State = Gval) or else (Goto_Array.The_Array (G_Tmp).Check_Index = 0) then
               G_Tmp := Goto_Array.The_Array (G_Tmp).Go_Next;
            else
               Result := False;
            end if;
         end loop;
         return Result;
      end Last_Goto_Nested;

      procedure Zero_Index_Nested (G : in Pt_Goto_Rec)
      --# global in out Goto_Array;
      --# derives Goto_Array from *,
      --#                         G;
      is
         G_Tmp : Pt_Goto_Rec;
      begin
         G_Tmp := G;
         while G_Tmp /= 0 loop
            Goto_Array.The_Array (G_Tmp).Check_Index := 0;
            G_Tmp                                    := Goto_Array.The_Array (G_Tmp).Go_Next;
         end loop;
      end Zero_Index_Nested;

      procedure Write_States (Last_Var : in Integer;
                              Next     : in Next_T)
      --# global in out Goto_List_Count;
      --# derives Goto_List_Count from *,
      --#                              Last_Var,
      --#                              Next;
      is
         I        : Integer;
         Next_Tmp : Next_T;
      begin
         Next_Tmp := Next;
         if Next_Tmp = Next_False_Const then
            Goto_List_Count := Goto_List_Count + 1;
         else
            Goto_List_Count := Goto_List_Count + 1;
            I               := Last_Var - 1;
            while Next_Tmp /= Next_False_Const loop
               if Next_Tmp (I) then
                  Goto_List_Count := Goto_List_Count + 1;
                  Next_Tmp (I)    := False;
               end if;
               I := I - 1;
            end loop;
         end if;
      end Write_States;

   begin
      G := Goto_List (I);
      while G /= 0 loop
         if Goto_Array.The_Array (G).Check_Index /= 0 then
            Org := 0;
            New_State_Set_Nested (G, Org, Last_Var, Next);
            G1 := G;
            Copy (G, Found, G1);
            while Found loop
               if Goto_Array.The_Array (G1).Check_Index - Org < 0 then
                  Write_States (Last_Var, Next);
                  New_State_Set_Nested (G1, Org, Last_Var, Next);
               else
                  Insert_State_Nested (G1, Org, Last_Var, Next);
               end if;
               Copy (G, Found, G1);
            end loop;
            Write_States (Last_Var, Next);
            if Last_Goto_Nested (G) then
               Zero_Index_Nested (G);
            end if;
         end if;
         G := Goto_Array.The_Array (G).Go_Next;
      end loop;
   end Go_Out;

   procedure Dump_Goto (F : in out SPARK.Ada.Text_IO.File_Type)
   --# global in     Goto_Array;
   --#        in     Goto_List;
   --#        in     Sparklalr_Memory.Stat_No;
   --#        in     Symbols_Dump.State;
   --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
   --# derives F,
   --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
   --#                                                    Goto_Array,
   --#                                                    Goto_List,
   --#                                                    Sparklalr_Memory.Stat_No,
   --#                                                    Symbols_Dump.State;
   is
      Posn : Integer;
   begin
      SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                       Spacing => 1);
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => " GOTO TABLE ");
      SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                       Spacing => 1);
      Posn := 1;
      for I in Integer range 1 .. Symbols_Dump.Get_Nnon_Terms loop
         SPARK.Ada.Text_IO.Put_Character_File (File => F,
                                               Item => ' ');
         Posn := Posn + 1;
         --# accept F, 10, Posn, "Ineffective assignment here expected and OK";
         Sparklalr_Common.Print
           (Std_Out => False,
            F       => F,
            String1 => Symbols_Dump.Get_Nterm_Set (I),
            Posn    => Posn,
            Tab     => 2,
            Comm    => False);
         --# end accept;
         SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                          Item => " : ");
         for J in Integer range 1 .. Sparklalr_Memory.Get_Stat_No loop
            if Goto_Search (J, I + Sparklalr_Common.Nt_Base) /= 0 then
               SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                                   Item  => J,
                                                   Width => 4,
                                                   Base  => 10);
               Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                             F       => F,
                                             C       => ' ',
                                             N       => 5);
               SPARK_Ada_Integer_Text_IO.Put_File
                 (File  => F,
                  Item  => Goto_Search (J, I + Sparklalr_Common.Nt_Base),
                  Width => 4,
                  Base  => 10);
               SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                                Spacing => 1);
            end if;
         end loop;
         SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                          Spacing => 1);
         Posn := 1;
      end loop;
      SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                       Spacing => 1);
   end Dump_Goto;

   procedure Goto_Gen
     (F                                      : in out SPARK.Ada.Text_IO.File_Type;
      Insertion, State_Index, Non_Term_Index : in     Integer;
      Call_Pa_Insert                         :    out Boolean)
   -- GENERATES AN ENTRY FOR INSERTION IN THE GOTO TABLE
   --# global in     Command_Line_Options.State;
   --#        in     Symbols_Dump.State;
   --#        in out Goto_Array;
   --#        in out Goto_Count;
   --#        in out Goto_List;
   --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
   --#        in out Sparklalr_Error.State;
   --# derives Call_Pa_Insert                        from Non_Term_Index &
   --#         F,
   --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
   --#                                                    Command_Line_Options.State,
   --#                                                    Goto_Array,
   --#                                                    Goto_List,
   --#                                                    Insertion,
   --#                                                    Non_Term_Index,
   --#                                                    State_Index,
   --#                                                    Symbols_Dump.State &
   --#         Goto_Array,
   --#         Goto_Count,
   --#         Goto_List,
   --#         Sparklalr_Error.State                 from *,
   --#                                                    Goto_Array,
   --#                                                    Goto_List,
   --#                                                    Insertion,
   --#                                                    Non_Term_Index,
   --#                                                    State_Index;
   is

      G : Integer;

      procedure Goto_Insert (F                                      : in out SPARK.Ada.Text_IO.File_Type;
                             State_Index, Non_Term_Index, Insertion : in     Integer)
      -- INSERTS A NEW ENTRY INTO THE GOTO TABLE
      --# global in     Command_Line_Options.State;
      --#        in     Symbols_Dump.State;
      --#        in out Goto_Array;
      --#        in out Goto_List;
      --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
      --# derives F                                     from *,
      --#                                                    Command_Line_Options.State,
      --#                                                    Non_Term_Index,
      --#                                                    Symbols_Dump.State &
      --#         Goto_Array                            from *,
      --#                                                    Goto_List,
      --#                                                    Insertion,
      --#                                                    Non_Term_Index,
      --#                                                    State_Index &
      --#         Goto_List                             from *,
      --#                                                    Goto_Array,
      --#                                                    Non_Term_Index &
      --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
      --#                                                    Command_Line_Options.State,
      --#                                                    Insertion,
      --#                                                    Non_Term_Index,
      --#                                                    State_Index,
      --#                                                    Symbols_Dump.State;
      is
         Posn               : Integer;
         Non_Term_Index_Tmp : Integer;
      begin
         Non_Term_Index_Tmp := Non_Term_Index - Sparklalr_Common.Nt_Base;
         if Command_Line_Options.Get_Debug_Level (5) then
            SPARK.Ada.Text_IO.Put_Output (Item => " GOTO : (STATE=");
            SPARK_Ada_Integer_Text_IO.Put_Output (Item  => State_Index,
                                                  Width => 3,
                                                  Base  => 10);
            SPARK.Ada.Text_IO.Put_Output (Item => ",NONTERM=");
            Posn := 29;
            --# accept F, 10, Posn, "Ineffective assignment here expected and OK";
            Sparklalr_Common.Print
              (Std_Out => True,
               F       => F,
               String1 => Symbols_Dump.Get_Nterm_Set (Non_Term_Index_Tmp),
               Posn    => Posn,
               Tab     => 29,
               Comm    => False);
            --# end accept;
            SPARK.Ada.Text_IO.Put_Output (Item => ") = ");
            SPARK_Ada_Integer_Text_IO.Put_Output (Item  => Insertion,
                                                  Width => 3,
                                                  Base  => 10);
            SPARK.Ada.Text_IO.New_Line_Output (Spacing => 1);
         end if;
         Goto_Array.Top                        := Goto_Array.Top + 1;
         Goto_Array.The_Array (Goto_Array.Top) :=
           Goto_Rec'
           (Index       => State_Index,
            Check_Index => State_Index,
            Entry_State => Insertion,
            Go_Next     => Goto_List (Non_Term_Index_Tmp));
         Goto_List (Non_Term_Index_Tmp)        := Goto_Array.Top;
      end Goto_Insert;

   begin -- Goto_Gen
      if Non_Term_Index > Sparklalr_Common.Nt_Base then
         G := Goto_Search (State_Index, Non_Term_Index);
         if (G /= 0) and then (G /= Insertion) then
            Sparklalr_Error.Error (F, 32);
         else
            if G = 0 then
               Goto_Count := Goto_Count + 1;
               Goto_Insert (F, State_Index, Non_Term_Index, Insertion);
            end if;
         end if;
         Call_Pa_Insert := False;
      else
         Call_Pa_Insert := True;
      end if;
   end Goto_Gen;

   procedure Goto_Out (F : in out SPARK.Ada.Text_IO.File_Type)
   --# global in     Goto_List;
   --#        in     Symbols_Dump.State;
   --#        in out Goto_Array;
   --#        in out Goto_Table;
   --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
   --# derives F                                     from *,
   --#                                                    Goto_Array,
   --#                                                    Goto_List,
   --#                                                    Goto_Table,
   --#                                                    Symbols_Dump.State &
   --#         Goto_Array,
   --#         Goto_Table,
   --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
   --#                                                    Goto_Array,
   --#                                                    Goto_List,
   --#                                                    Symbols_Dump.State;
   is

      procedure Aux_Got_Out (F : in out SPARK.Ada.Text_IO.File_Type)
      --# global in     Goto_List;
      --#        in     Symbols_Dump.State;
      --#        in out Goto_Array;
      --#        in out Goto_Table;
      --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
      --# derives F,
      --#         Goto_Array,
      --#         Goto_Table,
      --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
      --#                                                    Goto_Array,
      --#                                                    Goto_List,
      --#                                                    Symbols_Dump.State;
      is

         Posn           : Integer;
         Curr_Got_Index : Integer;

         procedure Go_Out_Nested
           (F              : in out SPARK.Ada.Text_IO.File_Type;
            I              : in     Integer;
            Curr_Got_Index : in out Integer;
            Posn           : in     Integer)
         --# global in     Goto_List;
         --#        in     Symbols_Dump.State;
         --#        in out Goto_Array;
         --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
         --# derives Curr_Got_Index,
         --#         Goto_Array                            from *,
         --#                                                    Goto_Array,
         --#                                                    Goto_List,
         --#                                                    I &
         --#         F                                     from *,
         --#                                                    Curr_Got_Index,
         --#                                                    Goto_Array,
         --#                                                    Goto_List,
         --#                                                    I,
         --#                                                    Posn,
         --#                                                    Symbols_Dump.State &
         --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
         --#                                                    Goto_Array,
         --#                                                    Goto_List,
         --#                                                    I,
         --#                                                    Posn,
         --#                                                    Symbols_Dump.State;
         is
            Comma_Required : Boolean;
            G, G1          : Pt_Goto_Rec;
            Org            : Integer;
            Last_Var       : Integer;
            Next           : Next_T;
            Found          : Boolean;
            Posn_Tmp       : Integer;

            procedure Write_States
              (F              : in out SPARK.Ada.Text_IO.File_Type;
               Nt             : in     Integer;
               G              : in     Pt_Goto_Rec;
               Org            : in     Integer;
               Last_Var       : in     Integer;
               Next           : in     Next_T;
               Curr_Got_Index : in out Integer;
               Posn           : in out Integer)
            --# global in     Goto_Array;
            --#        in     Symbols_Dump.State;
            --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
            --# derives Curr_Got_Index                        from *,
            --#                                                    Last_Var,
            --#                                                    Next &
            --#         F                                     from *,
            --#                                                    Curr_Got_Index,
            --#                                                    G,
            --#                                                    Goto_Array,
            --#                                                    Last_Var,
            --#                                                    Next,
            --#                                                    Nt,
            --#                                                    Org,
            --#                                                    Posn,
            --#                                                    Symbols_Dump.State &
            --#         Posn,
            --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
            --#                                                    Last_Var,
            --#                                                    Next,
            --#                                                    Nt,
            --#                                                    Posn,
            --#                                                    Symbols_Dump.State;
            is
               I        : Integer;
               Next_Tmp : Next_T;
            begin
               Next_Tmp := Next;
               if Next_Tmp = Next_False_Const then
                  SPARK.Ada.Text_IO.Put_File (File => F,
                                              Item => "State_Pair'(");
                  Sparklalr_Common.Print2 (F, Sparklalr_Common.Sp_Symbol_Str, Symbols_Dump.Get_Nterm_Set (Nt), Posn, 10, False);
                  SPARK.Ada.Text_IO.Put_File (File => F,
                                              Item => ", ");
                  SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                                      Item  => Last_Var + Org,
                                                      Width => 1,
                                                      Base  => 10);
                  SPARK.Ada.Text_IO.Put_File (File => F,
                                              Item => ", ");
                  SPARK_Ada_Integer_Text_IO.Put_File
                    (File  => F,
                     Item  => Goto_Array.The_Array (G).Entry_State,
                     Width => 1,
                     Base  => 10);
                  SPARK.Ada.Text_IO.Put_Character_File (File => F,
                                                        Item => ')');
                  Curr_Got_Index := Curr_Got_Index + 1;
               else
                  SPARK.Ada.Text_IO.Put_File (File => F,
                                              Item => "State_Pair'(");
                  Sparklalr_Common.Print2 (F, Sparklalr_Common.Sp_Symbol_Str, Symbols_Dump.Get_Nterm_Set (Nt), Posn, 10, False);
                  SPARK.Ada.Text_IO.Put_File (File => F,
                                              Item => ", ");
                  SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                                      Item  => Last_Var + Org,
                                                      Width => 1,
                                                      Base  => 10);
                  SPARK.Ada.Text_IO.Put_File (File => F,
                                              Item => ", ");
                  SPARK_Ada_Integer_Text_IO.Put_File
                    (File  => F,
                     Item  => Goto_Array.The_Array (G).Entry_State,
                     Width => 1,
                     Base  => 10);
                  SPARK.Ada.Text_IO.Put_Character_File (File => F,
                                                        Item => ')');
                  Curr_Got_Index := Curr_Got_Index + 1;
                  I              := Last_Var - 1;
                  while Next_Tmp /= Next_False_Const loop
                     if Next_Tmp (I) then
                        SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                                         Item => ",");
                        SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                                            Item  => Curr_Got_Index,
                                                            Width => 5,
                                                            Base  => 10);
                        SPARK.Ada.Text_IO.Put_File (File => F,
                                                    Item => " => ");
                        SPARK.Ada.Text_IO.Put_File (File => F,
                                                    Item => "State_Pair'(");
                        Sparklalr_Common.Print2
                          (F,
                           Sparklalr_Common.Sp_Symbol_Str,
                           Symbols_Dump.Get_Nterm_Set (Nt),
                           Posn,
                           10,
                           False);
                        SPARK.Ada.Text_IO.Put_File (File => F,
                                                    Item => ", ");
                        SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                                            Item  => I + Org,
                                                            Width => 1,
                                                            Base  => 10);
                        SPARK.Ada.Text_IO.Put_File (File => F,
                                                    Item => ", ");
                        SPARK_Ada_Integer_Text_IO.Put_File
                          (File  => F,
                           Item  => Goto_Array.The_Array (G).Entry_State,
                           Width => 1,
                           Base  => 10);
                        SPARK.Ada.Text_IO.Put_Character_File (File => F,
                                                              Item => ')');
                        Curr_Got_Index := Curr_Got_Index + 1;
                        Next_Tmp (I)   := False;
                     end if;
                     I := I - 1;
                  end loop;
               end if;
            end Write_States;

         begin -- Go_Out_Nested
            Posn_Tmp       := Posn;
            Comma_Required := False;
            G              := Goto_List (I);
            while G /= 0 loop
               if Goto_Array.The_Array (G).Index /= 0 then
                  if Comma_Required then
                     SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                                      Item => ",");
                  else
                     Comma_Required := True;
                  end if;
                  SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                                      Item  => Curr_Got_Index,
                                                      Width => 5,
                                                      Base  => 10);
                  SPARK.Ada.Text_IO.Put_File (File => F,
                                              Item => " => ");
                  Org := 0;
                  New_State_Set (G, Org, Last_Var, Next);
                  G1 := G;
                  Copy (G, Found, G1);
                  while Found loop
                     if Goto_Array.The_Array (G1).Index - Org < 0 then
                        Write_States (F, I, G, Org, Last_Var, Next, Curr_Got_Index, Posn_Tmp);
                        SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                                         Item => ",");
                        SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                                            Item  => Curr_Got_Index,
                                                            Width => 5,
                                                            Base  => 10);
                        SPARK.Ada.Text_IO.Put_File (File => F,
                                                    Item => " => ");
                        New_State_Set (G1, Org, Last_Var, Next);
                     else
                        Insert_State (G1, Org, Last_Var, Next);
                     end if;
                     Copy (G, Found, G1);
                  end loop;
                  Write_States (F, I, G, Org, Last_Var, Next, Curr_Got_Index, Posn_Tmp);
                  Zero_Index (G);
               end if;
               G := Goto_Array.The_Array (G).Go_Next;
            end loop;
         end Go_Out_Nested;

      begin -- Aux_Got_Out
         Curr_Got_Index := 1;
         SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                          Item => "   Goto_Table : constant Aux_GOT := Aux_GOT'(");
         Posn := 1;
         for I in Integer range 2 .. Symbols_Dump.Get_Nnon_Terms loop
            SPARK.Ada.Text_IO.Put_File (File => F,
                                        Item => "----- ");
            Posn := Posn + 6;
            Sparklalr_Common.Print
              (Std_Out => False,
               F       => F,
               String1 => Symbols_Dump.Get_Nterm_Set (I),
               Posn    => Posn,
               Tab     => 6,
               Comm    => False);
            SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                             Spacing => 1);
            Goto_Table (I).Lower := Curr_Got_Index;
            Go_Out_Nested (F, I, Curr_Got_Index, Posn);
            Goto_Table (I).Upper := Curr_Got_Index - 1;
            if I < Symbols_Dump.Get_Nnon_Terms then
               SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                                Item => ",");
            end if;
            Posn := 1;
         end loop;
         SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                          Item => ");");
         SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                          Spacing => 1);
      end Aux_Got_Out;

      procedure Main_Got_Out (F : in out SPARK.Ada.Text_IO.File_Type)
      --# global in     Goto_Table;
      --#        in     Symbols_Dump.State;
      --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
      --# derives F                                     from *,
      --#                                                    Goto_Table,
      --#                                                    Symbols_Dump.State &
      --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
      --#                                                    Symbols_Dump.State;
      is
         Posn : Integer;
      begin
         SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                          Item => "   Non_Term_Table : constant Main_GOT := Main_GOT'(");
         Posn := 1;
         for Nterm in Integer range 2 .. Symbols_Dump.Get_Nnon_Terms loop
            SPARK.Ada.Text_IO.Put_File (File => F,
                                        Item => "   ");
            Posn := Posn + 3;
            Sparklalr_Common.Print2 (F, Sparklalr_Common.Sp_Symbol_Str, Symbols_Dump.Get_Nterm_Set (Nterm), Posn, 3, False);
            SPARK.Ada.Text_IO.Put_File (File => F,
                                        Item => " => GOT_Index_Pair'(");
            SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                                Item  => Goto_Table (Nterm).Lower,
                                                Width => 1,
                                                Base  => 10);
            SPARK.Ada.Text_IO.Put_File (File => F,
                                        Item => ", ");
            SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                                Item  => Goto_Table (Nterm).Upper,
                                                Width => 1,
                                                Base  => 10);
            SPARK.Ada.Text_IO.Put_Character_File (File => F,
                                                  Item => ')');
            if Nterm < Symbols_Dump.Get_Nnon_Terms then
               SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                                Item => ",");
               Posn := 1;
            end if;
         end loop;
         SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                          Item => ");");
      end Main_Got_Out;

   begin -- Goto_Out
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "  type State_Pair is");
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "    record");
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "      Red_Goal                  : SP_Symbols.SP_Non_Terminal;");
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "      Current_State, Next_State : SP_Productions.SP_State;");
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "    end record;");
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "    pragma PACK(State_Pair);");
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "  type Aux_GOT is array (GOT_Index) of State_Pair;");
      SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                       Spacing => 1);
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "  type GOT_Index_Pair is");
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "    record");
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "      Lower, Upper : Goto_Index;");
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "    end record;");
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "    pragma PACK(GOT_Index_Pair);");
      SPARK.Ada.Text_IO.Put_Line_File
        (File => F,
         Item => "  type Main_GOT is array (SP_Symbols.SP_Grammar_Non_Terminal) of GOT_Index_Pair;");
      SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                       Spacing => 1);
      Aux_Got_Out (F);
      SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                       Spacing => 1);
      Main_Got_Out (F);
      SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                       Spacing => 1);
   end Goto_Out;

   procedure Goto_Out_Sp (F : in out SPARK.Ada.Text_IO.File_Type)
   --# global in     Goto_List;
   --#        in     Goto_List_Count;
   --#        in     Sparklalr_Memory.Stat_No;
   --#        in     Symbols_Dump.State;
   --#        in out Goto_Array;
   --#        in out Goto_Table;
   --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
   --# derives F                                     from *,
   --#                                                    Goto_Array,
   --#                                                    Goto_List,
   --#                                                    Goto_List_Count,
   --#                                                    Goto_Table,
   --#                                                    Sparklalr_Memory.Stat_No,
   --#                                                    Symbols_Dump.State &
   --#         Goto_Array,
   --#         Goto_Table,
   --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
   --#                                                    Goto_Array,
   --#                                                    Goto_List,
   --#                                                    Symbols_Dump.State;
   is

      Goto_Count_P2, State_Count_P2, Nt_Count_P2 : Integer;

      procedure Aux_Got_Out (F : in out SPARK.Ada.Text_IO.File_Type)
      --# global in     Goto_List;
      --#        in     Symbols_Dump.State;
      --#        in out Goto_Array;
      --#        in out Goto_Table;
      --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
      --# derives F,
      --#         Goto_Array,
      --#         Goto_Table,
      --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
      --#                                                    Goto_Array,
      --#                                                    Goto_List,
      --#                                                    Symbols_Dump.State;
      is

         Posn           : Integer;
         Curr_Got_Index : Integer;

         procedure Go_Out_Nested (F              : in out SPARK.Ada.Text_IO.File_Type;
                                  I              : in     Integer;
                                  Curr_Got_Index : in out Integer)
         --# global in     Goto_List;
         --#        in     Symbols_Dump.State;
         --#        in out Goto_Array;
         --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
         --# derives Curr_Got_Index,
         --#         Goto_Array                            from *,
         --#                                                    Goto_Array,
         --#                                                    Goto_List,
         --#                                                    I &
         --#         F                                     from *,
         --#                                                    Curr_Got_Index,
         --#                                                    Goto_Array,
         --#                                                    Goto_List,
         --#                                                    I,
         --#                                                    Symbols_Dump.State &
         --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
         --#                                                    Goto_Array,
         --#                                                    Goto_List,
         --#                                                    I,
         --#                                                    Symbols_Dump.State;
         is

            Comma_Required : Boolean;
            G, G1          : Pt_Goto_Rec;
            Org            : Integer;
            Last_Var       : Integer;
            Next           : Next_T;
            Found          : Boolean;

            procedure Write_States
              (F              : in out SPARK.Ada.Text_IO.File_Type;
               Nt             : in     Integer;
               G              : in     Pt_Goto_Rec;
               Org            : in     Integer;
               Last_Var       : in     Integer;
               Next           : in     Next_T;
               Curr_Got_Index : in out Integer)
            --# global in     Goto_Array;
            --#        in     Symbols_Dump.State;
            --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
            --# derives Curr_Got_Index                        from *,
            --#                                                    Last_Var,
            --#                                                    Next &
            --#         F                                     from *,
            --#                                                    Curr_Got_Index,
            --#                                                    G,
            --#                                                    Goto_Array,
            --#                                                    Last_Var,
            --#                                                    Next,
            --#                                                    Nt,
            --#                                                    Org,
            --#                                                    Symbols_Dump.State &
            --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
            --#                                                    Last_Var,
            --#                                                    Next,
            --#                                                    Nt,
            --#                                                    Symbols_Dump.State;
            is
               I, Posn  : Integer;
               Next_Tmp : Next_T;
            begin
               Next_Tmp := Next;
               if Next_Tmp = Next_False_Const then
                  SPARK.Ada.Text_IO.Put_File (File => F,
                                              Item => "(Current_State * ");
                  SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                                      Item  => Last_Var + Org,
                                                      Width => 1,
                                                      Base  => 10);
                  SPARK.Ada.Text_IO.Put_File (File => F,
                                              Item => " + Next_State * ");
                  SPARK_Ada_Integer_Text_IO.Put_File
                    (File  => F,
                     Item  => Goto_Array.The_Array (G).Entry_State,
                     Width => 1,
                     Base  => 10);
                  SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                                   Item => ") + Red_Goal * (SP_Symbols.SP_Non_Terminal'Pos (");
                  Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                                F       => F,
                                                C       => ' ',
                                                N       => 10);
                  Posn := 10;
                  --# accept F, 10, Posn, "Ineffective assignment here expected and OK";
                  Sparklalr_Common.Print2 (F, Sparklalr_Common.Sp_Symbol_Str, Symbols_Dump.Get_Nterm_Set (Nt), Posn, 10, False);
                  --# end accept;
                  SPARK.Ada.Text_IO.Put_File (File => F,
                                              Item => ") - First_Non_Terminal)");
                  Curr_Got_Index := Curr_Got_Index + 1;
               else
                  SPARK.Ada.Text_IO.Put_File (File => F,
                                              Item => "(Current_State * ");
                  SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                                      Item  => Last_Var + Org,
                                                      Width => 1,
                                                      Base  => 10);
                  SPARK.Ada.Text_IO.Put_File (File => F,
                                              Item => " + Next_State * ");
                  SPARK_Ada_Integer_Text_IO.Put_File
                    (File  => F,
                     Item  => Goto_Array.The_Array (G).Entry_State,
                     Width => 1,
                     Base  => 10);
                  SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                                   Item => ") + Red_Goal * (SP_Symbols.SP_Non_Terminal'Pos (");
                  Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                                F       => F,
                                                C       => ' ',
                                                N       => 10);
                  Posn := 10;
                  --# accept F, 10, Posn, "Ineffective assignment here expected and OK";
                  Sparklalr_Common.Print2 (F, Sparklalr_Common.Sp_Symbol_Str, Symbols_Dump.Get_Nterm_Set (Nt), Posn, 10, False);
                  --# end accept;
                  SPARK.Ada.Text_IO.Put_File (File => F,
                                              Item => ") - First_Non_Terminal)");
                  Curr_Got_Index := Curr_Got_Index + 1;
                  I              := Last_Var - 1;
                  while Next_Tmp /= Next_False_Const loop
                     if Next_Tmp (I) then
                        SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                                         Item => ",");
                        SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                                            Item  => Curr_Got_Index,
                                                            Width => 5,
                                                            Base  => 10);
                        SPARK.Ada.Text_IO.Put_File (File => F,
                                                    Item => " => ");
                        SPARK.Ada.Text_IO.Put_File (File => F,
                                                    Item => "(Current_State * ");
                        SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                                            Item  => I + Org,
                                                            Width => 1,
                                                            Base  => 10);
                        SPARK.Ada.Text_IO.Put_File (File => F,
                                                    Item => " + Next_State * ");
                        SPARK_Ada_Integer_Text_IO.Put_File
                          (File  => F,
                           Item  => Goto_Array.The_Array (G).Entry_State,
                           Width => 1,
                           Base  => 10);
                        SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                                         Item => ") + Red_Goal * (SP_Symbols.SP_Non_Terminal'Pos (");
                        Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                                      F       => F,
                                                      C       => ' ',
                                                      N       => 10);
                        Posn := 10;
                        --# accept F, 10, Posn, "Ineffective assignment here expected and OK";
                        Sparklalr_Common.Print2
                          (F,
                           Sparklalr_Common.Sp_Symbol_Str,
                           Symbols_Dump.Get_Nterm_Set (Nt),
                           Posn,
                           10,
                           False);
                        --# end accept;
                        SPARK.Ada.Text_IO.Put_File (File => F,
                                                    Item => ") - First_Non_Terminal)");
                        Curr_Got_Index := Curr_Got_Index + 1;
                        Next_Tmp (I)   := False;
                     end if;
                     I := I - 1;
                  end loop;
               end if;
            end Write_States;

         begin -- Go_Out_Nested
            Comma_Required := False;
            G              := Goto_List (I);
            while G /= 0 loop
               if Goto_Array.The_Array (G).Index /= 0 then
                  if Comma_Required then
                     SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                                      Item => ",");
                  else
                     Comma_Required := True;
                  end if;
                  SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                                      Item  => Curr_Got_Index,
                                                      Width => 5,
                                                      Base  => 10);
                  SPARK.Ada.Text_IO.Put_File (File => F,
                                              Item => " => ");
                  Org := 0;
                  New_State_Set (G, Org, Last_Var, Next);
                  G1 := G;
                  Copy (G, Found, G1);
                  while Found loop
                     if Goto_Array.The_Array (G1).Index - Org < 0 then
                        Write_States (F, I, G, Org, Last_Var, Next, Curr_Got_Index);
                        SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                                         Item => ",");
                        SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                                            Item  => Curr_Got_Index,
                                                            Width => 5,
                                                            Base  => 10);
                        SPARK.Ada.Text_IO.Put_File (File => F,
                                                    Item => " => ");
                        New_State_Set (G1, Org, Last_Var, Next);
                     else
                        Insert_State (G1, Org, Last_Var, Next);
                     end if;
                     Copy (G, Found, G1);
                  end loop;
                  Write_States (F, I, G, Org, Last_Var, Next, Curr_Got_Index);
                  Zero_Index (G);
               end if;
               G := Goto_Array.The_Array (G).Go_Next;
            end loop;
         end Go_Out_Nested;

      begin -- Aux_Got_Out
         Curr_Got_Index := 1;
         SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                          Item => "   Goto_Table : constant Aux_GOT := Aux_GOT'(");
         Posn := 1;
         for I in Integer range 2 .. Symbols_Dump.Get_Nnon_Terms loop
            SPARK.Ada.Text_IO.Put_File (File => F,
                                        Item => "----- ");
            Posn := Posn + 6;
            --# accept F, 10, Posn, "Ineffective assignment here expected and OK";
            Sparklalr_Common.Print2 (F, Sparklalr_Common.Sp_Symbol_Str, Symbols_Dump.Get_Nterm_Set (I), Posn, 6, False);
            --# end accept;
            SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                             Spacing => 1);
            Goto_Table (I).Lower := Curr_Got_Index;
            Go_Out_Nested (F, I, Curr_Got_Index);
            Goto_Table (I).Upper := Curr_Got_Index - 1;
            if I < Symbols_Dump.Get_Nnon_Terms then
               SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                                Item => ",");
            end if;
            Posn := 1;
         end loop;
         SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                          Item => ");");
         SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                          Spacing => 1);
      end Aux_Got_Out;

      procedure Main_Got_Out (F : in out SPARK.Ada.Text_IO.File_Type)
      --# global in     Goto_Table;
      --#        in     Symbols_Dump.State;
      --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
      --# derives F                                     from *,
      --#                                                    Goto_Table,
      --#                                                    Symbols_Dump.State &
      --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
      --#                                                    Symbols_Dump.State;
      is
         Posn : Integer;
      begin
         SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                          Item => "   Non_Term_Table : constant Main_GOT := Main_GOT'(");
         Posn := 1;
         for Nterm in Integer range 2 .. Symbols_Dump.Get_Nnon_Terms loop
            SPARK.Ada.Text_IO.Put_File (File => F,
                                        Item => "   ");
            Posn := Posn + 3;
            Sparklalr_Common.Print2 (F, Sparklalr_Common.Sp_Symbol_Str, Symbols_Dump.Get_Nterm_Set (Nterm), Posn, 3, False);
            SPARK.Ada.Text_IO.Put_File (File => F,
                                        Item => " => Lower_GOT_Index * ");
            SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                                Item  => Goto_Table (Nterm).Lower,
                                                Width => 1,
                                                Base  => 10);
            SPARK.Ada.Text_IO.Put_File (File => F,
                                        Item => " + Upper_GOT_Index * ");
            SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                                Item  => Goto_Table (Nterm).Upper,
                                                Width => 1,
                                                Base  => 10);
            if Nterm < Symbols_Dump.Get_Nnon_Terms then
               SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                                Item => ",");
               Posn := 1;
            end if;
         end loop;
         SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                          Item => ");");
      end Main_Got_Out;

   begin -- Goto_Out_Sp
      Nt_Count_P2 := 0;
      while 2 ** Nt_Count_P2 <= Symbols_Dump.Get_Nnon_Terms - 1 loop
         Nt_Count_P2 := Nt_Count_P2 + 1;
      end loop;
      Goto_Count_P2 := 0;
      while 2 ** Goto_Count_P2 <= Goto_List_Count loop
         Goto_Count_P2 := Goto_Count_P2 + 1;
      end loop;
      State_Count_P2 := 0;
      while 2 ** State_Count_P2 <= Sparklalr_Memory.Get_Stat_No loop
         State_Count_P2 := State_Count_P2 + 1;
      end loop;
      SPARK.Ada.Text_IO.Put_File (File => F,
                                  Item => "   type Packed_State_Pair is range 0 .. 2**");
      SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                          Item  => 2 * State_Count_P2 + Nt_Count_P2,
                                          Width => 1,
                                          Base  => 10);
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "-1;");
      SPARK.Ada.Text_IO.Put_File (File => F,
                                  Item => "   State_Size    : constant Packed_State_Pair := 2**");
      SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                          Item  => State_Count_P2,
                                          Width => 1,
                                          Base  => 10);
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => ";");
      SPARK.Ada.Text_IO.Put_File (File => F,
                                  Item => "   Red_Goal_Size : constant Packed_State_Pair := 2**");
      SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                          Item  => Nt_Count_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 => "   Current_State : constant Packed_State_Pair := 1;");
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "   Next_State    : constant Packed_State_Pair := State_Size;");
      SPARK.Ada.Text_IO.Put_Line_File
        (File => F,
         Item => "   Red_Goal      : constant Packed_State_Pair := State_Size * State_Size;");
      SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                       Spacing => 1);
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "   First_Non_Terminal : constant Packed_State_Pair :=");
      SPARK.Ada.Text_IO.Put_Line_File
        (File => F,
         Item => "     SP_Symbols.SP_Non_Terminal'Pos (SP_Symbols.SP_Non_Terminal'First);");
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "   type Aux_GOT is array (GOT_Index) of Packed_State_Pair;");
      SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                       Spacing => 1);
      SPARK.Ada.Text_IO.Put_File (File => F,
                                  Item => "   type Packed_GOT_Index_Pair is range 0 .. 2**");
      SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                          Item  => 2 * Goto_Count_P2,
                                          Width => 1,
                                          Base  => 10);
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "-1;");
      SPARK.Ada.Text_IO.Put_File (File => F,
                                  Item => "   GOT_Index_Size  : constant Packed_GOT_Index_Pair := 2**");
      SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                          Item  => Goto_Count_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 => "   Lower_GOT_Index : constant Packed_GOT_Index_Pair := 1;");
      SPARK.Ada.Text_IO.Put_Line_File
        (File => F,
         Item => "   Upper_GOT_Index : constant Packed_GOT_Index_Pair := GOT_Index_Size;");
      SPARK.Ada.Text_IO.Put_File (File => F,
                                  Item => "   type Main_GOT is array (SP_Symbols.SP_Grammar_Non_Terminal)");
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => " of Packed_GOT_Index_Pair;");
      SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                       Spacing => 1);
      Aux_Got_Out (F);
      SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                       Spacing => 1);
      Main_Got_Out (F);
   end Goto_Out_Sp;

   procedure Goto_Stats (Std_Out : in     Boolean;
                         F       : in out SPARK.Ada.Text_IO.File_Type)
   --# global in     Goto_Count;
   --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
   --# derives F,
   --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
   --#                                                    Goto_Count,
   --#                                                    Std_Out;
   is
   begin
      Sparklalr_Common.Put_Integer_File_Output (Std_Out => Std_Out,
                                                File    => F,
                                                Item    => Goto_Count,
                                                Width   => 6);
      Sparklalr_Common.Put_Line_File_Output (Std_Out => Std_Out,
                                             File    => F,
                                             Item    => " GOTO ENTRIES GENERATED");
   end Goto_Stats;

   procedure Init_Goto_List (I : in Sparklalr_Common.Non_Term_Range)
   --# global in out Goto_List;
   --# derives Goto_List from *,
   --#                        I;
   is
   begin
      Goto_List (I) := 0;
   end Init_Goto_List;

   function Get_Goto_List_Count return Integer
   --# global in Goto_List_Count;
   is
   begin
      return Goto_List_Count;
   end Get_Goto_List_Count;

   function Get_Next (Next : in Next_T;
                      I    : in Sparklalr_Common.Term_Range) return Boolean is
   begin
      return Next (I);
   end Get_Next;

   procedure Set_Next (Next  : in out Next_T;
                       I     : in     Sparklalr_Common.Term_Range;
                       Value : in     Boolean) is
   begin
      Next (I) := Value;
   end Set_Next;

end Sparklalr_Goto;
