1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
11 -- Copyright (C) 1992-2001 Free Software Foundation, Inc. --
13 -- GNAT is free software; you can redistribute it and/or modify it under --
14 -- terms of the GNU General Public License as published by the Free Soft- --
15 -- ware Foundation; either version 2, or (at your option) any later ver- --
16 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
17 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
18 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
19 -- for more details. You should have received a copy of the GNU General --
20 -- Public License distributed with GNAT; see file COPYING. If not, write --
21 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
22 -- MA 02111-1307, USA. --
24 -- GNAT was originally developed by the GNAT team at New York University. --
25 -- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
27 ------------------------------------------------------------------------------
29 with Uintp
; use Uintp
;
30 with Urealp
; use Urealp
;
36 -- Current source program character
38 Base_Char
: Character;
39 -- Either # or : (character at start of based number)
45 -- Value of base in Uint format
48 -- Value of integer scanned by Scan_Integer in Uint format
51 -- Value of integer in numeric value being scanned
54 -- Scale value for real literal
57 -- Scale in Uint format
59 Exponent_Is_Negative
: Boolean;
60 -- Set true for negative exponent
62 Extended_Digit_Value
: Int
;
63 -- Extended digit value
65 Point_Scanned
: Boolean;
66 -- Flag for decimal point scanned in numeric literal
68 -----------------------
69 -- Local Subprograms --
70 -----------------------
72 procedure Error_Digit_Expected
;
73 -- Signal error of bad digit, Scan_Ptr points to the location at which
74 -- the digit was expected on input, and is unchanged on return.
76 procedure Scan_Integer
;
77 -- Procedure to scan integer literal. On entry, Scan_Ptr points to a
78 -- digit, on exit Scan_Ptr points past the last character of the integer.
79 -- For each digit encountered, UI_Int_Value is multiplied by 10, and the
80 -- value of the digit added to the result. In addition, the value in
81 -- Scale is decremented by one for each actual digit scanned.
83 --------------------------
84 -- Error_Digit_Expected --
85 --------------------------
87 procedure Error_Digit_Expected
is
89 Error_Msg_S
("digit expected");
90 end Error_Digit_Expected
;
96 procedure Scan_Integer
is
98 -- Next character scanned
101 C
:= Source
(Scan_Ptr
);
103 -- Loop through digits (allowing underlines)
106 Accumulate_Checksum
(C
);
108 UI_Int_Value
* 10 + (Character'Pos (C
) - Character'Pos ('0'));
109 Scan_Ptr
:= Scan_Ptr
+ 1;
111 C
:= Source
(Scan_Ptr
);
114 Accumulate_Checksum
('_');
117 Scan_Ptr
:= Scan_Ptr
+ 1;
118 C
:= Source
(Scan_Ptr
);
120 Error_No_Double_Underline
;
123 if C
not in '0' .. '9' then
124 Error_Digit_Expected
;
129 exit when C
not in '0' .. '9';
135 ----------------------------------
136 -- Start of Processing for Nlit --
137 ----------------------------------
142 UI_Int_Value
:= Uint_0
;
146 Point_Scanned
:= False;
147 UI_Num_Value
:= UI_Int_Value
;
149 -- Various possibilities now for continuing the literal are
150 -- period, E/e (for exponent), or :/# (for based literal).
153 C
:= Source
(Scan_Ptr
);
157 -- Scan out point, but do not scan past .. which is a range sequence,
158 -- and must not be eaten up scanning a numeric literal.
160 while C
= '.' and then Source
(Scan_Ptr
+ 1) /= '.' loop
161 Accumulate_Checksum
('.');
163 if Point_Scanned
then
164 Error_Msg_S
("duplicate point ignored");
167 Point_Scanned
:= True;
168 Scan_Ptr
:= Scan_Ptr
+ 1;
169 C
:= Source
(Scan_Ptr
);
171 if C
not in '0' .. '9' then
172 Error_Msg
("real literal cannot end with point", Scan_Ptr
- 1);
175 UI_Num_Value
:= UI_Int_Value
;
179 -- Based literal case. The base is the value we already scanned.
180 -- In the case of colon, we insist that the following character
181 -- is indeed an extended digit or a period. This catches a number
182 -- of common errors, as well as catching the well known tricky
183 -- bug otherwise arising from "x : integer range 1 .. 10:= 6;"
186 or else (C
= ':' and then
187 (Source
(Scan_Ptr
+ 1) = '.'
189 Source
(Scan_Ptr
+ 1) in '0' .. '9'
191 Source
(Scan_Ptr
+ 1) in 'A' .. 'Z'
193 Source
(Scan_Ptr
+ 1) in 'a' .. 'z'))
195 Accumulate_Checksum
(C
);
197 UI_Base
:= UI_Int_Value
;
199 if UI_Base
< 2 or else UI_Base
> 16 then
200 Error_Msg_SC
("base not 2-16");
204 Base
:= UI_To_Int
(UI_Base
);
205 Scan_Ptr
:= Scan_Ptr
+ 1;
207 -- Scan out extended integer [. integer]
209 C
:= Source
(Scan_Ptr
);
210 UI_Int_Value
:= Uint_0
;
214 if C
in '0' .. '9' then
215 Accumulate_Checksum
(C
);
216 Extended_Digit_Value
:=
217 Int
'(Character'Pos (C)) - Int'(Character'Pos ('0'));
219 elsif C
in 'A' .. 'F' then
220 Accumulate_Checksum
(Character'Val (Character'Pos (C
) + 32));
221 Extended_Digit_Value
:=
222 Int
'(Character'Pos (C)) - Int'(Character'Pos ('A')) + 10;
224 elsif C
in 'a' .. 'f' then
225 Accumulate_Checksum
(C
);
226 Extended_Digit_Value
:=
227 Int
'(Character'Pos (C)) - Int'(Character'Pos ('a')) + 10;
230 Error_Msg_S
("extended digit expected");
234 if Extended_Digit_Value
>= Base
then
235 Error_Msg_S
("digit >= base");
238 UI_Int_Value
:= UI_Int_Value
* UI_Base
+ Extended_Digit_Value
;
240 Scan_Ptr
:= Scan_Ptr
+ 1;
241 C
:= Source
(Scan_Ptr
);
245 Accumulate_Checksum
('_');
246 Scan_Ptr
:= Scan_Ptr
+ 1;
247 C
:= Source
(Scan_Ptr
);
249 Error_No_Double_Underline
;
253 Accumulate_Checksum
('.');
255 if Point_Scanned
then
256 Error_Msg_S
("duplicate point ignored");
259 Scan_Ptr
:= Scan_Ptr
+ 1;
260 C
:= Source
(Scan_Ptr
);
261 Point_Scanned
:= True;
264 elsif C
= Base_Char
then
265 Accumulate_Checksum
(C
);
266 Scan_Ptr
:= Scan_Ptr
+ 1;
269 elsif C
= '#' or else C
= ':' then
270 Error_Msg_S
("based number delimiters must match");
271 Scan_Ptr
:= Scan_Ptr
+ 1;
274 elsif not Identifier_Char
(C
) then
275 if Base_Char
= '#' then
276 Error_Msg_S
("missing '#");
278 Error_Msg_S
("missing ':");
286 UI_Num_Value
:= UI_Int_Value
;
291 if not Point_Scanned
then
295 UI_Scale
:= UI_From_Int
(Scale
);
298 if Source
(Scan_Ptr
) = 'e' or else Source
(Scan_Ptr
) = 'E' then
299 Accumulate_Checksum
('e');
300 Scan_Ptr
:= Scan_Ptr
+ 1;
301 Exponent_Is_Negative
:= False;
303 if Source
(Scan_Ptr
) = '+' then
304 Accumulate_Checksum
('+');
305 Scan_Ptr
:= Scan_Ptr
+ 1;
307 elsif Source
(Scan_Ptr
) = '-' then
308 Accumulate_Checksum
('-');
310 if not Point_Scanned
then
311 Error_Msg_S
("negative exponent not allowed for integer literal");
313 Exponent_Is_Negative
:= True;
316 Scan_Ptr
:= Scan_Ptr
+ 1;
319 UI_Int_Value
:= Uint_0
;
321 if Source
(Scan_Ptr
) in '0' .. '9' then
324 Error_Digit_Expected
;
327 if Exponent_Is_Negative
then
328 UI_Scale
:= UI_Scale
- UI_Int_Value
;
330 UI_Scale
:= UI_Scale
+ UI_Int_Value
;
334 -- Case of real literal to be returned
336 if Point_Scanned
then
337 Token
:= Tok_Real_Literal
;
338 Token_Node
:= New_Node
(N_Real_Literal
, Token_Ptr
);
339 Set_Realval
(Token_Node
,
345 -- Case of integer literal to be returned
348 Token
:= Tok_Integer_Literal
;
349 Token_Node
:= New_Node
(N_Integer_Literal
, Token_Ptr
);
352 Set_Intval
(Token_Node
, UI_Num_Value
);
354 -- Avoid doing possibly expensive calculations in cases like
355 -- parsing 163E800_000# when semantics will not be done anyway.
356 -- This is especially useful when parsing garbled input.
358 elsif Operating_Mode
/= Check_Syntax
359 and then (Errors_Detected
= 0 or else Try_Semantics
)
361 Set_Intval
(Token_Node
, UI_Num_Value
* UI_Base
** UI_Scale
);
364 Set_Intval
(Token_Node
, No_Uint
);