-------------------------------------------------------------------------------
-- (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 SPARK.Ada.Command_Line;
with SPARK.Ada.Strings.Unbounded;
with SPARK.Ada.Text_IO.Unbounded_String;
with Sparklalr_Goto;
with Sparklalr_Level;
with Sparklalr_Parser;
with Sparklalr_Symbol;
with Symbols_Dump;

use type SPARK.Ada.Text_IO.Exception_T;
use type Sparklalr_Symbol.Symbol;

package body Sparklalr_Memory.Dump
--# own State is Action,
--#              Act_Open,
--#              Empty,
--#              First_Var,
--#              Free_List,
--#              Item_Array,
--#              Look_Array,
--#              Look_Tree,
--#              Mem,
--#              Memo,
--#              Memory_Array,
--#              Ntrdn,
--#              Prod_Ptr,
--#              Release_Point,
--#              State_Var,
--#              Terminal_Like;
is

   Look_Table_Size : constant := 10000;

   type Set_Of_Term is array (Sparklalr_Common.Term_Range) of Boolean;
   subtype Look_Set is Natural range 0 .. Look_Table_Size;
   subtype Look_Array_Range is Positive range 1 .. Look_Table_Size;
   type Look_Item is record
      Lset         : Set_Of_Term;
      Litem, Ritem : Look_Set;
   end record;
   type Look_Array_Array_T is array (Look_Array_Range) of Look_Item;
   type Look_Array_T is record
      The_Array : Look_Array_Array_T;
      Top       : Look_Set;
   end record;

   Set_Of_Term_False_Const : constant Set_Of_Term := Set_Of_Term'(others => False);

   subtype Item_Array_Range is Positive range 1 .. Item_Table_Size;
   subtype Memory_Array_Range is Positive range 1 .. Memory_Table_Size;

   type Item is record
      Dot : Pt_Memory;
      Lh  : Look_Set;
   end record;

   type Memory is record
      Tag : Integer;
      Ptr : Pt_Memory;

      -- No discriminated/variant records in SPARK, so
      -- a bare union will have to do...

      -- case Tag is
      --    when 1 =>
      Contents : Contents_T;
      --    when 2 =>
      Itm : Pt_Item;
      --    when 3 =>
      Mem_Pt : Pt_Memory;
      -- end case;
   end record;

   type Item_Array_Array_T is array (Item_Array_Range) of Item;
   type Memory_Array_Array_T is array (Memory_Array_Range) of Memory;

   type Item_Array_T is record
      The_Array : Item_Array_Array_T;
      Top       : Pt_Item;
   end record;
   type Memory_Array_T is record
      The_Array : Memory_Array_Array_T;
      Top       : Pt_Memory;
   end record;

   type Prod_Ptr_T is array (Sparklalr_Common.Production_Index) of Pt_Memory;
   type Ntrdn_T is array (Sparklalr_Common.Non_Term_Range) of Pt_Memory;
   type Empty_T is array (Sparklalr_Common.Non_Term_Range) of Boolean;
   type State_Var_T is array (Sparklalr_Common.State_Range) of Pt_Memory;
   type First_Var_T is array (Sparklalr_Common.Non_Term_Range) of Look_Set;

   Look_Tree                : Look_Set;
   Release_Point, Free_List : Pt_Memory;
   Memo, Mem                : Pt_Memory;
   Ntrdn                    : Ntrdn_T;
   Empty                    : Empty_T;
   Prod_Ptr                 : Prod_Ptr_T;
   Memory_Array             : Memory_Array_T;
   State_Var                : State_Var_T;
   First_Var                : First_Var_T;
   Terminal_Like            : Sparklalr_Memory.Symbol_Set_T;
   Look_Array               : Look_Array_T;
   Item_Array               : Item_Array_T;
   Action                   : SPARK.Ada.Text_IO.File_Type;
   Act_Open                 : Boolean;

   -- Local procedures/functions
   procedure Stack (It : in Integer)
   -- STACKS A NEW ENTRY ONTO THE PRODUCTION REPRESENTATION
   --# global in     Command_Line_Options.State;
   --#        in out Mem;
   --#        in out Memory_Array;
   --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
   --# derives Mem                                   from *,
   --#                                                    Memory_Array &
   --#         Memory_Array                          from *,
   --#                                                    It,
   --#                                                    Mem &
   --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
   --#                                                    Command_Line_Options.State,
   --#                                                    It,
   --#                                                    Mem,
   --#                                                    Memory_Array;
   is
   begin
      Memory_Array.Top                 := Memory_Array.Top + 1;
      Memory_Array.The_Array (Mem).Ptr := Memory_Array.Top;
      Mem                              := Memory_Array.The_Array (Mem).Ptr;
      Memory_Array.The_Array (Mem)     := Memory'(Tag      => 1,
                                                  Ptr      => 0,
                                                  Contents => It,
                                                  Itm      => 0,
                                                  Mem_Pt   => 0);
      if Command_Line_Options.Get_Debug_Level (1) then
         if Mem /= 0 then
            SPARK.Ada.Text_IO.Put_Output (Item => " STACK : ");
            SPARK_Ada_Integer_Text_IO.Put_Output (Item  => It,
                                                  Width => 4,
                                                  Base  => 10);
            SPARK.Ada.Text_IO.Put_Line_Output (Item => ", MEM = ");
         end if;
      end if;
   end Stack;

   function Mem_Length (Ptr1, Ptr2 : in Pt_Memory) return Integer
   --# global in Memory_Array;
   is
      Result   : Integer;
      Ptr1_Tmp : Pt_Memory;
   begin
      Ptr1_Tmp := Ptr1;
      Result   := 1;
      while (Ptr1_Tmp /= 0) and then (Ptr1_Tmp /= Ptr2) loop
         Ptr1_Tmp := Memory_Array.The_Array (Ptr1_Tmp).Ptr;
         Result   := Result + 1;
      end loop;
      return Result;
   end Mem_Length;
   -- End local procedures/functions

   procedure Initialise
   --# global in     Command_Line_Options.State;
   --#        in out SPARK.Ada.Command_Line.State;
   --#        in out SPARK.Ada.Text_IO.The_Standard_Error;
   --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
   --#           out Action;
   --#           out Act_Open;
   --#           out Empty;
   --#           out First_Var;
   --#           out Free_List;
   --#           out Item_Array;
   --#           out Look_Array;
   --#           out Look_Tree;
   --#           out Mem;
   --#           out Memo;
   --#           out Memory_Array;
   --#           out Ntrdn;
   --#           out Prod_Ptr;
   --#           out Release_Point;
   --#           out Sparklalr_Memory.Max_Right;
   --#           out Sparklalr_Memory.Prod_No;
   --#           out Sparklalr_Memory.Prod_Sum;
   --#           out Sparklalr_Memory.Stat_No;
   --#           out State_Var;
   --#           out Terminal_Like;
   --# derives Action,
   --#         Act_Open                              from Command_Line_Options.State &
   --#         Empty,
   --#         First_Var,
   --#         Free_List,
   --#         Item_Array,
   --#         Look_Array,
   --#         Look_Tree,
   --#         Mem,
   --#         Memo,
   --#         Memory_Array,
   --#         Ntrdn,
   --#         Prod_Ptr,
   --#         Release_Point,
   --#         Sparklalr_Memory.Max_Right,
   --#         Sparklalr_Memory.Prod_No,
   --#         Sparklalr_Memory.Prod_Sum,
   --#         Sparklalr_Memory.Stat_No,
   --#         State_Var,
   --#         Terminal_Like                         from  &
   --#         SPARK.Ada.Command_Line.State,
   --#         SPARK.Ada.Text_IO.The_Standard_Error,
   --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
   --#                                                    Command_Line_Options.State;
   is
   begin
      Sparklalr_Memory.Initialise;
      Look_Tree                     := 0;
      Release_Point                 := 0;
      Free_List                     := 0;
      Memory_Array                  :=
        Memory_Array_T'
        (The_Array => Memory_Array_Array_T'(others => Memory'(Tag      => 1,
                                                              Ptr      => 0,
                                                              Contents => 0,
                                                              Itm      => 0,
                                                              Mem_Pt   => 0)),
         Top       => 0);
      Memory_Array.Top              := 1;
      Memo                          := Memory_Array.Top;
      Memory_Array.The_Array (Memo) := Memory'(Tag      => 1,
                                               Ptr      => 0,
                                               Contents => -1,
                                               Itm      => 0,
                                               Mem_Pt   => 0);
      Mem                           := Memo;
      Ntrdn                         := Ntrdn_T'(others => 0);
      Empty                         := Empty_T'(others => False);
      Stack (Sparklalr_Common.Nt_Base + 1);
      Prod_Ptr     := Prod_Ptr_T'(others => 0);
      Prod_Ptr (1) := Memo;
      Stack (Sparklalr_Common.Nt_Base + 2);
      Stack (0); -- SPEND
      Stack (-1);
      Prod_Ptr (2)  := Mem;
      State_Var     := State_Var_T'(others => 0);
      First_Var     := First_Var_T'(others => 0);
      Terminal_Like := Sparklalr_Memory.Symbol_Set_T'(others => False);
      Look_Array    :=
        Look_Array_T'
        (The_Array => Look_Array_Array_T'(others => Look_Item'(Lset  => Set_Of_Term'(others => False),
                                                               Litem => 0,
                                                               Ritem => 0)),
         Top       => 0);
      Item_Array    := Item_Array_T'(The_Array => Item_Array_Array_T'(others => Item'(Dot => 0,
                                                                                      Lh  => 0)),
                                     Top       => 0);
      SPARK.Ada.Text_IO.Unbounded_String.Create
        (File => Action,
         Mode => SPARK.Ada.Text_IO.Out_File,
         Name => SPARK.Ada.Strings.Unbounded.Concat_Unbounded_String_String
           (Left  => Command_Line_Options.Get_File_Name,
            Right => ".ACT"),
         Form => SPARK.Ada.Strings.Unbounded.Null_Unbounded_String);
      if SPARK.Ada.Text_IO.Get_Last_Exception_File (File => Action) /= SPARK.Ada.Text_IO.No_Exception then
         Act_Open := False;
         SPARK.Ada.Text_IO.Put_Error (Item => "Unable to open output file ACT");
         SPARK.Ada.Command_Line.Set_Exit_Status (SPARK.Ada.Command_Line.Failure);
      else
         Act_Open := True;
      end if;
   end Initialise;

   procedure Mem_Dump
   --# global in     Command_Line_Options.State;
   --#        in     Empty;
   --#        in     Item_Array;
   --#        in     Look_Array;
   --#        in     Mem;
   --#        in     Memo;
   --#        in     Memory_Array;
   --#        in     Ntrdn;
   --#        in     Prod_Ptr;
   --#        in     Sparklalr_Memory.Prod_No;
   --#        in     Sparklalr_Memory.Stat_No;
   --#        in     State_Var;
   --#        in     Symbols_Dump.State;
   --#        in out SPARK.Ada.Command_Line.State;
   --#        in out SPARK.Ada.Text_IO.The_Standard_Error;
   --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
   --# derives SPARK.Ada.Command_Line.State,
   --#         SPARK.Ada.Text_IO.The_Standard_Error  from *,
   --#                                                    Command_Line_Options.State,
   --#                                                    Empty,
   --#                                                    Item_Array,
   --#                                                    Look_Array,
   --#                                                    Mem,
   --#                                                    Memo,
   --#                                                    Memory_Array,
   --#                                                    Ntrdn,
   --#                                                    Prod_Ptr,
   --#                                                    Sparklalr_Memory.Prod_No,
   --#                                                    Sparklalr_Memory.Stat_No,
   --#                                                    State_Var,
   --#                                                    Symbols_Dump.State &
   --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
   --#                                                    Empty,
   --#                                                    Mem,
   --#                                                    Memo,
   --#                                                    Memory_Array,
   --#                                                    Ntrdn,
   --#                                                    Sparklalr_Memory.Prod_No,
   --#                                                    Sparklalr_Memory.Stat_No,
   --#                                                    State_Var,
   --#                                                    Symbols_Dump.State;
   is

      Item_List_Table_Size : constant := 20000;
      subtype Pt_Item_List is Natural range 0 .. Item_List_Table_Size;
      subtype Item_List_Array_Range is Positive range 1 .. Item_List_Table_Size;
      type Item_List is record
         Pitem : Pt_Item;
         Inext : Pt_Item_List;
      end record;
      type Item_List_Array_Array_T is array (Item_List_Array_Range) of Item_List;
      type Item_List_Array_T is record
         The_Array : Item_List_Array_Array_T;
         Top       : Pt_Item_List;
      end record;
      Item_List_Array : Item_List_Array_T;

      Look_List_Table_Size : constant := 20000;
      subtype Pt_Look_List is Natural range 0 .. Look_List_Table_Size;
      subtype Look_List_Array_Range is Positive range 1 .. Look_List_Table_Size;
      type Look_List is record
         Plook : Look_Set;
         Lnext : Pt_Look_List;
      end record;
      type Look_List_Array_Array_T is array (Look_List_Array_Range) of Look_List;
      type Look_List_Array_T is record
         The_Array : Look_List_Array_Array_T;
         Top       : Pt_Look_List;
      end record;
      Look_List_Array : Look_List_Array_T;

      Diagnose      : SPARK.Ada.Text_IO.File_Type;
      Item_Head     : Pt_Item_List;
      Look_Head     : Pt_Look_List;
      Pmem, Mem_Stp : Pt_Memory;

      procedure Head (Heading : in     Integer;
                      F       : in out SPARK.Ada.Text_IO.File_Type)
      --# global SPARK.Ada.Text_IO.The_Standard_Output;
      --# derives F,
      --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
      --#                                                    Heading;
      is
      begin
         --# accept W, 303, "when others here covers all cases";
         case Heading is
            when 1 =>
               SPARK.Ada.Text_IO.Put_Character_File (File => F,
                                                     Item => 'O');
               Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                             F       => F,
                                             C       => ' ',
                                             N       => 5);
               SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                                Item => " PRODUCTION STORAGE : ");
               SPARK.Ada.Text_IO.Put_Character_File (File => F,
                                                     Item => 'O');
               Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                             F       => F,
                                             C       => ' ',
                                             N       => 5);
               SPARK.Ada.Text_IO.Put_File (File => F,
                                           Item => " ADDRESS  ");
               Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                             F       => F,
                                             C       => ' ',
                                             N       => 5);
               SPARK.Ada.Text_IO.Put_File (File => F,
                                           Item => " CONTENTS ");
               Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                             F       => F,
                                             C       => ' ',
                                             N       => 5);
               SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                                Item => " NEXT LOCATION");
            when 2 =>
               SPARK.Ada.Text_IO.Put_Character_File (File => F,
                                                     Item => 'O');
               Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                             F       => F,
                                             C       => ' ',
                                             N       => 5);
               SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                                Item => " EFF STORAGE : ");
               SPARK.Ada.Text_IO.Put_Character_File (File => F,
                                                     Item => '0');
               Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                             F       => F,
                                             C       => ' ',
                                             N       => 5);
               SPARK.Ada.Text_IO.Put_File (File => F,
                                           Item => " NONTERMINAL  ");
               Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                             F       => F,
                                             C       => ' ',
                                             N       => 5);
               SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                                Item => " EFF LIST ");
            when 3 =>
               SPARK.Ada.Text_IO.Put_Character_File (File => F,
                                                     Item => 'O');
               Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                             F       => F,
                                             C       => ' ',
                                             N       => 5);
               SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                                Item => " STATE STORAGE : ");
               SPARK.Ada.Text_IO.Put_Character_File (File => F,
                                                     Item => 'O');
               Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                             F       => F,
                                             C       => ' ',
                                             N       => 5);
               SPARK.Ada.Text_IO.Put_File (File => F,
                                           Item => " ADDRESS  ");
               Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                             F       => F,
                                             C       => ' ',
                                             N       => 5);
               SPARK.Ada.Text_IO.Put_File (File => F,
                                           Item => " ITEM ADR.");
               Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                             F       => F,
                                             C       => ' ',
                                             N       => 5);
               SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                                Item => " NEXT LOCATION");
            when 4 =>
               SPARK.Ada.Text_IO.Put_Character_File (File => F,
                                                     Item => '1');
               Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                             F       => F,
                                             C       => ' ',
                                             N       => 5);
               SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                                Item => " ITEM STORAGE : ");
               SPARK.Ada.Text_IO.Put_Character_File (File => F,
                                                     Item => 'O');
               Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                             F       => F,
                                             C       => ' ',
                                             N       => 5);
               SPARK.Ada.Text_IO.Put_File (File => F,
                                           Item => " ITEM ADR.");
               Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                             F       => F,
                                             C       => ' ',
                                             N       => 5);
               SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                                Item => " DOT ADR. ");
            when 5 =>
               SPARK.Ada.Text_IO.Put_Character_File (File => F,
                                                     Item => 'O');
               Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                             F       => F,
                                             C       => ' ',
                                             N       => 5);
               SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                                Item => " LOOKAHEAD SET STORAGE : ");
               SPARK.Ada.Text_IO.Put_Character_File (File => F,
                                                     Item => '0');
               Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                             F       => F,
                                             C       => ' ',
                                             N       => 5);
               SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                                Item => "   ITEM  LOOKAHEAD SET");
            when 6 =>
               SPARK.Ada.Text_IO.Put_Character_File (File => F,
                                                     Item => '1');
               Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                             F       => F,
                                             C       => ' ',
                                             N       => 5);
               SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                                Item => " PRODUCTION POINTERS : ");
               SPARK.Ada.Text_IO.Put_Character_File (File => F,
                                                     Item => 'O');
               Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                             F       => F,
                                             C       => ' ',
                                             N       => 5);
               SPARK.Ada.Text_IO.Put_File (File => F,
                                           Item => " PRODUCTION");
               Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                             F       => F,
                                             C       => ' ',
                                             N       => 4);
               SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                                Item => " ADDRESS ");
            when 7 =>
               SPARK.Ada.Text_IO.Put_Character_File (File => F,
                                                     Item => 'O');
               Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                             F       => F,
                                             C       => ' ',
                                             N       => 5);
               SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                                Item => " EFF LIST POINTERS : ");
               SPARK.Ada.Text_IO.Put_Character_File (File => F,
                                                     Item => 'O');
               Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                             F       => F,
                                             C       => ' ',
                                             N       => 5);
               SPARK.Ada.Text_IO.Put_File (File => F,
                                           Item => " NONTERMINAL");
               Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                             F       => F,
                                             C       => ' ',
                                             N       => 3);
               SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                                Item => " ADDRESS ");
            when 8 =>
               SPARK.Ada.Text_IO.Put_Character_File (File => F,
                                                     Item => 'O');
               Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                             F       => F,
                                             C       => ' ',
                                             N       => 5);
               SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                                Item => " STATE POINTERS : ");
               SPARK.Ada.Text_IO.Put_Character_File (File => F,
                                                     Item => 'O');
               Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                             F       => F,
                                             C       => ' ',
                                             N       => 5);
               SPARK.Ada.Text_IO.Put_File (File => F,
                                           Item => "  STATE   ");
               Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                             F       => F,
                                             C       => ' ',
                                             N       => 5);
               SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                                Item => " ADDRESS ");
            when others =>
               null;
         end case;
         --# end accept;
         SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                          Spacing => 1);
      end Head;

      procedure Print_Look (L : in     Look_Set;
                            F : in out SPARK.Ada.Text_IO.File_Type)
      --# global in Look_Array;
      --#        in Symbols_Dump.State;
      --# derives F from *,
      --#                L,
      --#                Look_Array,
      --#                Symbols_Dump.State;
      is
      begin
         for I in Integer range 0 .. Symbols_Dump.Get_Nterms loop
            if Look_Array.The_Array (L).Lset (I) then
               SPARK.Ada.Text_IO.Put_File (File => F,
                                           Item => Symbols_Dump.Get_Term_Set (I));
               SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                                Item => " ");
            end if;
         end loop;
      end Print_Look;

      procedure Out1 (Pmem    : in out Pt_Memory;
                      Mem_Stp : in     Pt_Memory;
                      F       : in out SPARK.Ada.Text_IO.File_Type)
      --# global in     Memory_Array;
      --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
      --# derives F,
      --#         Pmem,
      --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
      --#                                                    Memory_Array,
      --#                                                    Mem_Stp,
      --#                                                    Pmem;
      is
         Pmout1, Pmout2 : Pt_Memory;
      begin
         while Pmem /= Mem_Stp loop
            Pmout1 := Pmem;
            Pmout2 := Memory_Array.The_Array (Pmem).Ptr;
            Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                          F       => F,
                                          C       => ' ',
                                          N       => 5);
            SPARK_Ada_Integer_Text_IO.Put_File
              (File  => F,
               Item  => Pmout1,
               Width => SPARK_Ada_Integer_Text_IO.Default_Width,
               Base  => 10);
            Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                          F       => F,
                                          C       => ' ',
                                          N       => 5);

            --# accept W, 303, "when others here covers all cases";
            case Memory_Array.The_Array (Pmem).Tag is
               when 1 =>
                  SPARK_Ada_Integer_Text_IO.Put_File
                    (File  => F,
                     Item  => Memory_Array.The_Array (Pmem).Contents,
                     Width => SPARK_Ada_Integer_Text_IO.Default_Width,
                     Base  => 10);
               when 2 =>
                  SPARK_Ada_Integer_Text_IO.Put_File
                    (File  => F,
                     Item  => Memory_Array.The_Array (Pmem).Itm,
                     Width => SPARK_Ada_Integer_Text_IO.Default_Width,
                     Base  => 10);
               when 3 =>
                  SPARK_Ada_Integer_Text_IO.Put_File
                    (File  => F,
                     Item  => Memory_Array.The_Array (Pmem).Mem_Pt,
                     Width => SPARK_Ada_Integer_Text_IO.Default_Width,
                     Base  => 10);
               when others =>
                  null;
            end case;
            --# end accept;

            Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                          F       => F,
                                          C       => ' ',
                                          N       => 5);
            SPARK_Ada_Integer_Text_IO.Put_File
              (File  => F,
               Item  => Pmout2,
               Width => SPARK_Ada_Integer_Text_IO.Default_Width,
               Base  => 10);
            SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                             Spacing => 1);
            Pmem := Memory_Array.The_Array (Pmem).Ptr;
         end loop;
      end Out1;

      procedure Out2
        (Pmem      : in     Pt_Memory;
         Mem_Stp   : in     Pt_Memory;
         Item_Head :    out Pt_Item_List;
         F         : in out SPARK.Ada.Text_IO.File_Type)
      --# global in     Memory_Array;
      --#        in out Item_List_Array;
      --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
      --# derives F,
      --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
      --#                                                    Memory_Array,
      --#                                                    Mem_Stp,
      --#                                                    Pmem &
      --#         Item_Head,
      --#         Item_List_Array                       from Item_List_Array,
      --#                                                    Memory_Array,
      --#                                                    Mem_Stp,
      --#                                                    Pmem;
      is
         Pmout1, Pmout2, Pmem_Tmp : Pt_Memory;
         Temp_Item                : Pt_Item_List;
      begin
         Pmem_Tmp  := Pmem;
         Item_Head := 0;
         while Pmem_Tmp /= Mem_Stp loop
            Pmout1 := Pmem_Tmp;
            Pmout2 := Memory_Array.The_Array (Pmem_Tmp).Ptr;
            Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                          F       => F,
                                          C       => ' ',
                                          N       => 5);
            SPARK_Ada_Integer_Text_IO.Put_File
              (File  => F,
               Item  => Pmout1,
               Width => SPARK_Ada_Integer_Text_IO.Default_Width,
               Base  => 10);
            Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                          F       => F,
                                          C       => ' ',
                                          N       => 5);

            --# accept W, 303, "when others here covers all cases";
            case Memory_Array.The_Array (Pmem_Tmp).Tag is
               when 1 =>
                  SPARK_Ada_Integer_Text_IO.Put_File
                    (File  => F,
                     Item  => Memory_Array.The_Array (Pmem_Tmp).Contents,
                     Width => SPARK_Ada_Integer_Text_IO.Default_Width,
                     Base  => 10);
               when 2 =>
                  SPARK_Ada_Integer_Text_IO.Put_File
                    (File  => F,
                     Item  => Memory_Array.The_Array (Pmem_Tmp).Itm,
                     Width => SPARK_Ada_Integer_Text_IO.Default_Width,
                     Base  => 10);
               when 3 =>
                  SPARK_Ada_Integer_Text_IO.Put_File
                    (File  => F,
                     Item  => Memory_Array.The_Array (Pmem_Tmp).Mem_Pt,
                     Width => SPARK_Ada_Integer_Text_IO.Default_Width,
                     Base  => 10);
               when others =>
                  null;
            end case;
            --# end accept;

            Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                          F       => F,
                                          C       => ' ',
                                          N       => 5);
            SPARK_Ada_Integer_Text_IO.Put_File
              (File  => F,
               Item  => Pmout2,
               Width => SPARK_Ada_Integer_Text_IO.Default_Width,
               Base  => 10);
            SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                             Spacing => 1);
            Item_List_Array.Top                   := Item_List_Array.Top + 1;
            Temp_Item                             := Item_List_Array.Top;
            Item_List_Array.The_Array (Temp_Item) :=
              Item_List'(Inext => Item_Head,
                         Pitem => Memory_Array.The_Array (Pmem_Tmp).Itm);
            Item_Head                             := Temp_Item;
            Pmem_Tmp                              := Memory_Array.The_Array (Pmem_Tmp).Ptr;
         end loop;
      end Out2;

      procedure Out3 (Item_Head : in     Pt_Item_List;
                      Look_Head :    out Pt_Look_List;
                      F         : in out SPARK.Ada.Text_IO.File_Type)
      --# global in     Item_Array;
      --#        in     Item_List_Array;
      --#        in     Look_Array;
      --#        in     Symbols_Dump.State;
      --#        in out Look_List_Array;
      --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
      --# derives F                                     from *,
      --#                                                    Item_Array,
      --#                                                    Item_Head,
      --#                                                    Item_List_Array,
      --#                                                    Look_Array,
      --#                                                    Symbols_Dump.State &
      --#         Look_Head                             from Item_Head,
      --#                                                    Item_List_Array,
      --#                                                    Look_List_Array &
      --#         Look_List_Array                       from *,
      --#                                                    Item_Array,
      --#                                                    Item_Head,
      --#                                                    Item_List_Array &
      --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
      --#                                                    Item_Head,
      --#                                                    Item_List_Array;
      is
         I         : Pt_Item_List;
         Piout     : Pt_Item;
         Pmout1    : Pt_Memory;
         Temp_Look : Pt_Look_List;
      begin
         I         := Item_Head;
         Look_Head := 0;
         while I /= 0 loop
            Piout  := Item_List_Array.The_Array (I).Pitem;
            Pmout1 := Item_Array.The_Array (Item_List_Array.The_Array (I).Pitem).Dot;
            Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                          F       => F,
                                          C       => ' ',
                                          N       => 5);
            SPARK_Ada_Integer_Text_IO.Put_File
              (File  => F,
               Item  => Piout,
               Width => SPARK_Ada_Integer_Text_IO.Default_Width,
               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  => Pmout1,
               Width => SPARK_Ada_Integer_Text_IO.Default_Width,
               Base  => 10);
            Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                          F       => F,
                                          C       => ' ',
                                          N       => 6);
            SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                             Spacing => 1);
            Print_Look (Item_Array.The_Array (Item_List_Array.The_Array (I).Pitem).Lh, F);
            Look_List_Array.Top                   := Look_List_Array.Top + 1;
            Temp_Look                             := Look_List_Array.Top;
            Look_List_Array.The_Array (Temp_Look) :=
              Look_List'(Plook => Item_Array.The_Array (Item_List_Array.The_Array (I).Pitem).Lh,
                         Lnext => Look_Head);
            Look_Head                             := Temp_Look;
            I                                     := Item_List_Array.The_Array (I).Inext;
         end loop;
      end Out3;

      procedure Out4 (Look_Head : in     Pt_Look_List;
                      F         : in out SPARK.Ada.Text_IO.File_Type)
      --# global in Look_Array;
      --#        in Look_List_Array;
      --#        in Symbols_Dump.State;
      --# derives F from *,
      --#                Look_Array,
      --#                Look_Head,
      --#                Look_List_Array,
      --#                Symbols_Dump.State;
      is
         L : Pt_Look_List;
      begin
         L := Look_Head;
         while L /= 0 loop
            Print_Look (Look_List_Array.The_Array (L).Plook, F);
            L := Look_List_Array.The_Array (L).Lnext;
         end loop;
      end Out4;

      procedure Out5 (F : in out SPARK.Ada.Text_IO.File_Type)
      --# global in     Prod_Ptr;
      --#        in     Sparklalr_Memory.Prod_No;
      --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
      --# derives F                                     from *,
      --#                                                    Prod_Ptr,
      --#                                                    Sparklalr_Memory.Prod_No &
      --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
      --#                                                    Sparklalr_Memory.Prod_No;
      is
         Pmout1 : Pt_Memory;
      begin
         for I in Integer range 1 .. Sparklalr_Memory.Prod_No - 1 loop
            Pmout1 := Prod_Ptr (I);
            Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                          F       => F,
                                          C       => ' ',
                                          N       => 5);
            SPARK_Ada_Integer_Text_IO.Put_File
              (File  => F,
               Item  => I,
               Width => SPARK_Ada_Integer_Text_IO.Default_Width,
               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  => Pmout1,
               Width => SPARK_Ada_Integer_Text_IO.Default_Width,
               Base  => 10);
            SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                             Spacing => 1);
         end loop;
      end Out5;

      procedure Out6 (F : in out SPARK.Ada.Text_IO.File_Type)
      --# global in     Empty;
      --#        in     Ntrdn;
      --#        in     Symbols_Dump.State;
      --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
      --# derives F                                     from *,
      --#                                                    Empty,
      --#                                                    Ntrdn,
      --#                                                    Symbols_Dump.State &
      --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
      --#                                                    Empty,
      --#                                                    Symbols_Dump.State;
      is
         Pmout1 : Pt_Memory;
      begin
         for I in Integer range 1 .. Symbols_Dump.Get_Nnon_Terms loop
            Pmout1 := Ntrdn (I);
            if Empty (I) then
               Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                             F       => F,
                                             C       => ' ',
                                             N       => 5);
               SPARK_Ada_Integer_Text_IO.Put_File
                 (File  => F,
                  Item  => I,
                  Width => SPARK_Ada_Integer_Text_IO.Default_Width,
                  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  => Pmout1,
                  Width => SPARK_Ada_Integer_Text_IO.Default_Width,
                  Base  => 10);
               Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                             F       => F,
                                             C       => ' ',
                                             N       => 5);
               SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                                Item => "True");
            else
               Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                             F       => F,
                                             C       => ' ',
                                             N       => 5);
               SPARK_Ada_Integer_Text_IO.Put_File
                 (File  => F,
                  Item  => I,
                  Width => SPARK_Ada_Integer_Text_IO.Default_Width,
                  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  => Pmout1,
                  Width => SPARK_Ada_Integer_Text_IO.Default_Width,
                  Base  => 10);
               Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                             F       => F,
                                             C       => ' ',
                                             N       => 5);
               SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                                Item => "False");
            end if;
         end loop;
      end Out6;

      procedure Out7 (F : in out SPARK.Ada.Text_IO.File_Type)
      --# global in     Sparklalr_Memory.Stat_No;
      --#        in     State_Var;
      --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
      --# derives F                                     from *,
      --#                                                    Sparklalr_Memory.Stat_No,
      --#                                                    State_Var &
      --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
      --#                                                    Sparklalr_Memory.Stat_No;
      is
         Pmout1 : Pt_Memory;
      begin
         for I in Integer range 1 .. Sparklalr_Memory.Stat_No loop
            Pmout1 := State_Var (I);
            Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                          F       => F,
                                          C       => ' ',
                                          N       => 5);
            SPARK_Ada_Integer_Text_IO.Put_File
              (File  => F,
               Item  => I,
               Width => SPARK_Ada_Integer_Text_IO.Default_Width,
               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  => Pmout1,
               Width => SPARK_Ada_Integer_Text_IO.Default_Width,
               Base  => 10);
            SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                             Spacing => 1);
         end loop;
      end Out7;

   begin -- Mem_Dump
      Item_List_Array :=
        Item_List_Array_T'(The_Array => Item_List_Array_Array_T'(others => Item_List'(Pitem => 0,
                                                                                      Inext => 0)),
                           Top       => 0);
      Look_List_Array :=
        Look_List_Array_T'(The_Array => Look_List_Array_Array_T'(others => Look_List'(Plook => 0,
                                                                                      Lnext => 0)),
                           Top       => 0);
      SPARK.Ada.Text_IO.Put_Line_Output (Item => "DUMPMEM Set...");
      SPARK.Ada.Text_IO.Unbounded_String.Create
        (File => Diagnose,
         Mode => SPARK.Ada.Text_IO.Out_File,
         Name => SPARK.Ada.Strings.Unbounded.Concat_Unbounded_String_String
           (Left  => Command_Line_Options.Get_File_Name,
            Right => ".DGN"),
         Form => SPARK.Ada.Strings.Unbounded.Null_Unbounded_String);
      if SPARK.Ada.Text_IO.Get_Last_Exception_File (File => Diagnose) /= SPARK.Ada.Text_IO.No_Exception then
         SPARK.Ada.Text_IO.Put_Error (Item => "Unable to open DGN output file");
         SPARK.Ada.Command_Line.Set_Exit_Status (SPARK.Ada.Command_Line.Failure);
      end if;
      Pmem    := Memo;
      Mem_Stp := Ntrdn (1);
      SPARK.Ada.Text_IO.Put_Character_File (File => Diagnose,
                                            Item => '1');
      Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                    F       => Diagnose,
                                    C       => ' ',
                                    N       => 5);
      SPARK.Ada.Text_IO.Put_Line_File (File => Diagnose,
                                       Item => " MEMORY DUMP : ");
      Head (1, Diagnose);
      Out1 (Pmem, Mem_Stp, Diagnose);
      Mem_Stp := State_Var (1);
      Head (2, Diagnose);
      Out1 (Pmem, Mem_Stp, Diagnose);
      Mem_Stp := Mem;
      Head (3, Diagnose);
      Out2 (Pmem, Mem_Stp, Item_Head, Diagnose);
      Head (4, Diagnose);
      Out3 (Item_Head, Look_Head, Diagnose);
      Head (5, Diagnose);
      Out4 (Look_Head, Diagnose);
      Head (6, Diagnose);
      Out5 (Diagnose);
      Head (7, Diagnose);
      Out6 (Diagnose);
      Head (8, Diagnose);
      Out7 (Diagnose);
      SPARK.Ada.Text_IO.Close (File => Diagnose);
      if SPARK.Ada.Text_IO.Get_Last_Exception_File (File => Diagnose) /= SPARK.Ada.Text_IO.No_Exception then
         SPARK.Ada.Text_IO.Put_Error (Item => "Unable to close DGN output file");
         SPARK.Ada.Command_Line.Set_Exit_Status (SPARK.Ada.Command_Line.Failure);
      end if;
   end Mem_Dump;

   function Prodstart (P : in Pt_Memory) return Pt_Memory
   --# global in Memory_Array;
   --#        in Prod_Ptr;
   is
      P_Tmp : Pt_Memory;
   begin
      P_Tmp := P;
      while Memory_Array.The_Array (P_Tmp).Contents >= 0 loop
         P_Tmp := Memory_Array.The_Array (P_Tmp).Ptr;
      end loop;
      return Memory_Array.The_Array (Prod_Ptr (-Memory_Array.The_Array (P_Tmp).Contents)).Ptr;
   end Prodstart;

   procedure Dump_Items (F    : in out SPARK.Ada.Text_IO.File_Type;
                         S, T : in     Pt_Memory)
   --# global in     Item_Array;
   --#        in     Look_Array;
   --#        in     Memory_Array;
   --#        in     Prod_Ptr;
   --#        in     Symbols_Dump.State;
   --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
   --# derives F,
   --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
   --#                                                    Item_Array,
   --#                                                    Look_Array,
   --#                                                    Memory_Array,
   --#                                                    Prod_Ptr,
   --#                                                    S,
   --#                                                    Symbols_Dump.State,
   --#                                                    T;
   is

      P, Q    : Pt_Memory;
      C       : Integer;
      Dot_Out : Boolean;
      Posn    : Integer;
      S_Tmp   : Pt_Memory;

      procedure Dump_Look (F    : in out SPARK.Ada.Text_IO.File_Type;
                           L    : in     Look_Set;
                           Posn : in     Integer)
      --# global in     Look_Array;
      --#        in     Symbols_Dump.State;
      --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
      --# derives F,
      --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
      --#                                                    L,
      --#                                                    Look_Array,
      --#                                                    Posn,
      --#                                                    Symbols_Dump.State;
      is
         Tab      : Integer;
         Posn_Tmp : Integer;
      begin
         Posn_Tmp := Posn;
         SPARK.Ada.Text_IO.Put_Character_File (File => F,
                                               Item => '(');
         Posn_Tmp := Posn_Tmp + 1;
         Tab      := Posn_Tmp;
         for J in Integer range 0 .. Symbols_Dump.Get_Nterms loop
            if Look_Array.The_Array (L).Lset (J) then
               Sparklalr_Common.Print
                 (Std_Out => False,
                  F       => F,
                  String1 => Symbols_Dump.Get_Term_Set (J),
                  Posn    => Posn_Tmp,
                  Tab     => Tab,
                  Comm    => False);
               SPARK.Ada.Text_IO.Put_Character_File (File => F,
                                                     Item => ' ');
               Posn_Tmp := Posn_Tmp + 1;
            end if;
         end loop;
         SPARK.Ada.Text_IO.Put_Character_File (File => F,
                                               Item => ')');
      end Dump_Look;

   begin -- Dump_Items
      S_Tmp := S;
      SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                       Spacing => 1);
      Posn := 1;
      while (S_Tmp /= T) and then (S_Tmp /= 0) loop
         Q := Item_Array.The_Array (Memory_Array.The_Array (S_Tmp).Itm).Dot;
         P := Prodstart (Q);
         C := Memory_Array.The_Array (P).Contents;
         Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                       F       => F,
                                       C       => ' ',
                                       N       => 4);
         SPARK.Ada.Text_IO.Put_Character_File (File => F,
                                               Item => '[');
         Posn := Posn + 5;
         Sparklalr_Common.Print
           (Std_Out => False,
            F       => F,
            String1 => Symbols_Dump.Get_Nterm_Set (C - Sparklalr_Common.Nt_Base),
            Posn    => Posn,
            Tab     => 5,
            Comm    => False);
         SPARK.Ada.Text_IO.Put_File (File => F,
                                     Item => " : ");
         Posn    := Posn + 3;
         P       := Memory_Array.The_Array (P).Ptr;
         Dot_Out := False;
         while Memory_Array.The_Array (P).Contents > 0 loop
            C := Memory_Array.The_Array (P).Contents;
            if P = Q then
               Dot_Out := True;
               SPARK.Ada.Text_IO.Put_File (File => F,
                                           Item => ". ");
               Posn := Posn + 2;
            end if;
            if C > Sparklalr_Common.Nt_Base then
               Sparklalr_Common.Print
                 (Std_Out => False,
                  F       => F,
                  String1 => Symbols_Dump.Get_Nterm_Set (C - Sparklalr_Common.Nt_Base),
                  Posn    => Posn,
                  Tab     => 8,
                  Comm    => False);
            else
               if C <= Symbols_Dump.Get_Nterms then
                  Sparklalr_Common.Print
                    (Std_Out => False,
                     F       => F,
                     String1 => Symbols_Dump.Get_Term_Set (C),
                     Posn    => Posn,
                     Tab     => 8,
                     Comm    => False);
               else
                  SPARK.Ada.Text_IO.Put_File (File => F,
                                              Item => " *!* "); -- was ^Z
                  Posn := Posn + 5;
               end if;
            end if;
            SPARK.Ada.Text_IO.Put_Character_File (File => F,
                                                  Item => ' ');
            Posn := Posn + 1;
            P    := Memory_Array.The_Array (P).Ptr;
         end loop;
         if not Dot_Out then
            SPARK.Ada.Text_IO.Put_File (File => F,
                                        Item => " . ");
            Posn := Posn + 3;
         end if;
         SPARK.Ada.Text_IO.Put_File (File => F,
                                     Item => "] , ");
         Posn := Posn + 4;
         Dump_Look (F, Item_Array.The_Array (Memory_Array.The_Array (S_Tmp).Itm).Lh, Posn);
         SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                          Spacing => 1);
         Posn  := 1;
         S_Tmp := Memory_Array.The_Array (S_Tmp).Ptr;
      end loop;
   end Dump_Items;

   procedure Dump_Prdns (F : in out SPARK.Ada.Text_IO.File_Type)
   --# global in     Memory_Array;
   --#        in     Prod_Ptr;
   --#        in     Sparklalr_Memory.Prod_No;
   --#        in     Symbols_Dump.State;
   --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
   --# derives F,
   --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
   --#                                                    Memory_Array,
   --#                                                    Prod_Ptr,
   --#                                                    Sparklalr_Memory.Prod_No,
   --#                                                    Symbols_Dump.State;
   is
      P    : Pt_Memory;
      Posn : Integer;
   begin
      Posn := 1;
      for I in Integer range 1 .. Sparklalr_Memory.Prod_No - 1 loop
         SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                             Item  => I,
                                             Width => 4,
                                             Base  => 10);
         SPARK.Ada.Text_IO.Put_Character_File (File => F,
                                               Item => ' ');
         Posn := Posn + 5;
         P    := Memory_Array.The_Array (Prod_Ptr (I)).Ptr;
         Symbols_Dump.Print_Sym (F, Memory_Array.The_Array (P).Contents, Posn, 10, False);
         SPARK.Ada.Text_IO.Put_File (File => F,
                                     Item => " : ");
         Posn := Posn + 3;
         P    := Memory_Array.The_Array (P).Ptr;
         while Memory_Array.The_Array (P).Contents > 0 loop
            SPARK.Ada.Text_IO.Put_Character_File (File => F,
                                                  Item => ' ');
            Posn := Posn + 1;
            Symbols_Dump.Print_Sym (F, Memory_Array.The_Array (P).Contents, Posn, 10, False);
            P := Memory_Array.The_Array (P).Ptr;
         end loop;
         SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                          Spacing => 1);
         Posn := 1;
      end loop;
   end Dump_Prdns;

   procedure Summary
   --# global in     Memory_Array;
   --#        in     Prod_Ptr;
   --#        in     Sparklalr_Memory.Prod_No;
   --#        in out Sparklalr_Memory.Prod_Sum;
   --#           out Sparklalr_Memory.Max_Right;
   --# derives Sparklalr_Memory.Max_Right,
   --#         Sparklalr_Memory.Prod_Sum  from Memory_Array,
   --#                                         Prod_Ptr,
   --#                                         Sparklalr_Memory.Prod_No,
   --#                                         Sparklalr_Memory.Prod_Sum;
   is
      C, T : Pt_Memory;
   begin
      Sparklalr_Memory.Set_Max_Right (0);
      Sparklalr_Memory.Set_Prod_Sum (1, 1, 1);
      Sparklalr_Memory.Set_Prod_Sum (1, 2, 2);
      for I in Integer range 2 .. Sparklalr_Memory.Prod_No - 1 loop
         C := Memory_Array.The_Array (Prod_Ptr (I)).Ptr;
         Sparklalr_Memory.Set_Prod_Sum (I, 1, Memory_Array.The_Array (C).Contents - Sparklalr_Common.Nt_Base);
         T := Prod_Ptr (I + 1);
         Sparklalr_Memory.Set_Prod_Sum (I, 2, Mem_Length (Memory_Array.The_Array (C).Ptr, T) - 1);
         if Sparklalr_Memory.Prod_Sum (I) (2) > Sparklalr_Memory.Max_Right then
            Sparklalr_Memory.Set_Max_Right (Sparklalr_Memory.Prod_Sum (I) (2));
         end if;
      end loop;
   end Summary;

   procedure New_State (S      : in     Pt_Memory;
                        Result :    out Integer)
   -- FINDS THE GOTO STATE OF THE ITEM POINTED TO BY "S"
   --# global in     Mem;
   --#        in     Memory_Array;
   --#        in     Sparklalr_Memory.Stat_No;
   --#        in     State_Var;
   --#        in out Item_Array;
   --# derives Item_Array from *,
   --#                         Memory_Array,
   --#                         S &
   --#         Result     from Item_Array,
   --#                         Mem,
   --#                         Memory_Array,
   --#                         S,
   --#                         Sparklalr_Memory.Stat_No,
   --#                         State_Var;
   is

      Temp_Item : Pt_Item;

      procedure Go2 (Pitem : in Pt_Item)
      --# global in     Memory_Array;
      --#        in out Item_Array;
      --# derives Item_Array from *,
      --#                         Memory_Array,
      --#                         Pitem;
      is
      begin
         if Memory_Array.The_Array (Item_Array.The_Array (Pitem).Dot).Contents > 0 then
            Item_Array.The_Array (Pitem).Dot := Memory_Array.The_Array (Item_Array.The_Array (Pitem).Dot).Ptr;
         end if;
      end Go2;

      function Fstate (Pitem : in Pt_Item) return Integer
      --# global in Item_Array;
      --#        in Mem;
      --#        in Memory_Array;
      --#        in Sparklalr_Memory.Stat_No;
      --#        in State_Var;
      is
         Found : Boolean;
         I     : Integer;
         S, T  : Pt_Memory;
      begin
         I     := 1;
         Found := False;
         while (I <= Sparklalr_Memory.Stat_No) and then not Found loop
            S := State_Var (I);
            if I = Sparklalr_Memory.Stat_No then
               T := Mem;
            else
               T := State_Var (I + 1);
            end if;
            while (S /= T) and then not Found loop
               if Memory_Array.The_Array (S).Itm = Pitem then
                  Found := False;
               else
                  if Item_Array.The_Array (Memory_Array.The_Array (S).Itm).Dot = Item_Array.The_Array (Pitem).Dot then
                     if Item_Array.The_Array (Memory_Array.The_Array (S).Itm).Lh = Item_Array.The_Array (Pitem).Lh then
                        Found := True;
                     else
                        S := Memory_Array.The_Array (S).Ptr;
                     end if;
                  else
                     S := Memory_Array.The_Array (S).Ptr;
                  end if;
               end if;
            end loop;
            I := I + 1;
         end loop;
         return I - 1;
      end Fstate;

   begin
      Temp_Item := Memory_Array.The_Array (S).Itm;
      Go2 (Temp_Item);
      Result := Fstate (Temp_Item);
   end New_State;

   procedure Gen_Terminal_Like
   --# global in     Memory_Array;
   --#        in     Ntrdn;
   --#        in     Symbols_Dump.State;
   --#        in out Terminal_Like;
   --# derives Terminal_Like from *,
   --#                            Memory_Array,
   --#                            Ntrdn,
   --#                            Symbols_Dump.State;
   is
      S, T                          : Pt_Memory;
      Not_Closed, All_Terminal_Like : Boolean;
   begin
      for Index in Integer range -1 .. Symbols_Dump.Get_Nterms loop
         Terminal_Like (Index) := True;
      end loop;
      for Index in Integer range Symbols_Dump.Get_Nterms + 1 .. Sparklalr_Common.Max_Sym loop
         Terminal_Like (Index) := False;
      end loop;
      -- Form closure of TerminalLike
      Not_Closed := True;
      while Not_Closed loop
         Not_Closed := False;
         for Nt in Integer range 1 .. Symbols_Dump.Get_Nnon_Terms loop
            S                 := Ntrdn (Nt);
            T                 := Ntrdn (Nt + 1);
            All_Terminal_Like := True;
            while (S /= T) and then All_Terminal_Like loop
               if Memory_Array.The_Array (Memory_Array.The_Array (Memory_Array.The_Array (S).Mem_Pt).Ptr).Contents >= 0 then
                  if (Memory_Array.The_Array
                        (Memory_Array.The_Array
                           (Memory_Array.The_Array (Memory_Array.The_Array (S).Mem_Pt).Ptr).Ptr).Contents >= 0)
                    or else (not Terminal_Like
                               (Memory_Array.The_Array (Memory_Array.The_Array (Memory_Array.The_Array (S).Mem_Pt).Ptr).Contents))
                  then
                     All_Terminal_Like := False;
                  end if;
               else
                  All_Terminal_Like := False;
               end if;
               S := Memory_Array.The_Array (S).Ptr;
            end loop;
            if All_Terminal_Like and then not Terminal_Like (Nt + Sparklalr_Common.Nt_Base) then
               Terminal_Like (Nt + Sparklalr_Common.Nt_Base) := True;
               Not_Closed                                    := True;
            end if;
         end loop;
      end loop;
   end Gen_Terminal_Like;

   procedure Findntredns (F : in out SPARK.Ada.Text_IO.File_Type)
   -- FINDS DEFINING PRODUCTIONS FOR EACH NONTERMINAL
   --# global in     Command_Line_Options.State;
   --#        in     Prod_Ptr;
   --#        in     Sparklalr_Memory.Prod_No;
   --#        in     Symbols_Dump.State;
   --#        in out Empty;
   --#        in out Mem;
   --#        in out Memory_Array;
   --#        in out Ntrdn;
   --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
   --#        in out Sparklalr_Error.State;
   --# derives Empty                                 from *,
   --#                                                    Symbols_Dump.State &
   --#         F,
   --#         Sparklalr_Error.State                 from *,
   --#                                                    Mem,
   --#                                                    Memory_Array,
   --#                                                    Ntrdn,
   --#                                                    Prod_Ptr,
   --#                                                    Sparklalr_Memory.Prod_No,
   --#                                                    Symbols_Dump.State &
   --#         Mem,
   --#         Memory_Array,
   --#         Ntrdn                                 from *,
   --#                                                    Mem,
   --#                                                    Memory_Array,
   --#                                                    Prod_Ptr,
   --#                                                    Sparklalr_Memory.Prod_No,
   --#                                                    Symbols_Dump.State &
   --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
   --#                                                    Command_Line_Options.State,
   --#                                                    Mem,
   --#                                                    Memory_Array,
   --#                                                    Ntrdn,
   --#                                                    Prod_Ptr,
   --#                                                    Sparklalr_Memory.Prod_No,
   --#                                                    Symbols_Dump.State;
   is

      Frst : Boolean;
      M    : Pt_Memory;

      procedure Stack_Mem (M : in Pt_Memory)
      -- STACKS POINTERS TO INTERNAL PRODUCTION REPRESENTATION
      --# global in     Command_Line_Options.State;
      --#        in out Mem;
      --#        in out Memory_Array;
      --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
      --# derives Mem                                   from *,
      --#                                                    Memory_Array &
      --#         Memory_Array                          from *,
      --#                                                    M,
      --#                                                    Mem &
      --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
      --#                                                    Command_Line_Options.State,
      --#                                                    M,
      --#                                                    Mem,
      --#                                                    Memory_Array;
      is
      begin
         Memory_Array.Top                 := Memory_Array.Top + 1;
         Memory_Array.The_Array (Mem).Ptr := Memory_Array.Top;
         Mem                              := Memory_Array.The_Array (Mem).Ptr;
         Memory_Array.The_Array (Mem)     := Memory'(Tag      => 3,
                                                     Ptr      => 0,
                                                     Contents => 0,
                                                     Itm      => 0,
                                                     Mem_Pt   => M);
         if Command_Line_Options.Get_Debug_Level (2) then
            if M /= 0 then
               SPARK.Ada.Text_IO.Put_Output (Item => " STACKM:EM , MEM =");
            end if;
            if Mem /= 0 then
               SPARK.Ada.Text_IO.Put_Line_Output (Item => " ");
            end if;
         end if;
      end Stack_Mem;

   begin -- Findntredns
      for I in Integer range 1 .. Symbols_Dump.Get_Nnon_Terms loop
         Frst      := True;
         Ntrdn (I) := 0;
         Empty (I) := False;
         for J in Integer range 1 .. Sparklalr_Memory.Prod_No - 1 loop
            if Memory_Array.The_Array (Memory_Array.The_Array (Prod_Ptr (J)).Ptr).Contents = I + Sparklalr_Common.Nt_Base then
               M := Memory_Array.The_Array (Prod_Ptr (J)).Ptr;
               Stack_Mem (M);
               if Frst then
                  Frst      := False;
                  Ntrdn (I) := Mem;
               end if;
            end if;
         end loop;
         Ntrdn (Symbols_Dump.Get_Nnon_Terms + 1) := Mem;
         if 0 = Ntrdn (I) then
            Sparklalr_Error.Error (F, 30);
            SPARK.Ada.Text_IO.Put_Character_File (File => F,
                                                  Item => ' ');
            SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                             Item => Symbols_Dump.Get_Nterm_Set (I));
            SPARK.Ada.Text_IO.Put_Character_Output (Item => ' ');
            SPARK.Ada.Text_IO.Put_Line_Output (Item => Symbols_Dump.Get_Nterm_Set (I));
         end if;
      end loop;
      Stack_Mem (0);
      Ntrdn (Symbols_Dump.Get_Nnon_Terms + 1) := Mem;
      Empty (Symbols_Dump.Get_Nnon_Terms + 1) := False;
      if Command_Line_Options.Get_Debug_Level (4) then
         for J in Integer range 1 .. Symbols_Dump.Get_Nnon_Terms loop
            if Ntrdn (J) /= 0 then
               SPARK.Ada.Text_IO.Put_Output (Item => " NTRDN ");
               SPARK_Ada_Integer_Text_IO.Put_Output (Item  => J,
                                                     Width => 3,
                                                     Base  => 10);
               SPARK.Ada.Text_IO.Put_Line_Output (Item => " INDEX = ");
            end if;
         end loop;
      end if;
   end Findntredns;

   procedure Mem_Stats (Std_Out : in     Boolean;
                        F       : in out SPARK.Ada.Text_IO.File_Type)
   --# global in     Mem;
   --#        in     Memo;
   --#        in     Memory_Array;
   --#        in     Ntrdn;
   --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
   --# derives F,
   --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
   --#                                                    Mem,
   --#                                                    Memo,
   --#                                                    Memory_Array,
   --#                                                    Ntrdn,
   --#                                                    Std_Out;
   is
      Measure1, Measure2 : Integer;
   begin
      Measure1 := Mem_Length (Memo, Mem);
      Measure2 := Mem_Length (Memo, Ntrdn (1));
      Sparklalr_Common.Put_Integer_File_Output (Std_Out => Std_Out,
                                                File    => F,
                                                Item    => Measure1,
                                                Width   => 6);
      Sparklalr_Common.Put_Line_File_Output (Std_Out => Std_Out,
                                             File    => F,
                                             Item    => " MEMORY RECORDS USED.");
      Sparklalr_Common.Put_Integer_File_Output (Std_Out => Std_Out,
                                                File    => F,
                                                Item    => Measure2,
                                                Width   => 6);
      Sparklalr_Common.Put_Line_File_Output
        (Std_Out => Std_Out,
         File    => F,
         Item    => " MEMORY RECORDS USED FOR PRODUCTION STORAGE.");
      Sparklalr_Common.Put_Integer_File_Output (Std_Out => Std_Out,
                                                File    => F,
                                                Item    => Measure1 - Measure2,
                                                Width   => 6);
      Sparklalr_Common.Put_File_Output (Std_Out => Std_Out,
                                        File    => F,
                                        Item    => " MEMORY RECORDS USED FOR OTHER");
      Sparklalr_Common.Put_Line_File_Output (Std_Out => Std_Out,
                                             File    => F,
                                             Item    => " INFORMATION.");
   end Mem_Stats;

   procedure Productions_Package_Out (F : in out SPARK.Ada.Text_IO.File_Type)
   --# global in     Memory_Array;
   --#        in     Prod_Ptr;
   --#        in     Sparklalr_Memory.Max_Right;
   --#        in     Sparklalr_Memory.Prod_No;
   --#        in     Sparklalr_Memory.Stat_No;
   --#        in     Symbols_Dump.State;
   --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
   --# derives F                                     from *,
   --#                                                    Memory_Array,
   --#                                                    Prod_Ptr,
   --#                                                    Sparklalr_Memory.Max_Right,
   --#                                                    Sparklalr_Memory.Prod_No,
   --#                                                    Sparklalr_Memory.Stat_No,
   --#                                                    Symbols_Dump.State &
   --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
   --#                                                    Memory_Array,
   --#                                                    Prod_Ptr,
   --#                                                    Sparklalr_Memory.Prod_No,
   --#                                                    Symbols_Dump.State;
   is
      Posn : Integer;
      P    : Pt_Memory;
   begin
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "package SP_Productions is");
      SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                       Spacing => 1);
      Posn := 1;
      for I in Integer range 1 .. Sparklalr_Memory.Prod_No - 1 loop
         SPARK.Ada.Text_IO.Put_File (File => F,
                                     Item => "--_");
         SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                             Item  => I,
                                             Width => 4,
                                             Base  => 10);
         SPARK.Ada.Text_IO.Put_Character_File (File => F,
                                               Item => ' ');
         Posn := Posn + 8;
         P    := Memory_Array.The_Array (Prod_Ptr (I)).Ptr;
         Symbols_Dump.Print_Sym (F, Memory_Array.The_Array (P).Contents, Posn, 10, True);
         SPARK.Ada.Text_IO.Put_File (File => F,
                                     Item => " ::=");
         Posn := Posn + 5;
         P    := Memory_Array.The_Array (P).Ptr;
         while Memory_Array.The_Array (P).Contents > 1 loop -- > SPEND and SPDEFAULT
            Posn := Posn + 1;
            Symbols_Dump.Print_Sym (F, Memory_Array.The_Array (P).Contents, Posn, 10, True);
            P := Memory_Array.The_Array (P).Ptr;
         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);
      SPARK.Ada.Text_IO.Put_File (File => F,
                                  Item => "   SP_Max_Prod   : constant Positive := ");
      SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                          Item  => Sparklalr_Memory.Prod_No - 1,
                                          Width => 1,
                                          Base  => 10);
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => ";");
      SPARK.Ada.Text_IO.Put_File (File => F,
                                  Item => "   SP_Max_Right  : constant Positive := ");
      SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                          Item  => Sparklalr_Memory.Max_Right,
                                          Width => 1,
                                          Base  => 10);
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => ";");
      SPARK.Ada.Text_IO.Put_File (File => F,
                                  Item => "   SP_Max_State  : constant Positive := ");
      SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                          Item  => Sparklalr_Memory.Stat_No,
                                          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 SP_Prod_No is range 0 .. SP_Max_Prod;");
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "   type SP_Right   is range 0 .. SP_Max_Right;");
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "   type SP_State   is range 0 .. SP_Max_State;");
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "   subtype Valid_States is SP_State range 1 .. SP_State'Last;");
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "   No_State : constant SP_State := SP_State'First;");
      SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                       Spacing => 1);
      SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                       Item => "end SP_Productions;");
   end Productions_Package_Out;

   procedure Rhs_Process
     (F          : in out SPARK.Ada.Text_IO.File_Type;
      Symb       : in out Sparklalr_Symbol.Symbol;
      Gram_Rules : in     Boolean;
      Col        : in out Sparklalr_Error.Err_Col_T;
      Signpost   : in     Sparklalr_Input.Symbol_Set_Type)
   --# global in     Act_Open;
   --#        in     Command_Line_Options.State;
   --#        in     Sparklalr_Char_Class.Charmap;
   --#        in out Action;
   --#        in out Mem;
   --#        in out Memory_Array;
   --#        in out Prod_Ptr;
   --#        in out SPARK.Ada.Command_Line.State;
   --#        in out SPARK.Ada.Text_IO.The_Standard_Error;
   --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
   --#        in out Sparklalr_Error.State;
   --#        in out Sparklalr_Input.State;
   --#        in out Sparklalr_Level.State;
   --#        in out Sparklalr_Memory.Prod_No;
   --#        in out Symbols_Dump.State;
   --# derives Action,
   --#         SPARK.Ada.Command_Line.State,
   --#         SPARK.Ada.Text_IO.The_Standard_Error,
   --#         Sparklalr_Memory.Prod_No              from *,
   --#                                                    Act_Open,
   --#                                                    Col,
   --#                                                    Command_Line_Options.State,
   --#                                                    Signpost,
   --#                                                    Sparklalr_Char_Class.Charmap,
   --#                                                    Sparklalr_Error.State,
   --#                                                    Sparklalr_Input.State,
   --#                                                    Sparklalr_Memory.Prod_No,
   --#                                                    Symbols_Dump.State &
   --#         Col,
   --#         F,
   --#         Sparklalr_Error.State,
   --#         Sparklalr_Input.State                 from *,
   --#                                                    Act_Open,
   --#                                                    Col,
   --#                                                    Command_Line_Options.State,
   --#                                                    Signpost,
   --#                                                    Sparklalr_Char_Class.Charmap,
   --#                                                    Sparklalr_Error.State,
   --#                                                    Sparklalr_Input.State,
   --#                                                    Symbols_Dump.State &
   --#         Mem,
   --#         Memory_Array,
   --#         Prod_Ptr,
   --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
   --#                                                    Act_Open,
   --#                                                    Col,
   --#                                                    Command_Line_Options.State,
   --#                                                    Mem,
   --#                                                    Memory_Array,
   --#                                                    Prod_Ptr,
   --#                                                    Signpost,
   --#                                                    Sparklalr_Char_Class.Charmap,
   --#                                                    Sparklalr_Error.State,
   --#                                                    Sparklalr_Input.State,
   --#                                                    Sparklalr_Memory.Prod_No,
   --#                                                    Symb,
   --#                                                    Symbols_Dump.State &
   --#         Sparklalr_Level.State                 from *,
   --#                                                    Act_Open,
   --#                                                    Col,
   --#                                                    Command_Line_Options.State,
   --#                                                    Gram_Rules,
   --#                                                    Mem,
   --#                                                    Memory_Array,
   --#                                                    Prod_Ptr,
   --#                                                    Signpost,
   --#                                                    Sparklalr_Char_Class.Charmap,
   --#                                                    Sparklalr_Error.State,
   --#                                                    Sparklalr_Input.State,
   --#                                                    Sparklalr_Memory.Prod_No,
   --#                                                    Symb,
   --#                                                    Symbols_Dump.State &
   --#         Symb                                  from Act_Open,
   --#                                                    Col,
   --#                                                    Command_Line_Options.State,
   --#                                                    Signpost,
   --#                                                    Sparklalr_Char_Class.Charmap,
   --#                                                    Sparklalr_Error.State,
   --#                                                    Sparklalr_Input.State,
   --#                                                    Symbols_Dump.State &
   --#         Symbols_Dump.State                    from *,
   --#                                                    Col,
   --#                                                    Sparklalr_Char_Class.Charmap,
   --#                                                    Sparklalr_Error.State,
   --#                                                    Sparklalr_Input.State;
   is

      Symbolset_Skipto : Sparklalr_Input.Symbol_Set_Type;
      Next_Symb_Var    : Sparklalr_Symbol.Symbol;
      Token            : Sparklalr_Common.Id_Name;

      procedure Complete_Production
      --# global in     Command_Line_Options.State;
      --#        in out Mem;
      --#        in out Memory_Array;
      --#        in out Prod_Ptr;
      --#        in out SPARK.Ada.Command_Line.State;
      --#        in out SPARK.Ada.Text_IO.The_Standard_Error;
      --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
      --#        in out Sparklalr_Level.State;
      --#        in out Sparklalr_Memory.Prod_No;
      --# derives Mem                                   from *,
      --#                                                    Memory_Array &
      --#         Memory_Array,
      --#         Prod_Ptr                              from *,
      --#                                                    Mem,
      --#                                                    Memory_Array,
      --#                                                    Sparklalr_Memory.Prod_No &
      --#         SPARK.Ada.Command_Line.State,
      --#         SPARK.Ada.Text_IO.The_Standard_Error,
      --#         Sparklalr_Level.State,
      --#         Sparklalr_Memory.Prod_No              from *,
      --#                                                    Sparklalr_Memory.Prod_No &
      --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
      --#                                                    Command_Line_Options.State,
      --#                                                    Mem,
      --#                                                    Memory_Array,
      --#                                                    Sparklalr_Memory.Prod_No;
      is
      begin
         Stack (-Sparklalr_Memory.Prod_No);
         if Sparklalr_Memory.Prod_No < Sparklalr_Common.Prod_Lim then
            Sparklalr_Memory.Set_Prod_No (Sparklalr_Memory.Prod_No + 1);
            Prod_Ptr (Sparklalr_Memory.Prod_No) := Mem;
            Sparklalr_Level.Initiate_Level (Sparklalr_Memory.Prod_No);
         else
            SPARK.Ada.Text_IO.Put_Error (Item => "Production limit exceeded");
            SPARK.Ada.Command_Line.Set_Exit_Status (SPARK.Ada.Command_Line.Failure);
         end if;
      end Complete_Production;

      procedure Dup_Lhs
      --# global in     Command_Line_Options.State;
      --#        in     Prod_Ptr;
      --#        in     Sparklalr_Memory.Prod_No;
      --#        in out Mem;
      --#        in out Memory_Array;
      --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
      --# derives Mem                                   from *,
      --#                                                    Memory_Array &
      --#         Memory_Array                          from *,
      --#                                                    Mem,
      --#                                                    Prod_Ptr,
      --#                                                    Sparklalr_Memory.Prod_No &
      --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
      --#                                                    Command_Line_Options.State,
      --#                                                    Mem,
      --#                                                    Memory_Array,
      --#                                                    Prod_Ptr,
      --#                                                    Sparklalr_Memory.Prod_No;
      is
         It : Integer;
      begin
         It := Memory_Array.The_Array (Memory_Array.The_Array (Prod_Ptr (Sparklalr_Memory.Prod_No - 1)).Ptr).Contents;
         Stack (It);
      end Dup_Lhs;

      procedure Rhs_Element
        (Symb       : in     Sparklalr_Symbol.Symbol;
         F          : in out SPARK.Ada.Text_IO.File_Type;
         Gram_Rules : in     Boolean;
         Token      : in     Sparklalr_Common.Id_Name;
         Col        : in     Sparklalr_Error.Err_Col_T)
      --# global in     Command_Line_Options.State;
      --#        in     Sparklalr_Memory.Prod_No;
      --#        in out Mem;
      --#        in out Memory_Array;
      --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
      --#        in out Sparklalr_Error.State;
      --#        in out Sparklalr_Level.State;
      --#        in out Symbols_Dump.State;
      --# derives F,
      --#         Symbols_Dump.State                    from *,
      --#                                                    Symb,
      --#                                                    Symbols_Dump.State,
      --#                                                    Token &
      --#         Mem                                   from *,
      --#                                                    Memory_Array &
      --#         Memory_Array                          from *,
      --#                                                    Mem,
      --#                                                    Symb,
      --#                                                    Symbols_Dump.State,
      --#                                                    Token &
      --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
      --#                                                    Command_Line_Options.State,
      --#                                                    Mem,
      --#                                                    Memory_Array,
      --#                                                    Symb,
      --#                                                    Symbols_Dump.State,
      --#                                                    Token &
      --#         Sparklalr_Error.State                 from *,
      --#                                                    Col,
      --#                                                    Symb,
      --#                                                    Symbols_Dump.State,
      --#                                                    Token &
      --#         Sparklalr_Level.State                 from *,
      --#                                                    Gram_Rules,
      --#                                                    Mem,
      --#                                                    Memory_Array,
      --#                                                    Sparklalr_Memory.Prod_No,
      --#                                                    Symb,
      --#                                                    Symbols_Dump.State,
      --#                                                    Token;
      is
         Result_Find : Integer;
      begin
         Symbols_Dump.Find (Symb = Sparklalr_Symbol.Ident, F, Gram_Rules, Token, Col, Result_Find);
         Stack (Result_Find);
         if (Symb = Sparklalr_Symbol.Lit) or else (Memory_Array.The_Array (Mem).Contents < Sparklalr_Common.Nt_Base) then
            Sparklalr_Level.Assign_Level
              (Sparklalr_Memory.Prod_No,
               Sparklalr_Level.Get_Term_Lev (Memory_Array.The_Array (Mem).Contents));
         end if;
      end Rhs_Element;

      -- Precedence definitions should not be used in a grammar file for SPARKLALR
      procedure Term_Precedence
        (F          : in out SPARK.Ada.Text_IO.File_Type;
         Gram_Rules : in     Boolean;
         Col        : in out Sparklalr_Error.Err_Col_T)
      --# global in     Sparklalr_Char_Class.Charmap;
      --#        in     Sparklalr_Memory.Prod_No;
      --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
      --#        in out Sparklalr_Error.State;
      --#        in out Sparklalr_Input.State;
      --#        in out Sparklalr_Level.State;
      --#        in out Symbols_Dump.State;
      --# derives Col,
      --#         SPARK.Ada.Text_IO.The_Standard_Output,
      --#         Sparklalr_Input.State,
      --#         Symbols_Dump.State                    from *,
      --#                                                    Col,
      --#                                                    Sparklalr_Char_Class.Charmap,
      --#                                                    Sparklalr_Error.State,
      --#                                                    Sparklalr_Input.State &
      --#         F,
      --#         Sparklalr_Error.State                 from *,
      --#                                                    Col,
      --#                                                    Sparklalr_Char_Class.Charmap,
      --#                                                    Sparklalr_Error.State,
      --#                                                    Sparklalr_Input.State,
      --#                                                    Symbols_Dump.State &
      --#         Sparklalr_Level.State                 from *,
      --#                                                    Col,
      --#                                                    Gram_Rules,
      --#                                                    Sparklalr_Char_Class.Charmap,
      --#                                                    Sparklalr_Error.State,
      --#                                                    Sparklalr_Input.State,
      --#                                                    Sparklalr_Memory.Prod_No,
      --#                                                    Symbols_Dump.State;
      is
         Dummy : Integer;
         Symb  : Sparklalr_Symbol.Symbol;
         Token : Sparklalr_Common.Id_Name;
      begin
         Sparklalr_Input.Scan (F, Col, Symb, Token);
         if Symb = Sparklalr_Symbol.Ident then
            Symbols_Dump.Find (True, F, Gram_Rules, Token, Col, Dummy);
            if Dummy >= Sparklalr_Common.Nt_Base then
               Sparklalr_Error.Syn_Error (13, Col);
            else
               Sparklalr_Level.Assign_Level (Sparklalr_Memory.Prod_No, Sparklalr_Level.Get_Term_Lev (Dummy));
            end if;
         else
            Sparklalr_Error.Syn_Error (12, Col);
         end if;
      end Term_Precedence;

   begin -- Rhs_Process
      if Symb = Sparklalr_Symbol.Uparrow then
         Dup_Lhs;
      end if;
      Sparklalr_Input.Scan (F, Col, Symb, Token);
      Next_Symb_Var := Symb;
      while (Next_Symb_Var = Sparklalr_Symbol.Ident) or else (Next_Symb_Var = Sparklalr_Symbol.Lit) loop
         Rhs_Element (Symb, F, Gram_Rules, Token, Col);
         Sparklalr_Input.Scan (F, Col, Symb, Token);
         Next_Symb_Var := Symb;
      end loop;
      if Symb = Sparklalr_Symbol.Prec then
         Term_Precedence (F, Gram_Rules, Col);
         --# accept F, 10, Token, "Ineffective assignment here expected and OK";
         Sparklalr_Input.Scan (F, Col, Symb, Token);
         --# end accept;
      end if;
      if Symb = Sparklalr_Symbol.Equals then
         if Act_Open and then Command_Line_Options.Get_Parser then
            Sparklalr_Input.Copy_Action (Action, F, Signpost, Col, Symb);
         else
            Sparklalr_Input.Skip_Action (F, Signpost, Col, Symb);
         end if;
      end if;
      if (Symb = Sparklalr_Symbol.Scolon)
        or else (Symb = Sparklalr_Symbol.Uparrow)
        or else (Symb = Sparklalr_Symbol.Ampmark) then
         Complete_Production;
      else
         Sparklalr_Error.Syn_Error (5, Col);
         Symbolset_Skipto := Sparklalr_Input.Signpost_To_Symbol_Set_Type (Signpost);
         Sparklalr_Input.Set_Symbol_Set (Symbolset_Skipto, Sparklalr_Symbol.Scolon, True);
         Sparklalr_Input.Set_Symbol_Set (Symbolset_Skipto, Sparklalr_Symbol.Uparrow, True);
         Sparklalr_Input.Skipto (F, Symbolset_Skipto, Col, Symb);
      end if;
   end Rhs_Process;

   procedure Lhs_Process
     (F          : in out SPARK.Ada.Text_IO.File_Type;
      Gram_Rules : in     Boolean;
      Token      : in     Sparklalr_Common.Id_Name;
      Col        : in     Sparklalr_Error.Err_Col_T)
   --# global in     Command_Line_Options.State;
   --#        in out Mem;
   --#        in out Memory_Array;
   --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
   --#        in out Sparklalr_Error.State;
   --#        in out Sparklalr_Level.State;
   --#        in out Symbols_Dump.State;
   --# derives F,
   --#         Symbols_Dump.State                    from *,
   --#                                                    Symbols_Dump.State,
   --#                                                    Token &
   --#         Mem                                   from *,
   --#                                                    Memory_Array &
   --#         Memory_Array                          from *,
   --#                                                    Mem,
   --#                                                    Symbols_Dump.State,
   --#                                                    Token &
   --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
   --#                                                    Command_Line_Options.State,
   --#                                                    Mem,
   --#                                                    Memory_Array,
   --#                                                    Symbols_Dump.State,
   --#                                                    Token &
   --#         Sparklalr_Error.State                 from *,
   --#                                                    Col,
   --#                                                    Mem,
   --#                                                    Memory_Array,
   --#                                                    Symbols_Dump.State,
   --#                                                    Token &
   --#         Sparklalr_Level.State                 from *,
   --#                                                    Gram_Rules,
   --#                                                    Symbols_Dump.State,
   --#                                                    Token;
   is
      Result_Find : Integer;
   begin
      Symbols_Dump.Find (True, F, Gram_Rules, Token, Col, Result_Find);
      Stack (Result_Find);
      if Memory_Array.The_Array (Mem).Contents < Sparklalr_Common.Nt_Base then
         Sparklalr_Error.Syn_Error (14, Col);
      end if;
   end Lhs_Process;

   procedure State_Generation (F : in out SPARK.Ada.Text_IO.File_Type)
   -- GENERATES COLLECTIONS OF ACCESSIBLE SETS OF ITEMS
   --# global in     Command_Line_Options.State;
   --#        in     Memo;
   --#        in     Ntrdn;
   --#        in     Prod_Ptr;
   --#        in     Sparklalr_Memory.Prod_No;
   --#        in     Symbols_Dump.State;
   --#        in out Empty;
   --#        in out First_Var;
   --#        in out Free_List;
   --#        in out Item_Array;
   --#        in out Look_Array;
   --#        in out Look_Tree;
   --#        in out Mem;
   --#        in out Memory_Array;
   --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
   --#        in out Sparklalr_Error.State;
   --#        in out Sparklalr_Goto.State;
   --#        in out Sparklalr_Parser.State;
   --#           out Release_Point;
   --#           out Sparklalr_Memory.Stat_No;
   --#           out State_Var;
   --# derives Empty                                 from *,
   --#                                                    Memory_Array,
   --#                                                    Prod_Ptr,
   --#                                                    Sparklalr_Memory.Prod_No &
   --#         F,
   --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
   --#                                                    Command_Line_Options.State,
   --#                                                    Empty,
   --#                                                    First_Var,
   --#                                                    Free_List,
   --#                                                    Item_Array,
   --#                                                    Look_Array,
   --#                                                    Look_Tree,
   --#                                                    Mem,
   --#                                                    Memo,
   --#                                                    Memory_Array,
   --#                                                    Ntrdn,
   --#                                                    Prod_Ptr,
   --#                                                    Sparklalr_Goto.State,
   --#                                                    Sparklalr_Memory.Prod_No,
   --#                                                    Sparklalr_Parser.State,
   --#                                                    Symbols_Dump.State &
   --#         First_Var                             from *,
   --#                                                    Empty,
   --#                                                    Look_Array,
   --#                                                    Look_Tree,
   --#                                                    Memory_Array,
   --#                                                    Ntrdn,
   --#                                                    Prod_Ptr,
   --#                                                    Sparklalr_Memory.Prod_No,
   --#                                                    Symbols_Dump.State &
   --#         Free_List,
   --#         Item_Array,
   --#         Look_Array,
   --#         Look_Tree,
   --#         Mem,
   --#         Memory_Array,
   --#         Release_Point,
   --#         Sparklalr_Goto.State,
   --#         Sparklalr_Memory.Stat_No,
   --#         Sparklalr_Parser.State,
   --#         State_Var                             from Empty,
   --#                                                    First_Var,
   --#                                                    Free_List,
   --#                                                    Item_Array,
   --#                                                    Look_Array,
   --#                                                    Look_Tree,
   --#                                                    Mem,
   --#                                                    Memo,
   --#                                                    Memory_Array,
   --#                                                    Ntrdn,
   --#                                                    Prod_Ptr,
   --#                                                    Sparklalr_Goto.State,
   --#                                                    Sparklalr_Memory.Prod_No,
   --#                                                    Sparklalr_Parser.State,
   --#                                                    Symbols_Dump.State &
   --#         Sparklalr_Error.State                 from *,
   --#                                                    Empty,
   --#                                                    First_Var,
   --#                                                    Free_List,
   --#                                                    Item_Array,
   --#                                                    Look_Array,
   --#                                                    Look_Tree,
   --#                                                    Mem,
   --#                                                    Memo,
   --#                                                    Memory_Array,
   --#                                                    Ntrdn,
   --#                                                    Prod_Ptr,
   --#                                                    Sparklalr_Goto.State,
   --#                                                    Sparklalr_Memory.Prod_No,
   --#                                                    Sparklalr_Parser.State,
   --#                                                    Symbols_Dump.State;
   is

      type State_Changed_T is array (Sparklalr_Common.State_Range) of Boolean;
      type State_Hash_T is array (Sparklalr_Common.State_Range) of Sparklalr_Common.State_Range;
      subtype Set_Size_Elem is Natural range 0 .. 4095;
      type Set_Size_T is array (Sparklalr_Common.State_Range) of Set_Size_Elem;

      S, A                : Pt_Memory;
      Max_State           : Sparklalr_Common.State_Range;
      New_State_Var       : Boolean;
      B                   : Integer;
      Empty_Set           : Boolean;
      Dum                 : Pt_Memory;
      Previous            : Sparklalr_Common.State_Range;
      Changes             : Boolean;
      Result_State_Exists : Boolean;
      Look_Set_Added      : Boolean;
      P                   : Look_Set;
      Set_Size            : Set_Size_T;
      State_Hash          : State_Hash_T;
      Prev_Stat           : Sparklalr_Common.State_Range;
      State_Overflow      : Boolean;
      State_Changed       : State_Changed_T;
      Result_Pa_Search    : Integer;
      Call_Pa_Insert      : Boolean;
      Core                : Pt_Memory;
      Look_Ahead          : Look_Set;
      Pl                  : Sparklalr_Parser.Pt_Pa_Rec;
      I                   : Integer;

      function Set_Of_Term_Inequals (A, B : in Set_Of_Term) return Boolean -- A <= B
      is
         Result : Boolean;
         I      : Integer;
      begin
         Result := True;
         I      := Sparklalr_Common.Term_Range'First;
         while Result and then (I in Sparklalr_Common.Term_Range) loop
            if A (I) and then not B (I) then
               Result := False;
            end if;
            I := I + 1;
         end loop;
         return Result;
      end Set_Of_Term_Inequals;

      procedure Look_Table (S              : in     Set_Of_Term;
                            P              :    out Look_Set;
                            Look_Set_Added : in out Boolean)
      --# global in out Look_Array;
      --#        in out Look_Tree;
      --# derives Look_Array,
      --#         Look_Set_Added from *,
      --#                             Look_Array,
      --#                             Look_Tree,
      --#                             S &
      --#         Look_Tree      from *,
      --#                             Look_Array &
      --#         P              from Look_Array,
      --#                             Look_Tree,
      --#                             S;
      is

         T : Look_Set;

         procedure New_Look (S : in     Set_Of_Term;
                             T :    out Look_Set)
         --# global in out Look_Array;
         --# derives Look_Array from *,
         --#                         S &
         --#         T          from Look_Array;
         is
         begin
            Look_Array.Top           := Look_Array.Top + 1;
            T                        := Look_Array.Top;
            Look_Array.The_Array (T) := Look_Item'(Lset  => S,
                                                   Litem => 0,
                                                   Ritem => 0);
         end New_Look;

      begin
         P := Look_Tree;
         if P /= 0 then
            while Look_Array.The_Array (P).Lset /= S loop
               if Set_Of_Term_Inequals (Look_Array.The_Array (P).Lset, S) then
                  if Look_Array.The_Array (P).Ritem = 0 then
                     New_Look (S, T);
                     Look_Set_Added                 := True;
                     Look_Array.The_Array (P).Ritem := T;
                  end if;
                  P := Look_Array.The_Array (P).Ritem;
               else
                  if Look_Array.The_Array (P).Litem = 0 then
                     New_Look (S, T);
                     Look_Set_Added                 := True;
                     Look_Array.The_Array (P).Litem := T;
                  end if;
                  P := Look_Array.The_Array (P).Litem;
               end if;
            end loop;
         else
            New_Look (S, T);
            Look_Set_Added := True;
            Look_Tree      := T;
            P              := Look_Tree;
         end if;
      end Look_Table;

      procedure Eff (F : in out SPARK.Ada.Text_IO.File_Type)
      -- DETERMINES WHETHER A NONTERMINAL CAN PRODUCE THE EMPTY SYMBOL
      --# global in     Command_Line_Options.State;
      --#        in     Memory_Array;
      --#        in     Ntrdn;
      --#        in     Prod_Ptr;
      --#        in     Sparklalr_Memory.Prod_No;
      --#        in     Symbols_Dump.State;
      --#        in out Empty;
      --#        in out First_Var;
      --#        in out Look_Array;
      --#        in out Look_Tree;
      --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
      --# derives Empty                                 from *,
      --#                                                    Memory_Array,
      --#                                                    Prod_Ptr,
      --#                                                    Sparklalr_Memory.Prod_No &
      --#         F,
      --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
      --#                                                    Command_Line_Options.State,
      --#                                                    Empty,
      --#                                                    Memory_Array,
      --#                                                    Ntrdn,
      --#                                                    Prod_Ptr,
      --#                                                    Sparklalr_Memory.Prod_No,
      --#                                                    Symbols_Dump.State &
      --#         First_Var,
      --#         Look_Array,
      --#         Look_Tree                             from *,
      --#                                                    Empty,
      --#                                                    Look_Array,
      --#                                                    Look_Tree,
      --#                                                    Memory_Array,
      --#                                                    Ntrdn,
      --#                                                    Prod_Ptr,
      --#                                                    Sparklalr_Memory.Prod_No,
      --#                                                    Symbols_Dump.State;
      is

         type Temp_First_T is array (Sparklalr_Common.Non_Term_Range) of Set_Of_Term;

         C                 : Integer;
         Changes, Continue : Boolean;
         P, S, T           : Pt_Memory;
         Temp_First        : Temp_First_T;
         Posn              : Integer;
         Look_Set_Added    : Boolean;

         procedure Findemptyredns
         -- FINDS THOSE PRODUCTIONS WHICH CAN PRODUCE THE EMPTY SYMBOL
         --# global in     Memory_Array;
         --#        in     Prod_Ptr;
         --#        in     Sparklalr_Memory.Prod_No;
         --#        in out Empty;
         --# derives Empty from *,
         --#                    Memory_Array,
         --#                    Prod_Ptr,
         --#                    Sparklalr_Memory.Prod_No;
         is
            I                         : Integer;
            P                         : Pt_Memory;
            Finished, Closed, Keep_On : Boolean;
         begin
            for J in Integer range 2 .. Sparklalr_Memory.Prod_No - 1 loop
               if Memory_Array.The_Array (Memory_Array.The_Array (Memory_Array.The_Array (Prod_Ptr (J)).Ptr).Ptr).Contents <
                 0 then
                  Empty (Memory_Array.The_Array (Memory_Array.The_Array (Prod_Ptr (J)).Ptr).Contents - Sparklalr_Common.Nt_Base) :=
                    True;
               end if;
            end loop;
            -- NOW DETERMINE CLOSURE OF ALL EMPTY REDUCTIONS
            Closed := False;
            while not Closed loop
               Keep_On := True;
               I       := 2;
               while Keep_On and then (I <= Sparklalr_Memory.Prod_No - 1) loop
                  if not Empty (Memory_Array.The_Array (Memory_Array.The_Array (Prod_Ptr (I)).Ptr).Contents -
                                  Sparklalr_Common.Nt_Base) then
                     P        := Memory_Array.The_Array (Memory_Array.The_Array (Prod_Ptr (I)).Ptr).Ptr;
                     Finished := False;
                     while (Memory_Array.The_Array (P).Contents > Sparklalr_Common.Nt_Base) and then not Finished loop
                        if Empty (Memory_Array.The_Array (P).Contents - Sparklalr_Common.Nt_Base) then
                           P := Memory_Array.The_Array (P).Ptr;
                        else
                           Finished := True;
                        end if;
                     end loop;
                     if Memory_Array.The_Array (P).Contents < 0 then
                        Empty (Memory_Array.The_Array (Memory_Array.The_Array (Prod_Ptr (I)).Ptr).Contents -
                                 Sparklalr_Common.Nt_Base) := True;
                        Keep_On := False;
                     end if;
                  end if;
                  I := I + 1;
               end loop;
               if I >= Sparklalr_Memory.Prod_No - 1 then
                  Closed := True;
               end if;
            end loop;
         end Findemptyredns;

      begin -- Eff
         Temp_First := Temp_First_T'(others => Set_Of_Term_False_Const);
         Findemptyredns;
         for I in Integer range 1 .. Symbols_Dump.Get_Nnon_Terms loop
            T := Ntrdn (I + 1);
            S := Ntrdn (I);
            while S /= T loop
               P        := Memory_Array.The_Array (Memory_Array.The_Array (S).Mem_Pt).Ptr;
               Continue := True;
               while (Memory_Array.The_Array (P).Contents > 0) and then Continue loop
                  C := Memory_Array.The_Array (P).Contents;
                  if C < Sparklalr_Common.Nt_Base then
                     Temp_First (I) (C)  := True;
                     Continue            := False;
                  else
                     if not Empty (C - Sparklalr_Common.Nt_Base) then
                        Continue := False;
                     else
                        P := Memory_Array.The_Array (P).Ptr;
                     end if;
                  end if;
               end loop;
               S := Memory_Array.The_Array (S).Ptr;
            end loop;
         end loop;
         -- NOW  REFLECT TRANSITIVITY
         Changes := True;
         while Changes loop
            Changes := False;
            for I in Integer range 1 .. Symbols_Dump.Get_Nnon_Terms loop
               T := Ntrdn (I + 1);
               S := Ntrdn (I);
               while S /= T loop
                  Continue := True;
                  P        := Memory_Array.The_Array (Memory_Array.The_Array (S).Mem_Pt).Ptr;
                  C        := Memory_Array.The_Array (P).Contents;
                  while (C > Sparklalr_Common.Nt_Base) and then Continue loop
                     Changes := Changes
                       or else not (Set_Of_Term_Inequals (Temp_First (C - Sparklalr_Common.Nt_Base), Temp_First (I)));
                     if Changes then
                        Temp_First (I) := Temp_First (I) or Temp_First (C - Sparklalr_Common.Nt_Base);
                     end if;
                     if not Empty (C - Sparklalr_Common.Nt_Base) then
                        Continue := False;
                     else
                        P := Memory_Array.The_Array (P).Ptr;
                        C := Memory_Array.The_Array (P).Contents;
                     end if;
                  end loop;
                  S := Memory_Array.The_Array (S).Ptr;
               end loop;
            end loop;
         end loop;
         if Command_Line_Options.Get_Debug_Level (8) then
            Posn := 1;
            for I in Integer range 1 .. Symbols_Dump.Get_Nnon_Terms loop
               SPARK.Ada.Text_IO.Put_Output (Item => " EFF (");
               SPARK.Ada.Text_IO.Put_Output (Item => Symbols_Dump.Get_Nterm_Set (I));
               SPARK.Ada.Text_IO.Put_Output (Item => ") = [");
               Posn := Posn + 16;
               for J in Integer range 0 .. Symbols_Dump.Get_Nterms loop
                  if Temp_First (I) (J) then
                     Sparklalr_Common.Print
                       (Std_Out => True,
                        F       => F,
                        String1 => Symbols_Dump.Get_Term_Set (J),
                        Posn    => Posn,
                        Tab     => 17,
                        Comm    => False);
                  end if;
               end loop;
               SPARK.Ada.Text_IO.Put_Line_Output (Item => " ]");
               Posn := 1;
            end loop;
         end if;
         if Command_Line_Options.Get_Debug_Level (9) then
            for I in Integer range 1 .. Symbols_Dump.Get_Nnon_Terms loop
               SPARK.Ada.Text_IO.Put_Output (Item => " EMPTY : ");
               SPARK.Ada.Text_IO.Put_Output (Item => Symbols_Dump.Get_Nterm_Set (I));
               SPARK.Ada.Text_IO.Put_Character_Output (Item => ' ');
               if Empty (I) then
                  SPARK.Ada.Text_IO.Put_Line_Output (Item => " EMPTY");
               else
                  SPARK.Ada.Text_IO.Put_Line_Output (Item => " NONEMPTY");
               end if;
            end loop;
         end if;
         for I in Integer range 1 .. Symbols_Dump.Get_Nnon_Terms loop
            --# accept F, 10, Look_Set_Added, "Ineffective assignment here expected and OK" &
            --#        F, 10, "Unused variable Look_Set_Added";
            Look_Set_Added := False;
            Look_Table (Temp_First (I), First_Var (I), Look_Set_Added);
            --# end accept;
         end loop;
      end Eff;

      procedure Mark
      --# global in     Mem;
      --#           out Release_Point;
      --# derives Release_Point from Mem;
      is
      begin
         Release_Point := Mem;
      end Mark;

      procedure Stack_Item (F          : in out SPARK.Ada.Text_IO.File_Type;
                            Core       : in     Pt_Memory;
                            Look_Ahead : in     Look_Set)
      -- ADDS AN ITEM TO THE TOP OF MEMORY
      --# global in     Command_Line_Options.State;
      --#        in     Look_Array;
      --#        in     Symbols_Dump.State;
      --#        in out Free_List;
      --#        in out Item_Array;
      --#        in out Mem;
      --#        in out Memory_Array;
      --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
      --# derives F,
      --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
      --#                                                    Command_Line_Options.State,
      --#                                                    Core,
      --#                                                    Free_List,
      --#                                                    Item_Array,
      --#                                                    Look_Ahead,
      --#                                                    Look_Array,
      --#                                                    Mem,
      --#                                                    Memory_Array,
      --#                                                    Symbols_Dump.State &
      --#         Free_List,
      --#         Mem                                   from Free_List,
      --#                                                    Memory_Array &
      --#         Item_Array                            from *,
      --#                                                    Core,
      --#                                                    Free_List,
      --#                                                    Look_Ahead,
      --#                                                    Memory_Array &
      --#         Memory_Array                          from *,
      --#                                                    Free_List,
      --#                                                    Item_Array,
      --#                                                    Mem;
      is
         M    : Pt_Memory;
         L    : Look_Set;
         Posn : Integer;
      begin
         if Free_List /= 0 then
            M         := Free_List;
            Free_List := Memory_Array.The_Array (Free_List).Ptr;
         else
            Memory_Array.Top               := Memory_Array.Top + 1;
            M                              := Memory_Array.Top;
            Memory_Array.The_Array (M).Tag := 2;
            Item_Array.Top                 := Item_Array.Top + 1;
            Memory_Array.The_Array (M).Itm := Item_Array.Top;
         end if;
         Item_Array.The_Array (Memory_Array.The_Array (M).Itm) := Item'(Dot => Core,
                                                                        Lh  => Look_Ahead);
         Memory_Array.The_Array (Mem).Ptr                      := M;
         Memory_Array.The_Array (M).Ptr                        := 0;
         Mem                                                   := M;

         --# assert True;

         if Command_Line_Options.Get_Debug_Level (3) then
            Posn := 1;
            if Memory_Array.The_Array (M).Itm /= 0 then
               SPARK.Ada.Text_IO.Put_Output (Item => " STACKITEM : , MEM = ");
               Posn := Posn + 27;
            end if;
            if Mem /= 0 then
               SPARK.Ada.Text_IO.Put_Character_Output (Item => ' ');
               Posn := Posn + 6;
            end if;
            if (Memory_Array.The_Array (M).Itm /= 0) then
               if Item_Array.The_Array (Memory_Array.The_Array (M).Itm).Dot /= 0 then
                  SPARK.Ada.Text_IO.Put_Output (Item => " ,DOT = ");
                  SPARK.Ada.Text_IO.Put_Output (Item => " , LOOKAHEAD = [");
                  Posn := Posn + 30;
                  L    := Item_Array.The_Array (Memory_Array.The_Array (M).Itm).Lh;
                  for I in Integer range 0 .. Symbols_Dump.Get_Nterms loop
                     if Look_Array.The_Array (L).Lset (I) then
                        Sparklalr_Common.Print
                          (Std_Out => True,
                           F       => F,
                           String1 => Symbols_Dump.Get_Term_Set (I),
                           Posn    => Posn,
                           Tab     => 3,
                           Comm    => False);
                     end if;
                  end loop;
                  SPARK.Ada.Text_IO.Put_Line_Output (Item => "]");
               end if;
            end if;
         end if;
      end Stack_Item;

      procedure Close (F      : in out SPARK.Ada.Text_IO.File_Type;
                       Nstate : in     Integer)
      -- CLOSES A SET OF ITEMS
      --# global in     Command_Line_Options.State;
      --#        in     Empty;
      --#        in     First_Var;
      --#        in     Ntrdn;
      --#        in     State_Var;
      --#        in     Symbols_Dump.State;
      --#        in out Free_List;
      --#        in out Item_Array;
      --#        in out Look_Array;
      --#        in out Look_Tree;
      --#        in out Mem;
      --#        in out Memory_Array;
      --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
      --# derives F,
      --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
      --#                                                    Command_Line_Options.State,
      --#                                                    Empty,
      --#                                                    First_Var,
      --#                                                    Free_List,
      --#                                                    Item_Array,
      --#                                                    Look_Array,
      --#                                                    Look_Tree,
      --#                                                    Mem,
      --#                                                    Memory_Array,
      --#                                                    Nstate,
      --#                                                    Ntrdn,
      --#                                                    State_Var,
      --#                                                    Symbols_Dump.State &
      --#         Free_List,
      --#         Item_Array,
      --#         Look_Array,
      --#         Look_Tree,
      --#         Mem,
      --#         Memory_Array                          from Empty,
      --#                                                    First_Var,
      --#                                                    Free_List,
      --#                                                    Item_Array,
      --#                                                    Look_Array,
      --#                                                    Look_Tree,
      --#                                                    Mem,
      --#                                                    Memory_Array,
      --#                                                    Nstate,
      --#                                                    Ntrdn,
      --#                                                    State_Var;
      is

         P, Q, S, A, C  : Pt_Memory;
         Lasts          : Pt_Memory;
         Temp_Item      : Item;
         Temp_Set       : Set_Of_Term;
         B              : Integer;
         Dummy          : Pt_Memory;
         End_Search     : Boolean;
         Not_Found      : Boolean;
         Look_Set_Added : Boolean;

         procedure New_Item
           (Nstate         : in     Integer;
            Temp_Item      : in     Item;
            Not_Found      :    out Boolean;
            Look_Set_Added : in out Boolean)
         -- DETERMINES WHETHER AN ITEM ALREADY EXISTS IN THE STATE "NSTATE"
         -- IF IT EXISTS THE LOOKAHEAD SETS ARE UNITED
         --# global in     Memory_Array;
         --#        in     State_Var;
         --#        in out Item_Array;
         --#        in out Look_Array;
         --#        in out Look_Tree;
         --# derives Item_Array,
         --#         Look_Array,
         --#         Look_Set_Added,
         --#         Look_Tree      from *,
         --#                             Item_Array,
         --#                             Look_Array,
         --#                             Look_Tree,
         --#                             Memory_Array,
         --#                             Nstate,
         --#                             State_Var,
         --#                             Temp_Item &
         --#         Not_Found      from Item_Array,
         --#                             Look_Array,
         --#                             Look_Tree,
         --#                             Memory_Array,
         --#                             Nstate,
         --#                             State_Var,
         --#                             Temp_Item;
         is
            S, Lasts : Pt_Memory;
            Found    : Boolean;
         begin
            S     := State_Var (Nstate);
            Lasts := State_Var (Nstate + 1);
            Found := False;
            loop
               if Temp_Item.Dot = Item_Array.The_Array (Memory_Array.The_Array (S).Itm).Dot then
                  Found := True;
                  Look_Table
                    (Look_Array.The_Array (Item_Array.The_Array (Memory_Array.The_Array (S).Itm).Lh).Lset or
                       Look_Array.The_Array (Temp_Item.Lh).Lset,
                     Item_Array.The_Array (Memory_Array.The_Array (S).Itm).Lh,
                     Look_Set_Added);
               else
                  S := Memory_Array.The_Array (S).Ptr;
               end if;
               exit when Found or else (S = Lasts);
            end loop;
            Not_Found := not Found;
         end New_Item;

      begin
         loop
            Look_Set_Added := False;
            S              := State_Var (Nstate);
            Lasts          := State_Var (Nstate + 1);
            while S /= Lasts loop
               A := Item_Array.The_Array (Memory_Array.The_Array (S).Itm).Dot;
               B := Memory_Array.The_Array (A).Contents;
               if B > Sparklalr_Common.Nt_Base then
                  P := Ntrdn (B - Sparklalr_Common.Nt_Base);
                  Q := Ntrdn ((B - Sparklalr_Common.Nt_Base) + 1);
                  while P /= Q loop
                     C             := Memory_Array.The_Array (Memory_Array.The_Array (P).Mem_Pt).Ptr;
                     Temp_Item.Dot := C;
                     Temp_Set      := Set_Of_Term'(others => False);
                     Dummy         := A;
                     loop
                        Dummy := Memory_Array.The_Array (Dummy).Ptr;
                        if Memory_Array.The_Array (Dummy).Contents > Sparklalr_Common.Nt_Base then
                           Temp_Set   := Temp_Set or
                             Look_Array.The_Array (First_Var (Memory_Array.The_Array (Dummy).Contents -
                                                                Sparklalr_Common.Nt_Base)).Lset;
                           End_Search := not Empty (Memory_Array.The_Array (Dummy).Contents - Sparklalr_Common.Nt_Base);
                        else
                           if Memory_Array.The_Array (Dummy).Contents > 0 then
                              Temp_Set (Memory_Array.The_Array (Dummy).Contents) := True;
                              End_Search                                         := True;
                           else
                              Temp_Set   := Temp_Set or
                                Look_Array.The_Array (Item_Array.The_Array (Memory_Array.The_Array (S).Itm).Lh).Lset;
                              End_Search := True;
                           end if;
                        end if;
                        exit when End_Search;
                     end loop;
                     Look_Table (Temp_Set, Temp_Item.Lh, Look_Set_Added);
                     New_Item (Nstate, Temp_Item, Not_Found, Look_Set_Added);
                     if Not_Found then
                        Stack_Item (F          => F,
                                    Core       => Temp_Item.Dot,
                                    Look_Ahead => Temp_Item.Lh);
                     end if;
                     P := Memory_Array.The_Array (P).Ptr;
                  end loop;
               end if;
               S := Memory_Array.The_Array (S).Ptr;
            end loop;
            exit when not Look_Set_Added;
         end loop;
      end Close;

      procedure Absorb_State (State2  : in     Integer;
                              Changes :    out Boolean)
      -- ABSORBS STATNO INTO STATE2
      --# global in     Release_Point;
      --#        in     Sparklalr_Memory.Stat_No;
      --#        in     State_Var;
      --#        in out Free_List;
      --#        in out Item_Array;
      --#        in out Look_Array;
      --#        in out Look_Tree;
      --#        in out Mem;
      --#        in out Memory_Array;
      --# derives Changes,
      --#         Item_Array,
      --#         Look_Array,
      --#         Look_Tree    from Item_Array,
      --#                           Look_Array,
      --#                           Look_Tree,
      --#                           Memory_Array,
      --#                           Sparklalr_Memory.Stat_No,
      --#                           State2,
      --#                           State_Var &
      --#         Free_List,
      --#         Memory_Array from Free_List,
      --#                           Mem,
      --#                           Memory_Array,
      --#                           Release_Point &
      --#         Mem          from Release_Point;
      is

         Dum1, Dum2     : Pt_Memory;
         Look_Set_Added : Boolean;

         function Diff (Left, Right : in Set_Of_Term) return Set_Of_Term is
            Result : Set_Of_Term;
         begin
            Result := Set_Of_Term_False_Const;
            for I in Sparklalr_Common.Term_Range loop
               if Left (I) then
                  Result (I) := not Right (I);
               else
                  Result (I) := False;
               end if;
            end loop;
            return Result;
         end Diff;

         procedure Release
         --# global in     Release_Point;
         --#        in out Free_List;
         --#        in out Mem;
         --#        in out Memory_Array;
         --# derives Free_List,
         --#         Memory_Array from Free_List,
         --#                           Mem,
         --#                           Memory_Array,
         --#                           Release_Point &
         --#         Mem          from Release_Point;
         is
         begin
            Memory_Array.The_Array (Mem).Ptr := Free_List;
            Free_List                        := Memory_Array.The_Array (Release_Point).Ptr;
            Mem                              := Release_Point;
            Memory_Array.The_Array (Mem).Ptr := 0;
         end Release;

      begin
         Dum1    := State_Var (Sparklalr_Memory.Stat_No);
         Changes := False;
         loop
            Dum2 := State_Var (State2);
            while Item_Array.The_Array (Memory_Array.The_Array (Dum1).Itm).Dot /=
              Item_Array.The_Array (Memory_Array.The_Array (Dum2).Itm).Dot loop
               Dum2 := Memory_Array.The_Array (Dum2).Ptr;
            end loop;
            if Diff
              (Look_Array.The_Array (Item_Array.The_Array (Memory_Array.The_Array (Dum1).Itm).Lh).Lset,
               Look_Array.The_Array (Item_Array.The_Array (Memory_Array.The_Array (Dum2).Itm).Lh).Lset) /=
              Set_Of_Term_False_Const then
               Changes := True;
               --# accept F, 10, Look_Set_Added, "Ineffective assignment here expected and OK" &
               --#        F, 10, "Unused variable Look_Set_Added";
               Look_Set_Added := False;
               Look_Table
                 (Look_Array.The_Array (Item_Array.The_Array (Memory_Array.The_Array (Dum2).Itm).Lh).Lset or
                    Look_Array.The_Array (Item_Array.The_Array (Memory_Array.The_Array (Dum1).Itm).Lh).Lset,
                  Item_Array.The_Array (Memory_Array.The_Array (Dum2).Itm).Lh,
                  Look_Set_Added);
               --# end accept;
            end if;
            Dum1 := Memory_Array.The_Array (Dum1).Ptr;
            exit when Dum1 = 0;
         end loop;
         Release;
      end Absorb_State;

      procedure State_Exists
        (Sno            : in     Integer;
         Super_State    :    out Sparklalr_Common.State_Range;
         Result         :    out Boolean;
         Set_Size       : in     Set_Size_T;
         State_Hash     : in out State_Hash_T;
         State_Overflow : in out Boolean)
      -- DETERMINES WHETHER THE CORES OF THE CURRENT SET OF ITEMS
      -- IS EQUIVALENT TO THE CORES OF AN EXISTING SET
      --# global in     Item_Array;
      --#        in     Memory_Array;
      --#        in     Sparklalr_Memory.Stat_No;
      --#        in     State_Var;
      --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
      --# derives Result,
      --#         Super_State                           from Item_Array,
      --#                                                    Memory_Array,
      --#                                                    Set_Size,
      --#                                                    Sno,
      --#                                                    State_Hash,
      --#                                                    State_Var &
      --#         SPARK.Ada.Text_IO.The_Standard_Output,
      --#         State_Overflow                        from *,
      --#                                                    Item_Array,
      --#                                                    Memory_Array,
      --#                                                    Set_Size,
      --#                                                    Sno,
      --#                                                    State_Hash,
      --#                                                    State_Var &
      --#         State_Hash                            from *,
      --#                                                    Item_Array,
      --#                                                    Memory_Array,
      --#                                                    Set_Size,
      --#                                                    Sno,
      --#                                                    Sparklalr_Memory.Stat_No,
      --#                                                    State_Overflow,
      --#                                                    State_Var;
      is

         Test_State              : Integer;
         State_Found, Item_Found : Boolean;
         Dum1, Dum2              : Pt_Memory;
         I, N                    : Integer;
         H, D                    : Integer;

         function Hash_Itm (Itm : in Pt_Item) return Integer
         --# global in Item_Array;
         is
            Two_Power18 : constant := 262244;
            Hashcon1    : constant := 8192; -- = HASHCON2 DIV (STATEMAX+1)
            Hashcon2    : constant := 16777216; -- = 100000000B
            Hashcon3    : constant := 2925; -- = 5555B
         begin
            return (((Item_Array.The_Array (Itm).Dot mod Two_Power18) * Hashcon3) mod Hashcon2) / Hashcon1;
         end Hash_Itm;

      begin
         H           := Hash_Itm (Memory_Array.The_Array (State_Var (Sno)).Itm);
         D           := 1;
         Test_State  := State_Hash (H);
         State_Found := False;
         N           := Set_Size (Sno);
         while (Test_State /= 0) and then not State_Found loop
            Item_Found := False;
            if Set_Size (Test_State) = N then
               Dum1 := State_Var (Sno);
               loop
                  Dum2       := State_Var (Test_State);
                  I          := N;
                  Item_Found := False;
                  loop
                     if Item_Array.The_Array (Memory_Array.The_Array (Dum1).Itm).Dot =
                       Item_Array.The_Array (Memory_Array.The_Array (Dum2).Itm).Dot then
                        Item_Found := True;
                     else
                        Dum2 := Memory_Array.The_Array (Dum2).Ptr;
                        I    := I - 1;
                     end if;
                     exit when Item_Found or else (I = 0);
                  end loop;
                  if Item_Found then
                     Dum1 := Memory_Array.The_Array (Dum1).Ptr;
                  end if;
                  exit when (Dum1 = 0) or else not Item_Found;
               end loop;
            end if;
            if Item_Found then
               State_Found := True;
            else
               if D /= Sparklalr_Common.State_Max then
                  H := H + D;
                  D := D + 2;
                  if H > Sparklalr_Common.State_Max then
                     H := (H - Sparklalr_Common.State_Max) - 1;
                  end if;
                  Test_State := State_Hash (H);
               else
                  Test_State := 0;
                  SPARK.Ada.Text_IO.Put_Line_Output (Item => " HASH TABLE OVERFLOW");
                  State_Overflow := True;
               end if;
            end if;
         end loop;
         if not (State_Found or else State_Overflow) then
            State_Hash (H) := Sparklalr_Memory.Stat_No;
         end if;
         Result      := State_Found;
         Super_State := Test_State;
      end State_Exists;

      procedure Next_State (Prev_Stat     : in out Sparklalr_Common.State_Range;
                            State_Changed : in out State_Changed_T)
      --# global in Sparklalr_Memory.Stat_No;
      --# derives Prev_Stat,
      --#         State_Changed from Prev_Stat,
      --#                            Sparklalr_Memory.Stat_No,
      --#                            State_Changed;
      is
         I : Integer;
      begin
         if Prev_Stat /= Sparklalr_Memory.Stat_No then
            I := Prev_Stat + 1;
         else
            I := 1;
         end if;
         while (I /= Prev_Stat) and then not State_Changed (I) loop
            if I /= Sparklalr_Memory.Stat_No then
               I := I + 1;
            else
               I := 1;
            end if;
         end loop;
         if State_Changed (I) then
            Prev_Stat := I;
         else
            Prev_Stat := Sparklalr_Memory.Stat_No + 1;
         end if;
         State_Changed (I) := False;
      end Next_State;

   begin -- State_Generation
      Eff (F => F);
      Sparklalr_Parser.Init_Pa_List;
      State_Var  := State_Var_T'(others => 0);
      State_Hash := State_Hash_T'(others => 0);
      for J in Integer range 1 .. Symbols_Dump.Get_Nnon_Terms loop
         Sparklalr_Goto.Init_Goto_List (J);
      end loop;
      State_Overflow := False;
      -- GENERATE THE FIRST SET
      --# accept F, 10, Look_Set_Added, "Ineffective assignment here expected and OK" &
      --#        F, 10, "Unused variable Look_Set_Added";
      Look_Set_Added := False;
      Look_Table (Set_Of_Term'(0      => True,
                               others => False), P, Look_Set_Added);
      --# end accept;
      Core := Memory_Array.The_Array (Memory_Array.The_Array (Memo).Ptr).Ptr;
      Stack_Item (F          => F,
                  Core       => Core,
                  Look_Ahead => P);
      Set_Size      := Set_Size_T'(others => 0);
      Set_Size (1)  := 1;
      State_Var (1) := Mem;
      Close (F      => F,
             Nstate => 1);
      -- GENERATE THE REMAINING SETS
      State_Changed     := State_Changed_T'(others => False);
      State_Changed (1) := False;
      Prev_Stat         := 1;
      Max_State         := 0;
      Sparklalr_Memory.Set_Stat_No (1);
      loop
         --# assert True;
         New_State_Var := Prev_Stat > Max_State;
         if New_State_Var then
            Max_State := Prev_Stat;
         end if;
         S := State_Var (Prev_Stat);
         I := 1;
         loop
            Mark;
            if I > Symbols_Dump.Get_Nterms then
               B := (Sparklalr_Common.Nt_Base + I) - Symbols_Dump.Get_Nterms;
            else
               B := I;
            end if;
            Dum       := S;
            Empty_Set := True;
            Sparklalr_Memory.Set_Stat_No (Sparklalr_Memory.Stat_No + 1);
            Set_Size (Sparklalr_Memory.Stat_No) := 0;
            loop
               --# assert True;
               A := Item_Array.The_Array (Memory_Array.The_Array (Dum).Itm).Dot;
               if Memory_Array.The_Array (A).Contents = B then
                  Core       := Memory_Array.The_Array (A).Ptr;
                  Look_Ahead := Item_Array.The_Array (Memory_Array.The_Array (Dum).Itm).Lh;
                  Stack_Item (F          => F,
                              Core       => Core,
                              Look_Ahead => Look_Ahead);
                  Set_Size (Sparklalr_Memory.Stat_No) := Set_Size (Sparklalr_Memory.Stat_No) + 1;
                  if Empty_Set then
                     if Command_Line_Options.Get_Debug_Level (7) and then (Mem /= 0) then
                        SPARK.Ada.Text_IO.Put_Output (Item => " STATE: ");
                        SPARK_Ada_Integer_Text_IO.Put_Output (Item  => Sparklalr_Memory.Stat_No + 1,
                                                              Width => 3,
                                                              Base  => 10);
                        SPARK.Ada.Text_IO.Put_Line_Output (Item => " AT ");
                     end if;
                     if Sparklalr_Memory.Stat_No < Sparklalr_Common.State_Max then
                        State_Var (Sparklalr_Memory.Stat_No) := Mem;
                        Empty_Set                            := False;
                     else
                        SPARK.Ada.Text_IO.New_Line_Output (Spacing => 1);
                        SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                                         Spacing => 1);
                        SPARK.Ada.Text_IO.Put_Line_Output (Item => " STATE OVERFLOW");
                        SPARK.Ada.Text_IO.Put_Line_File (File => F,
                                                         Item => " STATE OVERFLOW");
                        State_Overflow := True;
                        Sparklalr_Memory.Set_Stat_No (Sparklalr_Memory.Stat_No - 1);
                     end if;
                  end if;
               end if;
               Dum := Memory_Array.The_Array (Dum).Ptr;
               exit when (Dum = State_Var (Prev_Stat + 1)) or else State_Overflow;
            end loop;

            --# assert True;

            if Empty_Set or else State_Overflow then
               Sparklalr_Memory.Set_Stat_No (Sparklalr_Memory.Stat_No - 1);
            else
               --# accept F, 41, "Stable expression here expected and OK";
               if New_State_Var then
                  State_Exists (Sparklalr_Memory.Stat_No, Previous, Result_State_Exists, Set_Size, State_Hash, State_Overflow);
                  if Result_State_Exists then
                     Absorb_State (Previous, Changes);
                     State_Var (Sparklalr_Memory.Stat_No) := 0;
                     Sparklalr_Memory.Set_Stat_No (Sparklalr_Memory.Stat_No - 1);
                     if Changes then
                        Close (F      => F,
                               Nstate => Previous);
                        State_Changed (Previous) := True;
                     end if;
                     Sparklalr_Goto.Goto_Gen (F, Previous, Prev_Stat, B, Call_Pa_Insert);
                     if Call_Pa_Insert then
                        Sparklalr_Parser.Pa_Insert
                          (F           => F,
                           State_Index => Prev_Stat,
                           Term_Index  => B,
                           Insertion   => Sparklalr_Common.Code (Sparklalr_Common.Shift, Previous));
                     end if;
                  else
                     Close (F      => F,
                            Nstate => Sparklalr_Memory.Stat_No);
                     State_Changed (Sparklalr_Memory.Stat_No) := True;
                     Sparklalr_Goto.Goto_Gen (F, Sparklalr_Memory.Stat_No, Prev_Stat, B, Call_Pa_Insert);
                     if Call_Pa_Insert then
                        Sparklalr_Parser.Pa_Insert
                          (F           => F,
                           State_Index => Prev_Stat,
                           Term_Index  => B,
                           Insertion   => Sparklalr_Common.Code (Sparklalr_Common.Shift, Sparklalr_Memory.Stat_No));
                     end if;
                  end if;
               else
                  if B > Symbols_Dump.Get_Nterms then
                     Previous := Sparklalr_Goto.Goto_Search (Prev_Stat, B);
                  else
                     --# accept F, 10, Pl, "Ineffective assignment here expected and OK";
                     Sparklalr_Parser.Pa_Search (Prev_Stat, B, Result_Pa_Search, Pl);
                     --# end accept;
                     Previous := Sparklalr_Common.Decode (Result_Pa_Search);
                  end if;
                  Absorb_State (Previous, Changes);
                  State_Var (Sparklalr_Memory.Stat_No) := 0;
                  Sparklalr_Memory.Set_Stat_No (Sparklalr_Memory.Stat_No - 1);
                  if Changes then
                     Close (F      => F,
                            Nstate => Previous);
                     State_Changed (Previous) := True;
                  end if;
               end if;
               --# end accept;
            end if;
            I := I + 1;
            exit when (I > Symbols_Dump.Get_Nterms + Symbols_Dump.Get_Nnon_Terms) or else State_Overflow;
         end loop;
         Next_State (Prev_Stat, State_Changed);
         exit when (Prev_Stat > Sparklalr_Memory.Stat_No) or else State_Overflow;
      end loop;
      --# accept F, 10, Look_Set_Added, "Ineffective assignment here expected and OK";
      Look_Table (Set_Of_Term'(others => False), P, Look_Set_Added);
      --# end accept;
      Stack_Item (F          => F,
                  Core       => 0,
                  Look_Ahead => P);
      State_Var (Sparklalr_Memory.Stat_No + 1) := Mem;
      --# accept F, 33, Pl, "Pl is unused OK";
   end State_Generation;

   function Get_Next (Ptr : in Pt_Memory) return Pt_Memory
   --# global in Memory_Array;
   is
   begin
      return Memory_Array.The_Array (Ptr).Ptr;
   end Get_Next;

   function Get_Contents (Ptr : in Pt_Memory) return Contents_T
   --# global in Memory_Array;
   is
   begin
      return Memory_Array.The_Array (Ptr).Contents;
   end Get_Contents;

   function Get_Item (Ptr : in Pt_Memory) return Pt_Item
   --# global in Memory_Array;
   is
   begin
      return Memory_Array.The_Array (Ptr).Itm;
   end Get_Item;

   function Get_Mem_Pt (Ptr : in Pt_Memory) return Pt_Memory
   --# global in Memory_Array;
   is
   begin
      return Memory_Array.The_Array (Ptr).Mem_Pt;
   end Get_Mem_Pt;

   function Get_Dot (Ptr : in Pt_Item) return Pt_Memory
   --# global in Item_Array;
   is
   begin
      return Item_Array.The_Array (Ptr).Dot;
   end Get_Dot;

   function Get_Lh_Lset (Ptr : in Pt_Item;
                         I   : in Sparklalr_Common.Term_Range) return Boolean
   --# global in Item_Array;
   --#        in Look_Array;
   is
   begin
      return Look_Array.The_Array (Item_Array.The_Array (Ptr).Lh).Lset (I);
   end Get_Lh_Lset;

   function Get_Terminal_Like (S : in Sparklalr_Common.Sym_Range) return Boolean
   --# global in Terminal_Like;
   is
   begin
      return Terminal_Like (S);
   end Get_Terminal_Like;

   function Get_State (S : in Sparklalr_Common.State_Range) return Pt_Memory
   --# global in State_Var;
   is
   begin
      return State_Var (S);
   end Get_State;

   function Get_Ntrdn (I : in Sparklalr_Common.Non_Term_Range) return Pt_Memory
   --# global in Ntrdn;
   is
   begin
      return Ntrdn (I);
   end Get_Ntrdn;

end Sparklalr_Memory.Dump;
