with Dyn;
--================================================================
-- DYN contains dynamic-string manipulation operations. We used ==
-- it only to show a certain degree of "reusability" in Ada.    ==
-- DYN is created by ... and a machine-readable version of it   ==
-- can be found on the INFO-ADA.                                ==
--================================================================

separate (Compilation_Unit)
function Concatenate
            (First_Token_Location : in Ada_Compilation_Unit;
             Last_Token_Location : in Ada_Compilation_Unit) return String is

    --===============================================================
    -- Concatenate will append one or more significant tokens      ==
    -- starting from First_Token_Location up to and including      ==
    -- Last_Token_Location. If First_Token_Location is ahead of    ==
    -- Last_Token_Location, exception SYNTAX_ERROR will be raised. ==
    -- The result will be returned in string format.               ==
    --===============================================================

    -- keeps track of the string value of the current token
    Current_String : Dyn.Dyn_String := Dyn.D_String ("");

    -- Next_String contains the string values of all
    -- significant tokens between First_Token_Location to
    -- Last_Token_Location inclusive.
    Next_String : Dyn.Dyn_String := Dyn.D_String ("");

    -- Current_Token contains the current token.
    Current_Token : Token_Package.Token;

    Pointer_To_Current_Token : New_List.List;

begin
    -- Concatenate

    -- copy First_Token_Location
    New_List.Share (The_List => New_List.List (First_Token_Location),
                    With_The_List => Pointer_To_Current_Token);

    Concatenate_Tokens:
        loop

            Current_Token := New_List.Content_Of (Pointer_To_Current_Token);

            -- concatenate previous token with current token
            Current_String := Dyn.D_String
                                 (Token_Package.Value_Of (Current_Token));

            Next_String := Dyn."&" (Next_String, Current_String);

            exit Concatenate_Tokens when
               New_List.Is_Equal (Pointer_To_Current_Token,
                                  New_List.List (Last_Token_Location));

            -- advance First_Token_Location to the next significant
            -- token.
            New_List.Share (The_List => New_List.Seek
                                           (Pointer_To_Current_Token, +1),
                            With_The_List => Pointer_To_Current_Token);

        end loop Concatenate_Tokens;

    return Dyn.Str (Next_String);

exception
    when New_List.Overflow =>
        raise Syntax_Error;

end Concatenate;