with Lines;
with Bounded_String;
with List_Generic;
package Structured_Comments_Solution is

    --
    --
    --      STRUCTURED COMMENT:
    --      Structured comments have the following characterstics:
    --
    --      - They begin with the Ada comment designator "--".
    --
    --      - They contain a keyword field and a value field separated by
    --        a colon.  (eg.  -- KEYWORD:  This is the value field  )
    --
    --      - Keywords may be any string but may not stretch across multiple
    --        lines.
    --
    --      - Value fields may stretch across several lines.
    --
    --      - All structured comments are terminated with a line
    --        containing a comment designator "--" with no following text.
    --
    --      EXAMPLES:
    --
    --           -- KEYWORD1:  This is a value field
    --           --
    --           -- KEYWORD2:  This is a value field that
    --           --            stretches across multiple lines.
    --           --
    --
    --
    --    Indiviual structured comments may be composed into comment blocks.
    --    A comment block is a series of structured comments with a
    --    designated order.
    --
    --    In the following example of a comment block:
    --
    --         -- AUTHOR: Blipo Bottombly
    --         --
    --         -- DATE: January 14, 1986
    --         --
    --         -- FUNCTIONAL UNIT: Database
    --         --
    --         -- DESCRIPTION: This is intended as an example
    --         --              of a multi-line structured
    --         --              comment. It does not need
    --         --                  to be aligned in
    --         --            any way.
    --         --
    --
    --    there is one comment block composed of 4 structured comments.
    --    The first has the keyword "AUTHOR" and a value field of
    --    " Blipo Bottombly".  The last comment in the block has the keyword
    --    "DESCRIPTION" and has a multiline value field.  The "value" of the
    --    value field should be a single string with embedded line feed
    --    characters to indicate line breaks.
    --
    --

    type Structured_Comment is private;

    subtype Comment_Keyword is String;

    function Define (Keyword : Comment_Keyword) return Structured_Comment;
    --
    -- The keyword of a structured comment is defined here.
    -- The value field is filled in by the Parse operation.


    function Keyword (Comment : Structured_Comment) return Comment_Keyword;

    function Value_Field (Comment : Structured_Comment) return Lines.Lines_Type;
    --
    -- This function will return an "empty" Lines_Type until a comment block
    -- contintaing this structured commment is parsed.

    type Comment_Block is private;

    function Initialize return Comment_Block;

    procedure Add_Structured_Comment
                 (To : in out Comment_Block; Comment : Structured_Comment);
    --
    -- This procedure must preserve the order in which comments appear
    -- in a block.  The first comments added to a block is the one at
    -- the top.

    type Comment_Iterator is limited private;

    procedure Initialize (Iter : out Comment_Iterator;
                          From_Block : Comment_Block);

    function Done (Iter : Comment_Iterator) return Boolean;
    function Value (Iter : Comment_Iterator) return Structured_Comment;
    procedure Next (Iter : in out Comment_Iterator);

    procedure Parse (Comment_Lines : Lines.Lines_Type;
                     Block : in out Comment_Block);

    -- parses a series of lines to determine if it matches the
    -- definition of a comment block.  If is does, the block is updated to
    -- contain values for the fields that appear after the keyword for
    -- each comment in the block.  If is does not match the block, the
    -- exception Illegal_Block_Format is raised.

    Illegal_Block_Format : exception;

private

    package Bounded renames Bounded_String;

    Max_Length : constant := 80;

    subtype Keyword_String is Bounded.Variable_String (Max_Length);

    type Structured_Comment is
        record
            Keyword : Keyword_String := Bounded.Value ("", Max_Length);
            Value : Lines.Lines_Type := Lines.Make;
        end record;

    package Comment_List is new List_Generic (Structured_Comment);

    type Comment_Block is new Comment_List.List;

    type Comment_Iterator is access Comment_List.Iterator;
end Structured_Comments_Solution;

