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