-------------------------------------------------------------------------------
-- (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 Fatal;
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_Char_Class;
with Sparklalr_Level;
with Sparklalr_Memory;
with Symbols_Dump;

use type SPARK.Ada.Text_IO.Exception_T;
use type Sparklalr_Char_Class.Char_Class;

package body Sparklalr_Input
--# own State is Ch,
--#              Gram_In,
--#              Keymap,
--#              Keytable;
is

   Nkeywords : constant := 13; -- NUMBER OF KEYWORDS LEFT,RIGHT,...

   subtype Keymap_Elem is Sparklalr_Symbol.Symbol range Sparklalr_Symbol.Ampmark .. Sparklalr_Symbol.Ampmain;
   subtype Keywords_Range is Natural range 0 .. Nkeywords;

   type Keytable_T is array (Keywords_Range) of Sparklalr_Common.Id_Name;
   type Keymap_T is array (Keywords_Range) of Keymap_Elem;
   Keytable : Keytable_T;
   Keymap   : Keymap_T;
   Gram_In  : SPARK.Ada.Text_IO.File_Type;
   Ch       : Character;

   -- Local procedures/functions
   procedure Get_Char (F   : in out SPARK.Ada.Text_IO.File_Type;
                       Col : in out Sparklalr_Error.Err_Col_T)
   --# global in     Sparklalr_Char_Class.Charmap;
   --#        in out Gram_In;
   --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
   --#        in out Sparklalr_Error.State;
   --#           out Ch;
   --# derives Ch,
   --#         Col                                   from Col,
   --#                                                    Gram_In &
   --#         F,
   --#         SPARK.Ada.Text_IO.The_Standard_Output,
   --#         Sparklalr_Error.State                 from *,
   --#                                                    Col,
   --#                                                    Gram_In,
   --#                                                    Sparklalr_Error.State &
   --#         Gram_In                               from *,
   --#                                                    Col,
   --#                                                    Sparklalr_Char_Class.Charmap,
   --#                                                    Sparklalr_Error.State;
   is
   begin
      Ch := ' ';
      if not SPARK.Ada.Text_IO.End_Of_File_File (File => Gram_In) then
         if SPARK.Ada.Text_IO.End_Of_Line_File (File => Gram_In) or else (Col = Sparklalr_Common.Line_Length) then
            Sparklalr_Error.Write_The_Line (Gram_In, F, Col);
         else
            SPARK.Ada.Text_IO.Get_Character_File (File => Gram_In,
                                                  Item => Ch);
            Col := Col + 1;
            Sparklalr_Error.Set_Line_Out (Col, Ch);
         end if;
      end if;
   end Get_Char;
   -- End local procedures/functions

   procedure Initialise (Signpost : out Symbol_Set_Type)
   --# global in     Command_Line_Options.State;
   --#        in out SPARK.Ada.Command_Line.State;
   --#        in out SPARK.Ada.Text_IO.The_Standard_Error;
   --#           out Ch;
   --#           out Gram_In;
   --#           out Keymap;
   --#           out Keytable;
   --#           out Sparklalr_Char_Class.Charmap;
   --#           out Sparklalr_Error.State;
   --#           out Sparklalr_Level.State;
   --# derives Ch,
   --#         Keymap,
   --#         Keytable,
   --#         Signpost,
   --#         Sparklalr_Char_Class.Charmap,
   --#         Sparklalr_Level.State                from  &
   --#         Gram_In,
   --#         Sparklalr_Error.State                from Command_Line_Options.State &
   --#         SPARK.Ada.Command_Line.State,
   --#         SPARK.Ada.Text_IO.The_Standard_Error from *,
   --#                                                   Command_Line_Options.State;
   is

      procedure Init_Maps
      --# global out Keymap;
      --#        out Keytable;
      --#        out Sparklalr_Char_Class.Charmap;
      --# derives Keymap,
      --#         Keytable,
      --#         Sparklalr_Char_Class.Charmap from ;
      is
      begin
         Sparklalr_Char_Class.Initialise;
         Keytable      := Keytable_T'(others => "                                                  ");
         Keymap        := Keymap_T'(others => Sparklalr_Symbol.Ampmark);
         Keytable (0)  := "                                                  ";
         Keymap (0)    := Sparklalr_Symbol.Ampmark;
         Keytable (1)  := "CONST                                             ";
         Keymap (1)    := Sparklalr_Symbol.Ampconst;
         Keytable (2)  := "FUNC                                              ";
         Keymap (2)    := Sparklalr_Symbol.Ampfunc;
         Keytable (3)  := "GRAM                                              ";
         Keymap (3)    := Sparklalr_Symbol.Ampgram;
         Keytable (4)  := "LABEL                                             ";
         Keymap (4)    := Sparklalr_Symbol.Amplabel;
         Keytable (5)  := "LEFT                                              ";
         Keymap (5)    := Sparklalr_Symbol.Left;
         Keytable (6)  := "MAIN                                              ";
         Keymap (6)    := Sparklalr_Symbol.Ampmain;
         Keytable (7)  := "NON                                               ";
         Keymap (7)    := Sparklalr_Symbol.Non;
         Keytable (8)  := "PREC                                              ";
         Keymap (8)    := Sparklalr_Symbol.Prec;
         Keytable (9)  := "PROG                                              ";
         Keymap (9)    := Sparklalr_Symbol.Ampprog;
         Keytable (10) := "RIGHT                                             ";
         Keymap (10)   := Sparklalr_Symbol.Right;
         Keytable (11) := "TERM                                              ";
         Keymap (11)   := Sparklalr_Symbol.Ampterm;
         Keytable (12) := "TYPE                                              ";
         Keymap (12)   := Sparklalr_Symbol.Amptype;
         Keytable (13) := "VAR                                               ";
         Keymap (13)   := Sparklalr_Symbol.Ampvar;
      end Init_Maps;

   begin -- Initialise
      Init_Maps;
      SPARK.Ada.Text_IO.Unbounded_String.Open
        (File => Gram_In,
         Mode => SPARK.Ada.Text_IO.In_File,
         Name => SPARK.Ada.Strings.Unbounded.Concat_Unbounded_String_String
           (Left  => Command_Line_Options.Get_File_Name,
            Right => ".LLA"),
         Form => SPARK.Ada.Strings.Unbounded.Null_Unbounded_String);
      if SPARK.Ada.Text_IO.Get_Last_Exception_File (File => Gram_In) /= SPARK.Ada.Text_IO.No_Exception then
         SPARK.Ada.Text_IO.Put_Line_Error (Item => "Unable to open LLA input grammar file");
         SPARK.Ada.Command_Line.Set_Exit_Status (SPARK.Ada.Command_Line.Failure);
         Fatal.Stop_With_Command_Line_Exception;
      end if;
      Ch       := ' ';
      Signpost :=
        Symbol_Set_Type'(Sparklalr_Symbol.Ampmark | Sparklalr_Symbol.Ampterm .. Sparklalr_Symbol.Endfile => True,
                         others                                                                          => False);
      Sparklalr_Error.Initialise (Gram_In);
      Sparklalr_Level.Initialise;
   end Initialise;

   procedure Finalize (F : in out SPARK.Ada.Text_IO.File_Type)
   --# global in     Gram_In;
   --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
   --#        in out Sparklalr_Error.State;
   --# derives F,
   --#         SPARK.Ada.Text_IO.The_Standard_Output,
   --#         Sparklalr_Error.State                 from *,
   --#                                                    Gram_In;
   is
   begin
      if not SPARK.Ada.Text_IO.End_Of_File_File (File => Gram_In) then
         Sparklalr_Error.Error (F, 0);
      end if;
   end Finalize;

   function Signpost_To_Symbol_Set_Type (Signpost : in Symbol_Set_Type) return Symbol_Set_Type is
      subtype I_Range is Sparklalr_Symbol.Symbol range Sparklalr_Symbol.Ampmark .. Sparklalr_Symbol.Endfile;

      Result : Symbol_Set_Type;

   begin
      Result := Symbol_Set_Type'(others => False);
      for I in I_Range loop
         Result (I) := Signpost (I);
      end loop;
      return Result;
   end Signpost_To_Symbol_Set_Type;

   procedure Scan
     (F     : in out SPARK.Ada.Text_IO.File_Type;
      Col   : in out Sparklalr_Error.Err_Col_T;
      Symb  :    out Sparklalr_Symbol.Symbol;
      Token :    out Sparklalr_Common.Id_Name)
   --# global in     Keymap;
   --#        in     Keytable;
   --#        in     Sparklalr_Char_Class.Charmap;
   --#        in out Ch;
   --#        in out Gram_In;
   --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
   --#        in out Sparklalr_Error.State;
   --# derives Ch,
   --#         Col,
   --#         F,
   --#         Gram_In,
   --#         SPARK.Ada.Text_IO.The_Standard_Output,
   --#         Sparklalr_Error.State                 from *,
   --#                                                    Col,
   --#                                                    Gram_In,
   --#                                                    Keytable,
   --#                                                    Sparklalr_Char_Class.Charmap,
   --#                                                    Sparklalr_Error.State &
   --#         Symb                                  from Col,
   --#                                                    Gram_In,
   --#                                                    Keymap,
   --#                                                    Keytable,
   --#                                                    Sparklalr_Char_Class.Charmap,
   --#                                                    Sparklalr_Error.State &
   --#         Token                                 from Col,
   --#                                                    Gram_In,
   --#                                                    Keytable,
   --#                                                    Sparklalr_Char_Class.Charmap,
   --#                                                    Sparklalr_Error.State;
   is

      Continue : Boolean;

      procedure Error_Symbol (Col  : in     Sparklalr_Error.Err_Col_T;
                              Symb :    out Sparklalr_Symbol.Symbol)
      --# global in out Sparklalr_Error.State;
      --# derives Sparklalr_Error.State from *,
      --#                                    Col &
      --#         Symb                  from ;
      is
      begin
         Sparklalr_Error.Syn_Error (10, Col);
         Symb := Sparklalr_Symbol.Errsym;
      end Error_Symbol;

      procedure Scan_Number
        (F    : in out SPARK.Ada.Text_IO.File_Type;
         Col  : in out Sparklalr_Error.Err_Col_T;
         Symb :    out Sparklalr_Symbol.Symbol)
      --# global in     Sparklalr_Char_Class.Charmap;
      --#        in out Ch;
      --#        in out Gram_In;
      --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
      --#        in out Sparklalr_Error.State;
      --# derives Ch,
      --#         Col,
      --#         F,
      --#         Gram_In,
      --#         SPARK.Ada.Text_IO.The_Standard_Output,
      --#         Sparklalr_Error.State                 from *,
      --#                                                    Col,
      --#                                                    Gram_In,
      --#                                                    Sparklalr_Char_Class.Charmap,
      --#                                                    Sparklalr_Error.State &
      --#         Symb                                  from ;
      is
         C           : Character;
         End_Of_Line : Boolean;
      begin
         --# accept F, 10, End_Of_Line, "Ineffective assignment here expected";
         SPARK.Ada.Text_IO.Look_Ahead_File (File        => Gram_In,
                                            Item        => C,
                                            End_Of_Line => End_Of_Line);
         --# end accept;
         while Sparklalr_Char_Class.Get_Charmap (C) = Sparklalr_Char_Class.Digit loop
            Get_Char (F, Col);
            --# accept F, 10, End_Of_Line, "Ineffective assignment here expected";
            SPARK.Ada.Text_IO.Look_Ahead_File (File        => Gram_In,
                                               Item        => C,
                                               End_Of_Line => End_Of_Line);
            --# end accept;
         end loop;
         Symb := Sparklalr_Symbol.Number;
         --# accept F, 33, End_Of_Line, "Unused OK";
      end Scan_Number;

      procedure Scan_Comment
        (F    : in out SPARK.Ada.Text_IO.File_Type;
         Col  : in out Sparklalr_Error.Err_Col_T;
         Symb :    out Sparklalr_Symbol.Symbol)
      --# global in     Sparklalr_Char_Class.Charmap;
      --#        in out Ch;
      --#        in out Gram_In;
      --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
      --#        in out Sparklalr_Error.State;
      --# derives Ch,
      --#         Col,
      --#         F,
      --#         Gram_In,
      --#         SPARK.Ada.Text_IO.The_Standard_Output,
      --#         Sparklalr_Error.State                 from *,
      --#                                                    Col,
      --#                                                    Gram_In,
      --#                                                    Sparklalr_Char_Class.Charmap,
      --#                                                    Sparklalr_Error.State &
      --#         Symb                                  from Gram_In;
      is
         CCH         : Character;
         C           : Character;
         End_Of_Line : Boolean;
      begin
         Symb := Sparklalr_Symbol.Nullsymb;
         --# accept F, 10, End_Of_Line, "Ineffective assignment here expected";
         SPARK.Ada.Text_IO.Look_Ahead_File (File        => Gram_In,
                                            Item        => C,
                                            End_Of_Line => End_Of_Line);
         --# end accept;
         if C = '*' then
            loop
               Get_Char (F, Col);
               CCH := Ch;
               --# accept F, 10, End_Of_Line, "Ineffective assignment here expected";
               SPARK.Ada.Text_IO.Look_Ahead_File (File        => Gram_In,
                                                  Item        => C,
                                                  End_Of_Line => End_Of_Line);
               --# end accept;
               exit when SPARK.Ada.Text_IO.End_Of_File_File (File => Gram_In) or else ((CCH = '*') and then (C = ')'));
            end loop;
            Get_Char (F, Col);
         else
            Error_Symbol (Col, Symb);
         end if;
         --# accept F, 33, End_Of_Line, "Unused OK";
      end Scan_Comment;

      procedure Scan_Ident
        (F     : in out SPARK.Ada.Text_IO.File_Type;
         Col   : in out Sparklalr_Error.Err_Col_T;
         Symb  :    out Sparklalr_Symbol.Symbol;
         Token :    out Sparklalr_Common.Id_Name)
      --# global in     Sparklalr_Char_Class.Charmap;
      --#        in out Ch;
      --#        in out Gram_In;
      --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
      --#        in out Sparklalr_Error.State;
      --# derives Ch,
      --#         Col,
      --#         F,
      --#         Gram_In,
      --#         SPARK.Ada.Text_IO.The_Standard_Output,
      --#         Sparklalr_Error.State                 from *,
      --#                                                    Col,
      --#                                                    Gram_In,
      --#                                                    Sparklalr_Char_Class.Charmap,
      --#                                                    Sparklalr_Error.State &
      --#         Symb                                  from  &
      --#         Token                                 from Ch,
      --#                                                    Col,
      --#                                                    Gram_In,
      --#                                                    Sparklalr_Char_Class.Charmap,
      --#                                                    Sparklalr_Error.State;
      is
         Name        : Sparklalr_Common.Id_Name;
         I           : Integer;
         C           : Character;
         End_Of_Line : Boolean;
      begin
         Name     := "                                                  ";
         Symb     := Sparklalr_Symbol.Ident;
         Name (1) := Ch;
         I        := 1;
         --# accept F, 10, End_Of_Line, "Ineffective assignment here expected";
         SPARK.Ada.Text_IO.Look_Ahead_File (File        => Gram_In,
                                            Item        => C,
                                            End_Of_Line => End_Of_Line);
         --# end accept;
         while (Sparklalr_Char_Class.Get_Charmap (C) = Sparklalr_Char_Class.Letter)
           or else (Sparklalr_Char_Class.Get_Charmap (C) = Sparklalr_Char_Class.Digit)
           or else (Sparklalr_Char_Class.Get_Charmap (C) = Sparklalr_Char_Class.Underscore) loop
            Get_Char (F, Col);
            I := I + 1;
            if I <= Sparklalr_Common.Id_Length then
               Name (I) := Ch;
            end if;
            --# accept F, 10, End_Of_Line, "Ineffective assignment here expected";
            SPARK.Ada.Text_IO.Look_Ahead_File (File        => Gram_In,
                                               Item        => C,
                                               End_Of_Line => End_Of_Line);
            --# end accept;
         end loop;
         Token := Name;
         --# accept F, 33, End_Of_Line, "Unused OK";
      end Scan_Ident;

      procedure Scan_Ampersand
        (F     : in out SPARK.Ada.Text_IO.File_Type;
         Col   : in out Sparklalr_Error.Err_Col_T;
         Symb  :    out Sparklalr_Symbol.Symbol;
         Token :    out Sparklalr_Common.Id_Name)
      --# global in     Keymap;
      --#        in     Keytable;
      --#        in     Sparklalr_Char_Class.Charmap;
      --#        in out Ch;
      --#        in out Gram_In;
      --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
      --#        in out Sparklalr_Error.State;
      --# derives Ch,
      --#         Col,
      --#         F,
      --#         Gram_In,
      --#         SPARK.Ada.Text_IO.The_Standard_Output from *,
      --#                                                    Col,
      --#                                                    Gram_In,
      --#                                                    Sparklalr_Char_Class.Charmap,
      --#                                                    Sparklalr_Error.State &
      --#         Sparklalr_Error.State                 from *,
      --#                                                    Col,
      --#                                                    Gram_In,
      --#                                                    Keytable,
      --#                                                    Sparklalr_Char_Class.Charmap &
      --#         Symb                                  from Col,
      --#                                                    Gram_In,
      --#                                                    Keymap,
      --#                                                    Keytable,
      --#                                                    Sparklalr_Char_Class.Charmap,
      --#                                                    Sparklalr_Error.State &
      --#         Token                                 from Col,
      --#                                                    Gram_In,
      --#                                                    Sparklalr_Char_Class.Charmap,
      --#                                                    Sparklalr_Error.State;
      is
         C           : Character;
         End_Of_Line : Boolean;

         procedure Assign_Key
           (Col   : in     Sparklalr_Error.Err_Col_T;
            Symb  :    out Sparklalr_Symbol.Symbol;
            Token : in     Sparklalr_Common.Id_Name)
         --# global in     Keymap;
         --#        in     Keytable;
         --#        in out Sparklalr_Error.State;
         --# derives Sparklalr_Error.State from *,
         --#                                    Col,
         --#                                    Keytable,
         --#                                    Token &
         --#         Symb                  from Keymap,
         --#                                    Keytable,
         --#                                    Token;
         is
            I, J, K : Integer;
         begin
            I := 0;
            J := Nkeywords + 1;
            while I + 1 /= J loop
               K := (I + J) / 2;
               if Token >= Keytable (K) then
                  I := K;
               else
                  J := K;
               end if;
            end loop;
            if Token = Keytable (I) then
               Symb := Keymap (I);
            else
               Sparklalr_Error.Syn_Error (2, Col);
               Symb := Sparklalr_Symbol.Errsym;
            end if;
         end Assign_Key;

      begin -- Scan_Ampersand
         Token := "                                                  ";
         --# accept F, 10, End_Of_Line, "Ineffective assignment here expected";
         SPARK.Ada.Text_IO.Look_Ahead_File (File        => Gram_In,
                                            Item        => C,
                                            End_Of_Line => End_Of_Line);
         --# end accept;
         if Sparklalr_Char_Class.Get_Charmap (C) = Sparklalr_Char_Class.Letter then
            Get_Char (F, Col);
            --# accept F, 10, Symb, "Ineffective assigment to Symb here expected and OK";
            Scan_Ident (F, Col, Symb, Token);
            --# end accept;
            Assign_Key (Col, Symb, Token);
         else
            if Sparklalr_Char_Class.Get_Charmap (C) = Sparklalr_Char_Class.Ampchar then
               Get_Char (F, Col);
               Symb := Sparklalr_Symbol.Ampmark;
            else
               Symb := Sparklalr_Symbol.Ampersand;
            end if;
         end if;
         --# accept F, 33, End_Of_Line, "Unused OK";
      end Scan_Ampersand;

   begin -- Scan
      Symb     := Sparklalr_Symbol.Nullsymb;
      Token    := "                                                  ";
      Continue := True;
      while Continue loop
         Get_Char (F, Col);
         while (Ch = ' ') and then not SPARK.Ada.Text_IO.End_Of_File_File (File => Gram_In) loop
            -- SKIP BLANKS
            Get_Char (F, Col);
         end loop;
         if SPARK.Ada.Text_IO.End_Of_File_File (File => Gram_In) then
            Symb     := Sparklalr_Symbol.Endfile;
            Continue := False;
         else
            case Sparklalr_Char_Class.Get_Charmap (Ch) is
               when Sparklalr_Char_Class.Letter =>
                  Scan_Ident (F, Col, Symb, Token);
                  Continue := False;
               when Sparklalr_Char_Class.Digit =>
                  Scan_Number (F, Col, Symb);
                  Continue := False;
               when Sparklalr_Char_Class.Equalchar =>
                  Symb     := Sparklalr_Symbol.Equals;
                  Continue := False;
               when Sparklalr_Char_Class.Uparrowchar =>
                  Symb     := Sparklalr_Symbol.Uparrow;
                  Continue := False;
               when Sparklalr_Char_Class.Commachar =>
                  Symb     := Sparklalr_Symbol.Comma;
                  Continue := False;
               when Sparklalr_Char_Class.Scolonchar =>
                  Symb     := Sparklalr_Symbol.Scolon;
                  Continue := False;
               when Sparklalr_Char_Class.Colonchar =>
                  Symb     := Sparklalr_Symbol.Colon;
                  Continue := False;
               when Sparklalr_Char_Class.Ampchar =>
                  Scan_Ampersand (F, Col, Symb, Token);
                  Continue := False;
               when Sparklalr_Char_Class.Lparenchar =>
                  Scan_Comment (F, Col, Symb);
                  Continue := True;
               when Sparklalr_Char_Class.Otherchar =>
                  Error_Symbol (Col, Symb);
                  Continue := False;
               when others =>
                  null;
            end case;
         end if;
      end loop;
   end Scan;

   procedure Skipto
     (F       : in out SPARK.Ada.Text_IO.File_Type;
      Arg_Set : in     Symbol_Set_Type;
      Col     : in out Sparklalr_Error.Err_Col_T;
      Symb    : in out Sparklalr_Symbol.Symbol)
   --# global in     Keymap;
   --#        in     Keytable;
   --#        in     Sparklalr_Char_Class.Charmap;
   --#        in out Ch;
   --#        in out Gram_In;
   --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
   --#        in out Sparklalr_Error.State;
   --# derives Ch,
   --#         Col,
   --#         F,
   --#         Gram_In,
   --#         SPARK.Ada.Text_IO.The_Standard_Output,
   --#         Sparklalr_Error.State,
   --#         Symb                                  from *,
   --#                                                    Arg_Set,
   --#                                                    Col,
   --#                                                    Gram_In,
   --#                                                    Keymap,
   --#                                                    Keytable,
   --#                                                    Sparklalr_Char_Class.Charmap,
   --#                                                    Sparklalr_Error.State,
   --#                                                    Symb;
   is
      Token : Sparklalr_Common.Id_Name;
   begin
      if not (Arg_Set (Symb)) then
         --# accept F, 10, Token, "Ineffective assignment here expected and OK";
         Scan (F, Col, Symb, Token);
         --# end accept;
         while not (Arg_Set (Symb)) loop
            if Symb = Sparklalr_Symbol.Ampersand then
               loop
                  --# accept F, 10, Token, "Ineffective assignment here expected and OK";
                  Scan (F, Col, Symb, Token);
                  --# end accept;
                  exit when Symb = Sparklalr_Symbol.Ampersand;
               end loop;
            end if;
            --# accept F, 10, Token, "Ineffective assignment here expected and OK";
            Scan (F, Col, Symb, Token);
            --# end accept;
         end loop;
      end if;
      --# accept F, 33, Token, "Token is unused OK";
   end Skipto;

   procedure Copy_Action
     (F, Echo  : in out SPARK.Ada.Text_IO.File_Type;
      Signpost : in     Symbol_Set_Type;
      Col      : in out Sparklalr_Error.Err_Col_T;
      Symb     : in out Sparklalr_Symbol.Symbol)
   --# global in     Keymap;
   --#        in     Keytable;
   --#        in     Sparklalr_Char_Class.Charmap;
   --#        in     Sparklalr_Memory.Prod_No;
   --#        in out Ch;
   --#        in out Gram_In;
   --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
   --#        in out Sparklalr_Error.State;
   --#        in out Sparklalr_Level.State;
   --# derives Ch,
   --#         Col,
   --#         Echo,
   --#         Gram_In,
   --#         SPARK.Ada.Text_IO.The_Standard_Output,
   --#         Sparklalr_Error.State,
   --#         Symb                                  from *,
   --#                                                    Col,
   --#                                                    Gram_In,
   --#                                                    Keymap,
   --#                                                    Keytable,
   --#                                                    Signpost,
   --#                                                    Sparklalr_Char_Class.Charmap,
   --#                                                    Sparklalr_Error.State,
   --#                                                    Symb &
   --#         F,
   --#         Sparklalr_Level.State                 from *,
   --#                                                    Col,
   --#                                                    Gram_In,
   --#                                                    Keymap,
   --#                                                    Keytable,
   --#                                                    Signpost,
   --#                                                    Sparklalr_Char_Class.Charmap,
   --#                                                    Sparklalr_Error.State,
   --#                                                    Sparklalr_Memory.Prod_No,
   --#                                                    Symb;
   is

      Lmargin          : Integer;
      New_Line         : Boolean;
      Symbolset_Skipto : Symbol_Set_Type;
      C                : Character;
      Quote            : Character;
      Token            : Sparklalr_Common.Id_Name;
      End_Of_Line      : Boolean;

      procedure Copy_String
        (Quote   : in     Character;
         F, Echo : in out SPARK.Ada.Text_IO.File_Type;
         Col     : in out Sparklalr_Error.Err_Col_T)
      --# global in     Sparklalr_Char_Class.Charmap;
      --#        in out Ch;
      --#        in out Gram_In;
      --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
      --#        in out Sparklalr_Error.State;
      --# derives Ch,
      --#         Col,
      --#         Echo,
      --#         F,
      --#         Gram_In,
      --#         SPARK.Ada.Text_IO.The_Standard_Output,
      --#         Sparklalr_Error.State                 from *,
      --#                                                    Col,
      --#                                                    Gram_In,
      --#                                                    Quote,
      --#                                                    Sparklalr_Char_Class.Charmap,
      --#                                                    Sparklalr_Error.State;
      is
      begin
         if not SPARK.Ada.Text_IO.End_Of_Line_File (File => Gram_In) then
            loop
               Get_Char (Echo, Col);
               SPARK.Ada.Text_IO.Put_Character_File (File => F,
                                                     Item => Ch);
               exit when (Ch = Quote) or else SPARK.Ada.Text_IO.End_Of_Line_File (File => Gram_In);
            end loop;
         end if;
      end Copy_String;

      procedure Copy_Comment (F, Echo : in out SPARK.Ada.Text_IO.File_Type;
                              Col     : in out Sparklalr_Error.Err_Col_T)
      --# global in     Sparklalr_Char_Class.Charmap;
      --#        in out Gram_In;
      --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
      --#        in out Sparklalr_Error.State;
      --#           out Ch;
      --# derives Ch                                    from Col,
      --#                                                    Gram_In,
      --#                                                    Sparklalr_Char_Class.Charmap,
      --#                                                    Sparklalr_Error.State &
      --#         Col,
      --#         Echo,
      --#         F,
      --#         Gram_In,
      --#         SPARK.Ada.Text_IO.The_Standard_Output,
      --#         Sparklalr_Error.State                 from *,
      --#                                                    Col,
      --#                                                    Gram_In,
      --#                                                    Sparklalr_Char_Class.Charmap,
      --#                                                    Sparklalr_Error.State;
      is
         C           : Character;
         End_Of_Line : Boolean;
      begin
         loop
            Get_Char (Echo, Col);
            SPARK.Ada.Text_IO.Put_Character_File (File => F,
                                                  Item => Ch);
            --# accept F, 10, End_Of_Line, "Ineffective assignment here expected";
            SPARK.Ada.Text_IO.Look_Ahead_File (File        => Gram_In,
                                               Item        => C,
                                               End_Of_Line => End_Of_Line);
            --# end accept;
            exit when (Ch = '*') and then (C = ')');
         end loop;
         --# accept F, 33, End_Of_Line, "Unused OK";
      end Copy_Comment;

   begin -- Copy_Action
      Symbolset_Skipto                              := Signpost_To_Symbol_Set_Type (Signpost);
      Symbolset_Skipto (Sparklalr_Symbol.Ampersand) := True;
      Symbolset_Skipto (Sparklalr_Symbol.Scolon)    := True;
      Skipto (Echo, Symbolset_Skipto, Col, Symb);
      if Symb = Sparklalr_Symbol.Ampersand then
         Sparklalr_Level.Set_Level_Action_Flag (Sparklalr_Memory.Get_Prod_No, True);
         SPARK.Ada.Text_IO.Put_File (File => F,
                                     Item => "    when");
         SPARK_Ada_Integer_Text_IO.Put_File (File  => F,
                                             Item  => Sparklalr_Memory.Get_Prod_No,
                                             Width => 5,
                                             Base  => 10);
         SPARK.Ada.Text_IO.Put_File (File => F,
                                     Item => " => ");
         New_Line := False;
         --# accept F, 10, End_Of_Line, "Ineffective assignment here expected";
         SPARK.Ada.Text_IO.Look_Ahead_File (File        => Gram_In,
                                            Item        => C,
                                            End_Of_Line => End_Of_Line);
         --# end accept;
         while (C = ' ') and then not SPARK.Ada.Text_IO.End_Of_File_File (File => Gram_In) loop
            if SPARK.Ada.Text_IO.End_Of_Line_File (File => Gram_In) then
               New_Line := True;
            end if;
            --# accept F, 10, Ch, "Ineffective assigment to Ch here expected and OK";
            Get_Char (Echo, Col);
            --# end accept;
            --# accept F, 10, End_Of_Line, "Ineffective assignment here expected";
            SPARK.Ada.Text_IO.Look_Ahead_File (File        => Gram_In,
                                               Item        => C,
                                               End_Of_Line => End_Of_Line);
            --# end accept;
         end loop;
         Lmargin := Col;
         if New_Line then
            SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                             Spacing => 1);
         end if;
         --# accept F, 10, End_Of_Line, "Ineffective assignment here expected";
         SPARK.Ada.Text_IO.Look_Ahead_File (File        => Gram_In,
                                            Item        => C,
                                            End_Of_Line => End_Of_Line);
         --# end accept;
         while (C /= '&') and then not SPARK.Ada.Text_IO.End_Of_File_File (File => Gram_In) loop
            if New_Line then
               Sparklalr_Common.Put_N_Chars (Std_Out => False,
                                             F       => F,
                                             C       => ' ',
                                             N       => 6);
            end if;
            New_Line := False;
            Get_Char (Echo, Col);
            if Ch = '\' then
               Sparklalr_Error.Syn_Error (18, Col);
            else
               SPARK.Ada.Text_IO.Put_Character_File (File => F,
                                                     Item => Ch);
               if (Ch = ''') or else (Ch = '"') then
                  Quote := Ch;
                  --# accept F, 10, Ch, "Ineffective assigment to Ch here expected and OK";
                  Copy_String (Quote, F, Echo, Col);
                  --# end accept;
               else
                  --# accept F, 10, End_Of_Line, "Ineffective assignment here expected";
                  SPARK.Ada.Text_IO.Look_Ahead_File (File        => Gram_In,
                                                     Item        => C,
                                                     End_Of_Line => End_Of_Line);
                  --# end accept;
                  if (Ch = '(') and then (C = '*') then
                     --# accept F, 10, Ch, "Ineffective assigment to Ch here expected and OK";
                     Copy_Comment (F, Echo, Col);
                     --# end accept;
                  end if;
               end if;
            end if;
            if SPARK.Ada.Text_IO.End_Of_Line_File (File => Gram_In) then
               --# accept F, 10, End_Of_Line, "Ineffective assignment here expected";
               SPARK.Ada.Text_IO.Look_Ahead_File (File        => Gram_In,
                                                  Item        => C,
                                                  End_Of_Line => End_Of_Line);
               --# end accept;
               while (C = ' ') and then (Col /= Lmargin) and then not SPARK.Ada.Text_IO.End_Of_File_File (File => Gram_In) loop
                  --# accept F, 10, Ch, "Ineffective assigment to Ch here expected and OK";
                  Get_Char (Echo, Col);
                  --# end accept;
                  --# accept F, 10, End_Of_Line, "Ineffective assignment here expected";
                  SPARK.Ada.Text_IO.Look_Ahead_File (File        => Gram_In,
                                                     Item        => C,
                                                     End_Of_Line => End_Of_Line);
                  --# end accept;
               end loop;
               SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                                Spacing => 1);
               New_Line := True;
            end if;
            --# accept F, 10, End_Of_Line, "Ineffective assignment here expected";
            SPARK.Ada.Text_IO.Look_Ahead_File (File        => Gram_In,
                                               Item        => C,
                                               End_Of_Line => End_Of_Line);
            --# end accept;
         end loop;
         SPARK.Ada.Text_IO.New_Line_File (File    => F,
                                          Spacing => 1);
         Get_Char (Echo, Col);
         --# accept F, 10, Token, "Ineffective assignment here expected and OK";
         Scan (Echo, Col, Symb, Token);
         --# end accept;
      else
         Sparklalr_Error.Syn_Error (4, Col);
      end if;
      --# accept F, 33, End_Of_Line, "Unused OK" &
      --#        F, 33, Token, "Token is unused OK";
   end Copy_Action;

   procedure Skip_Action
     (F        : in out SPARK.Ada.Text_IO.File_Type;
      Signpost : in     Symbol_Set_Type;
      Col      : in out Sparklalr_Error.Err_Col_T;
      Symb     : in out Sparklalr_Symbol.Symbol)
   --# global in     Keymap;
   --#        in     Keytable;
   --#        in     Sparklalr_Char_Class.Charmap;
   --#        in out Ch;
   --#        in out Gram_In;
   --#        in out SPARK.Ada.Text_IO.The_Standard_Output;
   --#        in out Sparklalr_Error.State;
   --# derives Ch,
   --#         Col,
   --#         F,
   --#         Gram_In,
   --#         SPARK.Ada.Text_IO.The_Standard_Output,
   --#         Sparklalr_Error.State,
   --#         Symb                                  from *,
   --#                                                    Col,
   --#                                                    Gram_In,
   --#                                                    Keymap,
   --#                                                    Keytable,
   --#                                                    Signpost,
   --#                                                    Sparklalr_Char_Class.Charmap,
   --#                                                    Sparklalr_Error.State,
   --#                                                    Symb;
   is
      Symbolset_Skipto : Symbol_Set_Type;
      C                : Character;
      Token            : Sparklalr_Common.Id_Name;
      End_Of_Line      : Boolean;
   begin
      Symbolset_Skipto                              := Signpost_To_Symbol_Set_Type (Signpost);
      Symbolset_Skipto (Sparklalr_Symbol.Ampersand) := True;
      Symbolset_Skipto (Sparklalr_Symbol.Scolon)    := True;
      Skipto (F, Symbolset_Skipto, Col, Symb);
      if Symb = Sparklalr_Symbol.Ampersand then
         --# accept F, 10, End_Of_Line, "Ineffective assignment here expected";
         SPARK.Ada.Text_IO.Look_Ahead_File (File        => Gram_In,
                                            Item        => C,
                                            End_Of_Line => End_Of_Line);
         --# end accept;
         while (C /= '&') and then not SPARK.Ada.Text_IO.End_Of_File_File (File => Gram_In) loop
            --# accept F, 10, Ch, "Ineffective assigment to Ch here expected and OK";
            Get_Char (F, Col);
            --# end accept;
            --# accept F, 10, End_Of_Line, "Ineffective assignment here expected";
            SPARK.Ada.Text_IO.Look_Ahead_File (File        => Gram_In,
                                               Item        => C,
                                               End_Of_Line => End_Of_Line);
            --# end accept;
         end loop;
         Get_Char (F, Col);
         --# accept F, 10, Token, "Ineffective assignment here expected and OK";
         Scan (F, Col, Symb, Token);
         --# end accept;
      else
         Sparklalr_Error.Syn_Error (4, Col);
      end if;
      --# accept F, 33, End_Of_Line, "Unused OK" &
      --#        F, 33, Token, "Token is unused OK";
   end Skip_Action;

   procedure Proc_Term
     (F          : in out SPARK.Ada.Text_IO.File_Type;
      Gram_Rules :    out Boolean;
      Col        : in out Sparklalr_Error.Err_Col_T;
      Signpost   : in     Symbol_Set_Type;
      Symb       :    out Sparklalr_Symbol.Symbol)
   --# global in     Keymap;
   --#        in     Keytable;
   --#        in     Sparklalr_Char_Class.Charmap;
   --#        in out Ch;
   --#        in out Gram_In;
   --#        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 Ch,
   --#         Col,
   --#         F,
   --#         Gram_In,
   --#         SPARK.Ada.Text_IO.The_Standard_Output,
   --#         Sparklalr_Error.State,
   --#         Sparklalr_Level.State,
   --#         Symbols_Dump.State                    from *,
   --#                                                    Col,
   --#                                                    Gram_In,
   --#                                                    Keymap,
   --#                                                    Keytable,
   --#                                                    Signpost,
   --#                                                    Sparklalr_Char_Class.Charmap,
   --#                                                    Sparklalr_Error.State,
   --#                                                    Symbols_Dump.State &
   --#         Gram_Rules                            from  &
   --#         Symb                                  from Col,
   --#                                                    Gram_In,
   --#                                                    Keymap,
   --#                                                    Keytable,
   --#                                                    Signpost,
   --#                                                    Sparklalr_Char_Class.Charmap,
   --#                                                    Sparklalr_Error.State,
   --#                                                    Symbols_Dump.State;
   is

      Current_Lev : Sparklalr_Level.Lev_Struct;
      Dummy       : Integer;
      pragma Unreferenced (Dummy);
      Next_Symb_Var    : Sparklalr_Symbol.Symbol;
      Symbolset_Skipto : Symbol_Set_Type;
      Token            : Sparklalr_Common.Id_Name;

      procedure Element_Process
        (Current_Lev : in     Sparklalr_Level.Lev_Struct;
         F           : in out SPARK.Ada.Text_IO.File_Type;
         Token       : in     Sparklalr_Common.Id_Name;
         Col         : in     Sparklalr_Error.Err_Col_T)
      --# global 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 &
      --#         Sparklalr_Error.State from *,
      --#                                    Col,
      --#                                    Symbols_Dump.State,
      --#                                    Token &
      --#         Sparklalr_Level.State from *,
      --#                                    Current_Lev,
      --#                                    Symbols_Dump.State,
      --#                                    Token;
      is
         Dummy : Integer;
      begin
         Symbols_Dump.Find (False, F, False, Token, Col, Dummy);
         Sparklalr_Level.Assign_Term_Lev (Dummy, Current_Lev);
      end Element_Process;

   begin -- Proc_Term
      Gram_Rules := False;
      Token      := "SPEND                                             ";
      --# accept F, 10, Dummy, "Ineffective assigment to Dummy here expected and OK";
      Symbols_Dump.Define (False, F, False, Token, Col, Dummy);
      --# end accept;
      Sparklalr_Level.Initiate_Term_Lev (0);
      Token := "SPDEFAULT                                         ";
      --# accept F, 10, Dummy, "Ineffective assigment to Dummy here expected and OK";
      Symbols_Dump.Define (False, F, False, Token, Col, Dummy);
      --# end accept;
      Sparklalr_Level.Initiate_Term_Lev (1);
      Token := "SPACCEPT                                          ";
      --# accept F, 10, Dummy, "Ineffective assigment to Dummy here expected and OK";
      Symbols_Dump.Define (True, F, False, Token, Col, Dummy);
      --# end accept;
      Sparklalr_Level.Initiate (Current_Lev);
      Scan (F, Col, Symb, Token);
      while not Signpost (Symb) loop
         if (Symb = Sparklalr_Symbol.Left) or else (Symb = Sparklalr_Symbol.Right) or else (Symb = Sparklalr_Symbol.Non) then
            Sparklalr_Level.Associativity (Symb, Current_Lev);
            Scan (F, Col, Symb, Token);
         end if;
         if (Symb = Sparklalr_Symbol.Ident) or else (Symb = Sparklalr_Symbol.Lit) then
            loop -- PROCESS LIST
               Element_Process (Current_Lev, F, Token, Col);
               Scan (F, Col, Symb, Token);
               Next_Symb_Var := Symb;
               if (Next_Symb_Var = Sparklalr_Symbol.Comma) or else (Next_Symb_Var = Sparklalr_Symbol.Scolon) then
                  Scan (F, Col, Symb, Token);
               end if;
               exit when not ((Symb = Sparklalr_Symbol.Ident) or else (Symb = Sparklalr_Symbol.Lit));
            end loop;
         else
            Sparklalr_Error.Syn_Error (8, Col);
            Symbolset_Skipto                          := Symbol_Set_False_Const;
            Symbolset_Skipto (Sparklalr_Symbol.Left)  := True;
            Symbolset_Skipto (Sparklalr_Symbol.Right) := True;
            Symbolset_Skipto (Sparklalr_Symbol.Non)   := True;
            Symbolset_Skipto (Sparklalr_Symbol.Ident) := True;
            Symbolset_Skipto (Sparklalr_Symbol.Lit)   := True;
            Skipto (F, Symbolset_Skipto, Col, Symb);
         end if;
      end loop;
      --# accept F, 33, Dummy, "Dummy is unused OK";
   end Proc_Term;

   procedure Set_Symbol_Set (Symbol_Set : in out Symbol_Set_Type;
                             Symb       : in     Sparklalr_Symbol.Symbol;
                             Value      : in     Boolean) is
   begin
      Symbol_Set (Symb) := Value;
   end Set_Symbol_Set;

   function Get_Symbol_Set (Symbol_Set : in Symbol_Set_Type;
                            Symb       : in Sparklalr_Symbol.Symbol) return Boolean is
   begin
      return Symbol_Set (Symb);
   end Get_Symbol_Set;

end Sparklalr_Input;
