* c-decl.c (duplicate_decls): Conditionalize DECL_SAVED_TREE copy.
[official-gcc.git] / gcc / ada / scn-nlit.adb
blobd1fc9ea325f19903f387d89f42e0f0ee27482ce8
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- S C N . N L I T --
6 -- --
7 -- B o d y --
8 -- --
9 -- $Revision$ --
10 -- --
11 -- Copyright (C) 1992-2001 Free Software Foundation, Inc. --
12 -- --
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. --
23 -- --
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). --
26 -- --
27 ------------------------------------------------------------------------------
29 with Uintp; use Uintp;
30 with Urealp; use Urealp;
32 separate (Scn)
33 procedure Nlit is
35 C : Character;
36 -- Current source program character
38 Base_Char : Character;
39 -- Either # or : (character at start of based number)
41 Base : Int;
42 -- Value of base
44 UI_Base : Uint;
45 -- Value of base in Uint format
47 UI_Int_Value : Uint;
48 -- Value of integer scanned by Scan_Integer in Uint format
50 UI_Num_Value : Uint;
51 -- Value of integer in numeric value being scanned
53 Scale : Int;
54 -- Scale value for real literal
56 UI_Scale : Uint;
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
88 begin
89 Error_Msg_S ("digit expected");
90 end Error_Digit_Expected;
92 -------------------
93 -- Scan_Integer --
94 -------------------
96 procedure Scan_Integer is
97 C : Character;
98 -- Next character scanned
100 begin
101 C := Source (Scan_Ptr);
103 -- Loop through digits (allowing underlines)
105 loop
106 Accumulate_Checksum (C);
107 UI_Int_Value :=
108 UI_Int_Value * 10 + (Character'Pos (C) - Character'Pos ('0'));
109 Scan_Ptr := Scan_Ptr + 1;
110 Scale := Scale - 1;
111 C := Source (Scan_Ptr);
113 if C = '_' then
114 Accumulate_Checksum ('_');
116 loop
117 Scan_Ptr := Scan_Ptr + 1;
118 C := Source (Scan_Ptr);
119 exit when C /= '_';
120 Error_No_Double_Underline;
121 end loop;
123 if C not in '0' .. '9' then
124 Error_Digit_Expected;
125 exit;
126 end if;
128 else
129 exit when C not in '0' .. '9';
130 end if;
131 end loop;
133 end Scan_Integer;
135 ----------------------------------
136 -- Start of Processing for Nlit --
137 ----------------------------------
139 begin
140 Base := 10;
141 UI_Base := Uint_10;
142 UI_Int_Value := Uint_0;
143 Scale := 0;
144 Scan_Integer;
145 Scale := 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).
152 Scale := 0;
153 C := Source (Scan_Ptr);
155 if C = '.' then
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");
165 end if;
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);
173 else
174 Scan_Integer;
175 UI_Num_Value := UI_Int_Value;
176 end if;
177 end loop;
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;"
185 elsif C = '#'
186 or else (C = ':' and then
187 (Source (Scan_Ptr + 1) = '.'
188 or else
189 Source (Scan_Ptr + 1) in '0' .. '9'
190 or else
191 Source (Scan_Ptr + 1) in 'A' .. 'Z'
192 or else
193 Source (Scan_Ptr + 1) in 'a' .. 'z'))
194 then
195 Accumulate_Checksum (C);
196 Base_Char := 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");
201 UI_Base := Uint_16;
202 end if;
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;
211 Scale := 0;
213 loop
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;
229 else
230 Error_Msg_S ("extended digit expected");
231 exit;
232 end if;
234 if Extended_Digit_Value >= Base then
235 Error_Msg_S ("digit >= base");
236 end if;
238 UI_Int_Value := UI_Int_Value * UI_Base + Extended_Digit_Value;
239 Scale := Scale - 1;
240 Scan_Ptr := Scan_Ptr + 1;
241 C := Source (Scan_Ptr);
243 if C = '_' then
244 loop
245 Accumulate_Checksum ('_');
246 Scan_Ptr := Scan_Ptr + 1;
247 C := Source (Scan_Ptr);
248 exit when C /= '_';
249 Error_No_Double_Underline;
250 end loop;
252 elsif C = '.' then
253 Accumulate_Checksum ('.');
255 if Point_Scanned then
256 Error_Msg_S ("duplicate point ignored");
257 end if;
259 Scan_Ptr := Scan_Ptr + 1;
260 C := Source (Scan_Ptr);
261 Point_Scanned := True;
262 Scale := 0;
264 elsif C = Base_Char then
265 Accumulate_Checksum (C);
266 Scan_Ptr := Scan_Ptr + 1;
267 exit;
269 elsif C = '#' or else C = ':' then
270 Error_Msg_S ("based number delimiters must match");
271 Scan_Ptr := Scan_Ptr + 1;
272 exit;
274 elsif not Identifier_Char (C) then
275 if Base_Char = '#' then
276 Error_Msg_S ("missing '#");
277 else
278 Error_Msg_S ("missing ':");
279 end if;
281 exit;
282 end if;
284 end loop;
286 UI_Num_Value := UI_Int_Value;
287 end if;
289 -- Scan out exponent
291 if not Point_Scanned then
292 Scale := 0;
293 UI_Scale := Uint_0;
294 else
295 UI_Scale := UI_From_Int (Scale);
296 end if;
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");
312 else
313 Exponent_Is_Negative := True;
314 end if;
316 Scan_Ptr := Scan_Ptr + 1;
317 end if;
319 UI_Int_Value := Uint_0;
321 if Source (Scan_Ptr) in '0' .. '9' then
322 Scan_Integer;
323 else
324 Error_Digit_Expected;
325 end if;
327 if Exponent_Is_Negative then
328 UI_Scale := UI_Scale - UI_Int_Value;
329 else
330 UI_Scale := UI_Scale + UI_Int_Value;
331 end if;
332 end if;
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,
340 UR_From_Components (
341 Num => UI_Num_Value,
342 Den => -UI_Scale,
343 Rbase => Base));
345 -- Case of integer literal to be returned
347 else
348 Token := Tok_Integer_Literal;
349 Token_Node := New_Node (N_Integer_Literal, Token_Ptr);
351 if UI_Scale = 0 then
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)
360 then
361 Set_Intval (Token_Node, UI_Num_Value * UI_Base ** UI_Scale);
363 else
364 Set_Intval (Token_Node, No_Uint);
365 end if;
367 end if;
369 return;
371 end Nlit;