diff options
| author | Jed Barber <jjbarber@y7mail.com> | 2020-03-02 11:59:47 +1100 | 
|---|---|---|
| committer | Jed Barber <jjbarber@y7mail.com> | 2020-03-02 11:59:47 +1100 | 
| commit | 6653193ee68ef875e982febc94b6489915f1fb2c (patch) | |
| tree | be597fd98b20aa7d89bc20e0b02581c71cd4132c | |
| parent | e6933c358056c481930dc9820adac7e5c13f9316 (diff) | |
Ada port of Java StringTokenizer class added
| -rw-r--r-- | misc/scanners.adb | 97 | ||||
| -rw-r--r-- | misc/scanners.ads | 62 | 
2 files changed, 159 insertions, 0 deletions
| diff --git a/misc/scanners.adb b/misc/scanners.adb new file mode 100644 index 0000000..296268b --- /dev/null +++ b/misc/scanners.adb @@ -0,0 +1,97 @@ + +package body Scanners is + + +    function Create +           (Input         : in String; +            Delimiters    : in String  := Default_Delimiters; +            Return_Delims : in Boolean := False) +        return Scanner is +    begin +        return This : Scanner do +            This.Text := UB.To_Unbounded_String (Input); +            This.Delimiters := SM.To_Set (Delimiters); +            This.Return_Delims := Return_Delims; +            This.Reset; +        end return; +    end Create; + + +    function Has_More_Tokens +           (This : in Scanner) +        return Boolean is +    begin +        return This.Next_Start <= This.Next_Finish; +    end Has_More_Tokens; + + +    procedure Queue_Next +           (This : in out Scanner) is +    begin +        if This.Return_Delims and then +           SM.Is_In (UB.Element (This.Text, This.Position), Default_Delimiter_Set) +        then +            This.Next_Start := This.Position; +            This.Next_Finish := This.Position; +        else +            UB.Find_Token +               (This.Text, This.Delimiters, This.Position, +                Ada.Strings.Outside, This.Next_Start, This.Next_Finish); +        end if; +        This.Position := This.Next_Finish + 1; +    end Queue_Next; + + +    function Next_Token +           (This : in out Scanner) +        return String +    is +        Old_Start  : Positive := This.Next_Start; +        Old_Finish : Natural  := This.Next_Finish; +    begin +        if not This.Has_More_Tokens then +            return ""; +        end if; +        if This.Position > UB.Length (This.Text) then +            This.Next_Finish := This.Next_Start - 1; +        else +            This.Queue_Next; +        end if; +        return UB.Slice (This.Text, Old_Start, Old_Finish); +    end Next_Token; + + +    function Remaining_Token_Count +           (This : in Scanner) +        return Natural +    is +        --  Copying an entire Scanner like this is not efficient, +        --  but this function will never be efficient, so at the +        --  moment I am choosing to favour clearer code. +        Test_Scan : Scanner := This; +        Count     : Natural := 0; +    begin +        while Test_Scan.Has_More_Tokens loop +            Count := Count + 1; +            exit when Test_Scan.Position > UB.Length (Test_Scan.Text); +            Test_Scan.Queue_Next; +        end loop; +        return Count; +    end Remaining_Token_Count; + + +    procedure Reset +           (This : in out Scanner) is +    begin +        This.Position := 1; +        if UB.Length (This.Text) > 0 then +            This.Queue_Next; +        else +            This.Next_Start := 1; +            This.Next_Finish := 0; +        end if; +    end Reset; + + +end Scanners; + diff --git a/misc/scanners.ads b/misc/scanners.ads new file mode 100644 index 0000000..4168fef --- /dev/null +++ b/misc/scanners.ads @@ -0,0 +1,62 @@ + +with Ada.Characters.Latin_1; +private with Ada.Strings.Unbounded, Ada.Strings.Maps; + +package Scanners is + +    --  This package roughly corresponds to +    --  the Java StringTokenizer class. + +    --  At the moment the most significant difference +    --  is that the Next_Token function does not raise +    --  an exception if there are no tokens to return. +    --- Instead, it returns an empty string. + +    type Scanner is tagged private; + +    Default_Delimiters : constant String := +        Ada.Characters.Latin_1.HT & +        Ada.Characters.Latin_1.LF & +        Ada.Characters.Latin_1.FF & +        Ada.Characters.Latin_1.CR & " "; + +    function Create +           (Input         : in String; +            Delimiters    : in String  := Default_Delimiters; +            Return_Delims : in Boolean := False) +        return Scanner; + +    function Has_More_Tokens +           (This : in Scanner) +        return Boolean; + +    function Next_Token +           (This : in out Scanner) +        return String; + +    function Remaining_Token_Count +           (This : in Scanner) +        return Natural; + +    procedure Reset +           (This : in out Scanner); + +private + +    package UB renames Ada.Strings.Unbounded; +    package SM renames Ada.Strings.Maps; + +    Default_Delimiter_Set : constant SM.Character_Set := +        SM.To_Set (Default_Delimiters); + +    type Scanner is tagged record +        Text          : UB.Unbounded_String := UB.Null_Unbounded_String; +        Position      : Positive            := 1; +        Next_Start    : Positive            := 1; +        Next_Finish   : Natural             := 0; +        Delimiters    : SM.Character_Set    := SM.Null_Set; +        Return_Delims : Boolean             := False; +    end record; + +end Scanners; + | 
