From 6653193ee68ef875e982febc94b6489915f1fb2c Mon Sep 17 00:00:00 2001 From: Jed Barber Date: Mon, 2 Mar 2020 11:59:47 +1100 Subject: Ada port of Java StringTokenizer class added --- misc/scanners.adb | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ misc/scanners.ads | 62 +++++++++++++++++++++++++++++++++++ 2 files changed, 159 insertions(+) create mode 100644 misc/scanners.adb create mode 100644 misc/scanners.ads 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; + -- cgit