------------------------------------------------------------------------------
--                                                                          --
--                      DISPLAY_SOURCE COMPONENTS                           --
--                                                                          --
--                         S O U R C E _ T R A V                            --
--                                                                          --
--                                 S p e c                                  --
--                                                                          --
--            Copyright (c) 1995-2000, Free Software Foundation, Inc.       --
--                                                                          --
-- Display_Source 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 2,  or  (at your option)  any later --
-- version. Display_Source is distributed in the hope  that it will be use- --
-- ful, but WITHOUT ANY WARRANTY; without even the implied warranty of MER- --
-- CHANTABILITY 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 GNAT; see file COPYING. If   --
-- not, write to the Free Software Foundation, 59 Temple Place Suite 330,   --
-- Boston, MA 02111-1307, USA.                                              --
--                                                                          --
-- Display_Source is distributed as a part of the ASIS implementation for   --
-- GNAT (ASIS-for-GNAT).                                                     --
--                                                                          --
-- The   original   version   of  Display_Source  has  been  developed  by  --
-- Jean-Charles  Marteau and Serge Reboul,  ENSIMAG  High School Graduates  --
-- (Computer sciences)  Grenoble,  France  in  Sema Group Grenoble, France. --
--                                                                          --
-- Display_Source is now maintained by Ada Core Technologies Inc            --
-- (http://www.gnat.com).                                                   --
------------------------------------------------------------------------------

-----------------------------------------------------------------
-- This package is part of the ASIS application display_source --
-----------------------------------------------------------------
-- It contains procedures to instantiate Traverse_Element with --
-- in order to make a redisplay of the given source.           --
-- This functionality is used for test purpose, but it could   --
-- be basis for an Asis application.                           --
-- In fact it is not finished yet, because some pretty features--
-- could be added in order to have something nicer ...         --
-----------------------------------------------------------------
with Asis;
with Stacks;

package Source_Trav is

   ------------------------------------
   -- Some type definitions required --
   ------------------------------------

   --  The different kinds of lists of elements
   type List_Kinds is
     (Not_In_A_List,
      Is_Comma_List,
      Is_Comma_Range_List,
      Is_Semi_Colon_List,
      Is_Comma_No_Parenthesis_List,
      Is_Vertical_Line_List);

   subtype Parenthesized_List is List_Kinds range
     Is_Comma_List .. Is_Semi_Colon_List;

   type String_Access is access String;
   --  added to fix the problem with 309

   Separator : array (List_Kinds) of String_Access :=
     (new String'("<<NO ! We're not in a list !>>"),
       new String'(","),
       new String'(","), -- we add "range <>" after each element
       new String'(";"),
       new String'(","),
       new String'("|"));

   -------------------------------------------------------------------
   --  Lexical Node :
   --  Normaly, only the first 3 parameters are to be known of the user
   --  the others are here for other procedures to deal with.
   type Lexical_Node is
      record
         --  Lexem is a string that the program will display after having
         --  finished to process the current lexical node.

--         Lexem : Ada.Strings.Unbounded.Unbounded_String :=
--           Ada.Strings.Unbounded.Null_Unbounded_String;

         Lexem : String_Access;

         --  This is the kind of the list we are currently in.
         --  use Not_In_A_List if you have a single element.
         List_Kind : List_Kinds := Not_In_A_List;

         --  This is the number of elements that remain to be processed in the
         --  list single elements are represented by a Number_Of_Elements
         --  equal to 1
         Number_Of_Elements : Natural := 1;

         ---------------------------------------------------------------------
         --  The boolean First_Passed is true when the first element of a list
         --  has been passed (used to know if the separarator and the
         --  parenthesis is to be displayed) cannot be set or read
         First_Passed : Boolean := False;

         --  Indentation is the number of space to be put after a return.
         --  This is the real indentation that will be used for the string
         --  contained in Lexem.
         --  cannot be set or read
         Indentation : Natural := 0;

         --  This is the indentation reference for children.
         --  This will become the new Indentation for childs element
         --  of this node. That is because Pass_Element turns this
         --  value into the Current_Indentation_Reference.
         --  It is set by the Indent procedure.
         --  cannot be read
         Indentation_Reference : Natural := 0;

         --  No_Space is used to specify that one's mustn't print a space
         --  before a selector for instance (A.B  or  A'First ...)
         --  It is set by the No_Space procedure
         --  cannot be read
         No_Space : Boolean := False;

         --  Return_list is used to specify that we should return after each
         --  element of a list ...
         --  It is set by procedure Check_If_Return_Separator
         --  cannot be read
         Return_List : Boolean := False;

         --  The problem in function calls is that the things don't appear in
         --  the order they should be displayed, so we must have this flag ...
         --  It is used to make the difference between
         --   1 + 2   and  "+" (1, 2)
         --  It is set by Infix procedure.
         --  And read by Is_Infix function.
         Infixed_Operator : Boolean := False;
      end record;
   -------------------------------------------------------------------

   type A_Lexical_Node is access all Lexical_Node;

   package Node_Stack is new Stacks (Lexical_Node, A_Lexical_Node);

   type Info_Source is record
      --  Default_Indentation_Element is the default number of spaces to add
      --  when you use the Indent function (note that Indent also accepts
      --  an optional parameter telling the number of spaces needed)
      Default_Indentation_Element : Natural := 2;

      --  When a list element sizes more than this number of
      --  space there a return between each element. (Not Implemented)
      Max_Size_Of_List_Elem_Before_Return : Natural := 10;

      --  Declaration of the stacks needed ...
      Lexical_Stack, Tmp_Stack : Node_Stack.Stack := Node_Stack.Empty_Stack;

      --  That is the reference for the current traversed element.
      --  it means that this is the value pushed by the function push.
      --  In Pass_Element, this value is reset with the Indentation_Reference
      --  of the Upper lexical node.
      Current_Indentation_Reference : Natural := 0;

      --  Last_Commented_Line is a counter that helps displaying the
      --  comments. It says that all comments from line 1 to
      --  Last_Commented_Line have already been displayed. 0 means that no
      --  line was displayed. It is a number of line in the original file.
      Last_Commented_Line : Natural := 0;

      --  Horizontal_Position and Vertical_Position are the current
      --  positions in the generated file.
      Horizontal_Position : Natural := 0;
      Vertical_Position   : Natural := 1;

      --  Is a limit to avoid line too long errors...
      --  In fact we should not need this ... but knowing
      --  when to put a new_line in lists is not that easy...
      Max_Line_Length : Positive := 100;

      --  Last_Char_Was_Return and Last_Char_Was_Space are used
      --  for smart display. In fact returns and spaces are not
      --  writen immediately, but just before writing something
      --  else, so these boolean are used to keep the trace of
      --  the corresponding characters.
      Last_Char_Was_Return : Boolean := False;
      Last_Char_Was_Space : Boolean := False;

      --  At the end of the display source ... the stack may not be
      --  empty, so we need this boolean to say that we don't want
      --  any element to be processed but only the stack to be poured.
      Finishing_Traversal : Boolean := False;
   end record;

   procedure Pre_Source
   (Element : in     Asis.Element;
    Control : in out Asis.Traverse_Control;
    State   : in out Info_Source);

   procedure Post_Source
   (Element : in     Asis.Element;
    Control : in out Asis.Traverse_Control;
    State   : in out Info_Source);

   procedure Initiate_Source
     (Unit    : in    Asis.Compilation_Unit;
      Name    : in    String;
      Control : in out Asis.Traverse_Control;
      State   : in out Info_Source);

   procedure Terminate_Source
     (Control : in out Asis.Traverse_Control;
      State   : in out Info_Source);

end Source_Trav;
