-------------------------------------------------------------------------------
-- (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 E_Strings;
with LexTokenManager;
with SPARK_IO;
with SP_Symbols;

use type LexTokenManager.Line_Numbers; use type SP_Symbols.SP_Symbol;

--# inherit Ada.Characters.Handling,
--#         Ada.Characters.Latin_1,
--#         CommandLineData,
--#         Dictionary,
--#         ErrorHandler,
--#         E_Strings,
--#         LexTokenLists,
--#         LexTokenManager,
--#         SPARK_IO,
--#         SP_Symbols,
--#         SystemErrors;
package SparkLex
--# own Curr_Line : Line_Context;
is
   --# function Curr_Line_Invariant (Curr_Line : Line_Context) return Boolean;

   type Line_Context is private;

   Null_Line_Context : constant Line_Context;

   procedure Clear_Line_Context;
   --# global out Curr_Line;
   --# derives Curr_Line from ;
   --# post Curr_Line_Invariant (Curr_Line);

   procedure Store_Line_Context (File_Line : out Line_Context);
   --# global in Curr_Line;
   --# derives File_Line from Curr_Line;
   --# pre Curr_Line_Invariant (Curr_Line);
   --# post Curr_Line_Invariant (File_Line);

   procedure Restore_Line_Context (File_Line : in Line_Context);
   --# global out Curr_Line;
   --# derives Curr_Line from File_Line;
   --# pre Curr_Line_Invariant (File_Line);
   --# post Curr_Line_Invariant (Curr_Line);

   -- Returns True iff ExStr is an FDL reserved word
   function Check_FDL_RW (Ex_Str : E_Strings.T) return Boolean;

   -- Scan ProgText and return next token found with class Token
   -- and value LexVal.  PunctToken is True iff the scanned token
   -- is deemed to be a "punctutation token" which can be ignored
   -- by the parser.
   --
   -- The exact list of "Punctutation Tokens" is defined in
   -- SPARKLex.Lex.IsPunctToken
   procedure Examiner_Lex
     (Prog_Text   : in     SPARK_IO.File_Type;
      Token       :    out SP_Symbols.SP_Terminal;
      Lex_Val     :    out LexTokenManager.Lex_Value;
      Punct_Token :    out Boolean);
   --# global in     CommandLineData.Content;
   --#        in     Dictionary.Dict;
   --#        in out Curr_Line;
   --#        in out ErrorHandler.Error_Context;
   --#        in out LexTokenManager.State;
   --#        in out SPARK_IO.File_Sys;
   --# derives Curr_Line,
   --#         ErrorHandler.Error_Context,
   --#         LexTokenManager.State,
   --#         Lex_Val,
   --#         Punct_Token,
   --#         SPARK_IO.File_Sys,
   --#         Token                      from CommandLineData.Content,
   --#                                         Curr_Line,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         LexTokenManager.State,
   --#                                         Prog_Text,
   --#                                         SPARK_IO.File_Sys;
   --# pre Curr_Line_Invariant (Curr_Line);
   --# post Curr_Line_Invariant (Curr_Line);

   -- This version behaves as ExaminerLex, but _allows_ identifiers
   -- beginning with $ to allow for pre-processing and macro-substitution
   -- of such identifiers by tools such as GNATPREP.
   procedure SPARK_Format_Lex
     (Prog_Text   : in     SPARK_IO.File_Type;
      Token       :    out SP_Symbols.SP_Terminal;
      Lex_Val     :    out LexTokenManager.Lex_Value;
      Punct_Token :    out Boolean);
   --# global in     CommandLineData.Content;
   --#        in     Dictionary.Dict;
   --#        in out Curr_Line;
   --#        in out ErrorHandler.Error_Context;
   --#        in out LexTokenManager.State;
   --#        in out SPARK_IO.File_Sys;
   --# derives Curr_Line,
   --#         ErrorHandler.Error_Context,
   --#         LexTokenManager.State,
   --#         Lex_Val,
   --#         Punct_Token,
   --#         SPARK_IO.File_Sys,
   --#         Token                      from CommandLineData.Content,
   --#                                         Curr_Line,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         LexTokenManager.State,
   --#                                         Prog_Text,
   --#                                         SPARK_IO.File_Sys;
   --# pre Curr_Line_Invariant (Curr_Line);
   --# post Curr_Line_Invariant (Curr_Line);

   -- Returns True if Token1 and Token2 are both
   --    Delimiters (such as operators, [ ], and %)
   -- or both Numbers (integers, real, based literals etc.)
   -- or both Character or String literals
   -- or both Identifiers
   -- or both Reserved Words
   -- or both "Others" (not falling into any of the catogories above)
   function Similar_Tokens (Token1, Token2 : SP_Symbols.SP_Terminal) return Boolean;

private

   type Program_Context is (In_Ada, In_Annotation);

   type Annotation_Context is (Start_Annotation, Mid_Annotation, Ended_Annotation);

   type Line_Context is record
      Context                                 : Program_Context;
      Anno_Context                            : Annotation_Context;
      Line_No                                 : LexTokenManager.Line_Numbers;
      Last_Token_Pos, Curr_Pos, Lookahead_Pos : E_Strings.Positions;
      Conts                                   : E_Strings.T;
   end record;

   Null_Line_Context : constant Line_Context :=
     Line_Context'
     (Context        => In_Ada,
      Anno_Context   => Start_Annotation,
      Line_No        => LexTokenManager.Line_Numbers'First,
      Last_Token_Pos => E_Strings.Positions'First,
      Curr_Pos       => E_Strings.Positions'First,
      Lookahead_Pos  => E_Strings.Positions'First,
      Conts          => E_Strings.Empty_String);
end SparkLex;
