1 |
281 |
jeremybenn |
------------------------------------------------------------------------------
|
2 |
|
|
-- --
|
3 |
|
|
-- GNAT COMPILER COMPONENTS --
|
4 |
|
|
-- --
|
5 |
|
|
-- P A R . C H 4 --
|
6 |
|
|
-- --
|
7 |
|
|
-- B o d y --
|
8 |
|
|
-- --
|
9 |
|
|
-- Copyright (C) 1992-2009, Free Software Foundation, Inc. --
|
10 |
|
|
-- --
|
11 |
|
|
-- GNAT is free software; you can redistribute it and/or modify it under --
|
12 |
|
|
-- terms of the GNU General Public License as published by the Free Soft- --
|
13 |
|
|
-- ware Foundation; either version 3, or (at your option) any later ver- --
|
14 |
|
|
-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
|
15 |
|
|
-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
|
16 |
|
|
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
|
17 |
|
|
-- for more details. You should have received a copy of the GNU General --
|
18 |
|
|
-- Public License distributed with GNAT; see file COPYING3. If not, go to --
|
19 |
|
|
-- http://www.gnu.org/licenses for a complete copy of the license. --
|
20 |
|
|
-- --
|
21 |
|
|
-- GNAT was originally developed by the GNAT team at New York University. --
|
22 |
|
|
-- Extensive contributions were provided by Ada Core Technologies Inc. --
|
23 |
|
|
-- --
|
24 |
|
|
------------------------------------------------------------------------------
|
25 |
|
|
|
26 |
|
|
pragma Style_Checks (All_Checks);
|
27 |
|
|
-- Turn off subprogram body ordering check. Subprograms are in order
|
28 |
|
|
-- by RM section rather than alphabetical
|
29 |
|
|
|
30 |
|
|
with Stringt; use Stringt;
|
31 |
|
|
|
32 |
|
|
separate (Par)
|
33 |
|
|
package body Ch4 is
|
34 |
|
|
|
35 |
|
|
-- Attributes that cannot have arguments
|
36 |
|
|
|
37 |
|
|
Is_Parameterless_Attribute : constant Attribute_Class_Array :=
|
38 |
|
|
(Attribute_Body_Version => True,
|
39 |
|
|
Attribute_External_Tag => True,
|
40 |
|
|
Attribute_Img => True,
|
41 |
|
|
Attribute_Version => True,
|
42 |
|
|
Attribute_Base => True,
|
43 |
|
|
Attribute_Class => True,
|
44 |
|
|
Attribute_Stub_Type => True,
|
45 |
|
|
others => False);
|
46 |
|
|
-- This map contains True for parameterless attributes that return a
|
47 |
|
|
-- string or a type. For those attributes, a left parenthesis after
|
48 |
|
|
-- the attribute should not be analyzed as the beginning of a parameters
|
49 |
|
|
-- list because it may denote a slice operation (X'Img (1 .. 2)) or
|
50 |
|
|
-- a type conversion (X'Class (Y)).
|
51 |
|
|
|
52 |
|
|
-- Note that this map designates the minimum set of attributes where a
|
53 |
|
|
-- construct in parentheses that is not an argument can appear right
|
54 |
|
|
-- after the attribute. For attributes like 'Size, we do not put them
|
55 |
|
|
-- in the map. If someone writes X'Size (3), that's illegal in any case,
|
56 |
|
|
-- but we get a better error message by parsing the (3) as an illegal
|
57 |
|
|
-- argument to the attribute, rather than some meaningless junk that
|
58 |
|
|
-- follows the attribute.
|
59 |
|
|
|
60 |
|
|
-----------------------
|
61 |
|
|
-- Local Subprograms --
|
62 |
|
|
-----------------------
|
63 |
|
|
|
64 |
|
|
function P_Aggregate_Or_Paren_Expr return Node_Id;
|
65 |
|
|
function P_Allocator return Node_Id;
|
66 |
|
|
function P_Record_Or_Array_Component_Association return Node_Id;
|
67 |
|
|
function P_Factor return Node_Id;
|
68 |
|
|
function P_Primary return Node_Id;
|
69 |
|
|
function P_Relation return Node_Id;
|
70 |
|
|
function P_Term return Node_Id;
|
71 |
|
|
|
72 |
|
|
function P_Binary_Adding_Operator return Node_Kind;
|
73 |
|
|
function P_Logical_Operator return Node_Kind;
|
74 |
|
|
function P_Multiplying_Operator return Node_Kind;
|
75 |
|
|
function P_Relational_Operator return Node_Kind;
|
76 |
|
|
function P_Unary_Adding_Operator return Node_Kind;
|
77 |
|
|
|
78 |
|
|
procedure Bad_Range_Attribute (Loc : Source_Ptr);
|
79 |
|
|
-- Called to place complaint about bad range attribute at the given
|
80 |
|
|
-- source location. Terminates by raising Error_Resync.
|
81 |
|
|
|
82 |
|
|
procedure P_Membership_Test (N : Node_Id);
|
83 |
|
|
-- N is the node for a N_In or N_Not_In node whose right operand has not
|
84 |
|
|
-- yet been processed. It is called just after scanning out the IN keyword.
|
85 |
|
|
-- On return, either Right_Opnd or Alternatives is set, as appropriate.
|
86 |
|
|
|
87 |
|
|
function P_Range_Attribute_Reference (Prefix_Node : Node_Id) return Node_Id;
|
88 |
|
|
-- Scan a range attribute reference. The caller has scanned out the
|
89 |
|
|
-- prefix. The current token is known to be an apostrophe and the
|
90 |
|
|
-- following token is known to be RANGE.
|
91 |
|
|
|
92 |
|
|
-------------------------
|
93 |
|
|
-- Bad_Range_Attribute --
|
94 |
|
|
-------------------------
|
95 |
|
|
|
96 |
|
|
procedure Bad_Range_Attribute (Loc : Source_Ptr) is
|
97 |
|
|
begin
|
98 |
|
|
Error_Msg ("range attribute cannot be used in expression!", Loc);
|
99 |
|
|
Resync_Expression;
|
100 |
|
|
end Bad_Range_Attribute;
|
101 |
|
|
|
102 |
|
|
--------------------------
|
103 |
|
|
-- 4.1 Name (also 6.4) --
|
104 |
|
|
--------------------------
|
105 |
|
|
|
106 |
|
|
-- NAME ::=
|
107 |
|
|
-- DIRECT_NAME | EXPLICIT_DEREFERENCE
|
108 |
|
|
-- | INDEXED_COMPONENT | SLICE
|
109 |
|
|
-- | SELECTED_COMPONENT | ATTRIBUTE
|
110 |
|
|
-- | TYPE_CONVERSION | FUNCTION_CALL
|
111 |
|
|
-- | CHARACTER_LITERAL
|
112 |
|
|
|
113 |
|
|
-- DIRECT_NAME ::= IDENTIFIER | OPERATOR_SYMBOL
|
114 |
|
|
|
115 |
|
|
-- PREFIX ::= NAME | IMPLICIT_DEREFERENCE
|
116 |
|
|
|
117 |
|
|
-- EXPLICIT_DEREFERENCE ::= NAME . all
|
118 |
|
|
|
119 |
|
|
-- IMPLICIT_DEREFERENCE ::= NAME
|
120 |
|
|
|
121 |
|
|
-- INDEXED_COMPONENT ::= PREFIX (EXPRESSION {, EXPRESSION})
|
122 |
|
|
|
123 |
|
|
-- SLICE ::= PREFIX (DISCRETE_RANGE)
|
124 |
|
|
|
125 |
|
|
-- SELECTED_COMPONENT ::= PREFIX . SELECTOR_NAME
|
126 |
|
|
|
127 |
|
|
-- SELECTOR_NAME ::= IDENTIFIER | CHARACTER_LITERAL | OPERATOR_SYMBOL
|
128 |
|
|
|
129 |
|
|
-- ATTRIBUTE_REFERENCE ::= PREFIX ' ATTRIBUTE_DESIGNATOR
|
130 |
|
|
|
131 |
|
|
-- ATTRIBUTE_DESIGNATOR ::=
|
132 |
|
|
-- IDENTIFIER [(static_EXPRESSION)]
|
133 |
|
|
-- | access | delta | digits
|
134 |
|
|
|
135 |
|
|
-- FUNCTION_CALL ::=
|
136 |
|
|
-- function_NAME
|
137 |
|
|
-- | function_PREFIX ACTUAL_PARAMETER_PART
|
138 |
|
|
|
139 |
|
|
-- ACTUAL_PARAMETER_PART ::=
|
140 |
|
|
-- (PARAMETER_ASSOCIATION {,PARAMETER_ASSOCIATION})
|
141 |
|
|
|
142 |
|
|
-- PARAMETER_ASSOCIATION ::=
|
143 |
|
|
-- [formal_parameter_SELECTOR_NAME =>] EXPLICIT_ACTUAL_PARAMETER
|
144 |
|
|
|
145 |
|
|
-- EXPLICIT_ACTUAL_PARAMETER ::= EXPRESSION | variable_NAME
|
146 |
|
|
|
147 |
|
|
-- Note: syntactically a procedure call looks just like a function call,
|
148 |
|
|
-- so this routine is in practice used to scan out procedure calls as well.
|
149 |
|
|
|
150 |
|
|
-- On return, Expr_Form is set to either EF_Name or EF_Simple_Name
|
151 |
|
|
|
152 |
|
|
-- Error recovery: can raise Error_Resync
|
153 |
|
|
|
154 |
|
|
-- Note: if on return Token = Tok_Apostrophe, then the apostrophe must be
|
155 |
|
|
-- followed by either a left paren (qualified expression case), or by
|
156 |
|
|
-- range (range attribute case). All other uses of apostrophe (i.e. all
|
157 |
|
|
-- other attributes) are handled in this routine.
|
158 |
|
|
|
159 |
|
|
-- Error recovery: can raise Error_Resync
|
160 |
|
|
|
161 |
|
|
function P_Name return Node_Id is
|
162 |
|
|
Scan_State : Saved_Scan_State;
|
163 |
|
|
Name_Node : Node_Id;
|
164 |
|
|
Prefix_Node : Node_Id;
|
165 |
|
|
Ident_Node : Node_Id;
|
166 |
|
|
Expr_Node : Node_Id;
|
167 |
|
|
Range_Node : Node_Id;
|
168 |
|
|
Arg_Node : Node_Id;
|
169 |
|
|
|
170 |
|
|
Arg_List : List_Id := No_List; -- kill junk warning
|
171 |
|
|
Attr_Name : Name_Id := No_Name; -- kill junk warning
|
172 |
|
|
|
173 |
|
|
begin
|
174 |
|
|
-- Case of not a name
|
175 |
|
|
|
176 |
|
|
if Token not in Token_Class_Name then
|
177 |
|
|
|
178 |
|
|
-- If it looks like start of expression, complain and scan expression
|
179 |
|
|
|
180 |
|
|
if Token in Token_Class_Literal
|
181 |
|
|
or else Token = Tok_Left_Paren
|
182 |
|
|
then
|
183 |
|
|
Error_Msg_SC ("name expected");
|
184 |
|
|
return P_Expression;
|
185 |
|
|
|
186 |
|
|
-- Otherwise some other junk, not much we can do
|
187 |
|
|
|
188 |
|
|
else
|
189 |
|
|
Error_Msg_AP ("name expected");
|
190 |
|
|
raise Error_Resync;
|
191 |
|
|
end if;
|
192 |
|
|
end if;
|
193 |
|
|
|
194 |
|
|
-- Loop through designators in qualified name
|
195 |
|
|
|
196 |
|
|
Name_Node := Token_Node;
|
197 |
|
|
|
198 |
|
|
loop
|
199 |
|
|
Scan; -- past designator
|
200 |
|
|
exit when Token /= Tok_Dot;
|
201 |
|
|
Save_Scan_State (Scan_State); -- at dot
|
202 |
|
|
Scan; -- past dot
|
203 |
|
|
|
204 |
|
|
-- If we do not have another designator after the dot, then join
|
205 |
|
|
-- the normal circuit to handle a dot extension (may be .all or
|
206 |
|
|
-- character literal case). Otherwise loop back to scan the next
|
207 |
|
|
-- designator.
|
208 |
|
|
|
209 |
|
|
if Token not in Token_Class_Desig then
|
210 |
|
|
goto Scan_Name_Extension_Dot;
|
211 |
|
|
else
|
212 |
|
|
Prefix_Node := Name_Node;
|
213 |
|
|
Name_Node := New_Node (N_Selected_Component, Prev_Token_Ptr);
|
214 |
|
|
Set_Prefix (Name_Node, Prefix_Node);
|
215 |
|
|
Set_Selector_Name (Name_Node, Token_Node);
|
216 |
|
|
end if;
|
217 |
|
|
end loop;
|
218 |
|
|
|
219 |
|
|
-- We have now scanned out a qualified designator. If the last token is
|
220 |
|
|
-- an operator symbol, then we certainly do not have the Snam case, so
|
221 |
|
|
-- we can just use the normal name extension check circuit
|
222 |
|
|
|
223 |
|
|
if Prev_Token = Tok_Operator_Symbol then
|
224 |
|
|
goto Scan_Name_Extension;
|
225 |
|
|
end if;
|
226 |
|
|
|
227 |
|
|
-- We have scanned out a qualified simple name, check for name extension
|
228 |
|
|
-- Note that we know there is no dot here at this stage, so the only
|
229 |
|
|
-- possible cases of name extension are apostrophe and left paren.
|
230 |
|
|
|
231 |
|
|
if Token = Tok_Apostrophe then
|
232 |
|
|
Save_Scan_State (Scan_State); -- at apostrophe
|
233 |
|
|
Scan; -- past apostrophe
|
234 |
|
|
|
235 |
|
|
-- If left paren, then this might be a qualified expression, but we
|
236 |
|
|
-- are only in the business of scanning out names, so return with
|
237 |
|
|
-- Token backed up to point to the apostrophe. The treatment for
|
238 |
|
|
-- the range attribute is similar (we do not consider x'range to
|
239 |
|
|
-- be a name in this grammar).
|
240 |
|
|
|
241 |
|
|
if Token = Tok_Left_Paren or else Token = Tok_Range then
|
242 |
|
|
Restore_Scan_State (Scan_State); -- to apostrophe
|
243 |
|
|
Expr_Form := EF_Simple_Name;
|
244 |
|
|
return Name_Node;
|
245 |
|
|
|
246 |
|
|
-- Otherwise we have the case of a name extended by an attribute
|
247 |
|
|
|
248 |
|
|
else
|
249 |
|
|
goto Scan_Name_Extension_Apostrophe;
|
250 |
|
|
end if;
|
251 |
|
|
|
252 |
|
|
-- Check case of qualified simple name extended by a left parenthesis
|
253 |
|
|
|
254 |
|
|
elsif Token = Tok_Left_Paren then
|
255 |
|
|
Scan; -- past left paren
|
256 |
|
|
goto Scan_Name_Extension_Left_Paren;
|
257 |
|
|
|
258 |
|
|
-- Otherwise the qualified simple name is not extended, so return
|
259 |
|
|
|
260 |
|
|
else
|
261 |
|
|
Expr_Form := EF_Simple_Name;
|
262 |
|
|
return Name_Node;
|
263 |
|
|
end if;
|
264 |
|
|
|
265 |
|
|
-- Loop scanning past name extensions. A label is used for control
|
266 |
|
|
-- transfer for this loop for ease of interfacing with the finite state
|
267 |
|
|
-- machine in the parenthesis scanning circuit, and also to allow for
|
268 |
|
|
-- passing in control to the appropriate point from the above code.
|
269 |
|
|
|
270 |
|
|
<<Scan_Name_Extension>>
|
271 |
|
|
|
272 |
|
|
-- Character literal used as name cannot be extended. Also this
|
273 |
|
|
-- cannot be a call, since the name for a call must be a designator.
|
274 |
|
|
-- Return in these cases, or if there is no name extension
|
275 |
|
|
|
276 |
|
|
if Token not in Token_Class_Namext
|
277 |
|
|
or else Prev_Token = Tok_Char_Literal
|
278 |
|
|
then
|
279 |
|
|
Expr_Form := EF_Name;
|
280 |
|
|
return Name_Node;
|
281 |
|
|
end if;
|
282 |
|
|
|
283 |
|
|
-- Merge here when we know there is a name extension
|
284 |
|
|
|
285 |
|
|
<<Scan_Name_Extension_OK>>
|
286 |
|
|
|
287 |
|
|
if Token = Tok_Left_Paren then
|
288 |
|
|
Scan; -- past left paren
|
289 |
|
|
goto Scan_Name_Extension_Left_Paren;
|
290 |
|
|
|
291 |
|
|
elsif Token = Tok_Apostrophe then
|
292 |
|
|
Save_Scan_State (Scan_State); -- at apostrophe
|
293 |
|
|
Scan; -- past apostrophe
|
294 |
|
|
goto Scan_Name_Extension_Apostrophe;
|
295 |
|
|
|
296 |
|
|
else -- Token = Tok_Dot
|
297 |
|
|
Save_Scan_State (Scan_State); -- at dot
|
298 |
|
|
Scan; -- past dot
|
299 |
|
|
goto Scan_Name_Extension_Dot;
|
300 |
|
|
end if;
|
301 |
|
|
|
302 |
|
|
-- Case of name extended by dot (selection), dot is already skipped
|
303 |
|
|
-- and the scan state at the point of the dot is saved in Scan_State.
|
304 |
|
|
|
305 |
|
|
<<Scan_Name_Extension_Dot>>
|
306 |
|
|
|
307 |
|
|
-- Explicit dereference case
|
308 |
|
|
|
309 |
|
|
if Token = Tok_All then
|
310 |
|
|
Prefix_Node := Name_Node;
|
311 |
|
|
Name_Node := New_Node (N_Explicit_Dereference, Token_Ptr);
|
312 |
|
|
Set_Prefix (Name_Node, Prefix_Node);
|
313 |
|
|
Scan; -- past ALL
|
314 |
|
|
goto Scan_Name_Extension;
|
315 |
|
|
|
316 |
|
|
-- Selected component case
|
317 |
|
|
|
318 |
|
|
elsif Token in Token_Class_Name then
|
319 |
|
|
Prefix_Node := Name_Node;
|
320 |
|
|
Name_Node := New_Node (N_Selected_Component, Prev_Token_Ptr);
|
321 |
|
|
Set_Prefix (Name_Node, Prefix_Node);
|
322 |
|
|
Set_Selector_Name (Name_Node, Token_Node);
|
323 |
|
|
Scan; -- past selector
|
324 |
|
|
goto Scan_Name_Extension;
|
325 |
|
|
|
326 |
|
|
-- Reserved identifier as selector
|
327 |
|
|
|
328 |
|
|
elsif Is_Reserved_Identifier then
|
329 |
|
|
Scan_Reserved_Identifier (Force_Msg => False);
|
330 |
|
|
Prefix_Node := Name_Node;
|
331 |
|
|
Name_Node := New_Node (N_Selected_Component, Prev_Token_Ptr);
|
332 |
|
|
Set_Prefix (Name_Node, Prefix_Node);
|
333 |
|
|
Set_Selector_Name (Name_Node, Token_Node);
|
334 |
|
|
Scan; -- past identifier used as selector
|
335 |
|
|
goto Scan_Name_Extension;
|
336 |
|
|
|
337 |
|
|
-- If dot is at end of line and followed by nothing legal,
|
338 |
|
|
-- then assume end of name and quit (dot will be taken as
|
339 |
|
|
-- an erroneous form of some other punctuation by our caller).
|
340 |
|
|
|
341 |
|
|
elsif Token_Is_At_Start_Of_Line then
|
342 |
|
|
Restore_Scan_State (Scan_State);
|
343 |
|
|
return Name_Node;
|
344 |
|
|
|
345 |
|
|
-- Here if nothing legal after the dot
|
346 |
|
|
|
347 |
|
|
else
|
348 |
|
|
Error_Msg_AP ("selector expected");
|
349 |
|
|
raise Error_Resync;
|
350 |
|
|
end if;
|
351 |
|
|
|
352 |
|
|
-- Here for an apostrophe as name extension. The scan position at the
|
353 |
|
|
-- apostrophe has already been saved, and the apostrophe scanned out.
|
354 |
|
|
|
355 |
|
|
<<Scan_Name_Extension_Apostrophe>>
|
356 |
|
|
|
357 |
|
|
Scan_Apostrophe : declare
|
358 |
|
|
function Apostrophe_Should_Be_Semicolon return Boolean;
|
359 |
|
|
-- Checks for case where apostrophe should probably be
|
360 |
|
|
-- a semicolon, and if so, gives appropriate message,
|
361 |
|
|
-- resets the scan pointer to the apostrophe, changes
|
362 |
|
|
-- the current token to Tok_Semicolon, and returns True.
|
363 |
|
|
-- Otherwise returns False.
|
364 |
|
|
|
365 |
|
|
function Apostrophe_Should_Be_Semicolon return Boolean is
|
366 |
|
|
begin
|
367 |
|
|
if Token_Is_At_Start_Of_Line then
|
368 |
|
|
Restore_Scan_State (Scan_State); -- to apostrophe
|
369 |
|
|
Error_Msg_SC ("|""''"" should be "";""");
|
370 |
|
|
Token := Tok_Semicolon;
|
371 |
|
|
return True;
|
372 |
|
|
else
|
373 |
|
|
return False;
|
374 |
|
|
end if;
|
375 |
|
|
end Apostrophe_Should_Be_Semicolon;
|
376 |
|
|
|
377 |
|
|
-- Start of processing for Scan_Apostrophe
|
378 |
|
|
|
379 |
|
|
begin
|
380 |
|
|
-- If range attribute after apostrophe, then return with Token
|
381 |
|
|
-- pointing to the apostrophe. Note that in this case the prefix
|
382 |
|
|
-- need not be a simple name (cases like A.all'range). Similarly
|
383 |
|
|
-- if there is a left paren after the apostrophe, then we also
|
384 |
|
|
-- return with Token pointing to the apostrophe (this is the
|
385 |
|
|
-- qualified expression case).
|
386 |
|
|
|
387 |
|
|
if Token = Tok_Range or else Token = Tok_Left_Paren then
|
388 |
|
|
Restore_Scan_State (Scan_State); -- to apostrophe
|
389 |
|
|
Expr_Form := EF_Name;
|
390 |
|
|
return Name_Node;
|
391 |
|
|
|
392 |
|
|
-- Here for cases where attribute designator is an identifier
|
393 |
|
|
|
394 |
|
|
elsif Token = Tok_Identifier then
|
395 |
|
|
Attr_Name := Token_Name;
|
396 |
|
|
|
397 |
|
|
if not Is_Attribute_Name (Attr_Name) then
|
398 |
|
|
if Apostrophe_Should_Be_Semicolon then
|
399 |
|
|
Expr_Form := EF_Name;
|
400 |
|
|
return Name_Node;
|
401 |
|
|
|
402 |
|
|
-- Here for a bad attribute name
|
403 |
|
|
|
404 |
|
|
else
|
405 |
|
|
Signal_Bad_Attribute;
|
406 |
|
|
Scan; -- past bad identifier
|
407 |
|
|
|
408 |
|
|
if Token = Tok_Left_Paren then
|
409 |
|
|
Scan; -- past left paren
|
410 |
|
|
|
411 |
|
|
loop
|
412 |
|
|
Discard_Junk_Node (P_Expression_If_OK);
|
413 |
|
|
exit when not Comma_Present;
|
414 |
|
|
end loop;
|
415 |
|
|
|
416 |
|
|
T_Right_Paren;
|
417 |
|
|
end if;
|
418 |
|
|
|
419 |
|
|
return Error;
|
420 |
|
|
end if;
|
421 |
|
|
end if;
|
422 |
|
|
|
423 |
|
|
if Style_Check then
|
424 |
|
|
Style.Check_Attribute_Name (False);
|
425 |
|
|
end if;
|
426 |
|
|
|
427 |
|
|
-- Here for case of attribute designator is not an identifier
|
428 |
|
|
|
429 |
|
|
else
|
430 |
|
|
if Token = Tok_Delta then
|
431 |
|
|
Attr_Name := Name_Delta;
|
432 |
|
|
|
433 |
|
|
elsif Token = Tok_Digits then
|
434 |
|
|
Attr_Name := Name_Digits;
|
435 |
|
|
|
436 |
|
|
elsif Token = Tok_Access then
|
437 |
|
|
Attr_Name := Name_Access;
|
438 |
|
|
|
439 |
|
|
elsif Token = Tok_Mod and then Ada_Version = Ada_05 then
|
440 |
|
|
Attr_Name := Name_Mod;
|
441 |
|
|
|
442 |
|
|
elsif Apostrophe_Should_Be_Semicolon then
|
443 |
|
|
Expr_Form := EF_Name;
|
444 |
|
|
return Name_Node;
|
445 |
|
|
|
446 |
|
|
else
|
447 |
|
|
Error_Msg_AP ("attribute designator expected");
|
448 |
|
|
raise Error_Resync;
|
449 |
|
|
end if;
|
450 |
|
|
|
451 |
|
|
if Style_Check then
|
452 |
|
|
Style.Check_Attribute_Name (True);
|
453 |
|
|
end if;
|
454 |
|
|
end if;
|
455 |
|
|
|
456 |
|
|
-- We come here with an OK attribute scanned, and the
|
457 |
|
|
-- corresponding Attribute identifier node stored in Ident_Node.
|
458 |
|
|
|
459 |
|
|
Prefix_Node := Name_Node;
|
460 |
|
|
Name_Node := New_Node (N_Attribute_Reference, Prev_Token_Ptr);
|
461 |
|
|
Scan; -- past attribute designator
|
462 |
|
|
Set_Prefix (Name_Node, Prefix_Node);
|
463 |
|
|
Set_Attribute_Name (Name_Node, Attr_Name);
|
464 |
|
|
|
465 |
|
|
-- Scan attribute arguments/designator. We skip this if we know
|
466 |
|
|
-- that the attribute cannot have an argument.
|
467 |
|
|
|
468 |
|
|
if Token = Tok_Left_Paren
|
469 |
|
|
and then not
|
470 |
|
|
Is_Parameterless_Attribute (Get_Attribute_Id (Attr_Name))
|
471 |
|
|
then
|
472 |
|
|
Set_Expressions (Name_Node, New_List);
|
473 |
|
|
Scan; -- past left paren
|
474 |
|
|
|
475 |
|
|
loop
|
476 |
|
|
declare
|
477 |
|
|
Expr : constant Node_Id := P_Expression_If_OK;
|
478 |
|
|
|
479 |
|
|
begin
|
480 |
|
|
if Token = Tok_Arrow then
|
481 |
|
|
Error_Msg_SC
|
482 |
|
|
("named parameters not permitted for attributes");
|
483 |
|
|
Scan; -- past junk arrow
|
484 |
|
|
|
485 |
|
|
else
|
486 |
|
|
Append (Expr, Expressions (Name_Node));
|
487 |
|
|
exit when not Comma_Present;
|
488 |
|
|
end if;
|
489 |
|
|
end;
|
490 |
|
|
end loop;
|
491 |
|
|
|
492 |
|
|
T_Right_Paren;
|
493 |
|
|
end if;
|
494 |
|
|
|
495 |
|
|
goto Scan_Name_Extension;
|
496 |
|
|
end Scan_Apostrophe;
|
497 |
|
|
|
498 |
|
|
-- Here for left parenthesis extending name (left paren skipped)
|
499 |
|
|
|
500 |
|
|
<<Scan_Name_Extension_Left_Paren>>
|
501 |
|
|
|
502 |
|
|
-- We now have to scan through a list of items, terminated by a
|
503 |
|
|
-- right parenthesis. The scan is handled by a finite state
|
504 |
|
|
-- machine. The possibilities are:
|
505 |
|
|
|
506 |
|
|
-- (discrete_range)
|
507 |
|
|
|
508 |
|
|
-- This is a slice. This case is handled in LP_State_Init
|
509 |
|
|
|
510 |
|
|
-- (expression, expression, ..)
|
511 |
|
|
|
512 |
|
|
-- This is interpreted as an indexed component, i.e. as a
|
513 |
|
|
-- case of a name which can be extended in the normal manner.
|
514 |
|
|
-- This case is handled by LP_State_Name or LP_State_Expr.
|
515 |
|
|
|
516 |
|
|
-- Note: conditional expressions (without an extra level of
|
517 |
|
|
-- parentheses) are permitted in this context).
|
518 |
|
|
|
519 |
|
|
-- (..., identifier => expression , ...)
|
520 |
|
|
|
521 |
|
|
-- If there is at least one occurrence of identifier => (but
|
522 |
|
|
-- none of the other cases apply), then we have a call.
|
523 |
|
|
|
524 |
|
|
-- Test for Id => case
|
525 |
|
|
|
526 |
|
|
if Token = Tok_Identifier then
|
527 |
|
|
Save_Scan_State (Scan_State); -- at Id
|
528 |
|
|
Scan; -- past Id
|
529 |
|
|
|
530 |
|
|
-- Test for => (allow := as an error substitute)
|
531 |
|
|
|
532 |
|
|
if Token = Tok_Arrow or else Token = Tok_Colon_Equal then
|
533 |
|
|
Restore_Scan_State (Scan_State); -- to Id
|
534 |
|
|
Arg_List := New_List;
|
535 |
|
|
goto LP_State_Call;
|
536 |
|
|
|
537 |
|
|
else
|
538 |
|
|
Restore_Scan_State (Scan_State); -- to Id
|
539 |
|
|
end if;
|
540 |
|
|
end if;
|
541 |
|
|
|
542 |
|
|
-- Here we have an expression after all
|
543 |
|
|
|
544 |
|
|
Expr_Node := P_Expression_Or_Range_Attribute_If_OK;
|
545 |
|
|
|
546 |
|
|
-- Check cases of discrete range for a slice
|
547 |
|
|
|
548 |
|
|
-- First possibility: Range_Attribute_Reference
|
549 |
|
|
|
550 |
|
|
if Expr_Form = EF_Range_Attr then
|
551 |
|
|
Range_Node := Expr_Node;
|
552 |
|
|
|
553 |
|
|
-- Second possibility: Simple_expression .. Simple_expression
|
554 |
|
|
|
555 |
|
|
elsif Token = Tok_Dot_Dot then
|
556 |
|
|
Check_Simple_Expression (Expr_Node);
|
557 |
|
|
Range_Node := New_Node (N_Range, Token_Ptr);
|
558 |
|
|
Set_Low_Bound (Range_Node, Expr_Node);
|
559 |
|
|
Scan; -- past ..
|
560 |
|
|
Expr_Node := P_Expression;
|
561 |
|
|
Check_Simple_Expression (Expr_Node);
|
562 |
|
|
Set_High_Bound (Range_Node, Expr_Node);
|
563 |
|
|
|
564 |
|
|
-- Third possibility: Type_name range Range
|
565 |
|
|
|
566 |
|
|
elsif Token = Tok_Range then
|
567 |
|
|
if Expr_Form /= EF_Simple_Name then
|
568 |
|
|
Error_Msg_SC -- CODEFIX???
|
569 |
|
|
("subtype mark must precede RANGE");
|
570 |
|
|
raise Error_Resync;
|
571 |
|
|
end if;
|
572 |
|
|
|
573 |
|
|
Range_Node := P_Subtype_Indication (Expr_Node);
|
574 |
|
|
|
575 |
|
|
-- Otherwise we just have an expression. It is true that we might
|
576 |
|
|
-- have a subtype mark without a range constraint but this case
|
577 |
|
|
-- is syntactically indistinguishable from the expression case.
|
578 |
|
|
|
579 |
|
|
else
|
580 |
|
|
Arg_List := New_List;
|
581 |
|
|
goto LP_State_Expr;
|
582 |
|
|
end if;
|
583 |
|
|
|
584 |
|
|
-- Fall through here with unmistakable Discrete range scanned,
|
585 |
|
|
-- which means that we definitely have the case of a slice. The
|
586 |
|
|
-- Discrete range is in Range_Node.
|
587 |
|
|
|
588 |
|
|
if Token = Tok_Comma then
|
589 |
|
|
Error_Msg_SC ("slice cannot have more than one dimension");
|
590 |
|
|
raise Error_Resync;
|
591 |
|
|
|
592 |
|
|
elsif Token /= Tok_Right_Paren then
|
593 |
|
|
T_Right_Paren;
|
594 |
|
|
raise Error_Resync;
|
595 |
|
|
|
596 |
|
|
else
|
597 |
|
|
Scan; -- past right paren
|
598 |
|
|
Prefix_Node := Name_Node;
|
599 |
|
|
Name_Node := New_Node (N_Slice, Sloc (Prefix_Node));
|
600 |
|
|
Set_Prefix (Name_Node, Prefix_Node);
|
601 |
|
|
Set_Discrete_Range (Name_Node, Range_Node);
|
602 |
|
|
|
603 |
|
|
-- An operator node is legal as a prefix to other names,
|
604 |
|
|
-- but not for a slice.
|
605 |
|
|
|
606 |
|
|
if Nkind (Prefix_Node) = N_Operator_Symbol then
|
607 |
|
|
Error_Msg_N ("illegal prefix for slice", Prefix_Node);
|
608 |
|
|
end if;
|
609 |
|
|
|
610 |
|
|
-- If we have a name extension, go scan it
|
611 |
|
|
|
612 |
|
|
if Token in Token_Class_Namext then
|
613 |
|
|
goto Scan_Name_Extension_OK;
|
614 |
|
|
|
615 |
|
|
-- Otherwise return (a slice is a name, but is not a call)
|
616 |
|
|
|
617 |
|
|
else
|
618 |
|
|
Expr_Form := EF_Name;
|
619 |
|
|
return Name_Node;
|
620 |
|
|
end if;
|
621 |
|
|
end if;
|
622 |
|
|
|
623 |
|
|
-- In LP_State_Expr, we have scanned one or more expressions, and
|
624 |
|
|
-- so we have a call or an indexed component which is a name. On
|
625 |
|
|
-- entry we have the expression just scanned in Expr_Node and
|
626 |
|
|
-- Arg_List contains the list of expressions encountered so far
|
627 |
|
|
|
628 |
|
|
<<LP_State_Expr>>
|
629 |
|
|
Append (Expr_Node, Arg_List);
|
630 |
|
|
|
631 |
|
|
if Token = Tok_Arrow then
|
632 |
|
|
Error_Msg
|
633 |
|
|
("expect identifier in parameter association",
|
634 |
|
|
Sloc (Expr_Node));
|
635 |
|
|
Scan; -- past arrow.
|
636 |
|
|
|
637 |
|
|
elsif not Comma_Present then
|
638 |
|
|
T_Right_Paren;
|
639 |
|
|
Prefix_Node := Name_Node;
|
640 |
|
|
Name_Node := New_Node (N_Indexed_Component, Sloc (Prefix_Node));
|
641 |
|
|
Set_Prefix (Name_Node, Prefix_Node);
|
642 |
|
|
Set_Expressions (Name_Node, Arg_List);
|
643 |
|
|
goto Scan_Name_Extension;
|
644 |
|
|
end if;
|
645 |
|
|
|
646 |
|
|
-- Comma present (and scanned out), test for identifier => case
|
647 |
|
|
-- Test for identifier => case
|
648 |
|
|
|
649 |
|
|
if Token = Tok_Identifier then
|
650 |
|
|
Save_Scan_State (Scan_State); -- at Id
|
651 |
|
|
Scan; -- past Id
|
652 |
|
|
|
653 |
|
|
-- Test for => (allow := as error substitute)
|
654 |
|
|
|
655 |
|
|
if Token = Tok_Arrow or else Token = Tok_Colon_Equal then
|
656 |
|
|
Restore_Scan_State (Scan_State); -- to Id
|
657 |
|
|
goto LP_State_Call;
|
658 |
|
|
|
659 |
|
|
-- Otherwise it's just an expression after all, so backup
|
660 |
|
|
|
661 |
|
|
else
|
662 |
|
|
Restore_Scan_State (Scan_State); -- to Id
|
663 |
|
|
end if;
|
664 |
|
|
end if;
|
665 |
|
|
|
666 |
|
|
-- Here we have an expression after all, so stay in this state
|
667 |
|
|
|
668 |
|
|
Expr_Node := P_Expression_If_OK;
|
669 |
|
|
goto LP_State_Expr;
|
670 |
|
|
|
671 |
|
|
-- LP_State_Call corresponds to the situation in which at least
|
672 |
|
|
-- one instance of Id => Expression has been encountered, so we
|
673 |
|
|
-- know that we do not have a name, but rather a call. We enter
|
674 |
|
|
-- it with the scan pointer pointing to the next argument to scan,
|
675 |
|
|
-- and Arg_List containing the list of arguments scanned so far.
|
676 |
|
|
|
677 |
|
|
<<LP_State_Call>>
|
678 |
|
|
|
679 |
|
|
-- Test for case of Id => Expression (named parameter)
|
680 |
|
|
|
681 |
|
|
if Token = Tok_Identifier then
|
682 |
|
|
Save_Scan_State (Scan_State); -- at Id
|
683 |
|
|
Ident_Node := Token_Node;
|
684 |
|
|
Scan; -- past Id
|
685 |
|
|
|
686 |
|
|
-- Deal with => (allow := as erroneous substitute)
|
687 |
|
|
|
688 |
|
|
if Token = Tok_Arrow or else Token = Tok_Colon_Equal then
|
689 |
|
|
Arg_Node := New_Node (N_Parameter_Association, Prev_Token_Ptr);
|
690 |
|
|
Set_Selector_Name (Arg_Node, Ident_Node);
|
691 |
|
|
T_Arrow;
|
692 |
|
|
Set_Explicit_Actual_Parameter (Arg_Node, P_Expression);
|
693 |
|
|
Append (Arg_Node, Arg_List);
|
694 |
|
|
|
695 |
|
|
-- If a comma follows, go back and scan next entry
|
696 |
|
|
|
697 |
|
|
if Comma_Present then
|
698 |
|
|
goto LP_State_Call;
|
699 |
|
|
|
700 |
|
|
-- Otherwise we have the end of a call
|
701 |
|
|
|
702 |
|
|
else
|
703 |
|
|
Prefix_Node := Name_Node;
|
704 |
|
|
Name_Node := New_Node (N_Function_Call, Sloc (Prefix_Node));
|
705 |
|
|
Set_Name (Name_Node, Prefix_Node);
|
706 |
|
|
Set_Parameter_Associations (Name_Node, Arg_List);
|
707 |
|
|
T_Right_Paren;
|
708 |
|
|
|
709 |
|
|
if Token in Token_Class_Namext then
|
710 |
|
|
goto Scan_Name_Extension_OK;
|
711 |
|
|
|
712 |
|
|
-- This is a case of a call which cannot be a name
|
713 |
|
|
|
714 |
|
|
else
|
715 |
|
|
Expr_Form := EF_Name;
|
716 |
|
|
return Name_Node;
|
717 |
|
|
end if;
|
718 |
|
|
end if;
|
719 |
|
|
|
720 |
|
|
-- Not named parameter: Id started an expression after all
|
721 |
|
|
|
722 |
|
|
else
|
723 |
|
|
Restore_Scan_State (Scan_State); -- to Id
|
724 |
|
|
end if;
|
725 |
|
|
end if;
|
726 |
|
|
|
727 |
|
|
-- Here if entry did not start with Id => which means that it
|
728 |
|
|
-- is a positional parameter, which is not allowed, since we
|
729 |
|
|
-- have seen at least one named parameter already.
|
730 |
|
|
|
731 |
|
|
Error_Msg_SC
|
732 |
|
|
("positional parameter association " &
|
733 |
|
|
"not allowed after named one");
|
734 |
|
|
|
735 |
|
|
Expr_Node := P_Expression_If_OK;
|
736 |
|
|
|
737 |
|
|
-- Leaving the '>' in an association is not unusual, so suggest
|
738 |
|
|
-- a possible fix.
|
739 |
|
|
|
740 |
|
|
if Nkind (Expr_Node) = N_Op_Eq then
|
741 |
|
|
Error_Msg_N ("\maybe `='>` was intended", Expr_Node);
|
742 |
|
|
end if;
|
743 |
|
|
|
744 |
|
|
-- We go back to scanning out expressions, so that we do not get
|
745 |
|
|
-- multiple error messages when several positional parameters
|
746 |
|
|
-- follow a named parameter.
|
747 |
|
|
|
748 |
|
|
goto LP_State_Expr;
|
749 |
|
|
|
750 |
|
|
-- End of treatment for name extensions starting with left paren
|
751 |
|
|
|
752 |
|
|
-- End of loop through name extensions
|
753 |
|
|
|
754 |
|
|
end P_Name;
|
755 |
|
|
|
756 |
|
|
-- This function parses a restricted form of Names which are either
|
757 |
|
|
-- designators, or designators preceded by a sequence of prefixes
|
758 |
|
|
-- that are direct names.
|
759 |
|
|
|
760 |
|
|
-- Error recovery: cannot raise Error_Resync
|
761 |
|
|
|
762 |
|
|
function P_Function_Name return Node_Id is
|
763 |
|
|
Designator_Node : Node_Id;
|
764 |
|
|
Prefix_Node : Node_Id;
|
765 |
|
|
Selector_Node : Node_Id;
|
766 |
|
|
Dot_Sloc : Source_Ptr := No_Location;
|
767 |
|
|
|
768 |
|
|
begin
|
769 |
|
|
-- Prefix_Node is set to the gathered prefix so far, Empty means that
|
770 |
|
|
-- no prefix has been scanned. This allows us to build up the result
|
771 |
|
|
-- in the required right recursive manner.
|
772 |
|
|
|
773 |
|
|
Prefix_Node := Empty;
|
774 |
|
|
|
775 |
|
|
-- Loop through prefixes
|
776 |
|
|
|
777 |
|
|
loop
|
778 |
|
|
Designator_Node := Token_Node;
|
779 |
|
|
|
780 |
|
|
if Token not in Token_Class_Desig then
|
781 |
|
|
return P_Identifier; -- let P_Identifier issue the error message
|
782 |
|
|
|
783 |
|
|
else -- Token in Token_Class_Desig
|
784 |
|
|
Scan; -- past designator
|
785 |
|
|
exit when Token /= Tok_Dot;
|
786 |
|
|
end if;
|
787 |
|
|
|
788 |
|
|
-- Here at a dot, with token just before it in Designator_Node
|
789 |
|
|
|
790 |
|
|
if No (Prefix_Node) then
|
791 |
|
|
Prefix_Node := Designator_Node;
|
792 |
|
|
else
|
793 |
|
|
Selector_Node := New_Node (N_Selected_Component, Dot_Sloc);
|
794 |
|
|
Set_Prefix (Selector_Node, Prefix_Node);
|
795 |
|
|
Set_Selector_Name (Selector_Node, Designator_Node);
|
796 |
|
|
Prefix_Node := Selector_Node;
|
797 |
|
|
end if;
|
798 |
|
|
|
799 |
|
|
Dot_Sloc := Token_Ptr;
|
800 |
|
|
Scan; -- past dot
|
801 |
|
|
end loop;
|
802 |
|
|
|
803 |
|
|
-- Fall out of the loop having just scanned a designator
|
804 |
|
|
|
805 |
|
|
if No (Prefix_Node) then
|
806 |
|
|
return Designator_Node;
|
807 |
|
|
else
|
808 |
|
|
Selector_Node := New_Node (N_Selected_Component, Dot_Sloc);
|
809 |
|
|
Set_Prefix (Selector_Node, Prefix_Node);
|
810 |
|
|
Set_Selector_Name (Selector_Node, Designator_Node);
|
811 |
|
|
return Selector_Node;
|
812 |
|
|
end if;
|
813 |
|
|
|
814 |
|
|
exception
|
815 |
|
|
when Error_Resync =>
|
816 |
|
|
return Error;
|
817 |
|
|
end P_Function_Name;
|
818 |
|
|
|
819 |
|
|
-- This function parses a restricted form of Names which are either
|
820 |
|
|
-- identifiers, or identifiers preceded by a sequence of prefixes
|
821 |
|
|
-- that are direct names.
|
822 |
|
|
|
823 |
|
|
-- Error recovery: cannot raise Error_Resync
|
824 |
|
|
|
825 |
|
|
function P_Qualified_Simple_Name return Node_Id is
|
826 |
|
|
Designator_Node : Node_Id;
|
827 |
|
|
Prefix_Node : Node_Id;
|
828 |
|
|
Selector_Node : Node_Id;
|
829 |
|
|
Dot_Sloc : Source_Ptr := No_Location;
|
830 |
|
|
|
831 |
|
|
begin
|
832 |
|
|
-- Prefix node is set to the gathered prefix so far, Empty means that
|
833 |
|
|
-- no prefix has been scanned. This allows us to build up the result
|
834 |
|
|
-- in the required right recursive manner.
|
835 |
|
|
|
836 |
|
|
Prefix_Node := Empty;
|
837 |
|
|
|
838 |
|
|
-- Loop through prefixes
|
839 |
|
|
|
840 |
|
|
loop
|
841 |
|
|
Designator_Node := Token_Node;
|
842 |
|
|
|
843 |
|
|
if Token = Tok_Identifier then
|
844 |
|
|
Scan; -- past identifier
|
845 |
|
|
exit when Token /= Tok_Dot;
|
846 |
|
|
|
847 |
|
|
elsif Token not in Token_Class_Desig then
|
848 |
|
|
return P_Identifier; -- let P_Identifier issue the error message
|
849 |
|
|
|
850 |
|
|
else
|
851 |
|
|
Scan; -- past designator
|
852 |
|
|
|
853 |
|
|
if Token /= Tok_Dot then
|
854 |
|
|
Error_Msg_SP ("identifier expected");
|
855 |
|
|
return Error;
|
856 |
|
|
end if;
|
857 |
|
|
end if;
|
858 |
|
|
|
859 |
|
|
-- Here at a dot, with token just before it in Designator_Node
|
860 |
|
|
|
861 |
|
|
if No (Prefix_Node) then
|
862 |
|
|
Prefix_Node := Designator_Node;
|
863 |
|
|
else
|
864 |
|
|
Selector_Node := New_Node (N_Selected_Component, Dot_Sloc);
|
865 |
|
|
Set_Prefix (Selector_Node, Prefix_Node);
|
866 |
|
|
Set_Selector_Name (Selector_Node, Designator_Node);
|
867 |
|
|
Prefix_Node := Selector_Node;
|
868 |
|
|
end if;
|
869 |
|
|
|
870 |
|
|
Dot_Sloc := Token_Ptr;
|
871 |
|
|
Scan; -- past dot
|
872 |
|
|
end loop;
|
873 |
|
|
|
874 |
|
|
-- Fall out of the loop having just scanned an identifier
|
875 |
|
|
|
876 |
|
|
if No (Prefix_Node) then
|
877 |
|
|
return Designator_Node;
|
878 |
|
|
else
|
879 |
|
|
Selector_Node := New_Node (N_Selected_Component, Dot_Sloc);
|
880 |
|
|
Set_Prefix (Selector_Node, Prefix_Node);
|
881 |
|
|
Set_Selector_Name (Selector_Node, Designator_Node);
|
882 |
|
|
return Selector_Node;
|
883 |
|
|
end if;
|
884 |
|
|
|
885 |
|
|
exception
|
886 |
|
|
when Error_Resync =>
|
887 |
|
|
return Error;
|
888 |
|
|
end P_Qualified_Simple_Name;
|
889 |
|
|
|
890 |
|
|
-- This procedure differs from P_Qualified_Simple_Name only in that it
|
891 |
|
|
-- raises Error_Resync if any error is encountered. It only returns after
|
892 |
|
|
-- scanning a valid qualified simple name.
|
893 |
|
|
|
894 |
|
|
-- Error recovery: can raise Error_Resync
|
895 |
|
|
|
896 |
|
|
function P_Qualified_Simple_Name_Resync return Node_Id is
|
897 |
|
|
Designator_Node : Node_Id;
|
898 |
|
|
Prefix_Node : Node_Id;
|
899 |
|
|
Selector_Node : Node_Id;
|
900 |
|
|
Dot_Sloc : Source_Ptr := No_Location;
|
901 |
|
|
|
902 |
|
|
begin
|
903 |
|
|
Prefix_Node := Empty;
|
904 |
|
|
|
905 |
|
|
-- Loop through prefixes
|
906 |
|
|
|
907 |
|
|
loop
|
908 |
|
|
Designator_Node := Token_Node;
|
909 |
|
|
|
910 |
|
|
if Token = Tok_Identifier then
|
911 |
|
|
Scan; -- past identifier
|
912 |
|
|
exit when Token /= Tok_Dot;
|
913 |
|
|
|
914 |
|
|
elsif Token not in Token_Class_Desig then
|
915 |
|
|
Discard_Junk_Node (P_Identifier); -- to issue the error message
|
916 |
|
|
raise Error_Resync;
|
917 |
|
|
|
918 |
|
|
else
|
919 |
|
|
Scan; -- past designator
|
920 |
|
|
|
921 |
|
|
if Token /= Tok_Dot then
|
922 |
|
|
Error_Msg_SP ("identifier expected");
|
923 |
|
|
raise Error_Resync;
|
924 |
|
|
end if;
|
925 |
|
|
end if;
|
926 |
|
|
|
927 |
|
|
-- Here at a dot, with token just before it in Designator_Node
|
928 |
|
|
|
929 |
|
|
if No (Prefix_Node) then
|
930 |
|
|
Prefix_Node := Designator_Node;
|
931 |
|
|
else
|
932 |
|
|
Selector_Node := New_Node (N_Selected_Component, Dot_Sloc);
|
933 |
|
|
Set_Prefix (Selector_Node, Prefix_Node);
|
934 |
|
|
Set_Selector_Name (Selector_Node, Designator_Node);
|
935 |
|
|
Prefix_Node := Selector_Node;
|
936 |
|
|
end if;
|
937 |
|
|
|
938 |
|
|
Dot_Sloc := Token_Ptr;
|
939 |
|
|
Scan; -- past period
|
940 |
|
|
end loop;
|
941 |
|
|
|
942 |
|
|
-- Fall out of the loop having just scanned an identifier
|
943 |
|
|
|
944 |
|
|
if No (Prefix_Node) then
|
945 |
|
|
return Designator_Node;
|
946 |
|
|
else
|
947 |
|
|
Selector_Node := New_Node (N_Selected_Component, Dot_Sloc);
|
948 |
|
|
Set_Prefix (Selector_Node, Prefix_Node);
|
949 |
|
|
Set_Selector_Name (Selector_Node, Designator_Node);
|
950 |
|
|
return Selector_Node;
|
951 |
|
|
end if;
|
952 |
|
|
end P_Qualified_Simple_Name_Resync;
|
953 |
|
|
|
954 |
|
|
----------------------
|
955 |
|
|
-- 4.1 Direct_Name --
|
956 |
|
|
----------------------
|
957 |
|
|
|
958 |
|
|
-- Parsed by P_Name and other functions in section 4.1
|
959 |
|
|
|
960 |
|
|
-----------------
|
961 |
|
|
-- 4.1 Prefix --
|
962 |
|
|
-----------------
|
963 |
|
|
|
964 |
|
|
-- Parsed by P_Name (4.1)
|
965 |
|
|
|
966 |
|
|
-------------------------------
|
967 |
|
|
-- 4.1 Explicit Dereference --
|
968 |
|
|
-------------------------------
|
969 |
|
|
|
970 |
|
|
-- Parsed by P_Name (4.1)
|
971 |
|
|
|
972 |
|
|
-------------------------------
|
973 |
|
|
-- 4.1 Implicit_Dereference --
|
974 |
|
|
-------------------------------
|
975 |
|
|
|
976 |
|
|
-- Parsed by P_Name (4.1)
|
977 |
|
|
|
978 |
|
|
----------------------------
|
979 |
|
|
-- 4.1 Indexed Component --
|
980 |
|
|
----------------------------
|
981 |
|
|
|
982 |
|
|
-- Parsed by P_Name (4.1)
|
983 |
|
|
|
984 |
|
|
----------------
|
985 |
|
|
-- 4.1 Slice --
|
986 |
|
|
----------------
|
987 |
|
|
|
988 |
|
|
-- Parsed by P_Name (4.1)
|
989 |
|
|
|
990 |
|
|
-----------------------------
|
991 |
|
|
-- 4.1 Selected_Component --
|
992 |
|
|
-----------------------------
|
993 |
|
|
|
994 |
|
|
-- Parsed by P_Name (4.1)
|
995 |
|
|
|
996 |
|
|
------------------------
|
997 |
|
|
-- 4.1 Selector Name --
|
998 |
|
|
------------------------
|
999 |
|
|
|
1000 |
|
|
-- Parsed by P_Name (4.1)
|
1001 |
|
|
|
1002 |
|
|
------------------------------
|
1003 |
|
|
-- 4.1 Attribute Reference --
|
1004 |
|
|
------------------------------
|
1005 |
|
|
|
1006 |
|
|
-- Parsed by P_Name (4.1)
|
1007 |
|
|
|
1008 |
|
|
-------------------------------
|
1009 |
|
|
-- 4.1 Attribute Designator --
|
1010 |
|
|
-------------------------------
|
1011 |
|
|
|
1012 |
|
|
-- Parsed by P_Name (4.1)
|
1013 |
|
|
|
1014 |
|
|
--------------------------------------
|
1015 |
|
|
-- 4.1.4 Range Attribute Reference --
|
1016 |
|
|
--------------------------------------
|
1017 |
|
|
|
1018 |
|
|
-- RANGE_ATTRIBUTE_REFERENCE ::= PREFIX ' RANGE_ATTRIBUTE_DESIGNATOR
|
1019 |
|
|
|
1020 |
|
|
-- RANGE_ATTRIBUTE_DESIGNATOR ::= range [(static_EXPRESSION)]
|
1021 |
|
|
|
1022 |
|
|
-- In the grammar, a RANGE attribute is simply a name, but its use is
|
1023 |
|
|
-- highly restricted, so in the parser, we do not regard it as a name.
|
1024 |
|
|
-- Instead, P_Name returns without scanning the 'RANGE part of the
|
1025 |
|
|
-- attribute, and the caller uses the following function to construct
|
1026 |
|
|
-- a range attribute in places where it is appropriate.
|
1027 |
|
|
|
1028 |
|
|
-- Note that RANGE here is treated essentially as an identifier,
|
1029 |
|
|
-- rather than a reserved word.
|
1030 |
|
|
|
1031 |
|
|
-- The caller has parsed the prefix, i.e. a name, and Token points to
|
1032 |
|
|
-- the apostrophe. The token after the apostrophe is known to be RANGE
|
1033 |
|
|
-- at this point. The prefix node becomes the prefix of the attribute.
|
1034 |
|
|
|
1035 |
|
|
-- Error_Recovery: Cannot raise Error_Resync
|
1036 |
|
|
|
1037 |
|
|
function P_Range_Attribute_Reference
|
1038 |
|
|
(Prefix_Node : Node_Id)
|
1039 |
|
|
return Node_Id
|
1040 |
|
|
is
|
1041 |
|
|
Attr_Node : Node_Id;
|
1042 |
|
|
|
1043 |
|
|
begin
|
1044 |
|
|
Attr_Node := New_Node (N_Attribute_Reference, Token_Ptr);
|
1045 |
|
|
Set_Prefix (Attr_Node, Prefix_Node);
|
1046 |
|
|
Scan; -- past apostrophe
|
1047 |
|
|
|
1048 |
|
|
if Style_Check then
|
1049 |
|
|
Style.Check_Attribute_Name (True);
|
1050 |
|
|
end if;
|
1051 |
|
|
|
1052 |
|
|
Set_Attribute_Name (Attr_Node, Name_Range);
|
1053 |
|
|
Scan; -- past RANGE
|
1054 |
|
|
|
1055 |
|
|
if Token = Tok_Left_Paren then
|
1056 |
|
|
Scan; -- past left paren
|
1057 |
|
|
Set_Expressions (Attr_Node, New_List (P_Expression_If_OK));
|
1058 |
|
|
T_Right_Paren;
|
1059 |
|
|
end if;
|
1060 |
|
|
|
1061 |
|
|
return Attr_Node;
|
1062 |
|
|
end P_Range_Attribute_Reference;
|
1063 |
|
|
|
1064 |
|
|
---------------------------------------
|
1065 |
|
|
-- 4.1.4 Range Attribute Designator --
|
1066 |
|
|
---------------------------------------
|
1067 |
|
|
|
1068 |
|
|
-- Parsed by P_Range_Attribute_Reference (4.4)
|
1069 |
|
|
|
1070 |
|
|
--------------------
|
1071 |
|
|
-- 4.3 Aggregate --
|
1072 |
|
|
--------------------
|
1073 |
|
|
|
1074 |
|
|
-- AGGREGATE ::= RECORD_AGGREGATE | EXTENSION_AGGREGATE | ARRAY_AGGREGATE
|
1075 |
|
|
|
1076 |
|
|
-- Parsed by P_Aggregate_Or_Paren_Expr (4.3), except in the case where
|
1077 |
|
|
-- an aggregate is known to be required (code statement, extension
|
1078 |
|
|
-- aggregate), in which cases this routine performs the necessary check
|
1079 |
|
|
-- that we have an aggregate rather than a parenthesized expression
|
1080 |
|
|
|
1081 |
|
|
-- Error recovery: can raise Error_Resync
|
1082 |
|
|
|
1083 |
|
|
function P_Aggregate return Node_Id is
|
1084 |
|
|
Aggr_Sloc : constant Source_Ptr := Token_Ptr;
|
1085 |
|
|
Aggr_Node : constant Node_Id := P_Aggregate_Or_Paren_Expr;
|
1086 |
|
|
|
1087 |
|
|
begin
|
1088 |
|
|
if Nkind (Aggr_Node) /= N_Aggregate
|
1089 |
|
|
and then
|
1090 |
|
|
Nkind (Aggr_Node) /= N_Extension_Aggregate
|
1091 |
|
|
then
|
1092 |
|
|
Error_Msg
|
1093 |
|
|
("aggregate may not have single positional component", Aggr_Sloc);
|
1094 |
|
|
return Error;
|
1095 |
|
|
else
|
1096 |
|
|
return Aggr_Node;
|
1097 |
|
|
end if;
|
1098 |
|
|
end P_Aggregate;
|
1099 |
|
|
|
1100 |
|
|
------------------------------------------------
|
1101 |
|
|
-- 4.3 Aggregate or Parenthesized Expression --
|
1102 |
|
|
------------------------------------------------
|
1103 |
|
|
|
1104 |
|
|
-- This procedure parses out either an aggregate or a parenthesized
|
1105 |
|
|
-- expression (these two constructs are closely related, since a
|
1106 |
|
|
-- parenthesized expression looks like an aggregate with a single
|
1107 |
|
|
-- positional component).
|
1108 |
|
|
|
1109 |
|
|
-- AGGREGATE ::=
|
1110 |
|
|
-- RECORD_AGGREGATE | EXTENSION_AGGREGATE | ARRAY_AGGREGATE
|
1111 |
|
|
|
1112 |
|
|
-- RECORD_AGGREGATE ::= (RECORD_COMPONENT_ASSOCIATION_LIST)
|
1113 |
|
|
|
1114 |
|
|
-- RECORD_COMPONENT_ASSOCIATION_LIST ::=
|
1115 |
|
|
-- RECORD_COMPONENT_ASSOCIATION {, RECORD_COMPONENT_ASSOCIATION}
|
1116 |
|
|
-- | null record
|
1117 |
|
|
|
1118 |
|
|
-- RECORD_COMPONENT_ASSOCIATION ::=
|
1119 |
|
|
-- [COMPONENT_CHOICE_LIST =>] EXPRESSION
|
1120 |
|
|
|
1121 |
|
|
-- COMPONENT_CHOICE_LIST ::=
|
1122 |
|
|
-- component_SELECTOR_NAME {| component_SELECTOR_NAME}
|
1123 |
|
|
-- | others
|
1124 |
|
|
|
1125 |
|
|
-- EXTENSION_AGGREGATE ::=
|
1126 |
|
|
-- (ANCESTOR_PART with RECORD_COMPONENT_ASSOCIATION_LIST)
|
1127 |
|
|
|
1128 |
|
|
-- ANCESTOR_PART ::= EXPRESSION | SUBTYPE_MARK
|
1129 |
|
|
|
1130 |
|
|
-- ARRAY_AGGREGATE ::=
|
1131 |
|
|
-- POSITIONAL_ARRAY_AGGREGATE | NAMED_ARRAY_AGGREGATE
|
1132 |
|
|
|
1133 |
|
|
-- POSITIONAL_ARRAY_AGGREGATE ::=
|
1134 |
|
|
-- (EXPRESSION, EXPRESSION {, EXPRESSION})
|
1135 |
|
|
-- | (EXPRESSION {, EXPRESSION}, others => EXPRESSION)
|
1136 |
|
|
-- | (EXPRESSION {, EXPRESSION}, others => <>)
|
1137 |
|
|
|
1138 |
|
|
-- NAMED_ARRAY_AGGREGATE ::=
|
1139 |
|
|
-- (ARRAY_COMPONENT_ASSOCIATION {, ARRAY_COMPONENT_ASSOCIATION})
|
1140 |
|
|
|
1141 |
|
|
-- PRIMARY ::= (EXPRESSION);
|
1142 |
|
|
|
1143 |
|
|
-- Error recovery: can raise Error_Resync
|
1144 |
|
|
|
1145 |
|
|
-- Note: POSITIONAL_ARRAY_AGGREGATE rule has been extended to give support
|
1146 |
|
|
-- to Ada 2005 limited aggregates (AI-287)
|
1147 |
|
|
|
1148 |
|
|
function P_Aggregate_Or_Paren_Expr return Node_Id is
|
1149 |
|
|
Aggregate_Node : Node_Id;
|
1150 |
|
|
Expr_List : List_Id;
|
1151 |
|
|
Assoc_List : List_Id;
|
1152 |
|
|
Expr_Node : Node_Id;
|
1153 |
|
|
Lparen_Sloc : Source_Ptr;
|
1154 |
|
|
Scan_State : Saved_Scan_State;
|
1155 |
|
|
|
1156 |
|
|
begin
|
1157 |
|
|
Lparen_Sloc := Token_Ptr;
|
1158 |
|
|
T_Left_Paren;
|
1159 |
|
|
|
1160 |
|
|
-- Conditional expression case
|
1161 |
|
|
|
1162 |
|
|
if Token = Tok_If then
|
1163 |
|
|
Expr_Node := P_Conditional_Expression;
|
1164 |
|
|
T_Right_Paren;
|
1165 |
|
|
return Expr_Node;
|
1166 |
|
|
|
1167 |
|
|
-- Note: the mechanism used here of rescanning the initial expression
|
1168 |
|
|
-- is distinctly unpleasant, but it saves a lot of fiddling in scanning
|
1169 |
|
|
-- out the discrete choice list.
|
1170 |
|
|
|
1171 |
|
|
-- Deal with expression and extension aggregate cases first
|
1172 |
|
|
|
1173 |
|
|
elsif Token /= Tok_Others then
|
1174 |
|
|
Save_Scan_State (Scan_State); -- at start of expression
|
1175 |
|
|
|
1176 |
|
|
-- Deal with (NULL RECORD) case
|
1177 |
|
|
|
1178 |
|
|
if Token = Tok_Null then
|
1179 |
|
|
Scan; -- past NULL
|
1180 |
|
|
|
1181 |
|
|
if Token = Tok_Record then
|
1182 |
|
|
Aggregate_Node := New_Node (N_Aggregate, Lparen_Sloc);
|
1183 |
|
|
Set_Null_Record_Present (Aggregate_Node, True);
|
1184 |
|
|
Scan; -- past RECORD
|
1185 |
|
|
T_Right_Paren;
|
1186 |
|
|
return Aggregate_Node;
|
1187 |
|
|
else
|
1188 |
|
|
Restore_Scan_State (Scan_State); -- to NULL that must be expr
|
1189 |
|
|
end if;
|
1190 |
|
|
end if;
|
1191 |
|
|
|
1192 |
|
|
-- Ada 2005 (AI-287): The box notation is allowed only with named
|
1193 |
|
|
-- notation because positional notation might be error prone. For
|
1194 |
|
|
-- example, in "(X, <>, Y, <>)", there is no type associated with
|
1195 |
|
|
-- the boxes, so you might not be leaving out the components you
|
1196 |
|
|
-- thought you were leaving out.
|
1197 |
|
|
|
1198 |
|
|
if Ada_Version >= Ada_05 and then Token = Tok_Box then
|
1199 |
|
|
Error_Msg_SC ("(Ada 2005) box notation only allowed with "
|
1200 |
|
|
& "named notation");
|
1201 |
|
|
Scan; -- past BOX
|
1202 |
|
|
Aggregate_Node := New_Node (N_Aggregate, Lparen_Sloc);
|
1203 |
|
|
return Aggregate_Node;
|
1204 |
|
|
end if;
|
1205 |
|
|
|
1206 |
|
|
Expr_Node := P_Expression_Or_Range_Attribute_If_OK;
|
1207 |
|
|
|
1208 |
|
|
-- Extension aggregate case
|
1209 |
|
|
|
1210 |
|
|
if Token = Tok_With then
|
1211 |
|
|
|
1212 |
|
|
if Nkind (Expr_Node) = N_Attribute_Reference
|
1213 |
|
|
and then Attribute_Name (Expr_Node) = Name_Range
|
1214 |
|
|
then
|
1215 |
|
|
Bad_Range_Attribute (Sloc (Expr_Node));
|
1216 |
|
|
return Error;
|
1217 |
|
|
end if;
|
1218 |
|
|
|
1219 |
|
|
if Ada_Version = Ada_83 then
|
1220 |
|
|
Error_Msg_SC ("(Ada 83) extension aggregate not allowed");
|
1221 |
|
|
end if;
|
1222 |
|
|
|
1223 |
|
|
Aggregate_Node := New_Node (N_Extension_Aggregate, Lparen_Sloc);
|
1224 |
|
|
Set_Ancestor_Part (Aggregate_Node, Expr_Node);
|
1225 |
|
|
Scan; -- past WITH
|
1226 |
|
|
|
1227 |
|
|
-- Deal with WITH NULL RECORD case
|
1228 |
|
|
|
1229 |
|
|
if Token = Tok_Null then
|
1230 |
|
|
Save_Scan_State (Scan_State); -- at NULL
|
1231 |
|
|
Scan; -- past NULL
|
1232 |
|
|
|
1233 |
|
|
if Token = Tok_Record then
|
1234 |
|
|
Scan; -- past RECORD
|
1235 |
|
|
Set_Null_Record_Present (Aggregate_Node, True);
|
1236 |
|
|
T_Right_Paren;
|
1237 |
|
|
return Aggregate_Node;
|
1238 |
|
|
|
1239 |
|
|
else
|
1240 |
|
|
Restore_Scan_State (Scan_State); -- to NULL that must be expr
|
1241 |
|
|
end if;
|
1242 |
|
|
end if;
|
1243 |
|
|
|
1244 |
|
|
if Token /= Tok_Others then
|
1245 |
|
|
Save_Scan_State (Scan_State);
|
1246 |
|
|
Expr_Node := P_Expression;
|
1247 |
|
|
else
|
1248 |
|
|
Expr_Node := Empty;
|
1249 |
|
|
end if;
|
1250 |
|
|
|
1251 |
|
|
-- Expression case
|
1252 |
|
|
|
1253 |
|
|
elsif Token = Tok_Right_Paren or else Token in Token_Class_Eterm then
|
1254 |
|
|
if Nkind (Expr_Node) = N_Attribute_Reference
|
1255 |
|
|
and then Attribute_Name (Expr_Node) = Name_Range
|
1256 |
|
|
then
|
1257 |
|
|
Error_Msg
|
1258 |
|
|
("|parentheses not allowed for range attribute", Lparen_Sloc);
|
1259 |
|
|
Scan; -- past right paren
|
1260 |
|
|
return Expr_Node;
|
1261 |
|
|
end if;
|
1262 |
|
|
|
1263 |
|
|
-- Bump paren count of expression
|
1264 |
|
|
|
1265 |
|
|
if Expr_Node /= Error then
|
1266 |
|
|
Set_Paren_Count (Expr_Node, Paren_Count (Expr_Node) + 1);
|
1267 |
|
|
end if;
|
1268 |
|
|
|
1269 |
|
|
T_Right_Paren; -- past right paren (error message if none)
|
1270 |
|
|
return Expr_Node;
|
1271 |
|
|
|
1272 |
|
|
-- Normal aggregate case
|
1273 |
|
|
|
1274 |
|
|
else
|
1275 |
|
|
Aggregate_Node := New_Node (N_Aggregate, Lparen_Sloc);
|
1276 |
|
|
end if;
|
1277 |
|
|
|
1278 |
|
|
-- Others case
|
1279 |
|
|
|
1280 |
|
|
else
|
1281 |
|
|
Aggregate_Node := New_Node (N_Aggregate, Lparen_Sloc);
|
1282 |
|
|
Expr_Node := Empty;
|
1283 |
|
|
end if;
|
1284 |
|
|
|
1285 |
|
|
-- Prepare to scan list of component associations
|
1286 |
|
|
|
1287 |
|
|
Expr_List := No_List; -- don't set yet, maybe all named entries
|
1288 |
|
|
Assoc_List := No_List; -- don't set yet, maybe all positional entries
|
1289 |
|
|
|
1290 |
|
|
-- This loop scans through component associations. On entry to the
|
1291 |
|
|
-- loop, an expression has been scanned at the start of the current
|
1292 |
|
|
-- association unless initial token was OTHERS, in which case
|
1293 |
|
|
-- Expr_Node is set to Empty.
|
1294 |
|
|
|
1295 |
|
|
loop
|
1296 |
|
|
-- Deal with others association first. This is a named association
|
1297 |
|
|
|
1298 |
|
|
if No (Expr_Node) then
|
1299 |
|
|
if No (Assoc_List) then
|
1300 |
|
|
Assoc_List := New_List;
|
1301 |
|
|
end if;
|
1302 |
|
|
|
1303 |
|
|
Append (P_Record_Or_Array_Component_Association, Assoc_List);
|
1304 |
|
|
|
1305 |
|
|
-- Improper use of WITH
|
1306 |
|
|
|
1307 |
|
|
elsif Token = Tok_With then
|
1308 |
|
|
Error_Msg_SC ("WITH must be preceded by single expression in " &
|
1309 |
|
|
"extension aggregate");
|
1310 |
|
|
raise Error_Resync;
|
1311 |
|
|
|
1312 |
|
|
-- A range attribute can only appear as part of a discrete choice
|
1313 |
|
|
-- list.
|
1314 |
|
|
|
1315 |
|
|
elsif Nkind (Expr_Node) = N_Attribute_Reference
|
1316 |
|
|
and then Attribute_Name (Expr_Node) = Name_Range
|
1317 |
|
|
and then Token /= Tok_Arrow
|
1318 |
|
|
and then Token /= Tok_Vertical_Bar
|
1319 |
|
|
then
|
1320 |
|
|
Bad_Range_Attribute (Sloc (Expr_Node));
|
1321 |
|
|
return Error;
|
1322 |
|
|
|
1323 |
|
|
-- Assume positional case if comma, right paren, or literal or
|
1324 |
|
|
-- identifier or OTHERS follows (the latter cases are missing
|
1325 |
|
|
-- comma cases). Also assume positional if a semicolon follows,
|
1326 |
|
|
-- which can happen if there are missing parens
|
1327 |
|
|
|
1328 |
|
|
elsif Token = Tok_Comma
|
1329 |
|
|
or else Token = Tok_Right_Paren
|
1330 |
|
|
or else Token = Tok_Others
|
1331 |
|
|
or else Token in Token_Class_Lit_Or_Name
|
1332 |
|
|
or else Token = Tok_Semicolon
|
1333 |
|
|
then
|
1334 |
|
|
if Present (Assoc_List) then
|
1335 |
|
|
Error_Msg_BC
|
1336 |
|
|
("""='>"" expected (positional association cannot follow " &
|
1337 |
|
|
"named association)");
|
1338 |
|
|
end if;
|
1339 |
|
|
|
1340 |
|
|
if No (Expr_List) then
|
1341 |
|
|
Expr_List := New_List;
|
1342 |
|
|
end if;
|
1343 |
|
|
|
1344 |
|
|
Append (Expr_Node, Expr_List);
|
1345 |
|
|
|
1346 |
|
|
-- Check for aggregate followed by left parent, maybe missing comma
|
1347 |
|
|
|
1348 |
|
|
elsif Nkind (Expr_Node) = N_Aggregate
|
1349 |
|
|
and then Token = Tok_Left_Paren
|
1350 |
|
|
then
|
1351 |
|
|
T_Comma;
|
1352 |
|
|
|
1353 |
|
|
if No (Expr_List) then
|
1354 |
|
|
Expr_List := New_List;
|
1355 |
|
|
end if;
|
1356 |
|
|
|
1357 |
|
|
Append (Expr_Node, Expr_List);
|
1358 |
|
|
|
1359 |
|
|
-- Anything else is assumed to be a named association
|
1360 |
|
|
|
1361 |
|
|
else
|
1362 |
|
|
Restore_Scan_State (Scan_State); -- to start of expression
|
1363 |
|
|
|
1364 |
|
|
if No (Assoc_List) then
|
1365 |
|
|
Assoc_List := New_List;
|
1366 |
|
|
end if;
|
1367 |
|
|
|
1368 |
|
|
Append (P_Record_Or_Array_Component_Association, Assoc_List);
|
1369 |
|
|
end if;
|
1370 |
|
|
|
1371 |
|
|
exit when not Comma_Present;
|
1372 |
|
|
|
1373 |
|
|
-- If we are at an expression terminator, something is seriously
|
1374 |
|
|
-- wrong, so let's get out now, before we start eating up stuff
|
1375 |
|
|
-- that doesn't belong to us!
|
1376 |
|
|
|
1377 |
|
|
if Token in Token_Class_Eterm then
|
1378 |
|
|
Error_Msg_AP ("expecting expression or component association");
|
1379 |
|
|
exit;
|
1380 |
|
|
end if;
|
1381 |
|
|
|
1382 |
|
|
-- Otherwise initiate for reentry to top of loop by scanning an
|
1383 |
|
|
-- initial expression, unless the first token is OTHERS.
|
1384 |
|
|
|
1385 |
|
|
if Token = Tok_Others then
|
1386 |
|
|
Expr_Node := Empty;
|
1387 |
|
|
else
|
1388 |
|
|
Save_Scan_State (Scan_State); -- at start of expression
|
1389 |
|
|
Expr_Node := P_Expression_Or_Range_Attribute_If_OK;
|
1390 |
|
|
|
1391 |
|
|
end if;
|
1392 |
|
|
end loop;
|
1393 |
|
|
|
1394 |
|
|
-- All component associations (positional and named) have been scanned
|
1395 |
|
|
|
1396 |
|
|
T_Right_Paren;
|
1397 |
|
|
Set_Expressions (Aggregate_Node, Expr_List);
|
1398 |
|
|
Set_Component_Associations (Aggregate_Node, Assoc_List);
|
1399 |
|
|
return Aggregate_Node;
|
1400 |
|
|
end P_Aggregate_Or_Paren_Expr;
|
1401 |
|
|
|
1402 |
|
|
------------------------------------------------
|
1403 |
|
|
-- 4.3 Record or Array Component Association --
|
1404 |
|
|
------------------------------------------------
|
1405 |
|
|
|
1406 |
|
|
-- RECORD_COMPONENT_ASSOCIATION ::=
|
1407 |
|
|
-- [COMPONENT_CHOICE_LIST =>] EXPRESSION
|
1408 |
|
|
-- | COMPONENT_CHOICE_LIST => <>
|
1409 |
|
|
|
1410 |
|
|
-- COMPONENT_CHOICE_LIST =>
|
1411 |
|
|
-- component_SELECTOR_NAME {| component_SELECTOR_NAME}
|
1412 |
|
|
-- | others
|
1413 |
|
|
|
1414 |
|
|
-- ARRAY_COMPONENT_ASSOCIATION ::=
|
1415 |
|
|
-- DISCRETE_CHOICE_LIST => EXPRESSION
|
1416 |
|
|
-- | DISCRETE_CHOICE_LIST => <>
|
1417 |
|
|
|
1418 |
|
|
-- Note: this routine only handles the named cases, including others.
|
1419 |
|
|
-- Cases where the component choice list is not present have already
|
1420 |
|
|
-- been handled directly.
|
1421 |
|
|
|
1422 |
|
|
-- Error recovery: can raise Error_Resync
|
1423 |
|
|
|
1424 |
|
|
-- Note: RECORD_COMPONENT_ASSOCIATION and ARRAY_COMPONENT_ASSOCIATION
|
1425 |
|
|
-- rules have been extended to give support to Ada 2005 limited
|
1426 |
|
|
-- aggregates (AI-287)
|
1427 |
|
|
|
1428 |
|
|
function P_Record_Or_Array_Component_Association return Node_Id is
|
1429 |
|
|
Assoc_Node : Node_Id;
|
1430 |
|
|
|
1431 |
|
|
begin
|
1432 |
|
|
Assoc_Node := New_Node (N_Component_Association, Token_Ptr);
|
1433 |
|
|
Set_Choices (Assoc_Node, P_Discrete_Choice_List);
|
1434 |
|
|
Set_Sloc (Assoc_Node, Token_Ptr);
|
1435 |
|
|
TF_Arrow;
|
1436 |
|
|
|
1437 |
|
|
if Token = Tok_Box then
|
1438 |
|
|
|
1439 |
|
|
-- Ada 2005(AI-287): The box notation is used to indicate the
|
1440 |
|
|
-- default initialization of aggregate components
|
1441 |
|
|
|
1442 |
|
|
if Ada_Version < Ada_05 then
|
1443 |
|
|
Error_Msg_SP
|
1444 |
|
|
("component association with '<'> is an Ada 2005 extension");
|
1445 |
|
|
Error_Msg_SP ("\unit must be compiled with -gnat05 switch");
|
1446 |
|
|
end if;
|
1447 |
|
|
|
1448 |
|
|
Set_Box_Present (Assoc_Node);
|
1449 |
|
|
Scan; -- Past box
|
1450 |
|
|
else
|
1451 |
|
|
Set_Expression (Assoc_Node, P_Expression);
|
1452 |
|
|
end if;
|
1453 |
|
|
|
1454 |
|
|
return Assoc_Node;
|
1455 |
|
|
end P_Record_Or_Array_Component_Association;
|
1456 |
|
|
|
1457 |
|
|
-----------------------------
|
1458 |
|
|
-- 4.3.1 Record Aggregate --
|
1459 |
|
|
-----------------------------
|
1460 |
|
|
|
1461 |
|
|
-- Case of enumeration aggregate is parsed by P_Aggregate (4.3)
|
1462 |
|
|
-- All other cases are parsed by P_Aggregate_Or_Paren_Expr (4.3)
|
1463 |
|
|
|
1464 |
|
|
----------------------------------------------
|
1465 |
|
|
-- 4.3.1 Record Component Association List --
|
1466 |
|
|
----------------------------------------------
|
1467 |
|
|
|
1468 |
|
|
-- Parsed by P_Aggregate_Or_Paren_Expr (4.3)
|
1469 |
|
|
|
1470 |
|
|
----------------------------------
|
1471 |
|
|
-- 4.3.1 Component Choice List --
|
1472 |
|
|
----------------------------------
|
1473 |
|
|
|
1474 |
|
|
-- Parsed by P_Aggregate_Or_Paren_Expr (4.3)
|
1475 |
|
|
|
1476 |
|
|
--------------------------------
|
1477 |
|
|
-- 4.3.1 Extension Aggregate --
|
1478 |
|
|
--------------------------------
|
1479 |
|
|
|
1480 |
|
|
-- Parsed by P_Aggregate_Or_Paren_Expr (4.3)
|
1481 |
|
|
|
1482 |
|
|
--------------------------
|
1483 |
|
|
-- 4.3.1 Ancestor Part --
|
1484 |
|
|
--------------------------
|
1485 |
|
|
|
1486 |
|
|
-- Parsed by P_Aggregate_Or_Paren_Expr (4.3)
|
1487 |
|
|
|
1488 |
|
|
----------------------------
|
1489 |
|
|
-- 4.3.1 Array Aggregate --
|
1490 |
|
|
----------------------------
|
1491 |
|
|
|
1492 |
|
|
-- Parsed by P_Aggregate_Or_Paren_Expr (4.3)
|
1493 |
|
|
|
1494 |
|
|
---------------------------------------
|
1495 |
|
|
-- 4.3.1 Positional Array Aggregate --
|
1496 |
|
|
---------------------------------------
|
1497 |
|
|
|
1498 |
|
|
-- Parsed by P_Aggregate_Or_Paren_Expr (4.3)
|
1499 |
|
|
|
1500 |
|
|
----------------------------------
|
1501 |
|
|
-- 4.3.1 Named Array Aggregate --
|
1502 |
|
|
----------------------------------
|
1503 |
|
|
|
1504 |
|
|
-- Parsed by P_Aggregate_Or_Paren_Expr (4.3)
|
1505 |
|
|
|
1506 |
|
|
----------------------------------------
|
1507 |
|
|
-- 4.3.1 Array Component Association --
|
1508 |
|
|
----------------------------------------
|
1509 |
|
|
|
1510 |
|
|
-- Parsed by P_Aggregate_Or_Paren_Expr (4.3)
|
1511 |
|
|
|
1512 |
|
|
---------------------
|
1513 |
|
|
-- 4.4 Expression --
|
1514 |
|
|
---------------------
|
1515 |
|
|
|
1516 |
|
|
-- EXPRESSION ::=
|
1517 |
|
|
-- RELATION {and RELATION} | RELATION {and then RELATION}
|
1518 |
|
|
-- | RELATION {or RELATION} | RELATION {or else RELATION}
|
1519 |
|
|
-- | RELATION {xor RELATION}
|
1520 |
|
|
|
1521 |
|
|
-- On return, Expr_Form indicates the categorization of the expression
|
1522 |
|
|
-- EF_Range_Attr is not a possible value (if a range attribute is found,
|
1523 |
|
|
-- an error message is given, and Error is returned).
|
1524 |
|
|
|
1525 |
|
|
-- Error recovery: cannot raise Error_Resync
|
1526 |
|
|
|
1527 |
|
|
function P_Expression return Node_Id is
|
1528 |
|
|
Logical_Op : Node_Kind;
|
1529 |
|
|
Prev_Logical_Op : Node_Kind;
|
1530 |
|
|
Op_Location : Source_Ptr;
|
1531 |
|
|
Node1 : Node_Id;
|
1532 |
|
|
Node2 : Node_Id;
|
1533 |
|
|
|
1534 |
|
|
begin
|
1535 |
|
|
Node1 := P_Relation;
|
1536 |
|
|
|
1537 |
|
|
if Token in Token_Class_Logop then
|
1538 |
|
|
Prev_Logical_Op := N_Empty;
|
1539 |
|
|
|
1540 |
|
|
loop
|
1541 |
|
|
Op_Location := Token_Ptr;
|
1542 |
|
|
Logical_Op := P_Logical_Operator;
|
1543 |
|
|
|
1544 |
|
|
if Prev_Logical_Op /= N_Empty and then
|
1545 |
|
|
Logical_Op /= Prev_Logical_Op
|
1546 |
|
|
then
|
1547 |
|
|
Error_Msg
|
1548 |
|
|
("mixed logical operators in expression", Op_Location);
|
1549 |
|
|
Prev_Logical_Op := N_Empty;
|
1550 |
|
|
else
|
1551 |
|
|
Prev_Logical_Op := Logical_Op;
|
1552 |
|
|
end if;
|
1553 |
|
|
|
1554 |
|
|
Node2 := Node1;
|
1555 |
|
|
Node1 := New_Op_Node (Logical_Op, Op_Location);
|
1556 |
|
|
Set_Left_Opnd (Node1, Node2);
|
1557 |
|
|
Set_Right_Opnd (Node1, P_Relation);
|
1558 |
|
|
exit when Token not in Token_Class_Logop;
|
1559 |
|
|
end loop;
|
1560 |
|
|
|
1561 |
|
|
Expr_Form := EF_Non_Simple;
|
1562 |
|
|
end if;
|
1563 |
|
|
|
1564 |
|
|
if Token = Tok_Apostrophe then
|
1565 |
|
|
Bad_Range_Attribute (Token_Ptr);
|
1566 |
|
|
return Error;
|
1567 |
|
|
else
|
1568 |
|
|
return Node1;
|
1569 |
|
|
end if;
|
1570 |
|
|
end P_Expression;
|
1571 |
|
|
|
1572 |
|
|
-- This function is identical to the normal P_Expression, except that it
|
1573 |
|
|
-- also permits the appearence of a conditional expression without the
|
1574 |
|
|
-- usual surrounding parentheses.
|
1575 |
|
|
|
1576 |
|
|
function P_Expression_If_OK return Node_Id is
|
1577 |
|
|
begin
|
1578 |
|
|
if Token = Tok_If then
|
1579 |
|
|
return P_Conditional_Expression;
|
1580 |
|
|
else
|
1581 |
|
|
return P_Expression;
|
1582 |
|
|
end if;
|
1583 |
|
|
end P_Expression_If_OK;
|
1584 |
|
|
|
1585 |
|
|
-- This function is identical to the normal P_Expression, except that it
|
1586 |
|
|
-- checks that the expression scan did not stop on a right paren. It is
|
1587 |
|
|
-- called in all contexts where a right parenthesis cannot legitimately
|
1588 |
|
|
-- follow an expression.
|
1589 |
|
|
|
1590 |
|
|
-- Error recovery: can not raise Error_Resync
|
1591 |
|
|
|
1592 |
|
|
function P_Expression_No_Right_Paren return Node_Id is
|
1593 |
|
|
Expr : constant Node_Id := P_Expression;
|
1594 |
|
|
begin
|
1595 |
|
|
Ignore (Tok_Right_Paren);
|
1596 |
|
|
return Expr;
|
1597 |
|
|
end P_Expression_No_Right_Paren;
|
1598 |
|
|
|
1599 |
|
|
----------------------------------------
|
1600 |
|
|
-- 4.4 Expression_Or_Range_Attribute --
|
1601 |
|
|
----------------------------------------
|
1602 |
|
|
|
1603 |
|
|
-- EXPRESSION ::=
|
1604 |
|
|
-- RELATION {and RELATION} | RELATION {and then RELATION}
|
1605 |
|
|
-- | RELATION {or RELATION} | RELATION {or else RELATION}
|
1606 |
|
|
-- | RELATION {xor RELATION}
|
1607 |
|
|
|
1608 |
|
|
-- RANGE_ATTRIBUTE_REFERENCE ::= PREFIX ' RANGE_ATTRIBUTE_DESIGNATOR
|
1609 |
|
|
|
1610 |
|
|
-- RANGE_ATTRIBUTE_DESIGNATOR ::= range [(static_EXPRESSION)]
|
1611 |
|
|
|
1612 |
|
|
-- On return, Expr_Form indicates the categorization of the expression
|
1613 |
|
|
-- and EF_Range_Attr is one of the possibilities.
|
1614 |
|
|
|
1615 |
|
|
-- Error recovery: cannot raise Error_Resync
|
1616 |
|
|
|
1617 |
|
|
-- In the grammar, a RANGE attribute is simply a name, but its use is
|
1618 |
|
|
-- highly restricted, so in the parser, we do not regard it as a name.
|
1619 |
|
|
-- Instead, P_Name returns without scanning the 'RANGE part of the
|
1620 |
|
|
-- attribute, and P_Expression_Or_Range_Attribute handles the range
|
1621 |
|
|
-- attribute reference. In the normal case where a range attribute is
|
1622 |
|
|
-- not allowed, an error message is issued by P_Expression.
|
1623 |
|
|
|
1624 |
|
|
function P_Expression_Or_Range_Attribute return Node_Id is
|
1625 |
|
|
Logical_Op : Node_Kind;
|
1626 |
|
|
Prev_Logical_Op : Node_Kind;
|
1627 |
|
|
Op_Location : Source_Ptr;
|
1628 |
|
|
Node1 : Node_Id;
|
1629 |
|
|
Node2 : Node_Id;
|
1630 |
|
|
Attr_Node : Node_Id;
|
1631 |
|
|
|
1632 |
|
|
begin
|
1633 |
|
|
Node1 := P_Relation;
|
1634 |
|
|
|
1635 |
|
|
if Token = Tok_Apostrophe then
|
1636 |
|
|
Attr_Node := P_Range_Attribute_Reference (Node1);
|
1637 |
|
|
Expr_Form := EF_Range_Attr;
|
1638 |
|
|
return Attr_Node;
|
1639 |
|
|
|
1640 |
|
|
elsif Token in Token_Class_Logop then
|
1641 |
|
|
Prev_Logical_Op := N_Empty;
|
1642 |
|
|
|
1643 |
|
|
loop
|
1644 |
|
|
Op_Location := Token_Ptr;
|
1645 |
|
|
Logical_Op := P_Logical_Operator;
|
1646 |
|
|
|
1647 |
|
|
if Prev_Logical_Op /= N_Empty and then
|
1648 |
|
|
Logical_Op /= Prev_Logical_Op
|
1649 |
|
|
then
|
1650 |
|
|
Error_Msg
|
1651 |
|
|
("mixed logical operators in expression", Op_Location);
|
1652 |
|
|
Prev_Logical_Op := N_Empty;
|
1653 |
|
|
else
|
1654 |
|
|
Prev_Logical_Op := Logical_Op;
|
1655 |
|
|
end if;
|
1656 |
|
|
|
1657 |
|
|
Node2 := Node1;
|
1658 |
|
|
Node1 := New_Op_Node (Logical_Op, Op_Location);
|
1659 |
|
|
Set_Left_Opnd (Node1, Node2);
|
1660 |
|
|
Set_Right_Opnd (Node1, P_Relation);
|
1661 |
|
|
exit when Token not in Token_Class_Logop;
|
1662 |
|
|
end loop;
|
1663 |
|
|
|
1664 |
|
|
Expr_Form := EF_Non_Simple;
|
1665 |
|
|
end if;
|
1666 |
|
|
|
1667 |
|
|
if Token = Tok_Apostrophe then
|
1668 |
|
|
Bad_Range_Attribute (Token_Ptr);
|
1669 |
|
|
return Error;
|
1670 |
|
|
else
|
1671 |
|
|
return Node1;
|
1672 |
|
|
end if;
|
1673 |
|
|
end P_Expression_Or_Range_Attribute;
|
1674 |
|
|
|
1675 |
|
|
-- Version that allows a non-parenthesized conditional expression
|
1676 |
|
|
|
1677 |
|
|
function P_Expression_Or_Range_Attribute_If_OK return Node_Id is
|
1678 |
|
|
begin
|
1679 |
|
|
if Token = Tok_If then
|
1680 |
|
|
return P_Conditional_Expression;
|
1681 |
|
|
else
|
1682 |
|
|
return P_Expression_Or_Range_Attribute;
|
1683 |
|
|
end if;
|
1684 |
|
|
end P_Expression_Or_Range_Attribute_If_OK;
|
1685 |
|
|
|
1686 |
|
|
-------------------
|
1687 |
|
|
-- 4.4 Relation --
|
1688 |
|
|
-------------------
|
1689 |
|
|
|
1690 |
|
|
-- RELATION ::=
|
1691 |
|
|
-- SIMPLE_EXPRESSION [RELATIONAL_OPERATOR SIMPLE_EXPRESSION]
|
1692 |
|
|
-- | SIMPLE_EXPRESSION [not] in RANGE
|
1693 |
|
|
-- | SIMPLE_EXPRESSION [not] in SUBTYPE_MARK
|
1694 |
|
|
|
1695 |
|
|
-- On return, Expr_Form indicates the categorization of the expression
|
1696 |
|
|
|
1697 |
|
|
-- Note: if Token = Tok_Apostrophe on return, then Expr_Form is set to
|
1698 |
|
|
-- EF_Simple_Name and the following token is RANGE (range attribute case).
|
1699 |
|
|
|
1700 |
|
|
-- Error recovery: cannot raise Error_Resync. If an error occurs within an
|
1701 |
|
|
-- expression, then tokens are scanned until either a non-expression token,
|
1702 |
|
|
-- a right paren (not matched by a left paren) or a comma, is encountered.
|
1703 |
|
|
|
1704 |
|
|
function P_Relation return Node_Id is
|
1705 |
|
|
Node1, Node2 : Node_Id;
|
1706 |
|
|
Optok : Source_Ptr;
|
1707 |
|
|
|
1708 |
|
|
begin
|
1709 |
|
|
Node1 := P_Simple_Expression;
|
1710 |
|
|
|
1711 |
|
|
if Token not in Token_Class_Relop then
|
1712 |
|
|
return Node1;
|
1713 |
|
|
|
1714 |
|
|
else
|
1715 |
|
|
-- Here we have a relational operator following. If so then scan it
|
1716 |
|
|
-- out. Note that the assignment symbol := is treated as a relational
|
1717 |
|
|
-- operator to improve the error recovery when it is misused for =.
|
1718 |
|
|
-- P_Relational_Operator also parses the IN and NOT IN operations.
|
1719 |
|
|
|
1720 |
|
|
Optok := Token_Ptr;
|
1721 |
|
|
Node2 := New_Op_Node (P_Relational_Operator, Optok);
|
1722 |
|
|
Set_Left_Opnd (Node2, Node1);
|
1723 |
|
|
|
1724 |
|
|
-- Case of IN or NOT IN
|
1725 |
|
|
|
1726 |
|
|
if Prev_Token = Tok_In then
|
1727 |
|
|
P_Membership_Test (Node2);
|
1728 |
|
|
|
1729 |
|
|
-- Case of relational operator (= /= < <= > >=)
|
1730 |
|
|
|
1731 |
|
|
else
|
1732 |
|
|
Set_Right_Opnd (Node2, P_Simple_Expression);
|
1733 |
|
|
end if;
|
1734 |
|
|
|
1735 |
|
|
Expr_Form := EF_Non_Simple;
|
1736 |
|
|
|
1737 |
|
|
if Token in Token_Class_Relop then
|
1738 |
|
|
Error_Msg_SC ("unexpected relational operator");
|
1739 |
|
|
raise Error_Resync;
|
1740 |
|
|
end if;
|
1741 |
|
|
|
1742 |
|
|
return Node2;
|
1743 |
|
|
end if;
|
1744 |
|
|
|
1745 |
|
|
-- If any error occurs, then scan to the next expression terminator symbol
|
1746 |
|
|
-- or comma or right paren at the outer (i.e. current) parentheses level.
|
1747 |
|
|
-- The flags are set to indicate a normal simple expression.
|
1748 |
|
|
|
1749 |
|
|
exception
|
1750 |
|
|
when Error_Resync =>
|
1751 |
|
|
Resync_Expression;
|
1752 |
|
|
Expr_Form := EF_Simple;
|
1753 |
|
|
return Error;
|
1754 |
|
|
end P_Relation;
|
1755 |
|
|
|
1756 |
|
|
----------------------------
|
1757 |
|
|
-- 4.4 Simple Expression --
|
1758 |
|
|
----------------------------
|
1759 |
|
|
|
1760 |
|
|
-- SIMPLE_EXPRESSION ::=
|
1761 |
|
|
-- [UNARY_ADDING_OPERATOR] TERM {BINARY_ADDING_OPERATOR TERM}
|
1762 |
|
|
|
1763 |
|
|
-- On return, Expr_Form indicates the categorization of the expression
|
1764 |
|
|
|
1765 |
|
|
-- Note: if Token = Tok_Apostrophe on return, then Expr_Form is set to
|
1766 |
|
|
-- EF_Simple_Name and the following token is RANGE (range attribute case).
|
1767 |
|
|
|
1768 |
|
|
-- Error recovery: cannot raise Error_Resync. If an error occurs within an
|
1769 |
|
|
-- expression, then tokens are scanned until either a non-expression token,
|
1770 |
|
|
-- a right paren (not matched by a left paren) or a comma, is encountered.
|
1771 |
|
|
|
1772 |
|
|
-- Note: P_Simple_Expression is called only internally by higher level
|
1773 |
|
|
-- expression routines. In cases in the grammar where a simple expression
|
1774 |
|
|
-- is required, the approach is to scan an expression, and then post an
|
1775 |
|
|
-- appropriate error message if the expression obtained is not simple. This
|
1776 |
|
|
-- gives better error recovery and treatment.
|
1777 |
|
|
|
1778 |
|
|
function P_Simple_Expression return Node_Id is
|
1779 |
|
|
Scan_State : Saved_Scan_State;
|
1780 |
|
|
Node1 : Node_Id;
|
1781 |
|
|
Node2 : Node_Id;
|
1782 |
|
|
Tokptr : Source_Ptr;
|
1783 |
|
|
|
1784 |
|
|
begin
|
1785 |
|
|
-- Check for cases starting with a name. There are two reasons for
|
1786 |
|
|
-- special casing. First speed things up by catching a common case
|
1787 |
|
|
-- without going through several routine layers. Second the caller must
|
1788 |
|
|
-- be informed via Expr_Form when the simple expression is a name.
|
1789 |
|
|
|
1790 |
|
|
if Token in Token_Class_Name then
|
1791 |
|
|
Node1 := P_Name;
|
1792 |
|
|
|
1793 |
|
|
-- Deal with apostrophe cases
|
1794 |
|
|
|
1795 |
|
|
if Token = Tok_Apostrophe then
|
1796 |
|
|
Save_Scan_State (Scan_State); -- at apostrophe
|
1797 |
|
|
Scan; -- past apostrophe
|
1798 |
|
|
|
1799 |
|
|
-- If qualified expression, scan it out and fall through
|
1800 |
|
|
|
1801 |
|
|
if Token = Tok_Left_Paren then
|
1802 |
|
|
Node1 := P_Qualified_Expression (Node1);
|
1803 |
|
|
Expr_Form := EF_Simple;
|
1804 |
|
|
|
1805 |
|
|
-- If range attribute, then we return with Token pointing to the
|
1806 |
|
|
-- apostrophe. Note: avoid the normal error check on exit. We
|
1807 |
|
|
-- know that the expression really is complete in this case!
|
1808 |
|
|
|
1809 |
|
|
else -- Token = Tok_Range then
|
1810 |
|
|
Restore_Scan_State (Scan_State); -- to apostrophe
|
1811 |
|
|
Expr_Form := EF_Simple_Name;
|
1812 |
|
|
return Node1;
|
1813 |
|
|
end if;
|
1814 |
|
|
end if;
|
1815 |
|
|
|
1816 |
|
|
-- If an expression terminator follows, the previous processing
|
1817 |
|
|
-- completely scanned out the expression (a common case), and
|
1818 |
|
|
-- left Expr_Form set appropriately for returning to our caller.
|
1819 |
|
|
|
1820 |
|
|
if Token in Token_Class_Sterm then
|
1821 |
|
|
null;
|
1822 |
|
|
|
1823 |
|
|
-- If we do not have an expression terminator, then complete the
|
1824 |
|
|
-- scan of a simple expression. This code duplicates the code
|
1825 |
|
|
-- found in P_Term and P_Factor.
|
1826 |
|
|
|
1827 |
|
|
else
|
1828 |
|
|
if Token = Tok_Double_Asterisk then
|
1829 |
|
|
if Style_Check then
|
1830 |
|
|
Style.Check_Exponentiation_Operator;
|
1831 |
|
|
end if;
|
1832 |
|
|
|
1833 |
|
|
Node2 := New_Op_Node (N_Op_Expon, Token_Ptr);
|
1834 |
|
|
Scan; -- past **
|
1835 |
|
|
Set_Left_Opnd (Node2, Node1);
|
1836 |
|
|
Set_Right_Opnd (Node2, P_Primary);
|
1837 |
|
|
Node1 := Node2;
|
1838 |
|
|
end if;
|
1839 |
|
|
|
1840 |
|
|
loop
|
1841 |
|
|
exit when Token not in Token_Class_Mulop;
|
1842 |
|
|
Tokptr := Token_Ptr;
|
1843 |
|
|
Node2 := New_Op_Node (P_Multiplying_Operator, Tokptr);
|
1844 |
|
|
|
1845 |
|
|
if Style_Check then
|
1846 |
|
|
Style.Check_Binary_Operator;
|
1847 |
|
|
end if;
|
1848 |
|
|
|
1849 |
|
|
Scan; -- past operator
|
1850 |
|
|
Set_Left_Opnd (Node2, Node1);
|
1851 |
|
|
Set_Right_Opnd (Node2, P_Factor);
|
1852 |
|
|
Node1 := Node2;
|
1853 |
|
|
end loop;
|
1854 |
|
|
|
1855 |
|
|
loop
|
1856 |
|
|
exit when Token not in Token_Class_Binary_Addop;
|
1857 |
|
|
Tokptr := Token_Ptr;
|
1858 |
|
|
Node2 := New_Op_Node (P_Binary_Adding_Operator, Tokptr);
|
1859 |
|
|
|
1860 |
|
|
if Style_Check then
|
1861 |
|
|
Style.Check_Binary_Operator;
|
1862 |
|
|
end if;
|
1863 |
|
|
|
1864 |
|
|
Scan; -- past operator
|
1865 |
|
|
Set_Left_Opnd (Node2, Node1);
|
1866 |
|
|
Set_Right_Opnd (Node2, P_Term);
|
1867 |
|
|
Node1 := Node2;
|
1868 |
|
|
end loop;
|
1869 |
|
|
|
1870 |
|
|
Expr_Form := EF_Simple;
|
1871 |
|
|
end if;
|
1872 |
|
|
|
1873 |
|
|
-- Cases where simple expression does not start with a name
|
1874 |
|
|
|
1875 |
|
|
else
|
1876 |
|
|
-- Scan initial sign and initial Term
|
1877 |
|
|
|
1878 |
|
|
if Token in Token_Class_Unary_Addop then
|
1879 |
|
|
Tokptr := Token_Ptr;
|
1880 |
|
|
Node1 := New_Op_Node (P_Unary_Adding_Operator, Tokptr);
|
1881 |
|
|
|
1882 |
|
|
if Style_Check then
|
1883 |
|
|
Style.Check_Unary_Plus_Or_Minus;
|
1884 |
|
|
end if;
|
1885 |
|
|
|
1886 |
|
|
Scan; -- past operator
|
1887 |
|
|
Set_Right_Opnd (Node1, P_Term);
|
1888 |
|
|
else
|
1889 |
|
|
Node1 := P_Term;
|
1890 |
|
|
end if;
|
1891 |
|
|
|
1892 |
|
|
-- In the following, we special-case a sequence of concatenations of
|
1893 |
|
|
-- string literals, such as "aaa" & "bbb" & ... & "ccc", with nothing
|
1894 |
|
|
-- else mixed in. For such a sequence, we return a tree representing
|
1895 |
|
|
-- "" & "aaabbb...ccc" (a single concatenation). This is done only if
|
1896 |
|
|
-- the number of concatenations is large. If semantic analysis
|
1897 |
|
|
-- resolves the "&" to a predefined one, then this folding gives the
|
1898 |
|
|
-- right answer. Otherwise, semantic analysis will complain about a
|
1899 |
|
|
-- capacity-exceeded error. The purpose of this trick is to avoid
|
1900 |
|
|
-- creating a deeply nested tree, which would cause deep recursion
|
1901 |
|
|
-- during semantics, causing stack overflow. This way, we can handle
|
1902 |
|
|
-- enormous concatenations in the normal case of predefined "&". We
|
1903 |
|
|
-- first build up the normal tree, and then rewrite it if
|
1904 |
|
|
-- appropriate.
|
1905 |
|
|
|
1906 |
|
|
declare
|
1907 |
|
|
Num_Concats_Threshold : constant Positive := 1000;
|
1908 |
|
|
-- Arbitrary threshold value to enable optimization
|
1909 |
|
|
|
1910 |
|
|
First_Node : constant Node_Id := Node1;
|
1911 |
|
|
Is_Strlit_Concat : Boolean;
|
1912 |
|
|
-- True iff we've parsed a sequence of concatenations of string
|
1913 |
|
|
-- literals, with nothing else mixed in.
|
1914 |
|
|
|
1915 |
|
|
Num_Concats : Natural;
|
1916 |
|
|
-- Number of "&" operators if Is_Strlit_Concat is True
|
1917 |
|
|
|
1918 |
|
|
begin
|
1919 |
|
|
Is_Strlit_Concat :=
|
1920 |
|
|
Nkind (Node1) = N_String_Literal
|
1921 |
|
|
and then Token = Tok_Ampersand;
|
1922 |
|
|
Num_Concats := 0;
|
1923 |
|
|
|
1924 |
|
|
-- Scan out sequence of terms separated by binary adding operators
|
1925 |
|
|
|
1926 |
|
|
loop
|
1927 |
|
|
exit when Token not in Token_Class_Binary_Addop;
|
1928 |
|
|
Tokptr := Token_Ptr;
|
1929 |
|
|
Node2 := New_Op_Node (P_Binary_Adding_Operator, Tokptr);
|
1930 |
|
|
Scan; -- past operator
|
1931 |
|
|
Set_Left_Opnd (Node2, Node1);
|
1932 |
|
|
Node1 := P_Term;
|
1933 |
|
|
Set_Right_Opnd (Node2, Node1);
|
1934 |
|
|
|
1935 |
|
|
-- Check if we're still concatenating string literals
|
1936 |
|
|
|
1937 |
|
|
Is_Strlit_Concat :=
|
1938 |
|
|
Is_Strlit_Concat
|
1939 |
|
|
and then Nkind (Node2) = N_Op_Concat
|
1940 |
|
|
and then Nkind (Node1) = N_String_Literal;
|
1941 |
|
|
|
1942 |
|
|
if Is_Strlit_Concat then
|
1943 |
|
|
Num_Concats := Num_Concats + 1;
|
1944 |
|
|
end if;
|
1945 |
|
|
|
1946 |
|
|
Node1 := Node2;
|
1947 |
|
|
end loop;
|
1948 |
|
|
|
1949 |
|
|
-- If we have an enormous series of concatenations of string
|
1950 |
|
|
-- literals, rewrite as explained above. The Is_Folded_In_Parser
|
1951 |
|
|
-- flag tells semantic analysis that if the "&" is not predefined,
|
1952 |
|
|
-- the folded value is wrong.
|
1953 |
|
|
|
1954 |
|
|
if Is_Strlit_Concat
|
1955 |
|
|
and then Num_Concats >= Num_Concats_Threshold
|
1956 |
|
|
then
|
1957 |
|
|
declare
|
1958 |
|
|
Empty_String_Val : String_Id;
|
1959 |
|
|
-- String_Id for ""
|
1960 |
|
|
|
1961 |
|
|
Strlit_Concat_Val : String_Id;
|
1962 |
|
|
-- Contains the folded value (which will be correct if the
|
1963 |
|
|
-- "&" operators are the predefined ones).
|
1964 |
|
|
|
1965 |
|
|
Cur_Node : Node_Id;
|
1966 |
|
|
-- For walking up the tree
|
1967 |
|
|
|
1968 |
|
|
New_Node : Node_Id;
|
1969 |
|
|
-- Folded node to replace Node1
|
1970 |
|
|
|
1971 |
|
|
Loc : constant Source_Ptr := Sloc (First_Node);
|
1972 |
|
|
|
1973 |
|
|
begin
|
1974 |
|
|
-- Walk up the tree starting at the leftmost string literal
|
1975 |
|
|
-- (First_Node), building up the Strlit_Concat_Val as we
|
1976 |
|
|
-- go. Note that we do not use recursion here -- the whole
|
1977 |
|
|
-- point is to avoid recursively walking that enormous tree.
|
1978 |
|
|
|
1979 |
|
|
Start_String;
|
1980 |
|
|
Store_String_Chars (Strval (First_Node));
|
1981 |
|
|
|
1982 |
|
|
Cur_Node := Parent (First_Node);
|
1983 |
|
|
while Present (Cur_Node) loop
|
1984 |
|
|
pragma Assert (Nkind (Cur_Node) = N_Op_Concat and then
|
1985 |
|
|
Nkind (Right_Opnd (Cur_Node)) = N_String_Literal);
|
1986 |
|
|
|
1987 |
|
|
Store_String_Chars (Strval (Right_Opnd (Cur_Node)));
|
1988 |
|
|
Cur_Node := Parent (Cur_Node);
|
1989 |
|
|
end loop;
|
1990 |
|
|
|
1991 |
|
|
Strlit_Concat_Val := End_String;
|
1992 |
|
|
|
1993 |
|
|
-- Create new folded node, and rewrite result with a concat-
|
1994 |
|
|
-- enation of an empty string literal and the folded node.
|
1995 |
|
|
|
1996 |
|
|
Start_String;
|
1997 |
|
|
Empty_String_Val := End_String;
|
1998 |
|
|
New_Node :=
|
1999 |
|
|
Make_Op_Concat (Loc,
|
2000 |
|
|
Make_String_Literal (Loc, Empty_String_Val),
|
2001 |
|
|
Make_String_Literal (Loc, Strlit_Concat_Val,
|
2002 |
|
|
Is_Folded_In_Parser => True));
|
2003 |
|
|
Rewrite (Node1, New_Node);
|
2004 |
|
|
end;
|
2005 |
|
|
end if;
|
2006 |
|
|
end;
|
2007 |
|
|
|
2008 |
|
|
-- All done, we clearly do not have name or numeric literal so this
|
2009 |
|
|
-- is a case of a simple expression which is some other possibility.
|
2010 |
|
|
|
2011 |
|
|
Expr_Form := EF_Simple;
|
2012 |
|
|
end if;
|
2013 |
|
|
|
2014 |
|
|
-- Come here at end of simple expression, where we do a couple of
|
2015 |
|
|
-- special checks to improve error recovery.
|
2016 |
|
|
|
2017 |
|
|
-- Special test to improve error recovery. If the current token
|
2018 |
|
|
-- is a period, then someone is trying to do selection on something
|
2019 |
|
|
-- that is not a name, e.g. a qualified expression.
|
2020 |
|
|
|
2021 |
|
|
if Token = Tok_Dot then
|
2022 |
|
|
Error_Msg_SC ("prefix for selection is not a name");
|
2023 |
|
|
raise Error_Resync;
|
2024 |
|
|
end if;
|
2025 |
|
|
|
2026 |
|
|
-- Special test to improve error recovery: If the current token is
|
2027 |
|
|
-- not the first token on a line (as determined by checking the
|
2028 |
|
|
-- previous token position with the start of the current line),
|
2029 |
|
|
-- then we insist that we have an appropriate terminating token.
|
2030 |
|
|
-- Consider the following two examples:
|
2031 |
|
|
|
2032 |
|
|
-- 1) if A nad B then ...
|
2033 |
|
|
|
2034 |
|
|
-- 2) A := B
|
2035 |
|
|
-- C := D
|
2036 |
|
|
|
2037 |
|
|
-- In the first example, we would like to issue a binary operator
|
2038 |
|
|
-- expected message and resynchronize to the then. In the second
|
2039 |
|
|
-- example, we do not want to issue a binary operator message, so
|
2040 |
|
|
-- that instead we will get the missing semicolon message. This
|
2041 |
|
|
-- distinction is of course a heuristic which does not always work,
|
2042 |
|
|
-- but in practice it is quite effective.
|
2043 |
|
|
|
2044 |
|
|
-- Note: the one case in which we do not go through this circuit is
|
2045 |
|
|
-- when we have scanned a range attribute and want to return with
|
2046 |
|
|
-- Token pointing to the apostrophe. The apostrophe is not normally
|
2047 |
|
|
-- an expression terminator, and is not in Token_Class_Sterm, but
|
2048 |
|
|
-- in this special case we know that the expression is complete.
|
2049 |
|
|
|
2050 |
|
|
if not Token_Is_At_Start_Of_Line
|
2051 |
|
|
and then Token not in Token_Class_Sterm
|
2052 |
|
|
then
|
2053 |
|
|
-- Normally the right error message is indeed that we expected a
|
2054 |
|
|
-- binary operator, but in the case of being between a right and left
|
2055 |
|
|
-- paren, e.g. in an aggregate, a more likely error is missing comma.
|
2056 |
|
|
|
2057 |
|
|
if Prev_Token = Tok_Right_Paren and then Token = Tok_Left_Paren then
|
2058 |
|
|
T_Comma;
|
2059 |
|
|
else
|
2060 |
|
|
Error_Msg_AP ("binary operator expected");
|
2061 |
|
|
end if;
|
2062 |
|
|
|
2063 |
|
|
raise Error_Resync;
|
2064 |
|
|
|
2065 |
|
|
else
|
2066 |
|
|
return Node1;
|
2067 |
|
|
end if;
|
2068 |
|
|
|
2069 |
|
|
-- If any error occurs, then scan to next expression terminator symbol
|
2070 |
|
|
-- or comma, right paren or vertical bar at the outer (i.e. current) paren
|
2071 |
|
|
-- level. Expr_Form is set to indicate a normal simple expression.
|
2072 |
|
|
|
2073 |
|
|
exception
|
2074 |
|
|
when Error_Resync =>
|
2075 |
|
|
Resync_Expression;
|
2076 |
|
|
Expr_Form := EF_Simple;
|
2077 |
|
|
return Error;
|
2078 |
|
|
end P_Simple_Expression;
|
2079 |
|
|
|
2080 |
|
|
-----------------------------------------------
|
2081 |
|
|
-- 4.4 Simple Expression or Range Attribute --
|
2082 |
|
|
-----------------------------------------------
|
2083 |
|
|
|
2084 |
|
|
-- SIMPLE_EXPRESSION ::=
|
2085 |
|
|
-- [UNARY_ADDING_OPERATOR] TERM {BINARY_ADDING_OPERATOR TERM}
|
2086 |
|
|
|
2087 |
|
|
-- RANGE_ATTRIBUTE_REFERENCE ::= PREFIX ' RANGE_ATTRIBUTE_DESIGNATOR
|
2088 |
|
|
|
2089 |
|
|
-- RANGE_ATTRIBUTE_DESIGNATOR ::= range [(static_EXPRESSION)]
|
2090 |
|
|
|
2091 |
|
|
-- Error recovery: cannot raise Error_Resync
|
2092 |
|
|
|
2093 |
|
|
function P_Simple_Expression_Or_Range_Attribute return Node_Id is
|
2094 |
|
|
Sexpr : Node_Id;
|
2095 |
|
|
Attr_Node : Node_Id;
|
2096 |
|
|
|
2097 |
|
|
begin
|
2098 |
|
|
-- We don't just want to roar ahead and call P_Simple_Expression
|
2099 |
|
|
-- here, since we want to handle the case of a parenthesized range
|
2100 |
|
|
-- attribute cleanly.
|
2101 |
|
|
|
2102 |
|
|
if Token = Tok_Left_Paren then
|
2103 |
|
|
declare
|
2104 |
|
|
Lptr : constant Source_Ptr := Token_Ptr;
|
2105 |
|
|
Scan_State : Saved_Scan_State;
|
2106 |
|
|
|
2107 |
|
|
begin
|
2108 |
|
|
Save_Scan_State (Scan_State);
|
2109 |
|
|
Scan; -- past left paren
|
2110 |
|
|
Sexpr := P_Simple_Expression;
|
2111 |
|
|
|
2112 |
|
|
if Token = Tok_Apostrophe then
|
2113 |
|
|
Attr_Node := P_Range_Attribute_Reference (Sexpr);
|
2114 |
|
|
Expr_Form := EF_Range_Attr;
|
2115 |
|
|
|
2116 |
|
|
if Token = Tok_Right_Paren then
|
2117 |
|
|
Scan; -- scan past right paren if present
|
2118 |
|
|
end if;
|
2119 |
|
|
|
2120 |
|
|
Error_Msg ("parentheses not allowed for range attribute", Lptr);
|
2121 |
|
|
|
2122 |
|
|
return Attr_Node;
|
2123 |
|
|
end if;
|
2124 |
|
|
|
2125 |
|
|
Restore_Scan_State (Scan_State);
|
2126 |
|
|
end;
|
2127 |
|
|
end if;
|
2128 |
|
|
|
2129 |
|
|
-- Here after dealing with parenthesized range attribute
|
2130 |
|
|
|
2131 |
|
|
Sexpr := P_Simple_Expression;
|
2132 |
|
|
|
2133 |
|
|
if Token = Tok_Apostrophe then
|
2134 |
|
|
Attr_Node := P_Range_Attribute_Reference (Sexpr);
|
2135 |
|
|
Expr_Form := EF_Range_Attr;
|
2136 |
|
|
return Attr_Node;
|
2137 |
|
|
|
2138 |
|
|
else
|
2139 |
|
|
return Sexpr;
|
2140 |
|
|
end if;
|
2141 |
|
|
end P_Simple_Expression_Or_Range_Attribute;
|
2142 |
|
|
|
2143 |
|
|
---------------
|
2144 |
|
|
-- 4.4 Term --
|
2145 |
|
|
---------------
|
2146 |
|
|
|
2147 |
|
|
-- TERM ::= FACTOR {MULTIPLYING_OPERATOR FACTOR}
|
2148 |
|
|
|
2149 |
|
|
-- Error recovery: can raise Error_Resync
|
2150 |
|
|
|
2151 |
|
|
function P_Term return Node_Id is
|
2152 |
|
|
Node1, Node2 : Node_Id;
|
2153 |
|
|
Tokptr : Source_Ptr;
|
2154 |
|
|
|
2155 |
|
|
begin
|
2156 |
|
|
Node1 := P_Factor;
|
2157 |
|
|
|
2158 |
|
|
loop
|
2159 |
|
|
exit when Token not in Token_Class_Mulop;
|
2160 |
|
|
Tokptr := Token_Ptr;
|
2161 |
|
|
Node2 := New_Op_Node (P_Multiplying_Operator, Tokptr);
|
2162 |
|
|
Scan; -- past operator
|
2163 |
|
|
Set_Left_Opnd (Node2, Node1);
|
2164 |
|
|
Set_Right_Opnd (Node2, P_Factor);
|
2165 |
|
|
Node1 := Node2;
|
2166 |
|
|
end loop;
|
2167 |
|
|
|
2168 |
|
|
return Node1;
|
2169 |
|
|
end P_Term;
|
2170 |
|
|
|
2171 |
|
|
-----------------
|
2172 |
|
|
-- 4.4 Factor --
|
2173 |
|
|
-----------------
|
2174 |
|
|
|
2175 |
|
|
-- FACTOR ::= PRIMARY [** PRIMARY] | abs PRIMARY | not PRIMARY
|
2176 |
|
|
|
2177 |
|
|
-- Error recovery: can raise Error_Resync
|
2178 |
|
|
|
2179 |
|
|
function P_Factor return Node_Id is
|
2180 |
|
|
Node1 : Node_Id;
|
2181 |
|
|
Node2 : Node_Id;
|
2182 |
|
|
|
2183 |
|
|
begin
|
2184 |
|
|
if Token = Tok_Abs then
|
2185 |
|
|
Node1 := New_Op_Node (N_Op_Abs, Token_Ptr);
|
2186 |
|
|
|
2187 |
|
|
if Style_Check then
|
2188 |
|
|
Style.Check_Abs_Not;
|
2189 |
|
|
end if;
|
2190 |
|
|
|
2191 |
|
|
Scan; -- past ABS
|
2192 |
|
|
Set_Right_Opnd (Node1, P_Primary);
|
2193 |
|
|
return Node1;
|
2194 |
|
|
|
2195 |
|
|
elsif Token = Tok_Not then
|
2196 |
|
|
Node1 := New_Op_Node (N_Op_Not, Token_Ptr);
|
2197 |
|
|
|
2198 |
|
|
if Style_Check then
|
2199 |
|
|
Style.Check_Abs_Not;
|
2200 |
|
|
end if;
|
2201 |
|
|
|
2202 |
|
|
Scan; -- past NOT
|
2203 |
|
|
Set_Right_Opnd (Node1, P_Primary);
|
2204 |
|
|
return Node1;
|
2205 |
|
|
|
2206 |
|
|
else
|
2207 |
|
|
Node1 := P_Primary;
|
2208 |
|
|
|
2209 |
|
|
if Token = Tok_Double_Asterisk then
|
2210 |
|
|
Node2 := New_Op_Node (N_Op_Expon, Token_Ptr);
|
2211 |
|
|
Scan; -- past **
|
2212 |
|
|
Set_Left_Opnd (Node2, Node1);
|
2213 |
|
|
Set_Right_Opnd (Node2, P_Primary);
|
2214 |
|
|
return Node2;
|
2215 |
|
|
else
|
2216 |
|
|
return Node1;
|
2217 |
|
|
end if;
|
2218 |
|
|
end if;
|
2219 |
|
|
end P_Factor;
|
2220 |
|
|
|
2221 |
|
|
------------------
|
2222 |
|
|
-- 4.4 Primary --
|
2223 |
|
|
------------------
|
2224 |
|
|
|
2225 |
|
|
-- PRIMARY ::=
|
2226 |
|
|
-- NUMERIC_LITERAL | null
|
2227 |
|
|
-- | STRING_LITERAL | AGGREGATE
|
2228 |
|
|
-- | NAME | QUALIFIED_EXPRESSION
|
2229 |
|
|
-- | ALLOCATOR | (EXPRESSION)
|
2230 |
|
|
|
2231 |
|
|
-- Error recovery: can raise Error_Resync
|
2232 |
|
|
|
2233 |
|
|
function P_Primary return Node_Id is
|
2234 |
|
|
Scan_State : Saved_Scan_State;
|
2235 |
|
|
Node1 : Node_Id;
|
2236 |
|
|
|
2237 |
|
|
begin
|
2238 |
|
|
-- The loop runs more than once only if misplaced pragmas are found
|
2239 |
|
|
|
2240 |
|
|
loop
|
2241 |
|
|
case Token is
|
2242 |
|
|
|
2243 |
|
|
-- Name token can start a name, call or qualified expression, all
|
2244 |
|
|
-- of which are acceptable possibilities for primary. Note also
|
2245 |
|
|
-- that string literal is included in name (as operator symbol)
|
2246 |
|
|
-- and type conversion is included in name (as indexed component).
|
2247 |
|
|
|
2248 |
|
|
when Tok_Char_Literal | Tok_Operator_Symbol | Tok_Identifier =>
|
2249 |
|
|
Node1 := P_Name;
|
2250 |
|
|
|
2251 |
|
|
-- All done unless apostrophe follows
|
2252 |
|
|
|
2253 |
|
|
if Token /= Tok_Apostrophe then
|
2254 |
|
|
return Node1;
|
2255 |
|
|
|
2256 |
|
|
-- Apostrophe following means that we have either just parsed
|
2257 |
|
|
-- the subtype mark of a qualified expression, or the prefix
|
2258 |
|
|
-- or a range attribute.
|
2259 |
|
|
|
2260 |
|
|
else -- Token = Tok_Apostrophe
|
2261 |
|
|
Save_Scan_State (Scan_State); -- at apostrophe
|
2262 |
|
|
Scan; -- past apostrophe
|
2263 |
|
|
|
2264 |
|
|
-- If range attribute, then this is always an error, since
|
2265 |
|
|
-- the only legitimate case (where the scanned expression is
|
2266 |
|
|
-- a qualified simple name) is handled at the level of the
|
2267 |
|
|
-- Simple_Expression processing. This case corresponds to a
|
2268 |
|
|
-- usage such as 3 + A'Range, which is always illegal.
|
2269 |
|
|
|
2270 |
|
|
if Token = Tok_Range then
|
2271 |
|
|
Restore_Scan_State (Scan_State); -- to apostrophe
|
2272 |
|
|
Bad_Range_Attribute (Token_Ptr);
|
2273 |
|
|
return Error;
|
2274 |
|
|
|
2275 |
|
|
-- If left paren, then we have a qualified expression.
|
2276 |
|
|
-- Note that P_Name guarantees that in this case, where
|
2277 |
|
|
-- Token = Tok_Apostrophe on return, the only two possible
|
2278 |
|
|
-- tokens following the apostrophe are left paren and
|
2279 |
|
|
-- RANGE, so we know we have a left paren here.
|
2280 |
|
|
|
2281 |
|
|
else -- Token = Tok_Left_Paren
|
2282 |
|
|
return P_Qualified_Expression (Node1);
|
2283 |
|
|
|
2284 |
|
|
end if;
|
2285 |
|
|
end if;
|
2286 |
|
|
|
2287 |
|
|
-- Numeric or string literal
|
2288 |
|
|
|
2289 |
|
|
when Tok_Integer_Literal |
|
2290 |
|
|
Tok_Real_Literal |
|
2291 |
|
|
Tok_String_Literal =>
|
2292 |
|
|
|
2293 |
|
|
Node1 := Token_Node;
|
2294 |
|
|
Scan; -- past number
|
2295 |
|
|
return Node1;
|
2296 |
|
|
|
2297 |
|
|
-- Left paren, starts aggregate or parenthesized expression
|
2298 |
|
|
|
2299 |
|
|
when Tok_Left_Paren =>
|
2300 |
|
|
declare
|
2301 |
|
|
Expr : constant Node_Id := P_Aggregate_Or_Paren_Expr;
|
2302 |
|
|
|
2303 |
|
|
begin
|
2304 |
|
|
if Nkind (Expr) = N_Attribute_Reference
|
2305 |
|
|
and then Attribute_Name (Expr) = Name_Range
|
2306 |
|
|
then
|
2307 |
|
|
Bad_Range_Attribute (Sloc (Expr));
|
2308 |
|
|
end if;
|
2309 |
|
|
|
2310 |
|
|
return Expr;
|
2311 |
|
|
end;
|
2312 |
|
|
|
2313 |
|
|
-- Allocator
|
2314 |
|
|
|
2315 |
|
|
when Tok_New =>
|
2316 |
|
|
return P_Allocator;
|
2317 |
|
|
|
2318 |
|
|
-- Null
|
2319 |
|
|
|
2320 |
|
|
when Tok_Null =>
|
2321 |
|
|
Scan; -- past NULL
|
2322 |
|
|
return New_Node (N_Null, Prev_Token_Ptr);
|
2323 |
|
|
|
2324 |
|
|
-- Pragma, not allowed here, so just skip past it
|
2325 |
|
|
|
2326 |
|
|
when Tok_Pragma =>
|
2327 |
|
|
P_Pragmas_Misplaced;
|
2328 |
|
|
|
2329 |
|
|
-- Deal with IF (possible unparenthesized conditional expression)
|
2330 |
|
|
|
2331 |
|
|
when Tok_If =>
|
2332 |
|
|
|
2333 |
|
|
-- If this looks like a real if, defined as an IF appearing at
|
2334 |
|
|
-- the start of a new line, then we consider we have a missing
|
2335 |
|
|
-- operand.
|
2336 |
|
|
|
2337 |
|
|
if Token_Is_At_Start_Of_Line then
|
2338 |
|
|
Error_Msg_AP ("missing operand");
|
2339 |
|
|
return Error;
|
2340 |
|
|
|
2341 |
|
|
-- If this looks like a conditional expression, then treat it
|
2342 |
|
|
-- that way with an error messasge.
|
2343 |
|
|
|
2344 |
|
|
elsif Extensions_Allowed then
|
2345 |
|
|
Error_Msg_SC
|
2346 |
|
|
("conditional expression must be parenthesized");
|
2347 |
|
|
return P_Conditional_Expression;
|
2348 |
|
|
|
2349 |
|
|
-- Otherwise treat as misused identifier
|
2350 |
|
|
|
2351 |
|
|
else
|
2352 |
|
|
return P_Identifier;
|
2353 |
|
|
end if;
|
2354 |
|
|
|
2355 |
|
|
-- Anything else is illegal as the first token of a primary, but
|
2356 |
|
|
-- we test for a reserved identifier so that it is treated nicely
|
2357 |
|
|
|
2358 |
|
|
when others =>
|
2359 |
|
|
if Is_Reserved_Identifier then
|
2360 |
|
|
return P_Identifier;
|
2361 |
|
|
|
2362 |
|
|
elsif Prev_Token = Tok_Comma then
|
2363 |
|
|
Error_Msg_SP ("|extra "","" ignored");
|
2364 |
|
|
raise Error_Resync;
|
2365 |
|
|
|
2366 |
|
|
else
|
2367 |
|
|
Error_Msg_AP ("missing operand");
|
2368 |
|
|
raise Error_Resync;
|
2369 |
|
|
end if;
|
2370 |
|
|
|
2371 |
|
|
end case;
|
2372 |
|
|
end loop;
|
2373 |
|
|
end P_Primary;
|
2374 |
|
|
|
2375 |
|
|
---------------------------
|
2376 |
|
|
-- 4.5 Logical Operator --
|
2377 |
|
|
---------------------------
|
2378 |
|
|
|
2379 |
|
|
-- LOGICAL_OPERATOR ::= and | or | xor
|
2380 |
|
|
|
2381 |
|
|
-- Note: AND THEN and OR ELSE are also treated as logical operators
|
2382 |
|
|
-- by the parser (even though they are not operators semantically)
|
2383 |
|
|
|
2384 |
|
|
-- The value returned is the appropriate Node_Kind code for the operator
|
2385 |
|
|
-- On return, Token points to the token following the scanned operator.
|
2386 |
|
|
|
2387 |
|
|
-- The caller has checked that the first token is a legitimate logical
|
2388 |
|
|
-- operator token (i.e. is either XOR, AND, OR).
|
2389 |
|
|
|
2390 |
|
|
-- Error recovery: cannot raise Error_Resync
|
2391 |
|
|
|
2392 |
|
|
function P_Logical_Operator return Node_Kind is
|
2393 |
|
|
begin
|
2394 |
|
|
if Token = Tok_And then
|
2395 |
|
|
if Style_Check then
|
2396 |
|
|
Style.Check_Binary_Operator;
|
2397 |
|
|
end if;
|
2398 |
|
|
|
2399 |
|
|
Scan; -- past AND
|
2400 |
|
|
|
2401 |
|
|
if Token = Tok_Then then
|
2402 |
|
|
Scan; -- past THEN
|
2403 |
|
|
return N_And_Then;
|
2404 |
|
|
else
|
2405 |
|
|
return N_Op_And;
|
2406 |
|
|
end if;
|
2407 |
|
|
|
2408 |
|
|
elsif Token = Tok_Or then
|
2409 |
|
|
if Style_Check then
|
2410 |
|
|
Style.Check_Binary_Operator;
|
2411 |
|
|
end if;
|
2412 |
|
|
|
2413 |
|
|
Scan; -- past OR
|
2414 |
|
|
|
2415 |
|
|
if Token = Tok_Else then
|
2416 |
|
|
Scan; -- past ELSE
|
2417 |
|
|
return N_Or_Else;
|
2418 |
|
|
else
|
2419 |
|
|
return N_Op_Or;
|
2420 |
|
|
end if;
|
2421 |
|
|
|
2422 |
|
|
else -- Token = Tok_Xor
|
2423 |
|
|
if Style_Check then
|
2424 |
|
|
Style.Check_Binary_Operator;
|
2425 |
|
|
end if;
|
2426 |
|
|
|
2427 |
|
|
Scan; -- past XOR
|
2428 |
|
|
return N_Op_Xor;
|
2429 |
|
|
end if;
|
2430 |
|
|
end P_Logical_Operator;
|
2431 |
|
|
|
2432 |
|
|
------------------------------
|
2433 |
|
|
-- 4.5 Relational Operator --
|
2434 |
|
|
------------------------------
|
2435 |
|
|
|
2436 |
|
|
-- RELATIONAL_OPERATOR ::= = | /= | < | <= | > | >=
|
2437 |
|
|
|
2438 |
|
|
-- The value returned is the appropriate Node_Kind code for the operator.
|
2439 |
|
|
-- On return, Token points to the operator token, NOT past it.
|
2440 |
|
|
|
2441 |
|
|
-- The caller has checked that the first token is a legitimate relational
|
2442 |
|
|
-- operator token (i.e. is one of the operator tokens listed above).
|
2443 |
|
|
|
2444 |
|
|
-- Error recovery: cannot raise Error_Resync
|
2445 |
|
|
|
2446 |
|
|
function P_Relational_Operator return Node_Kind is
|
2447 |
|
|
Op_Kind : Node_Kind;
|
2448 |
|
|
Relop_Node : constant array (Token_Class_Relop) of Node_Kind :=
|
2449 |
|
|
(Tok_Less => N_Op_Lt,
|
2450 |
|
|
Tok_Equal => N_Op_Eq,
|
2451 |
|
|
Tok_Greater => N_Op_Gt,
|
2452 |
|
|
Tok_Not_Equal => N_Op_Ne,
|
2453 |
|
|
Tok_Greater_Equal => N_Op_Ge,
|
2454 |
|
|
Tok_Less_Equal => N_Op_Le,
|
2455 |
|
|
Tok_In => N_In,
|
2456 |
|
|
Tok_Not => N_Not_In,
|
2457 |
|
|
Tok_Box => N_Op_Ne);
|
2458 |
|
|
|
2459 |
|
|
begin
|
2460 |
|
|
if Token = Tok_Box then
|
2461 |
|
|
Error_Msg_SC ("|""'<'>"" should be ""/=""");
|
2462 |
|
|
end if;
|
2463 |
|
|
|
2464 |
|
|
Op_Kind := Relop_Node (Token);
|
2465 |
|
|
|
2466 |
|
|
if Style_Check then
|
2467 |
|
|
Style.Check_Binary_Operator;
|
2468 |
|
|
end if;
|
2469 |
|
|
|
2470 |
|
|
Scan; -- past operator token
|
2471 |
|
|
|
2472 |
|
|
if Prev_Token = Tok_Not then
|
2473 |
|
|
T_In;
|
2474 |
|
|
end if;
|
2475 |
|
|
|
2476 |
|
|
return Op_Kind;
|
2477 |
|
|
end P_Relational_Operator;
|
2478 |
|
|
|
2479 |
|
|
---------------------------------
|
2480 |
|
|
-- 4.5 Binary Adding Operator --
|
2481 |
|
|
---------------------------------
|
2482 |
|
|
|
2483 |
|
|
-- BINARY_ADDING_OPERATOR ::= + | - | &
|
2484 |
|
|
|
2485 |
|
|
-- The value returned is the appropriate Node_Kind code for the operator.
|
2486 |
|
|
-- On return, Token points to the operator token (NOT past it).
|
2487 |
|
|
|
2488 |
|
|
-- The caller has checked that the first token is a legitimate adding
|
2489 |
|
|
-- operator token (i.e. is one of the operator tokens listed above).
|
2490 |
|
|
|
2491 |
|
|
-- Error recovery: cannot raise Error_Resync
|
2492 |
|
|
|
2493 |
|
|
function P_Binary_Adding_Operator return Node_Kind is
|
2494 |
|
|
Addop_Node : constant array (Token_Class_Binary_Addop) of Node_Kind :=
|
2495 |
|
|
(Tok_Ampersand => N_Op_Concat,
|
2496 |
|
|
Tok_Minus => N_Op_Subtract,
|
2497 |
|
|
Tok_Plus => N_Op_Add);
|
2498 |
|
|
begin
|
2499 |
|
|
return Addop_Node (Token);
|
2500 |
|
|
end P_Binary_Adding_Operator;
|
2501 |
|
|
|
2502 |
|
|
--------------------------------
|
2503 |
|
|
-- 4.5 Unary Adding Operator --
|
2504 |
|
|
--------------------------------
|
2505 |
|
|
|
2506 |
|
|
-- UNARY_ADDING_OPERATOR ::= + | -
|
2507 |
|
|
|
2508 |
|
|
-- The value returned is the appropriate Node_Kind code for the operator.
|
2509 |
|
|
-- On return, Token points to the operator token (NOT past it).
|
2510 |
|
|
|
2511 |
|
|
-- The caller has checked that the first token is a legitimate adding
|
2512 |
|
|
-- operator token (i.e. is one of the operator tokens listed above).
|
2513 |
|
|
|
2514 |
|
|
-- Error recovery: cannot raise Error_Resync
|
2515 |
|
|
|
2516 |
|
|
function P_Unary_Adding_Operator return Node_Kind is
|
2517 |
|
|
Addop_Node : constant array (Token_Class_Unary_Addop) of Node_Kind :=
|
2518 |
|
|
(Tok_Minus => N_Op_Minus,
|
2519 |
|
|
Tok_Plus => N_Op_Plus);
|
2520 |
|
|
begin
|
2521 |
|
|
return Addop_Node (Token);
|
2522 |
|
|
end P_Unary_Adding_Operator;
|
2523 |
|
|
|
2524 |
|
|
-------------------------------
|
2525 |
|
|
-- 4.5 Multiplying Operator --
|
2526 |
|
|
-------------------------------
|
2527 |
|
|
|
2528 |
|
|
-- MULTIPLYING_OPERATOR ::= * | / | mod | rem
|
2529 |
|
|
|
2530 |
|
|
-- The value returned is the appropriate Node_Kind code for the operator.
|
2531 |
|
|
-- On return, Token points to the operator token (NOT past it).
|
2532 |
|
|
|
2533 |
|
|
-- The caller has checked that the first token is a legitimate multiplying
|
2534 |
|
|
-- operator token (i.e. is one of the operator tokens listed above).
|
2535 |
|
|
|
2536 |
|
|
-- Error recovery: cannot raise Error_Resync
|
2537 |
|
|
|
2538 |
|
|
function P_Multiplying_Operator return Node_Kind is
|
2539 |
|
|
Mulop_Node : constant array (Token_Class_Mulop) of Node_Kind :=
|
2540 |
|
|
(Tok_Asterisk => N_Op_Multiply,
|
2541 |
|
|
Tok_Mod => N_Op_Mod,
|
2542 |
|
|
Tok_Rem => N_Op_Rem,
|
2543 |
|
|
Tok_Slash => N_Op_Divide);
|
2544 |
|
|
begin
|
2545 |
|
|
return Mulop_Node (Token);
|
2546 |
|
|
end P_Multiplying_Operator;
|
2547 |
|
|
|
2548 |
|
|
--------------------------------------
|
2549 |
|
|
-- 4.5 Highest Precedence Operator --
|
2550 |
|
|
--------------------------------------
|
2551 |
|
|
|
2552 |
|
|
-- Parsed by P_Factor (4.4)
|
2553 |
|
|
|
2554 |
|
|
-- Note: this rule is not in fact used by the grammar at any point!
|
2555 |
|
|
|
2556 |
|
|
--------------------------
|
2557 |
|
|
-- 4.6 Type Conversion --
|
2558 |
|
|
--------------------------
|
2559 |
|
|
|
2560 |
|
|
-- Parsed by P_Primary as a Name (4.1)
|
2561 |
|
|
|
2562 |
|
|
-------------------------------
|
2563 |
|
|
-- 4.7 Qualified Expression --
|
2564 |
|
|
-------------------------------
|
2565 |
|
|
|
2566 |
|
|
-- QUALIFIED_EXPRESSION ::=
|
2567 |
|
|
-- SUBTYPE_MARK ' (EXPRESSION) | SUBTYPE_MARK ' AGGREGATE
|
2568 |
|
|
|
2569 |
|
|
-- The caller has scanned the name which is the Subtype_Mark parameter
|
2570 |
|
|
-- and scanned past the single quote following the subtype mark. The
|
2571 |
|
|
-- caller has not checked that this name is in fact appropriate for
|
2572 |
|
|
-- a subtype mark name (i.e. it is a selected component or identifier).
|
2573 |
|
|
|
2574 |
|
|
-- Error_Recovery: cannot raise Error_Resync
|
2575 |
|
|
|
2576 |
|
|
function P_Qualified_Expression (Subtype_Mark : Node_Id) return Node_Id is
|
2577 |
|
|
Qual_Node : Node_Id;
|
2578 |
|
|
begin
|
2579 |
|
|
Qual_Node := New_Node (N_Qualified_Expression, Prev_Token_Ptr);
|
2580 |
|
|
Set_Subtype_Mark (Qual_Node, Check_Subtype_Mark (Subtype_Mark));
|
2581 |
|
|
Set_Expression (Qual_Node, P_Aggregate_Or_Paren_Expr);
|
2582 |
|
|
return Qual_Node;
|
2583 |
|
|
end P_Qualified_Expression;
|
2584 |
|
|
|
2585 |
|
|
--------------------
|
2586 |
|
|
-- 4.8 Allocator --
|
2587 |
|
|
--------------------
|
2588 |
|
|
|
2589 |
|
|
-- ALLOCATOR ::=
|
2590 |
|
|
-- new [NULL_EXCLUSION] SUBTYPE_INDICATION | new QUALIFIED_EXPRESSION
|
2591 |
|
|
|
2592 |
|
|
-- The caller has checked that the initial token is NEW
|
2593 |
|
|
|
2594 |
|
|
-- Error recovery: can raise Error_Resync
|
2595 |
|
|
|
2596 |
|
|
function P_Allocator return Node_Id is
|
2597 |
|
|
Alloc_Node : Node_Id;
|
2598 |
|
|
Type_Node : Node_Id;
|
2599 |
|
|
Null_Exclusion_Present : Boolean;
|
2600 |
|
|
|
2601 |
|
|
begin
|
2602 |
|
|
Alloc_Node := New_Node (N_Allocator, Token_Ptr);
|
2603 |
|
|
T_New;
|
2604 |
|
|
|
2605 |
|
|
-- Scan Null_Exclusion if present (Ada 2005 (AI-231))
|
2606 |
|
|
|
2607 |
|
|
Null_Exclusion_Present := P_Null_Exclusion;
|
2608 |
|
|
Set_Null_Exclusion_Present (Alloc_Node, Null_Exclusion_Present);
|
2609 |
|
|
Type_Node := P_Subtype_Mark_Resync;
|
2610 |
|
|
|
2611 |
|
|
if Token = Tok_Apostrophe then
|
2612 |
|
|
Scan; -- past apostrophe
|
2613 |
|
|
Set_Expression (Alloc_Node, P_Qualified_Expression (Type_Node));
|
2614 |
|
|
else
|
2615 |
|
|
Set_Expression
|
2616 |
|
|
(Alloc_Node,
|
2617 |
|
|
P_Subtype_Indication (Type_Node, Null_Exclusion_Present));
|
2618 |
|
|
end if;
|
2619 |
|
|
|
2620 |
|
|
return Alloc_Node;
|
2621 |
|
|
end P_Allocator;
|
2622 |
|
|
|
2623 |
|
|
------------------------------
|
2624 |
|
|
-- P_Conditional_Expression --
|
2625 |
|
|
------------------------------
|
2626 |
|
|
|
2627 |
|
|
function P_Conditional_Expression return Node_Id is
|
2628 |
|
|
Exprs : constant List_Id := New_List;
|
2629 |
|
|
Loc : constant Source_Ptr := Token_Ptr;
|
2630 |
|
|
Expr : Node_Id;
|
2631 |
|
|
State : Saved_Scan_State;
|
2632 |
|
|
|
2633 |
|
|
begin
|
2634 |
|
|
Inside_Conditional_Expression := Inside_Conditional_Expression + 1;
|
2635 |
|
|
|
2636 |
|
|
if Token = Tok_If and then not Extensions_Allowed then
|
2637 |
|
|
Error_Msg_SC ("|conditional expression is an Ada extension");
|
2638 |
|
|
Error_Msg_SC ("\|use -gnatX switch to compile this unit");
|
2639 |
|
|
end if;
|
2640 |
|
|
|
2641 |
|
|
Scan; -- past IF or ELSIF
|
2642 |
|
|
Append_To (Exprs, P_Expression_No_Right_Paren);
|
2643 |
|
|
TF_Then;
|
2644 |
|
|
Append_To (Exprs, P_Expression);
|
2645 |
|
|
|
2646 |
|
|
-- We now have scanned out IF expr THEN expr
|
2647 |
|
|
|
2648 |
|
|
-- Check for common error of semicolon before the ELSE
|
2649 |
|
|
|
2650 |
|
|
if Token = Tok_Semicolon then
|
2651 |
|
|
Save_Scan_State (State);
|
2652 |
|
|
Scan; -- past semicolon
|
2653 |
|
|
|
2654 |
|
|
if Token = Tok_Else or else Token = Tok_Elsif then
|
2655 |
|
|
Error_Msg_SP ("|extra "";"" ignored");
|
2656 |
|
|
|
2657 |
|
|
else
|
2658 |
|
|
Restore_Scan_State (State);
|
2659 |
|
|
end if;
|
2660 |
|
|
end if;
|
2661 |
|
|
|
2662 |
|
|
-- Scan out ELSIF sequence if present
|
2663 |
|
|
|
2664 |
|
|
if Token = Tok_Elsif then
|
2665 |
|
|
Expr := P_Conditional_Expression;
|
2666 |
|
|
Set_Is_Elsif (Expr);
|
2667 |
|
|
Append_To (Exprs, Expr);
|
2668 |
|
|
|
2669 |
|
|
-- Scan out ELSE phrase if present
|
2670 |
|
|
|
2671 |
|
|
elsif Token = Tok_Else then
|
2672 |
|
|
|
2673 |
|
|
-- Scan out ELSE expression
|
2674 |
|
|
|
2675 |
|
|
Scan; -- Past ELSE
|
2676 |
|
|
Append_To (Exprs, P_Expression);
|
2677 |
|
|
|
2678 |
|
|
-- Two expression case (implied True, filled in during semantics)
|
2679 |
|
|
|
2680 |
|
|
else
|
2681 |
|
|
null;
|
2682 |
|
|
end if;
|
2683 |
|
|
|
2684 |
|
|
-- If we have an END IF, diagnose as not needed
|
2685 |
|
|
|
2686 |
|
|
if Token = Tok_End then
|
2687 |
|
|
Error_Msg_SC
|
2688 |
|
|
("`END IF` not allowed at end of conditional expression");
|
2689 |
|
|
Scan; -- past END
|
2690 |
|
|
|
2691 |
|
|
if Token = Tok_If then
|
2692 |
|
|
Scan; -- past IF;
|
2693 |
|
|
end if;
|
2694 |
|
|
end if;
|
2695 |
|
|
|
2696 |
|
|
Inside_Conditional_Expression := Inside_Conditional_Expression - 1;
|
2697 |
|
|
|
2698 |
|
|
-- Return the Conditional_Expression node
|
2699 |
|
|
|
2700 |
|
|
return
|
2701 |
|
|
Make_Conditional_Expression (Loc,
|
2702 |
|
|
Expressions => Exprs);
|
2703 |
|
|
end P_Conditional_Expression;
|
2704 |
|
|
|
2705 |
|
|
-----------------------
|
2706 |
|
|
-- P_Membership_Test --
|
2707 |
|
|
-----------------------
|
2708 |
|
|
|
2709 |
|
|
procedure P_Membership_Test (N : Node_Id) is
|
2710 |
|
|
Alt : constant Node_Id :=
|
2711 |
|
|
P_Range_Or_Subtype_Mark
|
2712 |
|
|
(Allow_Simple_Expression => Extensions_Allowed);
|
2713 |
|
|
|
2714 |
|
|
begin
|
2715 |
|
|
-- Set case
|
2716 |
|
|
|
2717 |
|
|
if Token = Tok_Vertical_Bar then
|
2718 |
|
|
if not Extensions_Allowed then
|
2719 |
|
|
Error_Msg_SC ("set notation is a language extension");
|
2720 |
|
|
Error_Msg_SC ("\|use -gnatX switch to compile this unit");
|
2721 |
|
|
end if;
|
2722 |
|
|
|
2723 |
|
|
Set_Alternatives (N, New_List (Alt));
|
2724 |
|
|
Set_Right_Opnd (N, Empty);
|
2725 |
|
|
|
2726 |
|
|
-- Loop to accumulate alternatives
|
2727 |
|
|
|
2728 |
|
|
while Token = Tok_Vertical_Bar loop
|
2729 |
|
|
Scan; -- past vertical bar
|
2730 |
|
|
Append_To
|
2731 |
|
|
(Alternatives (N),
|
2732 |
|
|
P_Range_Or_Subtype_Mark (Allow_Simple_Expression => True));
|
2733 |
|
|
end loop;
|
2734 |
|
|
|
2735 |
|
|
-- Not set case
|
2736 |
|
|
|
2737 |
|
|
else
|
2738 |
|
|
Set_Right_Opnd (N, Alt);
|
2739 |
|
|
Set_Alternatives (N, No_List);
|
2740 |
|
|
end if;
|
2741 |
|
|
end P_Membership_Test;
|
2742 |
|
|
|
2743 |
|
|
end Ch4;
|