-------------------------------------------------------------------------------
-- (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 CommandLineData;
with ExaminerConstants;
with E_Strings;

--# inherit Ada.Characters.Handling,
--#         Ada.Characters.Latin_1,
--#         CommandLineData,
--#         ExaminerConstants,
--#         E_Strings,
--#         SPARK_IO,
--#         Statistics,
--#         SystemErrors;

package LexTokenManager
--# own State;
--# initializes State;
is
   type Lex_String is private;

   Null_String : constant Lex_String;

   The_First_Token : constant Lex_String;

   -- Common Attributes
   Aft_Token               : constant Lex_String;
   Base_Token              : constant Lex_String;
   Delta_Token             : constant Lex_String;
   Digits_Token            : constant Lex_String;
   Emax_Token              : constant Lex_String;
   Epsilon_Token           : constant Lex_String;
   First_Token             : constant Lex_String;
   Fore_Token              : constant Lex_String;
   Large_Token             : constant Lex_String;
   Last_Token              : constant Lex_String;
   Length_Token            : constant Lex_String;
   Machine_Emax_Token      : constant Lex_String;
   Machine_Emin_Token      : constant Lex_String;
   Machine_Mantissa_Token  : constant Lex_String;
   Machine_Overflows_Token : constant Lex_String;
   Machine_Radix_Token     : constant Lex_String;
   Machine_Rounds_Token    : constant Lex_String;
   Mantissa_Token          : constant Lex_String;
   Pos_Token               : constant Lex_String;
   Pred_Token              : constant Lex_String;
   Range_Token             : constant Lex_String;
   Safe_Emax_Token         : constant Lex_String;
   Safe_Large_Token        : constant Lex_String;
   Safe_Small_Token        : constant Lex_String;
   Size_Token              : constant Lex_String;
   Small_Token             : constant Lex_String;
   Succ_Token              : constant Lex_String;
   Val_Token               : constant Lex_String;

   -- Identifiers in Standard
   Left_Token  : constant Lex_String;
   Right_Token : constant Lex_String;
   True_Token  : constant Lex_String;
   False_Token : constant Lex_String;

   -- Numeric literals
   Zero_Value : constant Lex_String;
   One_Value  : constant Lex_String;

   -- Index file
   Super_Index_Token : constant Lex_String;

   -- Pragmas
   Interface_Token      : constant Lex_String;
   Import_Token         : constant Lex_String;
   Link_Name_Token      : constant Lex_String;
   External_Name_Token  : constant Lex_String;
   Entity_Token         : constant Lex_String;
   Convention_Token     : constant Lex_String;
   Elaborate_Body_Token : constant Lex_String;

   -- SPARK95 Predefined packages
   Ada_Token   : constant Lex_String;
   SPARK_Token : constant Lex_String;

   -- SPARK95 Attributes
   Denorm_Token         : constant Lex_String;
   Model_Emin_Token     : constant Lex_String;
   Model_Epsilon_Token  : constant Lex_String;
   Model_Mantissa_Token : constant Lex_String;
   Model_Small_Token    : constant Lex_String;
   Safe_First_Token     : constant Lex_String;
   Safe_Last_Token      : constant Lex_String;
   Component_Size_Token : constant Lex_String;
   Min_Token            : constant Lex_String;
   Max_Token            : constant Lex_String;
   Signed_Zeros_Token   : constant Lex_String;
   Valid_Token          : constant Lex_String;

   -- More SPARK95 Predefined packages
   Characters_Token : constant Lex_String;
   Latin_1_Token    : constant Lex_String;

   -- More SPARK95 Attributes
   Adjacent_Token          : constant Lex_String;
   Compose_Token           : constant Lex_String;
   Copy_Sign_Token         : constant Lex_String;
   Leading_Part_Token      : constant Lex_String;
   Remainder_Token         : constant Lex_String;
   Scaling_Token           : constant Lex_String;
   Ceiling_Token           : constant Lex_String;
   Exponent_Token          : constant Lex_String;
   Floor_Token             : constant Lex_String;
   Fraction_Token          : constant Lex_String;
   Machine_Token           : constant Lex_String;
   Model_Token             : constant Lex_String;
   Rounding_Token          : constant Lex_String;
   Truncation_Token        : constant Lex_String;
   Unbiased_Rounding_Token : constant Lex_String;
   Address_Token           : constant Lex_String;
   Modulus_Token           : constant Lex_String;

   -- SPARK95 Proof Attributes
   Tail_Token   : constant Lex_String;
   Append_Token : constant Lex_String;

   -- Package System and its constants and types. "Address" is already
   -- defined above.
   System_Token             : constant Lex_String;
   Min_Int_Token            : constant Lex_String;
   Max_Int_Token            : constant Lex_String;
   Max_Binary_Modulus_Token : constant Lex_String;
   Max_Base_Digits_Token    : constant Lex_String;
   Max_Digits_Token         : constant Lex_String;
   Max_Mantissa_Token       : constant Lex_String;
   Fine_Delta_Token         : constant Lex_String;
   Null_Address_Token       : constant Lex_String;
   Storage_Unit_Token       : constant Lex_String;
   Word_Size_Token          : constant Lex_String;
   Any_Priority_Token       : constant Lex_String;
   Priority_Token           : constant Lex_String;
   Interrupt_Priority_Token : constant Lex_String;
   Default_Priority_Token   : constant Lex_String;

   -- RavenSPARK Pragmas, attributes and packages
   Atomic_Token                   : constant Lex_String;
   Real_Time_Token                : constant Lex_String;
   Inherit_Token                  : constant Lex_String;
   Synchronous_Task_Control_Token : constant Lex_String;
   Attach_Handler_Token           : constant Lex_String;
   Interrupt_Handler_Token        : constant Lex_String;
   Interrupts_Token               : constant Lex_String;
   Access_Token                   : constant Lex_String;
   Atomic_Components_Token        : constant Lex_String;
   Volatile_Components_Token      : constant Lex_String;
   Main_Program_Token             : constant Lex_String;

   -- predefined generic units
   Unchecked_Conversion_Token : constant Lex_String;

   -- composite constant rule generation
   Rule_Token    : constant Lex_String;
   No_Rule_Token : constant Lex_String;

   -- the 'Always_Valid token
   Always_Valid_Token : constant Lex_String;

   -- Ada0Y identifiers.
   --
   -- "Assert" is a predefined pragma in Ada0Y.  It's already
   -- a reserved word in SPARK, but we still
   -- need a token for it so the corresponding warning can
   -- be suppressed in the warning control file.
   --
   -- There is a special production in the grammar to
   -- allow "pragma Assert ..."
   Assert_Token : constant Lex_String;

   -- "overriding" is a reserved word in
   -- Ada2005, but let's have a token for it so we
   -- can at least issue a warning
   Overriding_Token : constant Lex_String;

   -- Package System - more predefined identifiers
   Bit_Order_Token         : constant Lex_String;
   High_Order_First_Token  : constant Lex_String;
   Low_Order_First_Token   : constant Lex_String;
   Default_Bit_Order_Token : constant Lex_String;

   -- More Pragmas
   All_Calls_Remote_Token        : constant Lex_String;
   Asynchronous_Token            : constant Lex_String;
   Controlled_Token              : constant Lex_String;
   Discard_Names_Token           : constant Lex_String;
   Elaborate_Token               : constant Lex_String;
   Elaborate_All_Token           : constant Lex_String;
   Export_Token                  : constant Lex_String;
   Inline_Token                  : constant Lex_String;
   Inspection_Point_Token        : constant Lex_String;
   Linker_Options_Token          : constant Lex_String;
   List_Token                    : constant Lex_String;
   Locking_Policy_Token          : constant Lex_String;
   Normalize_Scalars_Token       : constant Lex_String;
   Optimize_Token                : constant Lex_String;
   Pack_Token                    : constant Lex_String;
   Page_Token                    : constant Lex_String;
   Preelaborate_Token            : constant Lex_String;
   Pure_Token                    : constant Lex_String;
   Queueing_Policy_Token         : constant Lex_String;
   Remote_Call_Interface_Token   : constant Lex_String;
   Remote_Types_Token            : constant Lex_String;
   Restrictions_Token            : constant Lex_String;
   Reviewable_Token              : constant Lex_String;
   Shared_Passive_Token          : constant Lex_String;
   Storage_Size_Token            : constant Lex_String;
   Suppress_Token                : constant Lex_String;
   Task_Dispatching_Policy_Token : constant Lex_String;
   Volatile_Token                : constant Lex_String;

   -- More Ada '83 Pragmas
   Memory_Size_Token : constant Lex_String;
   Shared_Token      : constant Lex_String;
   System_Name_Token : constant Lex_String;

   -- Ada 2005
   Mod_Token              : constant Lex_String;
   Machine_Rounding_Token : constant Lex_String;

   Priority_Last_Token : constant Lex_String;
   Standard_Token      : constant Lex_String;
   Integer_Token       : constant Lex_String;
   Float_Token         : constant Lex_String;
   Seconds_Count_Token : constant Lex_String;
   Interrupt_ID_Token  : constant Lex_String;

   -- Dictionary types
   Universal_Integer_Token : constant Lex_String;
   Universal_Real_Token    : constant Lex_String;
   Universal_Fixed_Token   : constant Lex_String;
   Character_Token         : constant Lex_String;
   Boolean_Token           : constant Lex_String;
   Duration_Token          : constant Lex_String;
   String_Token            : constant Lex_String;
   Natural_Token           : constant Lex_String;
   Positive_Token          : constant Lex_String;

   -- More Ada95 predefined library packages
   Interfaces_Token : constant Lex_String;

   type Line_Numbers is new Integer range 0 .. Natural'Last;

   type Token_Position is record
      Start_Line_No : Line_Numbers;
      Start_Pos     : E_Strings.Lengths;
   end record;

   Null_Token_Position : constant Token_Position := Token_Position'(Start_Line_No => 0,
                                                                    Start_Pos     => 0);

   type Lex_Value is record
      Position  : Token_Position;
      Token_Str : Lex_String;
   end record;

   -- Type to identify result of string comparisons
   type Str_Comp_Result is (Str_Eq, Str_First, Str_Second);

   -- Performs case insensitive comparison of two Lex_Strings and
   -- returns a value of type StrCompResult (see above) to indicate
   -- which string comes first when ordered alphabetically.
   -- If both strings are null it returns StrEqual.
   -- If just one string is null then the null string is considered
   -- to come first.
   -- If one string is of length n chars and the other string is
   -- longer but identical for the first n chars then the shorter
   -- string is considered to come first.
   -- (See also CompStr and CompStrCaseSensitive in package body)
   function Lex_String_Case_Insensitive_Compare (Lex_Str1 : Lex_String;
                                                 Lex_Str2 : Lex_String) return Str_Comp_Result;
   --# global in State;

   function Lex_String_Case_Sensitive_Compare (Lex_Str1 : Lex_String;
                                               Lex_Str2 : Lex_String) return Str_Comp_Result;
   --# global in State;

   function Comp_Str_Case_Insensitive (Str     : E_Strings.T;
                                       Lex_Str : Lex_String) return Boolean;
   --# global in State;

   function Comp_Str_Case_Sensitive (Str     : E_Strings.T;
                                     Lex_Str : Lex_String) return Boolean;
   --# global in State;

   procedure Insert_Examiner_String (Str     : in     E_Strings.T;
                                     Lex_Str :    out Lex_String);
   --# global in out State;
   --# derives Lex_Str,
   --#         State   from State,
   --#                      Str;

   function Lex_String_To_String (Lex_Str : Lex_String) return E_Strings.T;
   --# global in State;

   function Is_Attribute_Token (Tok      : Lex_String;
                                Language : CommandLineData.Language_Profiles) return Boolean;
   --# global in State;

   procedure Initialise_String_Table;
   --# global in out State;
   --# derives State from *;

   procedure Report_Usage;
   --# global in     State;
   --#        in out Statistics.TableUsage;
   --# derives Statistics.TableUsage from *,
   --#                                    State;

   procedure Insert_Nat (N       : in     Natural;
                         Lex_Str :    out Lex_String);
   --# global in out State;
   --# derives Lex_Str,
   --#         State   from N,
   --#                      State;

   function Is_Standard_Token (Lex_Str : Lex_String) return Boolean;
   --# global in State;

   procedure Set_Last_Token;
   --# global in out State;
   --# derives State from *;

private
   type Lex_String is range 0 .. ExaminerConstants.String_Table_Size;
   --# assert Lex_String'Base is Integer;

   Null_String             : constant Lex_String := 0;
   The_First_Token         : constant Lex_String := 1;
   Aft_Token               : constant Lex_String := 1;
   Base_Token              : constant Lex_String := 8;
   Delta_Token             : constant Lex_String := 16;
   Digits_Token            : constant Lex_String := 25;
   Emax_Token              : constant Lex_String := 35;
   Epsilon_Token           : constant Lex_String := 43;
   First_Token             : constant Lex_String := 54;
   Fore_Token              : constant Lex_String := 63;
   Large_Token             : constant Lex_String := 71;
   Last_Token              : constant Lex_String := 80;
   Length_Token            : constant Lex_String := 88;
   Machine_Emax_Token      : constant Lex_String := 98;
   Machine_Emin_Token      : constant Lex_String := 114;
   Machine_Mantissa_Token  : constant Lex_String := 130;
   Machine_Overflows_Token : constant Lex_String := 150;
   Machine_Radix_Token     : constant Lex_String := 171;
   Machine_Rounds_Token    : constant Lex_String := 188;
   Mantissa_Token          : constant Lex_String := 206;
   Pos_Token               : constant Lex_String := 218;
   Pred_Token              : constant Lex_String := 225;
   Range_Token             : constant Lex_String := 233;
   Safe_Emax_Token         : constant Lex_String := 242;
   Safe_Large_Token        : constant Lex_String := 255;
   Safe_Small_Token        : constant Lex_String := 269;
   Size_Token              : constant Lex_String := 283;
   Small_Token             : constant Lex_String := 291;
   Succ_Token              : constant Lex_String := 300;
   Val_Token               : constant Lex_String := 308;
   Left_Token              : constant Lex_String := 315;
   Right_Token             : constant Lex_String := 323;
   True_Token              : constant Lex_String := 332;
   False_Token             : constant Lex_String := 340;
   Zero_Value              : constant Lex_String := 349;
   One_Value               : constant Lex_String := 354;
   Super_Index_Token       : constant Lex_String := 359;
   Interface_Token         : constant Lex_String := 373;
   Import_Token            : constant Lex_String := 386;
   Link_Name_Token         : constant Lex_String := 396;
   External_Name_Token     : constant Lex_String := 409;
   Entity_Token            : constant Lex_String := 426;
   Convention_Token        : constant Lex_String := 436;
   Elaborate_Body_Token    : constant Lex_String := 450;
   Ada_Token               : constant Lex_String := 468;
   SPARK_Token             : constant Lex_String := 475;
   Denorm_Token            : constant Lex_String := 484;
   Model_Emin_Token        : constant Lex_String := 494;
   Model_Epsilon_Token     : constant Lex_String := 508;
   Model_Mantissa_Token    : constant Lex_String := 525;
   Model_Small_Token       : constant Lex_String := 543;
   Safe_First_Token        : constant Lex_String := 558;
   Safe_Last_Token         : constant Lex_String := 572;
   Component_Size_Token    : constant Lex_String := 585;
   Min_Token               : constant Lex_String := 603;
   Max_Token               : constant Lex_String := 610;
   Signed_Zeros_Token      : constant Lex_String := 617;
   Valid_Token             : constant Lex_String := 633;
   Characters_Token        : constant Lex_String := 642;
   Latin_1_Token           : constant Lex_String := 656;
   Adjacent_Token          : constant Lex_String := 667;
   Compose_Token           : constant Lex_String := 679;
   Copy_Sign_Token         : constant Lex_String := 690;
   Leading_Part_Token      : constant Lex_String := 703;
   Remainder_Token         : constant Lex_String := 719;
   Scaling_Token           : constant Lex_String := 732;
   Ceiling_Token           : constant Lex_String := 743;
   Exponent_Token          : constant Lex_String := 754;
   Floor_Token             : constant Lex_String := 766;
   Fraction_Token          : constant Lex_String := 775;
   Machine_Token           : constant Lex_String := 787;
   Model_Token             : constant Lex_String := 798;
   Rounding_Token          : constant Lex_String := 807;
   Truncation_Token        : constant Lex_String := 819;
   Unbiased_Rounding_Token : constant Lex_String := 833;
   Address_Token           : constant Lex_String := 854;
   Modulus_Token           : constant Lex_String := 865;
   Tail_Token              : constant Lex_String := 876;
   Append_Token            : constant Lex_String := 884;

   -- System and its constants and types. "Address" is already
   -- defined above.
   System_Token             : constant Lex_String := 894;
   Min_Int_Token            : constant Lex_String := 904;
   Max_Int_Token            : constant Lex_String := 915;
   Max_Binary_Modulus_Token : constant Lex_String := 926;
   Max_Base_Digits_Token    : constant Lex_String := 948;
   Max_Digits_Token         : constant Lex_String := 967;
   Max_Mantissa_Token       : constant Lex_String := 981;
   Fine_Delta_Token         : constant Lex_String := 997;
   Null_Address_Token       : constant Lex_String := 1011;
   Storage_Unit_Token       : constant Lex_String := 1027;
   Word_Size_Token          : constant Lex_String := 1043;
   Any_Priority_Token       : constant Lex_String := 1056;
   Priority_Token           : constant Lex_String := 1072;
   Interrupt_Priority_Token : constant Lex_String := 1084;
   Default_Priority_Token   : constant Lex_String := 1106;

   -- RavenSPARK Pragmas, attributes, and identifiers
   Atomic_Token                   : constant Lex_String := 1126;
   Real_Time_Token                : constant Lex_String := 1136;
   Inherit_Token                  : constant Lex_String := 1149;
   Synchronous_Task_Control_Token : constant Lex_String := 1160;
   Attach_Handler_Token           : constant Lex_String := 1188;
   Interrupt_Handler_Token        : constant Lex_String := 1206;
   Interrupts_Token               : constant Lex_String := 1227;
   Access_Token                   : constant Lex_String := 1241;
   Atomic_Components_Token        : constant Lex_String := 1251;
   Volatile_Components_Token      : constant Lex_String := 1272;
   Main_Program_Token             : constant Lex_String := 1295;

   -- Ada0Y identifiers.
   Assert_Token     : constant Lex_String := 1311;
   Overriding_Token : constant Lex_String := 1321;

   -- Predefined generics
   Unchecked_Conversion_Token : constant Lex_String := 1335;

   -- Composite constant rule generation
   Rule_Token    : constant Lex_String := 1359;
   No_Rule_Token : constant Lex_String := 1367;

   -- the 'Always_Valid token
   Always_Valid_Token : constant Lex_String := 1377;

   Bit_Order_Token         : constant Lex_String := 1393;
   High_Order_First_Token  : constant Lex_String := 1406;
   Low_Order_First_Token   : constant Lex_String := 1426;
   Default_Bit_Order_Token : constant Lex_String := 1445;

   -- More Pragmas
   All_Calls_Remote_Token        : constant Lex_String := 1466;
   Asynchronous_Token            : constant Lex_String := 1486;
   Controlled_Token              : constant Lex_String := 1502;
   Discard_Names_Token           : constant Lex_String := 1516;
   Elaborate_Token               : constant Lex_String := 1533;
   Elaborate_All_Token           : constant Lex_String := 1546;
   Export_Token                  : constant Lex_String := 1563;
   Inline_Token                  : constant Lex_String := 1573;
   Inspection_Point_Token        : constant Lex_String := 1583;
   Linker_Options_Token          : constant Lex_String := 1603;
   List_Token                    : constant Lex_String := 1621;
   Locking_Policy_Token          : constant Lex_String := 1629;
   Normalize_Scalars_Token       : constant Lex_String := 1647;
   Optimize_Token                : constant Lex_String := 1668;
   Pack_Token                    : constant Lex_String := 1680;
   Page_Token                    : constant Lex_String := 1688;
   Preelaborate_Token            : constant Lex_String := 1696;
   Pure_Token                    : constant Lex_String := 1712;
   Queueing_Policy_Token         : constant Lex_String := 1720;
   Remote_Call_Interface_Token   : constant Lex_String := 1739;
   Remote_Types_Token            : constant Lex_String := 1764;
   Restrictions_Token            : constant Lex_String := 1780;
   Reviewable_Token              : constant Lex_String := 1796;
   Shared_Passive_Token          : constant Lex_String := 1810;
   Storage_Size_Token            : constant Lex_String := 1828;
   Suppress_Token                : constant Lex_String := 1844;
   Task_Dispatching_Policy_Token : constant Lex_String := 1856;
   Volatile_Token                : constant Lex_String := 1883;

   -- More Ada '83 Pragmas
   Memory_Size_Token : constant Lex_String := 1895;
   Shared_Token      : constant Lex_String := 1910;
   System_Name_Token : constant Lex_String := 1920;

   -- Ada 2005 Mod attribute
   Mod_Token              : constant Lex_String := 1935;
   Machine_Rounding_Token : constant Lex_String := 1942;

   Priority_Last_Token : constant Lex_String := 1962;
   Standard_Token      : constant Lex_String := 1979;
   Integer_Token       : constant Lex_String := 1991;
   Float_Token         : constant Lex_String := 2002;
   Seconds_Count_Token : constant Lex_String := 2011;
   Interrupt_ID_Token  : constant Lex_String := 2028;

   -- Dictionary types
   Universal_Integer_Token : constant Lex_String := 2044;
   Universal_Real_Token    : constant Lex_String := 2065;
   Universal_Fixed_Token   : constant Lex_String := 2083;
   Character_Token         : constant Lex_String := 2102;
   Boolean_Token           : constant Lex_String := 2115;
   Duration_Token          : constant Lex_String := 2126;
   String_Token            : constant Lex_String := 2138;
   Natural_Token           : constant Lex_String := 2148;
   Positive_Token          : constant Lex_String := 2159;

   -- More Ada95 predefined library packages
   Interfaces_Token : constant Lex_String := 2171;

   -- The next vacant token value is equal to the final token value above,
   -- plus the length of that token in characters, plus 4, so
   -- Interfaces_Token + Length("Interfaces") + 4 = 2171 + 10 + 4 = 2185
   Next_Vacant_Token : constant Lex_String := 2185;

   -- Use this value for the new Token that you want to add, then
   -- update these comments for next time and the declaration of
   -- Next_Vacant_Token for next time.

   -- See S.P0468.53.1 "Implementation and Testing of the Lexical
   -- Token Manager"

end LexTokenManager;
