blob: 296268bf0cb4432d7572a3686618efdd5aab20e6 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
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;
|