summaryrefslogtreecommitdiff
path: root/misc
diff options
context:
space:
mode:
Diffstat (limited to 'misc')
-rw-r--r--misc/scanners.adb97
-rw-r--r--misc/scanners.ads62
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;
+