diff options
Diffstat (limited to 'misc/scanners.adb')
-rw-r--r-- | misc/scanners.adb | 97 |
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; + |