markdown_24.0.0_70ffe37b/source/parser/implementation/markdown-emphasis_delimiters.ads

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
--
--  Copyright (C) 2021-2023, AdaCore
--
--  SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
--

--  Emphasis and links delimiters with a parsing routine

with Ada.Containers.Vectors;

with VSS.Strings.Character_Iterators;
with VSS.Strings.Cursors.Markers;
with VSS.Regular_Expressions;

private
package Markdown.Emphasis_Delimiters is
   pragma Preelaborate;

   type Delimiter_Kind is ('*', '_', '[', ']');
   --  A kind of delimiters used in emphasis or links

   subtype Emphasis_Kind is Delimiter_Kind range '*' .. '_';

   type Delimiter (Kind       : Delimiter_Kind := '*') is record
      From       : VSS.Strings.Cursors.Markers.Character_Marker;
      --  Where the delimiter starts
      Is_Deleted : Boolean := False;  --  Marker for ignorance

      case Kind is
         when Emphasis_Kind =>
            Count     : VSS.Strings.Character_Index;  --  number of stars, etc
            Is_Active : Boolean;
            Can_Open  : Boolean;
            Can_Close : Boolean;
         when '[' =>
            null;
         when ']' =>
            To : VSS.Strings.Cursors.Markers.Character_Marker;
      end case;
   end record;
   --  A delimiter used in emphasis or links

   type Scanner is tagged limited private;
   --  A delimiter scanner

   procedure Read_Delimiter
     (Self   : in out Scanner;
      Text   : VSS.Strings.Virtual_String;
      Cursor : in out VSS.Strings.Character_Iterators.Character_Iterator;
      Item   : out Delimiter;
      Found  : out Boolean)
        with Inline;
   --  Scan input Text starting from a position pointed by the Cursor and
   --  check for a delimiter run.
   --
   --  For emphasis a delimiter run is either a sequence of one or more `*`
   --  characters that is not preceded or followed by a non-backslash-escaped
   --  `*` character, or a sequence of one or more `_` characters that is not
   --  preceded or followed by a non-backslash-escaped `_` character.
   --
   --  For a link, a delimiter run is just `[` or `]` characters.
   --
   --  Return `Found = True` and Item if the delimiter is found.
   --  Move Cursor after delimiter or forward one character if not found.

   procedure Reset (Self : in out Scanner);
   --  Reset the scanner to an initial state

   type Delimiter_Filter_Kind is
     (Any_Element,
      Kind_Of,
      Emphasis_Close,
      Emphasis_Open);

   type Delimiter_Filter (Kind : Delimiter_Filter_Kind := Any_Element) is
      record
         case Kind is
            when Any_Element | Emphasis_Close =>
               null;
            when Kind_Of =>
               Given_Kind : Delimiter_Kind;
            when Emphasis_Open =>
               Emphasis   : Emphasis_Kind;
         end case;
      end record;

   subtype Delimiter_Index is Positive;

   package Delimiter_Vectors is new Ada.Containers.Vectors
     (Delimiter_Index, Delimiter);

   subtype Extended_Delimiter_Index is Delimiter_Vectors.Extended_Index;

   function Each
     (Self   : aliased Delimiter_Vectors.Vector;
      Filter : Delimiter_Filter := (Kind => Any_Element);
      From   : Delimiter_Index := 1;
      To     : Extended_Delimiter_Index := Extended_Delimiter_Index'Last)
        return Delimiter_Vectors.Vector_Iterator_Interfaces
          .Reversible_Iterator'Class;
   --  Iterate in a given range From .. To filtering elements according to
   --  Filter.

private

   type Scanner_State is record
      Is_White_Space : Boolean := True;
      Is_Punctuation : Boolean := False;
   end record;

   type Scanner is tagged limited record
      State   : Scanner_State;
      Pattern : VSS.Regular_Expressions.Regular_Expression;
   end record;

end Markdown.Emphasis_Delimiters;