1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2001-2010, Free Software Foundation, Inc. --
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. --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 ------------------------------------------------------------------------------
26 with Err_Vars
; use Err_Vars
;
27 with Prj
.Attr
; use Prj
.Attr
;
28 with Prj
.Err
; use Prj
.Err
;
31 with Uintp
; use Uintp
;
33 package body Prj
.Strt
is
35 Buffer
: String_Access
;
36 Buffer_Last
: Natural := 0;
38 type Choice_String
is record
40 Already_Used
: Boolean := False;
42 -- The string of a case label, and an indication that it has already
43 -- been used (to avoid duplicate case labels).
45 Choices_Initial
: constant := 10;
46 Choices_Increment
: constant := 100;
47 -- These should be in alloc.ads
49 Choice_Node_Low_Bound
: constant := 0;
50 Choice_Node_High_Bound
: constant := 099_999_999
;
51 -- In practice, infinite
53 type Choice_Node_Id
is
54 range Choice_Node_Low_Bound
.. Choice_Node_High_Bound
;
56 First_Choice_Node_Id
: constant Choice_Node_Id
:=
57 Choice_Node_Low_Bound
;
61 (Table_Component_Type
=> Choice_String
,
62 Table_Index_Type
=> Choice_Node_Id
'Base,
63 Table_Low_Bound
=> First_Choice_Node_Id
,
64 Table_Initial
=> Choices_Initial
,
65 Table_Increment
=> Choices_Increment
,
66 Table_Name
=> "Prj.Strt.Choices");
67 -- Used to store the case labels and check that there is no duplicate
69 package Choice_Lasts
is
71 (Table_Component_Type
=> Choice_Node_Id
,
72 Table_Index_Type
=> Nat
,
75 Table_Increment
=> 100,
76 Table_Name
=> "Prj.Strt.Choice_Lasts");
77 -- Used to store the indices of the choices in table Choices,
78 -- to distinguish nested case constructions.
80 Choice_First
: Choice_Node_Id
:= 0;
81 -- Index in table Choices of the first case label of the current
82 -- case construction. Zero means no current case construction.
84 type Name_Location
is record
85 Name
: Name_Id
:= No_Name
;
86 Location
: Source_Ptr
:= No_Location
;
88 -- Store the identifier and the location of a simple name
92 (Table_Component_Type
=> Name_Location
,
93 Table_Index_Type
=> Nat
,
96 Table_Increment
=> 100,
97 Table_Name
=> "Prj.Strt.Names");
98 -- Used to accumulate the single names of a name
100 procedure Add
(This_String
: Name_Id
);
101 -- Add a string to the case label list, indicating that it has not
104 procedure Add_To_Names
(NL
: Name_Location
);
105 -- Add one single names to table Names
107 procedure External_Reference
108 (In_Tree
: Project_Node_Tree_Ref
;
109 Current_Project
: Project_Node_Id
;
110 Current_Package
: Project_Node_Id
;
111 External_Value
: out Project_Node_Id
;
112 Flags
: Processing_Flags
);
113 -- Parse an external reference. Current token is "external"
115 procedure Attribute_Reference
116 (In_Tree
: Project_Node_Tree_Ref
;
117 Reference
: out Project_Node_Id
;
118 First_Attribute
: Attribute_Node_Id
;
119 Current_Project
: Project_Node_Id
;
120 Current_Package
: Project_Node_Id
;
121 Flags
: Processing_Flags
);
122 -- Parse an attribute reference. Current token is an apostrophe
125 (In_Tree
: Project_Node_Tree_Ref
;
126 Term
: out Project_Node_Id
;
127 Expr_Kind
: in out Variable_Kind
;
128 Current_Project
: Project_Node_Id
;
129 Current_Package
: Project_Node_Id
;
130 Optional_Index
: Boolean;
131 Flags
: Processing_Flags
);
132 -- Recursive procedure to parse one term or several terms concatenated
139 procedure Add
(This_String
: Name_Id
) is
141 Choices
.Increment_Last
;
142 Choices
.Table
(Choices
.Last
) :=
143 (The_String
=> This_String
,
144 Already_Used
=> False);
151 procedure Add_To_Names
(NL
: Name_Location
) is
153 Names
.Increment_Last
;
154 Names
.Table
(Names
.Last
) := NL
;
157 -------------------------
158 -- Attribute_Reference --
159 -------------------------
161 procedure Attribute_Reference
162 (In_Tree
: Project_Node_Tree_Ref
;
163 Reference
: out Project_Node_Id
;
164 First_Attribute
: Attribute_Node_Id
;
165 Current_Project
: Project_Node_Id
;
166 Current_Package
: Project_Node_Id
;
167 Flags
: Processing_Flags
)
169 Current_Attribute
: Attribute_Node_Id
:= First_Attribute
;
172 -- Declare the node of the attribute reference
176 (Of_Kind
=> N_Attribute_Reference
, In_Tree
=> In_Tree
);
177 Set_Location_Of
(Reference
, In_Tree
, To
=> Token_Ptr
);
178 Scan
(In_Tree
); -- past apostrophe
180 -- Body may be an attribute name
182 if Token
= Tok_Body
then
183 Token
:= Tok_Identifier
;
184 Token_Name
:= Snames
.Name_Body
;
187 Expect
(Tok_Identifier
, "identifier");
189 if Token
= Tok_Identifier
then
190 Set_Name_Of
(Reference
, In_Tree
, To
=> Token_Name
);
192 -- Check if the identifier is one of the attribute identifiers in the
193 -- context (package or project level attributes).
196 Attribute_Node_Id_Of
(Token_Name
, Starting_At
=> First_Attribute
);
198 -- If the identifier is not allowed, report an error
200 if Current_Attribute
= Empty_Attribute
then
201 Error_Msg_Name_1
:= Token_Name
;
202 Error_Msg
(Flags
, "unknown attribute %%", Token_Ptr
);
203 Reference
:= Empty_Node
;
205 -- Scan past the attribute name
210 -- Give its characteristics to this attribute reference
212 Set_Project_Node_Of
(Reference
, In_Tree
, To
=> Current_Project
);
213 Set_Package_Node_Of
(Reference
, In_Tree
, To
=> Current_Package
);
214 Set_Expression_Kind_Of
215 (Reference
, In_Tree
, To
=> Variable_Kind_Of
(Current_Attribute
));
218 To
=> Attribute_Kind_Of
(Current_Attribute
) in
219 Case_Insensitive_Associative_Array
..
220 Optional_Index_Case_Insensitive_Associative_Array
);
222 -- Scan past the attribute name
226 -- If the attribute is an associative array, get the index
228 if Attribute_Kind_Of
(Current_Attribute
) /= Single
then
229 Expect
(Tok_Left_Paren
, "`(`");
231 if Token
= Tok_Left_Paren
then
234 if Others_Allowed_For
(Current_Attribute
)
235 and then Token
= Tok_Others
237 Set_Associative_Array_Index_Of
238 (Reference
, In_Tree
, To
=> All_Other_Names
);
242 if Others_Allowed_For
(Current_Attribute
) then
244 (Tok_String_Literal
, "literal string or others");
246 Expect
(Tok_String_Literal
, "literal string");
249 if Token
= Tok_String_Literal
then
250 Set_Associative_Array_Index_Of
251 (Reference
, In_Tree
, To
=> Token_Name
);
257 Expect
(Tok_Right_Paren
, "`)`");
259 if Token
= Tok_Right_Paren
then
265 -- Change name of obsolete attributes
267 if Present
(Reference
) then
268 case Name_Of
(Reference
, In_Tree
) is
269 when Snames
.Name_Specification
=>
270 Set_Name_Of
(Reference
, In_Tree
, To
=> Snames
.Name_Spec
);
272 when Snames
.Name_Specification_Suffix
=>
274 (Reference
, In_Tree
, To
=> Snames
.Name_Spec_Suffix
);
276 when Snames
.Name_Implementation
=>
277 Set_Name_Of
(Reference
, In_Tree
, To
=> Snames
.Name_Body
);
279 when Snames
.Name_Implementation_Suffix
=>
281 (Reference
, In_Tree
, To
=> Snames
.Name_Body_Suffix
);
288 end Attribute_Reference
;
290 ---------------------------
291 -- End_Case_Construction --
292 ---------------------------
294 procedure End_Case_Construction
295 (Check_All_Labels
: Boolean;
296 Case_Location
: Source_Ptr
;
297 Flags
: Processing_Flags
)
299 Non_Used
: Natural := 0;
300 First_Non_Used
: Choice_Node_Id
:= First_Choice_Node_Id
;
302 -- First, if Check_All_Labels is True, check if all values
303 -- of the string type have been used.
305 if Check_All_Labels
then
306 for Choice
in Choice_First
.. Choices
.Last
loop
307 if not Choices
.Table
(Choice
).Already_Used
then
308 Non_Used
:= Non_Used
+ 1;
311 First_Non_Used
:= Choice
;
316 -- If only one is not used, report a single warning for this value
319 Error_Msg_Name_1
:= Choices
.Table
(First_Non_Used
).The_String
;
320 Error_Msg
(Flags
, "?value %% is not used as label", Case_Location
);
322 -- If several are not used, report a warning for each one of them
324 elsif Non_Used
> 1 then
326 (Flags
, "?the following values are not used as labels:",
329 for Choice
in First_Non_Used
.. Choices
.Last
loop
330 if not Choices
.Table
(Choice
).Already_Used
then
331 Error_Msg_Name_1
:= Choices
.Table
(Choice
).The_String
;
332 Error_Msg
(Flags
, "\?%%", Case_Location
);
338 -- If this is the only case construction, empty the tables
340 if Choice_Lasts
.Last
= 1 then
341 Choice_Lasts
.Set_Last
(0);
342 Choices
.Set_Last
(First_Choice_Node_Id
);
345 elsif Choice_Lasts
.Last
= 2 then
347 -- This is the second case construction, set the tables to the first
349 Choice_Lasts
.Set_Last
(1);
350 Choices
.Set_Last
(Choice_Lasts
.Table
(1));
354 -- This is the 3rd or more case construction, set the tables to the
357 Choice_Lasts
.Decrement_Last
;
358 Choices
.Set_Last
(Choice_Lasts
.Table
(Choice_Lasts
.Last
));
359 Choice_First
:= Choice_Lasts
.Table
(Choice_Lasts
.Last
- 1) + 1;
361 end End_Case_Construction
;
363 ------------------------
364 -- External_Reference --
365 ------------------------
367 procedure External_Reference
368 (In_Tree
: Project_Node_Tree_Ref
;
369 Current_Project
: Project_Node_Id
;
370 Current_Package
: Project_Node_Id
;
371 External_Value
: out Project_Node_Id
;
372 Flags
: Processing_Flags
)
374 Field_Id
: Project_Node_Id
:= Empty_Node
;
379 (Of_Kind
=> N_External_Value
,
381 And_Expr_Kind
=> Single
);
382 Set_Location_Of
(External_Value
, In_Tree
, To
=> Token_Ptr
);
384 -- The current token is External
386 -- Get the left parenthesis
389 Expect
(Tok_Left_Paren
, "`(`");
391 -- Scan past the left parenthesis
393 if Token
= Tok_Left_Paren
then
397 -- Get the name of the external reference
399 Expect
(Tok_String_Literal
, "literal string");
401 if Token
= Tok_String_Literal
then
404 (Of_Kind
=> N_Literal_String
,
406 And_Expr_Kind
=> Single
);
407 Set_String_Value_Of
(Field_Id
, In_Tree
, To
=> Token_Name
);
408 Set_External_Reference_Of
(External_Value
, In_Tree
, To
=> Field_Id
);
410 -- Scan past the first argument
416 when Tok_Right_Paren
=>
417 Scan
(In_Tree
); -- scan past right paren
420 Scan
(In_Tree
); -- scan past comma
422 -- Get the string expression for the default
425 Loc
: constant Source_Ptr
:= Token_Ptr
;
430 Expression
=> Field_Id
,
432 Current_Project
=> Current_Project
,
433 Current_Package
=> Current_Package
,
434 Optional_Index
=> False);
436 if Expression_Kind_Of
(Field_Id
, In_Tree
) = List
then
438 (Flags
, "expression must be a single string", Loc
);
440 Set_External_Default_Of
441 (External_Value
, In_Tree
, To
=> Field_Id
);
445 Expect
(Tok_Right_Paren
, "`)`");
447 if Token
= Tok_Right_Paren
then
448 Scan
(In_Tree
); -- scan past right paren
452 Error_Msg
(Flags
, "`,` or `)` expected", Token_Ptr
);
455 end External_Reference
;
457 -----------------------
458 -- Parse_Choice_List --
459 -----------------------
461 procedure Parse_Choice_List
462 (In_Tree
: Project_Node_Tree_Ref
;
463 First_Choice
: out Project_Node_Id
;
464 Flags
: Processing_Flags
)
466 Current_Choice
: Project_Node_Id
:= Empty_Node
;
467 Next_Choice
: Project_Node_Id
:= Empty_Node
;
468 Choice_String
: Name_Id
:= No_Name
;
469 Found
: Boolean := False;
472 -- Declare the node of the first choice
476 (Of_Kind
=> N_Literal_String
,
478 And_Expr_Kind
=> Single
);
480 -- Initially Current_Choice is the same as First_Choice
482 Current_Choice
:= First_Choice
;
485 Expect
(Tok_String_Literal
, "literal string");
486 exit when Token
/= Tok_String_Literal
;
487 Set_Location_Of
(Current_Choice
, In_Tree
, To
=> Token_Ptr
);
488 Choice_String
:= Token_Name
;
490 -- Give the string value to the current choice
492 Set_String_Value_Of
(Current_Choice
, In_Tree
, To
=> Choice_String
);
494 -- Check if the label is part of the string type and if it has not
495 -- been already used.
498 for Choice
in Choice_First
.. Choices
.Last
loop
499 if Choices
.Table
(Choice
).The_String
= Choice_String
then
501 -- This label is part of the string type
505 if Choices
.Table
(Choice
).Already_Used
then
507 -- But it has already appeared in a choice list for this
508 -- case construction so report an error.
510 Error_Msg_Name_1
:= Choice_String
;
511 Error_Msg
(Flags
, "duplicate case label %%", Token_Ptr
);
514 Choices
.Table
(Choice
).Already_Used
:= True;
521 -- If the label is not part of the string list, report an error
524 Error_Msg_Name_1
:= Choice_String
;
525 Error_Msg
(Flags
, "illegal case label %%", Token_Ptr
);
528 -- Scan past the label
532 -- If there is no '|', we are done
534 if Token
= Tok_Vertical_Bar
then
536 -- Otherwise, declare the node of the next choice, link it to
537 -- Current_Choice and set Current_Choice to this new node.
541 (Of_Kind
=> N_Literal_String
,
543 And_Expr_Kind
=> Single
);
544 Set_Next_Literal_String
545 (Current_Choice
, In_Tree
, To
=> Next_Choice
);
546 Current_Choice
:= Next_Choice
;
552 end Parse_Choice_List
;
554 ----------------------
555 -- Parse_Expression --
556 ----------------------
558 procedure Parse_Expression
559 (In_Tree
: Project_Node_Tree_Ref
;
560 Expression
: out Project_Node_Id
;
561 Current_Project
: Project_Node_Id
;
562 Current_Package
: Project_Node_Id
;
563 Optional_Index
: Boolean;
564 Flags
: Processing_Flags
)
566 First_Term
: Project_Node_Id
:= Empty_Node
;
567 Expression_Kind
: Variable_Kind
:= Undefined
;
570 -- Declare the node of the expression
573 Default_Project_Node
(Of_Kind
=> N_Expression
, In_Tree
=> In_Tree
);
574 Set_Location_Of
(Expression
, In_Tree
, To
=> Token_Ptr
);
576 -- Parse the term or terms of the expression
578 Terms
(In_Tree
=> In_Tree
,
580 Expr_Kind
=> Expression_Kind
,
582 Current_Project
=> Current_Project
,
583 Current_Package
=> Current_Package
,
584 Optional_Index
=> Optional_Index
);
586 -- Set the first term and the expression kind
588 Set_First_Term
(Expression
, In_Tree
, To
=> First_Term
);
589 Set_Expression_Kind_Of
(Expression
, In_Tree
, To
=> Expression_Kind
);
590 end Parse_Expression
;
592 ----------------------------
593 -- Parse_String_Type_List --
594 ----------------------------
596 procedure Parse_String_Type_List
597 (In_Tree
: Project_Node_Tree_Ref
;
598 First_String
: out Project_Node_Id
;
599 Flags
: Processing_Flags
)
601 Last_String
: Project_Node_Id
:= Empty_Node
;
602 Next_String
: Project_Node_Id
:= Empty_Node
;
603 String_Value
: Name_Id
:= No_Name
;
606 -- Declare the node of the first string
610 (Of_Kind
=> N_Literal_String
,
612 And_Expr_Kind
=> Single
);
614 -- Initially, Last_String is the same as First_String
616 Last_String
:= First_String
;
619 Expect
(Tok_String_Literal
, "literal string");
620 exit when Token
/= Tok_String_Literal
;
621 String_Value
:= Token_Name
;
623 -- Give its string value to Last_String
625 Set_String_Value_Of
(Last_String
, In_Tree
, To
=> String_Value
);
626 Set_Location_Of
(Last_String
, In_Tree
, To
=> Token_Ptr
);
628 -- Now, check if the string is already part of the string type
631 Current
: Project_Node_Id
:= First_String
;
634 while Current
/= Last_String
loop
635 if String_Value_Of
(Current
, In_Tree
) = String_Value
then
637 -- This is a repetition, report an error
639 Error_Msg_Name_1
:= String_Value
;
640 Error_Msg
(Flags
, "duplicate value %% in type", Token_Ptr
);
644 Current
:= Next_Literal_String
(Current
, In_Tree
);
648 -- Scan past the literal string
652 -- If there is no comma following the literal string, we are done
654 if Token
/= Tok_Comma
then
658 -- Declare the next string, link it to Last_String and set
659 -- Last_String to its node.
663 (Of_Kind
=> N_Literal_String
,
665 And_Expr_Kind
=> Single
);
666 Set_Next_Literal_String
(Last_String
, In_Tree
, To
=> Next_String
);
667 Last_String
:= Next_String
;
671 end Parse_String_Type_List
;
673 ------------------------------
674 -- Parse_Variable_Reference --
675 ------------------------------
677 procedure Parse_Variable_Reference
678 (In_Tree
: Project_Node_Tree_Ref
;
679 Variable
: out Project_Node_Id
;
680 Current_Project
: Project_Node_Id
;
681 Current_Package
: Project_Node_Id
;
682 Flags
: Processing_Flags
)
684 Current_Variable
: Project_Node_Id
:= Empty_Node
;
686 The_Package
: Project_Node_Id
:= Current_Package
;
687 The_Project
: Project_Node_Id
:= Current_Project
;
689 Specified_Project
: Project_Node_Id
:= Empty_Node
;
690 Specified_Package
: Project_Node_Id
:= Empty_Node
;
691 Look_For_Variable
: Boolean := True;
692 First_Attribute
: Attribute_Node_Id
:= Empty_Attribute
;
693 Variable_Name
: Name_Id
;
699 Expect
(Tok_Identifier
, "identifier");
701 if Token
/= Tok_Identifier
then
702 Look_For_Variable
:= False;
706 Add_To_Names
(NL
=> (Name
=> Token_Name
, Location
=> Token_Ptr
));
708 exit when Token
/= Tok_Dot
;
712 if Look_For_Variable
then
714 if Token
= Tok_Apostrophe
then
716 -- Attribute reference
726 -- This may be a project name or a package name.
727 -- Project name have precedence.
729 -- First, look if it can be a package name
733 (Package_Node_Id_Of
(Names
.Table
(1).Name
));
735 -- Now, look if it can be a project name
737 if Names
.Table
(1).Name
=
738 Name_Of
(Current_Project
, In_Tree
)
740 The_Project
:= Current_Project
;
744 Imported_Or_Extended_Project_Of
745 (Current_Project
, In_Tree
, Names
.Table
(1).Name
);
748 if No
(The_Project
) then
750 -- If it is neither a project name nor a package name,
753 if First_Attribute
= Empty_Attribute
then
754 Error_Msg_Name_1
:= Names
.Table
(1).Name
;
755 Error_Msg
(Flags
, "unknown project %",
756 Names
.Table
(1).Location
);
757 First_Attribute
:= Attribute_First
;
760 -- If it is a package name, check if the package has
761 -- already been declared in the current project.
764 First_Package_Of
(Current_Project
, In_Tree
);
766 while Present
(The_Package
)
767 and then Name_Of
(The_Package
, In_Tree
) /=
771 Next_Package_In_Project
(The_Package
, In_Tree
);
774 -- If it has not been already declared, report an
777 if No
(The_Package
) then
778 Error_Msg_Name_1
:= Names
.Table
(1).Name
;
779 Error_Msg
(Flags
, "package % not yet defined",
780 Names
.Table
(1).Location
);
785 -- It is a project name
787 First_Attribute
:= Attribute_First
;
788 The_Package
:= Empty_Node
;
793 -- We have either a project name made of several simple
794 -- names (long project), or a project name (short project)
795 -- followed by a package name. The long project name has
799 Short_Project
: Name_Id
;
800 Long_Project
: Name_Id
;
807 -- Get the name of the short project
809 for Index
in 1 .. Names
.Last
- 1 loop
811 (Get_Name_String
(Names
.Table
(Index
).Name
),
812 Buffer
, Buffer_Last
);
814 if Index
/= Names
.Last
- 1 then
815 Add_To_Buffer
(".", Buffer
, Buffer_Last
);
819 Name_Len
:= Buffer_Last
;
820 Name_Buffer
(1 .. Buffer_Last
) :=
821 Buffer
(1 .. Buffer_Last
);
822 Short_Project
:= Name_Find
;
824 -- Now, add the last simple name to get the name of the
827 Add_To_Buffer
(".", Buffer
, Buffer_Last
);
829 (Get_Name_String
(Names
.Table
(Names
.Last
).Name
),
830 Buffer
, Buffer_Last
);
831 Name_Len
:= Buffer_Last
;
832 Name_Buffer
(1 .. Buffer_Last
) :=
833 Buffer
(1 .. Buffer_Last
);
834 Long_Project
:= Name_Find
;
836 -- Check if the long project is imported or extended
838 if Long_Project
= Name_Of
(Current_Project
, In_Tree
) then
839 The_Project
:= Current_Project
;
843 Imported_Or_Extended_Project_Of
849 -- If the long project exists, then this is the prefix
852 if Present
(The_Project
) then
853 First_Attribute
:= Attribute_First
;
854 The_Package
:= Empty_Node
;
857 -- Otherwise, check if the short project is imported
861 Name_Of
(Current_Project
, In_Tree
)
863 The_Project
:= Current_Project
;
866 The_Project
:= Imported_Or_Extended_Project_Of
867 (Current_Project
, In_Tree
,
871 -- If short project does not exist, report an error
873 if No
(The_Project
) then
874 Error_Msg_Name_1
:= Long_Project
;
875 Error_Msg_Name_2
:= Short_Project
;
876 Error_Msg
(Flags
, "unknown projects % or %",
877 Names
.Table
(1).Location
);
878 The_Package
:= Empty_Node
;
879 First_Attribute
:= Attribute_First
;
882 -- Now, we check if the package has been declared
886 First_Package_Of
(The_Project
, In_Tree
);
887 while Present
(The_Package
)
888 and then Name_Of
(The_Package
, In_Tree
) /=
889 Names
.Table
(Names
.Last
).Name
892 Next_Package_In_Project
(The_Package
, In_Tree
);
895 -- If it has not, then we report an error
897 if No
(The_Package
) then
899 Names
.Table
(Names
.Last
).Name
;
900 Error_Msg_Name_2
:= Short_Project
;
902 "package % not declared in project %",
903 Names
.Table
(Names
.Last
).Location
);
904 First_Attribute
:= Attribute_First
;
907 -- Otherwise, we have the correct project and
912 (Package_Id_Of
(The_Package
, In_Tree
));
923 Current_Project
=> The_Project
,
924 Current_Package
=> The_Package
,
925 First_Attribute
=> First_Attribute
);
932 (Of_Kind
=> N_Variable_Reference
, In_Tree
=> In_Tree
);
934 if Look_For_Variable
then
938 -- Cannot happen (so why null instead of raise PE???)
944 -- Simple variable name
946 Set_Name_Of
(Variable
, In_Tree
, To
=> Names
.Table
(1).Name
);
950 -- Variable name with a simple name prefix that can be
951 -- a project name or a package name. Project names have
952 -- priority over package names.
954 Set_Name_Of
(Variable
, In_Tree
, To
=> Names
.Table
(2).Name
);
956 -- Check if it can be a package name
958 The_Package
:= First_Package_Of
(Current_Project
, In_Tree
);
960 while Present
(The_Package
)
961 and then Name_Of
(The_Package
, In_Tree
) /=
965 Next_Package_In_Project
(The_Package
, In_Tree
);
968 -- Now look for a possible project name
970 The_Project
:= Imported_Or_Extended_Project_Of
971 (Current_Project
, In_Tree
, Names
.Table
(1).Name
);
973 if Present
(The_Project
) then
974 Specified_Project
:= The_Project
;
976 elsif No
(The_Package
) then
977 Error_Msg_Name_1
:= Names
.Table
(1).Name
;
978 Error_Msg
(Flags
, "unknown package or project %",
979 Names
.Table
(1).Location
);
980 Look_For_Variable
:= False;
983 Specified_Package
:= The_Package
;
988 -- Variable name with a prefix that is either a project name
989 -- made of several simple names, or a project name followed
990 -- by a package name.
993 (Variable
, In_Tree
, To
=> Names
.Table
(Names
.Last
).Name
);
996 Short_Project
: Name_Id
;
997 Long_Project
: Name_Id
;
1000 -- First, we get the two possible project names
1006 -- Add all the simple names, except the last two
1008 for Index
in 1 .. Names
.Last
- 2 loop
1010 (Get_Name_String
(Names
.Table
(Index
).Name
),
1011 Buffer
, Buffer_Last
);
1013 if Index
/= Names
.Last
- 2 then
1014 Add_To_Buffer
(".", Buffer
, Buffer_Last
);
1018 Name_Len
:= Buffer_Last
;
1019 Name_Buffer
(1 .. Name_Len
) := Buffer
(1 .. Buffer_Last
);
1020 Short_Project
:= Name_Find
;
1022 -- Add the simple name before the name of the variable
1024 Add_To_Buffer
(".", Buffer
, Buffer_Last
);
1026 (Get_Name_String
(Names
.Table
(Names
.Last
- 1).Name
),
1027 Buffer
, Buffer_Last
);
1028 Name_Len
:= Buffer_Last
;
1029 Name_Buffer
(1 .. Name_Len
) := Buffer
(1 .. Buffer_Last
);
1030 Long_Project
:= Name_Find
;
1032 -- Check if the prefix is the name of an imported or
1033 -- extended project.
1035 The_Project
:= Imported_Or_Extended_Project_Of
1036 (Current_Project
, In_Tree
, Long_Project
);
1038 if Present
(The_Project
) then
1039 Specified_Project
:= The_Project
;
1042 -- Now check if the prefix may be a project name followed
1043 -- by a package name.
1045 -- First check for a possible project name
1048 Imported_Or_Extended_Project_Of
1049 (Current_Project
, In_Tree
, Short_Project
);
1051 if No
(The_Project
) then
1052 -- Unknown prefix, report an error
1054 Error_Msg_Name_1
:= Long_Project
;
1055 Error_Msg_Name_2
:= Short_Project
;
1057 (Flags
, "unknown projects % or %",
1058 Names
.Table
(1).Location
);
1059 Look_For_Variable
:= False;
1062 Specified_Project
:= The_Project
;
1064 -- Now look for the package in this project
1066 The_Package
:= First_Package_Of
(The_Project
, In_Tree
);
1068 while Present
(The_Package
)
1069 and then Name_Of
(The_Package
, In_Tree
) /=
1070 Names
.Table
(Names
.Last
- 1).Name
1073 Next_Package_In_Project
(The_Package
, In_Tree
);
1076 if No
(The_Package
) then
1078 -- The package does not exist, report an error
1080 Error_Msg_Name_1
:= Names
.Table
(2).Name
;
1081 Error_Msg
(Flags
, "unknown package %",
1082 Names
.Table
(Names
.Last
- 1).Location
);
1083 Look_For_Variable
:= False;
1086 Specified_Package
:= The_Package
;
1094 if Look_For_Variable
then
1095 Variable_Name
:= Name_Of
(Variable
, In_Tree
);
1096 Set_Project_Node_Of
(Variable
, In_Tree
, To
=> Specified_Project
);
1097 Set_Package_Node_Of
(Variable
, In_Tree
, To
=> Specified_Package
);
1099 if Present
(Specified_Project
) then
1100 The_Project
:= Specified_Project
;
1102 The_Project
:= Current_Project
;
1105 Current_Variable
:= Empty_Node
;
1107 -- Look for this variable
1109 -- If a package was specified, check if the variable has been
1110 -- declared in this package.
1112 if Present
(Specified_Package
) then
1114 First_Variable_Of
(Specified_Package
, In_Tree
);
1115 while Present
(Current_Variable
)
1117 Name_Of
(Current_Variable
, In_Tree
) /= Variable_Name
1119 Current_Variable
:= Next_Variable
(Current_Variable
, In_Tree
);
1123 -- Otherwise, if no project has been specified and we are in
1124 -- a package, first check if the variable has been declared in
1127 if No
(Specified_Project
)
1128 and then Present
(Current_Package
)
1131 First_Variable_Of
(Current_Package
, In_Tree
);
1132 while Present
(Current_Variable
)
1133 and then Name_Of
(Current_Variable
, In_Tree
) /= Variable_Name
1136 Next_Variable
(Current_Variable
, In_Tree
);
1140 -- If we have not found the variable in the package, check if the
1141 -- variable has been declared in the project, or in any of its
1144 if No
(Current_Variable
) then
1146 Proj
: Project_Node_Id
:= The_Project
;
1150 Current_Variable
:= First_Variable_Of
(Proj
, In_Tree
);
1152 Present
(Current_Variable
)
1154 Name_Of
(Current_Variable
, In_Tree
) /= Variable_Name
1157 Next_Variable
(Current_Variable
, In_Tree
);
1160 exit when Present
(Current_Variable
);
1162 Proj
:= Parent_Project_Of
(Proj
, In_Tree
);
1164 Set_Project_Node_Of
(Variable
, In_Tree
, To
=> Proj
);
1166 exit when No
(Proj
);
1172 -- If the variable was not found, report an error
1174 if No
(Current_Variable
) then
1175 Error_Msg_Name_1
:= Variable_Name
;
1177 (Flags
, "unknown variable %", Names
.Table
(Names
.Last
).Location
);
1181 if Present
(Current_Variable
) then
1182 Set_Expression_Kind_Of
1184 To
=> Expression_Kind_Of
(Current_Variable
, In_Tree
));
1186 if Kind_Of
(Current_Variable
, In_Tree
) =
1187 N_Typed_Variable_Declaration
1191 To
=> String_Type_Of
(Current_Variable
, In_Tree
));
1195 -- If the variable is followed by a left parenthesis, report an error
1196 -- but attempt to scan the index.
1198 if Token
= Tok_Left_Paren
then
1200 (Flags
, "\variables cannot be associative arrays", Token_Ptr
);
1202 Expect
(Tok_String_Literal
, "literal string");
1204 if Token
= Tok_String_Literal
then
1206 Expect
(Tok_Right_Paren
, "`)`");
1208 if Token
= Tok_Right_Paren
then
1213 end Parse_Variable_Reference
;
1215 ---------------------------------
1216 -- Start_New_Case_Construction --
1217 ---------------------------------
1219 procedure Start_New_Case_Construction
1220 (In_Tree
: Project_Node_Tree_Ref
;
1221 String_Type
: Project_Node_Id
)
1223 Current_String
: Project_Node_Id
;
1226 -- Set Choice_First, depending on whether this is the first case
1227 -- construction or not.
1229 if Choice_First
= 0 then
1231 Choices
.Set_Last
(First_Choice_Node_Id
);
1233 Choice_First
:= Choices
.Last
+ 1;
1236 -- Add the literal of the string type to the Choices table
1238 if Present
(String_Type
) then
1239 Current_String
:= First_Literal_String
(String_Type
, In_Tree
);
1240 while Present
(Current_String
) loop
1241 Add
(This_String
=> String_Value_Of
(Current_String
, In_Tree
));
1242 Current_String
:= Next_Literal_String
(Current_String
, In_Tree
);
1246 -- Set the value of the last choice in table Choice_Lasts
1248 Choice_Lasts
.Increment_Last
;
1249 Choice_Lasts
.Table
(Choice_Lasts
.Last
) := Choices
.Last
;
1250 end Start_New_Case_Construction
;
1257 (In_Tree
: Project_Node_Tree_Ref
;
1258 Term
: out Project_Node_Id
;
1259 Expr_Kind
: in out Variable_Kind
;
1260 Current_Project
: Project_Node_Id
;
1261 Current_Package
: Project_Node_Id
;
1262 Optional_Index
: Boolean;
1263 Flags
: Processing_Flags
)
1265 Next_Term
: Project_Node_Id
:= Empty_Node
;
1266 Term_Id
: Project_Node_Id
:= Empty_Node
;
1267 Current_Expression
: Project_Node_Id
:= Empty_Node
;
1268 Next_Expression
: Project_Node_Id
:= Empty_Node
;
1269 Current_Location
: Source_Ptr
:= No_Location
;
1270 Reference
: Project_Node_Id
:= Empty_Node
;
1273 -- Declare a new node for the term
1275 Term
:= Default_Project_Node
(Of_Kind
=> N_Term
, In_Tree
=> In_Tree
);
1276 Set_Location_Of
(Term
, In_Tree
, To
=> Token_Ptr
);
1279 when Tok_Left_Paren
=>
1281 -- If we have a left parenthesis and we don't know the expression
1282 -- kind, then this is a string list.
1293 -- If we already know that this is a single string, report
1294 -- an error, but set the expression kind to string list to
1295 -- avoid several errors.
1299 (Flags
, "literal string list cannot appear in a string",
1303 -- Declare a new node for this literal string list
1305 Term_Id
:= Default_Project_Node
1306 (Of_Kind
=> N_Literal_String_List
,
1308 And_Expr_Kind
=> List
);
1309 Set_Current_Term
(Term
, In_Tree
, To
=> Term_Id
);
1310 Set_Location_Of
(Term
, In_Tree
, To
=> Token_Ptr
);
1312 -- Scan past the left parenthesis
1316 -- If the left parenthesis is immediately followed by a right
1317 -- parenthesis, the literal string list is empty.
1319 if Token
= Tok_Right_Paren
then
1323 -- Otherwise parse the expression(s) in the literal string list
1326 Current_Location
:= Token_Ptr
;
1328 (In_Tree
=> In_Tree
,
1329 Expression
=> Next_Expression
,
1331 Current_Project
=> Current_Project
,
1332 Current_Package
=> Current_Package
,
1333 Optional_Index
=> Optional_Index
);
1335 -- The expression kind is String list, report an error
1337 if Expression_Kind_Of
(Next_Expression
, In_Tree
) = List
then
1338 Error_Msg
(Flags
, "single expression expected",
1342 -- If Current_Expression is empty, it means that the
1343 -- expression is the first in the string list.
1345 if No
(Current_Expression
) then
1346 Set_First_Expression_In_List
1347 (Term_Id
, In_Tree
, To
=> Next_Expression
);
1349 Set_Next_Expression_In_List
1350 (Current_Expression
, In_Tree
, To
=> Next_Expression
);
1353 Current_Expression
:= Next_Expression
;
1355 -- If there is a comma, continue with the next expression
1357 exit when Token
/= Tok_Comma
;
1358 Scan
(In_Tree
); -- past the comma
1361 -- We expect a closing right parenthesis
1363 Expect
(Tok_Right_Paren
, "`)`");
1365 if Token
= Tok_Right_Paren
then
1370 when Tok_String_Literal
=>
1372 -- If we don't know the expression kind (first term), then it is
1375 if Expr_Kind
= Undefined
then
1376 Expr_Kind
:= Single
;
1379 -- Declare a new node for the string literal
1382 Default_Project_Node
1383 (Of_Kind
=> N_Literal_String
, In_Tree
=> In_Tree
);
1384 Set_Current_Term
(Term
, In_Tree
, To
=> Term_Id
);
1385 Set_String_Value_Of
(Term_Id
, In_Tree
, To
=> Token_Name
);
1387 -- Scan past the string literal
1391 -- Check for possible index expression
1393 if Token
= Tok_At
then
1394 if not Optional_Index
then
1395 Error_Msg
(Flags
, "index not allowed here", Token_Ptr
);
1398 if Token
= Tok_Integer_Literal
then
1402 -- Set the index value
1406 Expect
(Tok_Integer_Literal
, "integer literal");
1408 if Token
= Tok_Integer_Literal
then
1410 Index
: constant Int
:= UI_To_Int
(Int_Literal_Value
);
1414 (Flags
, "index cannot be zero", Token_Ptr
);
1417 (Term_Id
, In_Tree
, To
=> Index
);
1426 when Tok_Identifier
=>
1427 Current_Location
:= Token_Ptr
;
1429 -- Get the variable or attribute reference
1431 Parse_Variable_Reference
1432 (In_Tree
=> In_Tree
,
1433 Variable
=> Reference
,
1435 Current_Project
=> Current_Project
,
1436 Current_Package
=> Current_Package
);
1437 Set_Current_Term
(Term
, In_Tree
, To
=> Reference
);
1439 if Present
(Reference
) then
1441 -- If we don't know the expression kind (first term), then it
1442 -- has the kind of the variable or attribute reference.
1444 if Expr_Kind
= Undefined
then
1445 Expr_Kind
:= Expression_Kind_Of
(Reference
, In_Tree
);
1447 elsif Expr_Kind
= Single
1448 and then Expression_Kind_Of
(Reference
, In_Tree
) = List
1450 -- If the expression is a single list, and the reference is
1451 -- a string list, report an error, and set the expression
1452 -- kind to string list to avoid multiple errors.
1457 "list variable cannot appear in single string expression",
1464 -- Project can appear in an expression as the prefix of an
1465 -- attribute reference of the current project.
1467 Current_Location
:= Token_Ptr
;
1469 Expect
(Tok_Apostrophe
, "`'`");
1471 if Token
= Tok_Apostrophe
then
1473 (In_Tree
=> In_Tree
,
1474 Reference
=> Reference
,
1476 First_Attribute
=> Prj
.Attr
.Attribute_First
,
1477 Current_Project
=> Current_Project
,
1478 Current_Package
=> Empty_Node
);
1479 Set_Current_Term
(Term
, In_Tree
, To
=> Reference
);
1482 -- Same checks as above for the expression kind
1484 if Present
(Reference
) then
1485 if Expr_Kind
= Undefined
then
1486 Expr_Kind
:= Expression_Kind_Of
(Reference
, In_Tree
);
1488 elsif Expr_Kind
= Single
1489 and then Expression_Kind_Of
(Reference
, In_Tree
) = List
1492 (Flags
, "lists cannot appear in single string expression",
1497 when Tok_External
=>
1499 -- An external reference is always a single string
1501 if Expr_Kind
= Undefined
then
1502 Expr_Kind
:= Single
;
1506 (In_Tree
=> In_Tree
,
1508 Current_Project
=> Current_Project
,
1509 Current_Package
=> Current_Package
,
1510 External_Value
=> Reference
);
1511 Set_Current_Term
(Term
, In_Tree
, To
=> Reference
);
1514 Error_Msg
(Flags
, "cannot be part of an expression", Token_Ptr
);
1519 -- If there is an '&', call Terms recursively
1521 if Token
= Tok_Ampersand
then
1522 Scan
(In_Tree
); -- scan past ampersand
1525 (In_Tree
=> In_Tree
,
1527 Expr_Kind
=> Expr_Kind
,
1529 Current_Project
=> Current_Project
,
1530 Current_Package
=> Current_Package
,
1531 Optional_Index
=> Optional_Index
);
1533 -- And link the next term to this term
1535 Set_Next_Term
(Term
, In_Tree
, To
=> Next_Term
);