-- $Date: 2004/02/14 09:59:14 $
-- $Revision: 1.16 $
-- $Author: jcrocholl $

with Ada.Text_IO; use Ada.Text_IO;

with Strings; use Strings;

-- Light-weight text input file readers.
package Readers is

   -- Light-weight text input file reader.
   type Reader is tagged limited record
      -- File access.
      Filename : String_Access-- Input file name.
      File     : File_Type;     -- Input file handle.
      -- Error messages.
      Line_Number : Positive := 1; -- Line number in input file.
      Column      : Positive := 1; -- Index in current line.
      -- Temporary data.
      Char : Character-- Look ahead character.
   end record;

   -- Access types for instance variables.
   type Reader_Access is access Reader;

   -------------------------------------------
   -- Internal initialization and finalization
   -------------------------------------------

   -- These don't need to be called directly because the functions
   -- Current_Input, Open and Close will do it for you.

   -- Initialize a newly created reader instance.
   procedure Initialize_Reader
     (This : access Reader'Class); -- Initialize this reader.

   -- Initialize a newly created reader instance with a file to read.
   procedure Initialize_Reader
     (This     : access Reader'Class-- Initialize this reader.
      Filename : in String);               -- Open this file for reading.

   -- Close the input file.
   procedure Finalize_Reader
     (This : access Reader'Class); -- Finalize this reader.

   -------------------
   -- Creating readers
   -------------------

   -- Create a reader for current input (stdin).
   function Current_Input
     return Reader_Access-- The newly created reader instance.

   -- Create a reader for file input.
   function Open
     (Filename : in String-- Open this file.
     return Reader_Access;  -- The newly created reader instance.

   -- Close a reader's input file.
   procedure Close
     (This : in out Reader_Access); -- Close this reader.

   --------------------------
   -- Wrappers for file input
   --------------------------

   -- Check for end of line.
   function End_Of_Line
     (This : access Reader'Class-- Check EOL on this reader.
     return Boolean;                   -- End of line reached?

   -- Check if the end of the input file has been reached.
   function End_Of_File
     (This : access Reader'Class-- Check EOF on this reader.
     return Boolean;                   -- End of input file?

   -- Get the next input character into This.C.
   procedure Get
     (This : access Reader'Class); -- Get character for this reader.

   -----------------
   -- Error handling
   -----------------

   -- The input syntax has been violated.
   Syntax_Error : exception;

   -- Print an error message, then raise Syntax_Error.
   procedure Error
     (This    : access Reader'Class-- Print error about this reader.
      Message : in String);               -- Print this message.

   -- Concatenate two strings in a special format acceptable for
   -- expectation errors.
   function "/"
     (A, B : in String-- Join these strings.
     return String;     -- The combination with some joining text.

   -- Print a formatted error message for unmatched expectations, then
   -- raise Syntax_Error.
   procedure Expect_Error
     (This    : access Reader'Class-- Print error about this reader.
      Found   : in String;                -- But this text was found.
      Choices : in String);               -- This text was expected.

   ---------------------
   -- Reading characters
   ---------------------

   -- Read the current character.
   function Get_Char
     (This : access Reader'Class-- Use this reader.
     return Character;                 -- The character that was read.

   -- Check if a given token was found.
   function Found_Char
     (This : access Reader'Class-- Check character in this reader.
      Char : in Character)             -- Check if this character was found.
     return Boolean;                   -- True if the given character was found.

   -- Test if the current look-ahead character is what we expect.
   -- Call Error if not, and that raises Syntax_Error.
   procedure Assert_Char
     (This : access Reader'Class-- Check character in this reader.
      Char : in Character);            -- Expect this character.

end Readers;