1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2001-2005, 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 2, 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 COPYING. If not, write --
19 -- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, --
20 -- Boston, MA 02110-1301, USA. --
22 -- GNAT was originally developed by the GNAT team at New York University. --
23 -- Extensive contributions were provided by Ada Core Technologies Inc. --
25 ------------------------------------------------------------------------------
27 with Err_Vars
; use Err_Vars
;
28 with Namet
; use Namet
;
29 with Prj
.Attr
; use Prj
.Attr
;
30 with Prj
.Err
; use Prj
.Err
;
33 with Uintp
; use Uintp
;
35 package body Prj
.Strt
is
37 Buffer
: String_Access
;
38 Buffer_Last
: Natural := 0;
40 type Choice_String
is record
42 Already_Used
: Boolean := False;
44 -- The string of a case label, and an indication that it has already
45 -- been used (to avoid duplicate case labels).
47 Choices_Initial
: constant := 10;
48 Choices_Increment
: constant := 50;
50 Choice_Node_Low_Bound
: constant := 0;
51 Choice_Node_High_Bound
: constant := 099_999_999
;
52 -- In practice, infinite
54 type Choice_Node_Id
is
55 range Choice_Node_Low_Bound
.. Choice_Node_High_Bound
;
57 First_Choice_Node_Id
: constant Choice_Node_Id
:=
58 Choice_Node_Low_Bound
;
61 new Table
.Table
(Table_Component_Type
=> Choice_String
,
62 Table_Index_Type
=> Choice_Node_Id
,
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
70 new Table
.Table
(Table_Component_Type
=> Choice_Node_Id
,
71 Table_Index_Type
=> Nat
,
74 Table_Increment
=> 100,
75 Table_Name
=> "Prj.Strt.Choice_Lasts");
76 -- Used to store the indices of the choices in table Choices,
77 -- to distinguish nested case constructions.
79 Choice_First
: Choice_Node_Id
:= 0;
80 -- Index in table Choices of the first case label of the current
81 -- case construction. Zero means no current case construction.
83 type Name_Location
is record
84 Name
: Name_Id
:= No_Name
;
85 Location
: Source_Ptr
:= No_Location
;
87 -- Store the identifier and the location of a simple name
90 new Table
.Table
(Table_Component_Type
=> Name_Location
,
91 Table_Index_Type
=> Nat
,
94 Table_Increment
=> 100,
95 Table_Name
=> "Prj.Strt.Names");
96 -- Used to accumulate the single names of a name
98 procedure Add
(This_String
: Name_Id
);
99 -- Add a string to the case label list, indicating that it has not
102 procedure Add_To_Names
(NL
: Name_Location
);
103 -- Add one single names to table Names
105 procedure External_Reference
106 (In_Tree
: Project_Node_Tree_Ref
;
107 Current_Project
: Project_Node_Id
;
108 Current_Package
: Project_Node_Id
;
109 External_Value
: out Project_Node_Id
);
110 -- Parse an external reference. Current token is "external"
112 procedure Attribute_Reference
113 (In_Tree
: Project_Node_Tree_Ref
;
114 Reference
: out Project_Node_Id
;
115 First_Attribute
: Attribute_Node_Id
;
116 Current_Project
: Project_Node_Id
;
117 Current_Package
: Project_Node_Id
);
118 -- Parse an attribute reference. Current token is an apostrophe
121 (In_Tree
: Project_Node_Tree_Ref
;
122 Term
: out Project_Node_Id
;
123 Expr_Kind
: in out Variable_Kind
;
124 Current_Project
: Project_Node_Id
;
125 Current_Package
: Project_Node_Id
;
126 Optional_Index
: Boolean);
127 -- Recursive procedure to parse one term or several terms concatenated
134 procedure Add
(This_String
: Name_Id
) is
136 Choices
.Increment_Last
;
137 Choices
.Table
(Choices
.Last
) :=
138 (The_String
=> This_String
,
139 Already_Used
=> False);
146 procedure Add_To_Names
(NL
: Name_Location
) is
148 Names
.Increment_Last
;
149 Names
.Table
(Names
.Last
) := NL
;
152 -------------------------
153 -- Attribute_Reference --
154 -------------------------
156 procedure Attribute_Reference
157 (In_Tree
: Project_Node_Tree_Ref
;
158 Reference
: out Project_Node_Id
;
159 First_Attribute
: Attribute_Node_Id
;
160 Current_Project
: Project_Node_Id
;
161 Current_Package
: Project_Node_Id
)
163 Current_Attribute
: Attribute_Node_Id
:= First_Attribute
;
166 -- Declare the node of the attribute reference
170 (Of_Kind
=> N_Attribute_Reference
, In_Tree
=> In_Tree
);
171 Set_Location_Of
(Reference
, In_Tree
, To
=> Token_Ptr
);
172 Scan
(In_Tree
); -- past apostrophe
174 -- Body may be an attribute name
176 if Token
= Tok_Body
then
177 Token
:= Tok_Identifier
;
178 Token_Name
:= Snames
.Name_Body
;
181 Expect
(Tok_Identifier
, "identifier");
183 if Token
= Tok_Identifier
then
184 Set_Name_Of
(Reference
, In_Tree
, To
=> Token_Name
);
186 -- Check if the identifier is one of the attribute identifiers in the
187 -- context (package or project level attributes).
190 Attribute_Node_Id_Of
(Token_Name
, Starting_At
=> First_Attribute
);
192 -- If the identifier is not allowed, report an error
194 if Current_Attribute
= Empty_Attribute
then
195 Error_Msg_Name_1
:= Token_Name
;
196 Error_Msg
("unknown attribute %", Token_Ptr
);
197 Reference
:= Empty_Node
;
199 -- Scan past the attribute name
204 -- Give its characteristics to this attribute reference
206 Set_Project_Node_Of
(Reference
, In_Tree
, To
=> Current_Project
);
207 Set_Package_Node_Of
(Reference
, In_Tree
, To
=> Current_Package
);
208 Set_Expression_Kind_Of
209 (Reference
, In_Tree
, To
=> Variable_Kind_Of
(Current_Attribute
));
212 To
=> Attribute_Kind_Of
(Current_Attribute
) =
213 Case_Insensitive_Associative_Array
);
215 -- Scan past the attribute name
219 -- If the attribute is an associative array, get the index
221 if Attribute_Kind_Of
(Current_Attribute
) /= Single
then
222 Expect
(Tok_Left_Paren
, "`(`");
224 if Token
= Tok_Left_Paren
then
226 Expect
(Tok_String_Literal
, "literal string");
228 if Token
= Tok_String_Literal
then
229 Set_Associative_Array_Index_Of
230 (Reference
, In_Tree
, To
=> Token_Name
);
232 Expect
(Tok_Right_Paren
, "`)`");
234 if Token
= Tok_Right_Paren
then
242 -- Change name of obsolete attributes
244 if Reference
/= Empty_Node
then
245 case Name_Of
(Reference
, In_Tree
) is
246 when Snames
.Name_Specification
=>
247 Set_Name_Of
(Reference
, In_Tree
, To
=> Snames
.Name_Spec
);
249 when Snames
.Name_Specification_Suffix
=>
251 (Reference
, In_Tree
, To
=> Snames
.Name_Spec_Suffix
);
253 when Snames
.Name_Implementation
=>
254 Set_Name_Of
(Reference
, In_Tree
, To
=> Snames
.Name_Body
);
256 when Snames
.Name_Implementation_Suffix
=>
258 (Reference
, In_Tree
, To
=> Snames
.Name_Body_Suffix
);
265 end Attribute_Reference
;
267 ---------------------------
268 -- End_Case_Construction --
269 ---------------------------
271 procedure End_Case_Construction
272 (Check_All_Labels
: Boolean;
273 Case_Location
: Source_Ptr
)
275 Non_Used
: Natural := 0;
276 First_Non_Used
: Choice_Node_Id
:= First_Choice_Node_Id
;
278 -- First, if Check_All_Labels is True, check if all values
279 -- of the string type have been used.
281 if Check_All_Labels
then
282 for Choice
in Choice_First
.. Choices
.Last
loop
283 if not Choices
.Table
(Choice
).Already_Used
then
284 Non_Used
:= Non_Used
+ 1;
287 First_Non_Used
:= Choice
;
292 -- If only one is not used, report a single warning for this value
295 Error_Msg_Name_1
:= Choices
.Table
(First_Non_Used
).The_String
;
296 Error_Msg
("?value { is not used as label", Case_Location
);
298 -- If several are not used, report a warning for each one of them
300 elsif Non_Used
> 1 then
302 ("?the following values are not used as labels:",
305 for Choice
in First_Non_Used
.. Choices
.Last
loop
306 if not Choices
.Table
(Choice
).Already_Used
then
307 Error_Msg_Name_1
:= Choices
.Table
(Choice
).The_String
;
308 Error_Msg
("\?{", Case_Location
);
314 -- If this is the only case construction, empty the tables
316 if Choice_Lasts
.Last
= 1 then
317 Choice_Lasts
.Set_Last
(0);
318 Choices
.Set_Last
(First_Choice_Node_Id
);
321 elsif Choice_Lasts
.Last
= 2 then
322 -- This is the second case onstruction, set the tables to the first
324 Choice_Lasts
.Set_Last
(1);
325 Choices
.Set_Last
(Choice_Lasts
.Table
(1));
329 -- This is the 3rd or more case construction, set the tables to the
332 Choice_Lasts
.Decrement_Last
;
333 Choices
.Set_Last
(Choice_Lasts
.Table
(Choice_Lasts
.Last
));
334 Choice_First
:= Choice_Lasts
.Table
(Choice_Lasts
.Last
- 1) + 1;
336 end End_Case_Construction
;
338 ------------------------
339 -- External_Reference --
340 ------------------------
342 procedure External_Reference
343 (In_Tree
: Project_Node_Tree_Ref
;
344 Current_Project
: Project_Node_Id
;
345 Current_Package
: Project_Node_Id
;
346 External_Value
: out Project_Node_Id
)
348 Field_Id
: Project_Node_Id
:= Empty_Node
;
353 (Of_Kind
=> N_External_Value
,
355 And_Expr_Kind
=> Single
);
356 Set_Location_Of
(External_Value
, In_Tree
, To
=> Token_Ptr
);
358 -- The current token is External
360 -- Get the left parenthesis
363 Expect
(Tok_Left_Paren
, "`(`");
365 -- Scan past the left parenthesis
367 if Token
= Tok_Left_Paren
then
371 -- Get the name of the external reference
373 Expect
(Tok_String_Literal
, "literal string");
375 if Token
= Tok_String_Literal
then
378 (Of_Kind
=> N_Literal_String
,
380 And_Expr_Kind
=> Single
);
381 Set_String_Value_Of
(Field_Id
, In_Tree
, To
=> Token_Name
);
382 Set_External_Reference_Of
(External_Value
, In_Tree
, To
=> Field_Id
);
384 -- Scan past the first argument
390 when Tok_Right_Paren
=>
392 -- Scan past the right parenthesis
397 -- Scan past the comma
401 -- Get the string expression for the default
404 Loc
: constant Source_Ptr
:= Token_Ptr
;
409 Expression
=> Field_Id
,
410 Current_Project
=> Current_Project
,
411 Current_Package
=> Current_Package
,
412 Optional_Index
=> False);
414 if Expression_Kind_Of
(Field_Id
, In_Tree
) = List
then
415 Error_Msg
("expression must be a single string", Loc
);
417 Set_External_Default_Of
418 (External_Value
, In_Tree
, To
=> Field_Id
);
422 Expect
(Tok_Right_Paren
, "`)`");
424 -- Scan past the right parenthesis
426 if Token
= Tok_Right_Paren
then
431 Error_Msg
("`,` or `)` expected", Token_Ptr
);
434 end External_Reference
;
436 -----------------------
437 -- Parse_Choice_List --
438 -----------------------
440 procedure Parse_Choice_List
441 (In_Tree
: Project_Node_Tree_Ref
;
442 First_Choice
: out Project_Node_Id
)
444 Current_Choice
: Project_Node_Id
:= Empty_Node
;
445 Next_Choice
: Project_Node_Id
:= Empty_Node
;
446 Choice_String
: Name_Id
:= No_Name
;
447 Found
: Boolean := False;
450 -- Declare the node of the first choice
454 (Of_Kind
=> N_Literal_String
,
456 And_Expr_Kind
=> Single
);
458 -- Initially Current_Choice is the same as First_Choice
460 Current_Choice
:= First_Choice
;
463 Expect
(Tok_String_Literal
, "literal string");
464 exit when Token
/= Tok_String_Literal
;
465 Set_Location_Of
(Current_Choice
, In_Tree
, To
=> Token_Ptr
);
466 Choice_String
:= Token_Name
;
468 -- Give the string value to the current choice
470 Set_String_Value_Of
(Current_Choice
, In_Tree
, To
=> Choice_String
);
472 -- Check if the label is part of the string type and if it has not
473 -- been already used.
476 for Choice
in Choice_First
.. Choices
.Last
loop
477 if Choices
.Table
(Choice
).The_String
= Choice_String
then
478 -- This label is part of the string type
482 if Choices
.Table
(Choice
).Already_Used
then
483 -- But it has already appeared in a choice list for this
484 -- case construction; report an error.
486 Error_Msg_Name_1
:= Choice_String
;
487 Error_Msg
("duplicate case label {", Token_Ptr
);
489 Choices
.Table
(Choice
).Already_Used
:= True;
496 -- If the label is not part of the string list, report an error
499 Error_Msg_Name_1
:= Choice_String
;
500 Error_Msg
("illegal case label {", Token_Ptr
);
503 -- Scan past the label
507 -- If there is no '|', we are done
509 if Token
= Tok_Vertical_Bar
then
510 -- Otherwise, declare the node of the next choice, link it to
511 -- Current_Choice and set Current_Choice to this new node.
515 (Of_Kind
=> N_Literal_String
,
517 And_Expr_Kind
=> Single
);
518 Set_Next_Literal_String
519 (Current_Choice
, In_Tree
, To
=> Next_Choice
);
520 Current_Choice
:= Next_Choice
;
526 end Parse_Choice_List
;
528 ----------------------
529 -- Parse_Expression --
530 ----------------------
532 procedure Parse_Expression
533 (In_Tree
: Project_Node_Tree_Ref
;
534 Expression
: out Project_Node_Id
;
535 Current_Project
: Project_Node_Id
;
536 Current_Package
: Project_Node_Id
;
537 Optional_Index
: Boolean)
539 First_Term
: Project_Node_Id
:= Empty_Node
;
540 Expression_Kind
: Variable_Kind
:= Undefined
;
543 -- Declare the node of the expression
546 Default_Project_Node
(Of_Kind
=> N_Expression
, In_Tree
=> In_Tree
);
547 Set_Location_Of
(Expression
, In_Tree
, To
=> Token_Ptr
);
549 -- Parse the term or terms of the expression
551 Terms
(In_Tree
=> In_Tree
,
553 Expr_Kind
=> Expression_Kind
,
554 Current_Project
=> Current_Project
,
555 Current_Package
=> Current_Package
,
556 Optional_Index
=> Optional_Index
);
558 -- Set the first term and the expression kind
560 Set_First_Term
(Expression
, In_Tree
, To
=> First_Term
);
561 Set_Expression_Kind_Of
(Expression
, In_Tree
, To
=> Expression_Kind
);
562 end Parse_Expression
;
564 ----------------------------
565 -- Parse_String_Type_List --
566 ----------------------------
568 procedure Parse_String_Type_List
569 (In_Tree
: Project_Node_Tree_Ref
;
570 First_String
: out Project_Node_Id
)
572 Last_String
: Project_Node_Id
:= Empty_Node
;
573 Next_String
: Project_Node_Id
:= Empty_Node
;
574 String_Value
: Name_Id
:= No_Name
;
577 -- Declare the node of the first string
581 (Of_Kind
=> N_Literal_String
,
583 And_Expr_Kind
=> Single
);
585 -- Initially, Last_String is the same as First_String
587 Last_String
:= First_String
;
590 Expect
(Tok_String_Literal
, "literal string");
591 exit when Token
/= Tok_String_Literal
;
592 String_Value
:= Token_Name
;
594 -- Give its string value to Last_String
596 Set_String_Value_Of
(Last_String
, In_Tree
, To
=> String_Value
);
597 Set_Location_Of
(Last_String
, In_Tree
, To
=> Token_Ptr
);
599 -- Now, check if the string is already part of the string type
602 Current
: Project_Node_Id
:= First_String
;
605 while Current
/= Last_String
loop
606 if String_Value_Of
(Current
, In_Tree
) = String_Value
then
607 -- This is a repetition, report an error
609 Error_Msg_Name_1
:= String_Value
;
610 Error_Msg
("duplicate value { in type", Token_Ptr
);
614 Current
:= Next_Literal_String
(Current
, In_Tree
);
618 -- Scan past the literal string
622 -- If there is no comma following the literal string, we are done
624 if Token
/= Tok_Comma
then
628 -- Declare the next string, link it to Last_String and set
629 -- Last_String to its node.
633 (Of_Kind
=> N_Literal_String
,
635 And_Expr_Kind
=> Single
);
636 Set_Next_Literal_String
(Last_String
, In_Tree
, To
=> Next_String
);
637 Last_String
:= Next_String
;
641 end Parse_String_Type_List
;
643 ------------------------------
644 -- Parse_Variable_Reference --
645 ------------------------------
647 procedure Parse_Variable_Reference
648 (In_Tree
: Project_Node_Tree_Ref
;
649 Variable
: out Project_Node_Id
;
650 Current_Project
: Project_Node_Id
;
651 Current_Package
: Project_Node_Id
)
653 Current_Variable
: Project_Node_Id
:= Empty_Node
;
655 The_Package
: Project_Node_Id
:= Current_Package
;
656 The_Project
: Project_Node_Id
:= Current_Project
;
658 Specified_Project
: Project_Node_Id
:= Empty_Node
;
659 Specified_Package
: Project_Node_Id
:= Empty_Node
;
660 Look_For_Variable
: Boolean := True;
661 First_Attribute
: Attribute_Node_Id
:= Empty_Attribute
;
662 Variable_Name
: Name_Id
;
668 Expect
(Tok_Identifier
, "identifier");
670 if Token
/= Tok_Identifier
then
671 Look_For_Variable
:= False;
675 Add_To_Names
(NL
=> (Name
=> Token_Name
, Location
=> Token_Ptr
));
677 exit when Token
/= Tok_Dot
;
681 if Look_For_Variable
then
683 if Token
= Tok_Apostrophe
then
685 -- Attribute reference
695 -- This may be a project name or a package name.
696 -- Project name have precedence.
698 -- First, look if it can be a package name
702 (Package_Node_Id_Of
(Names
.Table
(1).Name
));
704 -- Now, look if it can be a project name
706 The_Project
:= Imported_Or_Extended_Project_Of
707 (Current_Project
, In_Tree
, Names
.Table
(1).Name
);
709 if The_Project
= Empty_Node
then
710 -- If it is neither a project name nor a package name,
713 if First_Attribute
= Empty_Attribute
then
714 Error_Msg_Name_1
:= Names
.Table
(1).Name
;
715 Error_Msg
("unknown project %",
716 Names
.Table
(1).Location
);
717 First_Attribute
:= Attribute_First
;
720 -- If it is a package name, check if the package
721 -- has already been declared in the current project.
724 First_Package_Of
(Current_Project
, In_Tree
);
726 while The_Package
/= Empty_Node
727 and then Name_Of
(The_Package
, In_Tree
) /=
731 Next_Package_In_Project
(The_Package
, In_Tree
);
734 -- If it has not been already declared, report an
737 if The_Package
= Empty_Node
then
738 Error_Msg_Name_1
:= Names
.Table
(1).Name
;
739 Error_Msg
("package % not yet defined",
740 Names
.Table
(1).Location
);
745 -- It is a project name
747 First_Attribute
:= Attribute_First
;
748 The_Package
:= Empty_Node
;
753 -- We have either a project name made of several simple
754 -- names (long project), or a project name (short project)
755 -- followed by a package name. The long project name has
759 Short_Project
: Name_Id
;
760 Long_Project
: Name_Id
;
767 -- Get the name of the short project
769 for Index
in 1 .. Names
.Last
- 1 loop
771 (Get_Name_String
(Names
.Table
(Index
).Name
),
772 Buffer
, Buffer_Last
);
774 if Index
/= Names
.Last
- 1 then
775 Add_To_Buffer
(".", Buffer
, Buffer_Last
);
779 Name_Len
:= Buffer_Last
;
780 Name_Buffer
(1 .. Buffer_Last
) :=
781 Buffer
(1 .. Buffer_Last
);
782 Short_Project
:= Name_Find
;
784 -- Now, add the last simple name to get the name of the
787 Add_To_Buffer
(".", Buffer
, Buffer_Last
);
789 (Get_Name_String
(Names
.Table
(Names
.Last
).Name
),
790 Buffer
, Buffer_Last
);
791 Name_Len
:= Buffer_Last
;
792 Name_Buffer
(1 .. Buffer_Last
) :=
793 Buffer
(1 .. Buffer_Last
);
794 Long_Project
:= Name_Find
;
796 -- Check if the long project is imported or extended
798 The_Project
:= Imported_Or_Extended_Project_Of
799 (Current_Project
, In_Tree
, Long_Project
);
801 -- If the long project exists, then this is the prefix
804 if The_Project
/= Empty_Node
then
805 First_Attribute
:= Attribute_First
;
806 The_Package
:= Empty_Node
;
809 -- Otherwise, check if the short project is imported
812 The_Project
:= Imported_Or_Extended_Project_Of
813 (Current_Project
, In_Tree
,
816 -- If the short project does not exist, we report an
819 if The_Project
= Empty_Node
then
820 Error_Msg_Name_1
:= Long_Project
;
821 Error_Msg_Name_2
:= Short_Project
;
822 Error_Msg
("unknown projects % or %",
823 Names
.Table
(1).Location
);
824 The_Package
:= Empty_Node
;
825 First_Attribute
:= Attribute_First
;
828 -- Now, we check if the package has been declared
832 First_Package_Of
(The_Project
, In_Tree
);
833 while The_Package
/= Empty_Node
834 and then Name_Of
(The_Package
, In_Tree
) /=
835 Names
.Table
(Names
.Last
).Name
838 Next_Package_In_Project
(The_Package
, In_Tree
);
841 -- If it has not, then we report an error
843 if The_Package
= Empty_Node
then
845 Names
.Table
(Names
.Last
).Name
;
846 Error_Msg_Name_2
:= Short_Project
;
847 Error_Msg
("package % not declared in project %",
848 Names
.Table
(Names
.Last
).Location
);
849 First_Attribute
:= Attribute_First
;
852 -- Otherwise, we have the correct project and
857 (Package_Id_Of
(The_Package
, In_Tree
));
867 Current_Project
=> The_Project
,
868 Current_Package
=> The_Package
,
869 First_Attribute
=> First_Attribute
);
876 (Of_Kind
=> N_Variable_Reference
, In_Tree
=> In_Tree
);
878 if Look_For_Variable
then
888 -- Simple variable name
890 Set_Name_Of
(Variable
, In_Tree
, To
=> Names
.Table
(1).Name
);
894 -- Variable name with a simple name prefix that can be
895 -- a project name or a package name. Project names have
896 -- priority over package names.
898 Set_Name_Of
(Variable
, In_Tree
, To
=> Names
.Table
(2).Name
);
900 -- Check if it can be a package name
902 The_Package
:= First_Package_Of
(Current_Project
, In_Tree
);
904 while The_Package
/= Empty_Node
905 and then Name_Of
(The_Package
, In_Tree
) /=
909 Next_Package_In_Project
(The_Package
, In_Tree
);
912 -- Now look for a possible project name
914 The_Project
:= Imported_Or_Extended_Project_Of
915 (Current_Project
, In_Tree
, Names
.Table
(1).Name
);
917 if The_Project
/= Empty_Node
then
918 Specified_Project
:= The_Project
;
920 elsif The_Package
= Empty_Node
then
921 Error_Msg_Name_1
:= Names
.Table
(1).Name
;
922 Error_Msg
("unknown package or project %",
923 Names
.Table
(1).Location
);
924 Look_For_Variable
:= False;
927 Specified_Package
:= The_Package
;
932 -- Variable name with a prefix that is either a project name
933 -- made of several simple names, or a project name followed
934 -- by a package name.
937 (Variable
, In_Tree
, To
=> Names
.Table
(Names
.Last
).Name
);
940 Short_Project
: Name_Id
;
941 Long_Project
: Name_Id
;
944 -- First, we get the two possible project names
950 -- Add all the simple names, except the last two
952 for Index
in 1 .. Names
.Last
- 2 loop
954 (Get_Name_String
(Names
.Table
(Index
).Name
),
955 Buffer
, Buffer_Last
);
957 if Index
/= Names
.Last
- 2 then
958 Add_To_Buffer
(".", Buffer
, Buffer_Last
);
962 Name_Len
:= Buffer_Last
;
963 Name_Buffer
(1 .. Name_Len
) := Buffer
(1 .. Buffer_Last
);
964 Short_Project
:= Name_Find
;
966 -- Add the simple name before the name of the variable
968 Add_To_Buffer
(".", Buffer
, Buffer_Last
);
970 (Get_Name_String
(Names
.Table
(Names
.Last
- 1).Name
),
971 Buffer
, Buffer_Last
);
972 Name_Len
:= Buffer_Last
;
973 Name_Buffer
(1 .. Name_Len
) := Buffer
(1 .. Buffer_Last
);
974 Long_Project
:= Name_Find
;
976 -- Check if the prefix is the name of an imported or
979 The_Project
:= Imported_Or_Extended_Project_Of
980 (Current_Project
, In_Tree
, Long_Project
);
982 if The_Project
/= Empty_Node
then
983 Specified_Project
:= The_Project
;
986 -- Now check if the prefix may be a project name followed
987 -- by a package name.
989 -- First check for a possible project name
991 The_Project
:= Imported_Or_Extended_Project_Of
992 (Current_Project
, In_Tree
, Short_Project
);
994 if The_Project
= Empty_Node
then
995 -- Unknown prefix, report an error
997 Error_Msg_Name_1
:= Long_Project
;
998 Error_Msg_Name_2
:= Short_Project
;
999 Error_Msg
("unknown projects % or %",
1000 Names
.Table
(1).Location
);
1001 Look_For_Variable
:= False;
1004 Specified_Project
:= The_Project
;
1006 -- Now look for the package in this project
1008 The_Package
:= First_Package_Of
(The_Project
, In_Tree
);
1010 while The_Package
/= Empty_Node
1011 and then Name_Of
(The_Package
, In_Tree
) /=
1012 Names
.Table
(Names
.Last
- 1).Name
1015 Next_Package_In_Project
(The_Package
, In_Tree
);
1018 if The_Package
= Empty_Node
then
1019 -- The package does not vexist, report an error
1021 Error_Msg_Name_1
:= Names
.Table
(2).Name
;
1022 Error_Msg
("unknown package %",
1023 Names
.Table
(Names
.Last
- 1).Location
);
1024 Look_For_Variable
:= False;
1027 Specified_Package
:= The_Package
;
1035 if Look_For_Variable
then
1036 Variable_Name
:= Name_Of
(Variable
, In_Tree
);
1037 Set_Project_Node_Of
(Variable
, In_Tree
, To
=> Specified_Project
);
1038 Set_Package_Node_Of
(Variable
, In_Tree
, To
=> Specified_Package
);
1040 if Specified_Project
/= Empty_Node
then
1041 The_Project
:= Specified_Project
;
1044 The_Project
:= Current_Project
;
1047 Current_Variable
:= Empty_Node
;
1049 -- Look for this variable
1051 -- If a package was specified, check if the variable has been
1052 -- declared in this package.
1054 if Specified_Package
/= Empty_Node
then
1056 First_Variable_Of
(Specified_Package
, In_Tree
);
1058 while Current_Variable
/= Empty_Node
1060 Name_Of
(Current_Variable
, In_Tree
) /= Variable_Name
1062 Current_Variable
:= Next_Variable
(Current_Variable
, In_Tree
);
1066 -- Otherwise, if no project has been specified and we are in
1067 -- a package, first check if the variable has been declared in
1070 if Specified_Project
= Empty_Node
1071 and then Current_Package
/= Empty_Node
1074 First_Variable_Of
(Current_Package
, In_Tree
);
1076 while Current_Variable
/= Empty_Node
1077 and then Name_Of
(Current_Variable
, In_Tree
) /= Variable_Name
1080 Next_Variable
(Current_Variable
, In_Tree
);
1084 -- If we have not found the variable in the package, check if the
1085 -- variable has been declared in the project.
1087 if Current_Variable
= Empty_Node
then
1088 Current_Variable
:= First_Variable_Of
(The_Project
, In_Tree
);
1090 while Current_Variable
/= Empty_Node
1091 and then Name_Of
(Current_Variable
, In_Tree
) /= Variable_Name
1094 Next_Variable
(Current_Variable
, In_Tree
);
1099 -- If the variable was not found, report an error
1101 if Current_Variable
= Empty_Node
then
1102 Error_Msg_Name_1
:= Variable_Name
;
1104 ("unknown variable %", Names
.Table
(Names
.Last
).Location
);
1108 if Current_Variable
/= Empty_Node
then
1109 Set_Expression_Kind_Of
1111 To
=> Expression_Kind_Of
(Current_Variable
, In_Tree
));
1114 Kind_Of
(Current_Variable
, In_Tree
) = N_Typed_Variable_Declaration
1118 To
=> String_Type_Of
(Current_Variable
, In_Tree
));
1122 -- If the variable is followed by a left parenthesis, report an error
1123 -- but attempt to scan the index.
1125 if Token
= Tok_Left_Paren
then
1126 Error_Msg
("\variables cannot be associative arrays", Token_Ptr
);
1128 Expect
(Tok_String_Literal
, "literal string");
1130 if Token
= Tok_String_Literal
then
1132 Expect
(Tok_Right_Paren
, "`)`");
1134 if Token
= Tok_Right_Paren
then
1139 end Parse_Variable_Reference
;
1141 ---------------------------------
1142 -- Start_New_Case_Construction --
1143 ---------------------------------
1145 procedure Start_New_Case_Construction
1146 (In_Tree
: Project_Node_Tree_Ref
;
1147 String_Type
: Project_Node_Id
)
1149 Current_String
: Project_Node_Id
;
1152 -- Set Choice_First, depending on whether is the first case
1153 -- construction or not.
1155 if Choice_First
= 0 then
1157 Choices
.Set_Last
(First_Choice_Node_Id
);
1159 Choice_First
:= Choices
.Last
+ 1;
1162 -- Add to table Choices the literal of the string type
1164 if String_Type
/= Empty_Node
then
1165 Current_String
:= First_Literal_String
(String_Type
, In_Tree
);
1167 while Current_String
/= Empty_Node
loop
1168 Add
(This_String
=> String_Value_Of
(Current_String
, In_Tree
));
1169 Current_String
:= Next_Literal_String
(Current_String
, In_Tree
);
1173 -- Set the value of the last choice in table Choice_Lasts
1175 Choice_Lasts
.Increment_Last
;
1176 Choice_Lasts
.Table
(Choice_Lasts
.Last
) := Choices
.Last
;
1178 end Start_New_Case_Construction
;
1185 (In_Tree
: Project_Node_Tree_Ref
;
1186 Term
: out Project_Node_Id
;
1187 Expr_Kind
: in out Variable_Kind
;
1188 Current_Project
: Project_Node_Id
;
1189 Current_Package
: Project_Node_Id
;
1190 Optional_Index
: Boolean)
1192 Next_Term
: Project_Node_Id
:= Empty_Node
;
1193 Term_Id
: Project_Node_Id
:= Empty_Node
;
1194 Current_Expression
: Project_Node_Id
:= Empty_Node
;
1195 Next_Expression
: Project_Node_Id
:= Empty_Node
;
1196 Current_Location
: Source_Ptr
:= No_Location
;
1197 Reference
: Project_Node_Id
:= Empty_Node
;
1200 -- Declare a new node for the term
1202 Term
:= Default_Project_Node
(Of_Kind
=> N_Term
, In_Tree
=> In_Tree
);
1203 Set_Location_Of
(Term
, In_Tree
, To
=> Token_Ptr
);
1206 when Tok_Left_Paren
=>
1208 -- If we have a left parenthesis and we don't know the expression
1209 -- kind, then this is a string list.
1220 -- If we already know that this is a single string, report
1221 -- an error, but set the expression kind to string list to
1222 -- avoid several errors.
1226 ("literal string list cannot appear in a string",
1230 -- Declare a new node for this literal string list
1232 Term_Id
:= Default_Project_Node
1233 (Of_Kind
=> N_Literal_String_List
,
1235 And_Expr_Kind
=> List
);
1236 Set_Current_Term
(Term
, In_Tree
, To
=> Term_Id
);
1237 Set_Location_Of
(Term
, In_Tree
, To
=> Token_Ptr
);
1239 -- Scan past the left parenthesis
1243 -- If the left parenthesis is immediately followed by a right
1244 -- parenthesis, the literal string list is empty.
1246 if Token
= Tok_Right_Paren
then
1250 -- Otherwise, we parse the expression(s) in the literal string
1254 Current_Location
:= Token_Ptr
;
1256 (In_Tree
=> In_Tree
,
1257 Expression
=> Next_Expression
,
1258 Current_Project
=> Current_Project
,
1259 Current_Package
=> Current_Package
,
1260 Optional_Index
=> Optional_Index
);
1262 -- The expression kind is String list, report an error
1264 if Expression_Kind_Of
(Next_Expression
, In_Tree
) = List
then
1265 Error_Msg
("single expression expected",
1269 -- If Current_Expression is empty, it means that the
1270 -- expression is the first in the string list.
1272 if Current_Expression
= Empty_Node
then
1273 Set_First_Expression_In_List
1274 (Term_Id
, In_Tree
, To
=> Next_Expression
);
1276 Set_Next_Expression_In_List
1277 (Current_Expression
, In_Tree
, To
=> Next_Expression
);
1280 Current_Expression
:= Next_Expression
;
1282 -- If there is a comma, continue with the next expression
1284 exit when Token
/= Tok_Comma
;
1285 Scan
(In_Tree
); -- past the comma
1288 -- We expect a closing right parenthesis
1290 Expect
(Tok_Right_Paren
, "`)`");
1292 if Token
= Tok_Right_Paren
then
1297 when Tok_String_Literal
=>
1299 -- If we don't know the expression kind (first term), then it is
1302 if Expr_Kind
= Undefined
then
1303 Expr_Kind
:= Single
;
1306 -- Declare a new node for the string literal
1309 Default_Project_Node
1310 (Of_Kind
=> N_Literal_String
, In_Tree
=> In_Tree
);
1311 Set_Current_Term
(Term
, In_Tree
, To
=> Term_Id
);
1312 Set_String_Value_Of
(Term_Id
, In_Tree
, To
=> Token_Name
);
1314 -- Scan past the string literal
1318 -- Check for possible index expression
1320 if Token
= Tok_At
then
1321 if not Optional_Index
then
1322 Error_Msg
("index not allowed here", Token_Ptr
);
1325 if Token
= Tok_Integer_Literal
then
1329 -- Set the index value
1333 Expect
(Tok_Integer_Literal
, "integer literal");
1335 if Token
= Tok_Integer_Literal
then
1337 Index
: constant Int
:= UI_To_Int
(Int_Literal_Value
);
1340 Error_Msg
("index cannot be zero", Token_Ptr
);
1343 (Term_Id
, In_Tree
, To
=> Index
);
1352 when Tok_Identifier
=>
1353 Current_Location
:= Token_Ptr
;
1355 -- Get the variable or attribute reference
1357 Parse_Variable_Reference
1358 (In_Tree
=> In_Tree
,
1359 Variable
=> Reference
,
1360 Current_Project
=> Current_Project
,
1361 Current_Package
=> Current_Package
);
1362 Set_Current_Term
(Term
, In_Tree
, To
=> Reference
);
1364 if Reference
/= Empty_Node
then
1366 -- If we don't know the expression kind (first term), then it
1367 -- has the kind of the variable or attribute reference.
1369 if Expr_Kind
= Undefined
then
1370 Expr_Kind
:= Expression_Kind_Of
(Reference
, In_Tree
);
1372 elsif Expr_Kind
= Single
1373 and then Expression_Kind_Of
(Reference
, In_Tree
) = List
1375 -- If the expression is a single list, and the reference is
1376 -- a string list, report an error, and set the expression
1377 -- kind to string list to avoid multiple errors.
1381 ("list variable cannot appear in single string expression",
1388 -- project can appear in an expression as the prefix of an
1389 -- attribute reference of the current project.
1391 Current_Location
:= Token_Ptr
;
1393 Expect
(Tok_Apostrophe
, "`'`");
1395 if Token
= Tok_Apostrophe
then
1397 (In_Tree
=> In_Tree
,
1398 Reference
=> Reference
,
1399 First_Attribute
=> Prj
.Attr
.Attribute_First
,
1400 Current_Project
=> Current_Project
,
1401 Current_Package
=> Empty_Node
);
1402 Set_Current_Term
(Term
, In_Tree
, To
=> Reference
);
1405 -- Same checks as above for the expression kind
1407 if Reference
/= Empty_Node
then
1408 if Expr_Kind
= Undefined
then
1409 Expr_Kind
:= Expression_Kind_Of
(Reference
, In_Tree
);
1411 elsif Expr_Kind
= Single
1412 and then Expression_Kind_Of
(Reference
, In_Tree
) = List
1415 ("lists cannot appear in single string expression",
1420 when Tok_External
=>
1421 -- An external reference is always a single string
1423 if Expr_Kind
= Undefined
then
1424 Expr_Kind
:= Single
;
1428 (In_Tree
=> In_Tree
,
1429 Current_Project
=> Current_Project
,
1430 Current_Package
=> Current_Package
,
1431 External_Value
=> Reference
);
1432 Set_Current_Term
(Term
, In_Tree
, To
=> Reference
);
1435 Error_Msg
("cannot be part of an expression", Token_Ptr
);
1440 -- If there is an '&', call Terms recursively
1442 if Token
= Tok_Ampersand
then
1444 -- Scan past the '&'
1449 (In_Tree
=> In_Tree
,
1451 Expr_Kind
=> Expr_Kind
,
1452 Current_Project
=> Current_Project
,
1453 Current_Package
=> Current_Package
,
1454 Optional_Index
=> Optional_Index
);
1456 -- And link the next term to this term
1458 Set_Next_Term
(Term
, In_Tree
, To
=> Next_Term
);