File : marks-scanners.ads


-- Marks.Scanners (decl)
--
-- Root type for mark-scanners for various programming languages
-- or mark formats. Set of available scanners. Choosing the proper
-- scanner by command-line option or file-name suffix.
--
-- This package defines an abstract tagged type with an operation
-- to scan a source-code line and find the marks on this line. From
-- this abstract type, child packages derive concrete types, one for
-- each mark format, for example for the different formats (of comments)
-- used in different programming languages.
--
-- This package also maintains a set that contains all available
-- scanner objects and provides operations to enter (register)
-- scanners in the set and to choose a scanner from the set, either
-- by command-line option or by the suffix of the name of the source
-- file to be scanned.
--
-- Copyright (c) 2009 Tidorum Ltd.
--
-- This file is part of Find_Marks.
--
-- Find_Marks is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program 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
-- along with this program.  If not, see <http://www.gnu.org/licenses/>.


package Marks.Scanners is


   --
   ---   Scanning for marks: abstract root class
   --


   type Scanner_T is abstract tagged null record;
   --
   -- A class of objects that can scan source-code lines for marks.


   type Scanner_Ref is access all Scanner_T'Class;


   -- not overriding
   procedure Scan (
      Line     : in     String;
      Scanner  : in out Scanner_T;
      Markable :    out Boolean)
   is abstract;
   --
   -- Scans the Line to find the mark definitions as expected by
   -- this Scanner.
   --
   -- The procedure shall define each detected mark through the Define
   -- procedure (see below).
   --
   -- The procedure shall set Markable to show whether this source-code
   -- Line is a "markable" line in the sense that the compiler is likely
   -- to generate some instructions that are mapped to this Line, in the
   -- compiler-generated mapping of instruction address to source-line
   -- number.
   --
   -- Note that Scanner is "in out". Thus, it can keep track of context,
   -- for example to detect "block comments" in which not every line is
   -- independently recognizable as a comment.


   -- not overriding
   procedure Handle_Option (
      Option  : in     String;
      Scanner : in out Scanner_T;
      Valid   :    out Boolean;
      Chosen  :    out Boolean)
   is abstract;
   --
   -- Asks this Scanner to handle this command-line Option.
   --
   -- Option
   --    The command-line argument starting with '-'.
   -- Scanner
   --    The scanner object that perhaps handles this Option.
   -- Valid
   --    Whether this Scanner recognizes and handles this Option.
   -- Chosen
   --    Whether this command-line Option chooses this Scanner
   --    as the proper scanner for the following source-code
   --    files. Chosen implies Valid.


   -- not overriding
   function Suffix_Chooses_Me (
      Suffix  : String;
      Scanner : Scanner_T)
   return Boolean
   is abstract;
   --
   -- Whether this file-name Suffix chooses this Scanner as the
   -- proper scanner for the file with this name (and Suffix).


   --
   ---   The set of available scanners
   --


   procedure Register (Me : Scanner_Ref);
   --
   -- Enters this scanner object in the set of available scanners.


   function Scanner_By_Option (Option : String) return Scanner_Ref;
   --
   -- The scanner (if any) chosen by this command-line Option, from
   -- the set of available (registered) scanners.  Returns null if
   -- no registered scanner responds to the Option.


   function Scanner_By_Suffix (Suffix : String) return Scanner_Ref;
   --
   -- The scanner (if any) chosen by this file-name Suffix, from
   -- the set of available (registered) scanners. Returns null if
   -- no registered scanner responds to the Suffix.


   --
   ---   Scanning utilities for use in specific scanners
   --


   function Begins_By (Prefix, Text : String) return Boolean;
   --
   -- Whether the given Text begins with the given Prefix.


   function First_Visible (Text : String) return Natural;
   --
   -- The index in Text of the first non-whitespace character,
   -- or zero if there is no such character in the Text.


   procedure Find_First_Word (
      Within : in     String;
      First  : in out Positive;
      Last   :    out Natural);
   --
   -- Finds the first white-space-separated substring Within
   -- the given string, starting at Within(First). On return,
   -- the found substring is Within(First .. Last). If no such
   -- substring exists in Within(First ..) the return values
   -- show Last < First.


   procedure To_Part (
      Word  : in     String;
      Valid :    out Boolean;
      Part  : in out Part_T);
   --
   -- Tries to understand the Word as the name of a Part.
   -- On success, Valid is True and Part is this part.
   -- Otherwise Valid is False and Part is not changed.


   procedure To_Position (
      Word     : in     String;
      Valid    :    out Boolean;
      Position : in out Position_T);
   --
   -- Tries to understand the Word as identifying a Position.
   -- On success, Valid is True and Position is this Position.
   -- Otherwise Valid is False and Position is not changed.


   procedure To_Relation (
      Word     : in     String;
      Valid    :    out Boolean;
      Relation : in out Relation_T);
   --
   -- Tries to understand the Word as identifying a Relation.
   -- On success, Valid is True and Relation is this Position.
   -- Otherwise Valid is False and Relation is not changed.


   procedure Find_Mark_Properties (
      Within     : in     String;
      Properties : in out Properties_T;
      First      : in out Positive;
      Last       :    out Natural);
   --
   -- Successively finds whitespace-separated words Within
   -- the given string, starting at Within(First) and
   -- advancing from left to right, and tries to understand
   -- each word as a part name, a position, or a relation.
   -- Stops when there are no more words (giving Last < First)
   -- or when a word is found that does not name a part,
   -- position, or relation; that word is then the substring
   -- Within(First .. Last).
   --
   -- The word "line" is considered a meaningless noise
   -- word and is skipped without effect.
   --
   -- If no word naming a part is found, the Properties.Part
   -- component is not changed, and analogously for the components
   -- Properties.Position and Properties.Relation.


   procedure Find_Properties_And_Names (
      Text : in String;
      Quit : in String);
   --
   -- The text is expected to start with mark properties, for
   -- which Find_Mark_Properties is invoked, and to continue with
   -- a list of whitespace-separated marker names, for each of
   -- which a mark is defined with those properties and based on
   -- the current source-code position.
   --
   -- The list of marker names can be terminated by end of Text
   -- or by the Quit word (if Quit /= ""). The Quit word itself
   -- is not taken as a marker name.


end Marks.Scanners;