1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2001-2007, 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 Prj.Attr; use Prj.Attr;
29 with Prj.Err; use Prj.Err;
32 with Uintp; use Uintp;
34 package body Prj.Strt is
36 Buffer : String_Access;
37 Buffer_Last : Natural := 0;
39 type Choice_String is record
41 Already_Used : Boolean := False;
43 -- The string of a case label, and an indication that it has already
44 -- been used (to avoid duplicate case labels).
46 Choices_Initial : constant := 10;
47 Choices_Increment : constant := 100;
48 -- These should be in alloc.ads
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;
62 (Table_Component_Type => Choice_String,
63 Table_Index_Type => Choice_Node_Id'Base,
64 Table_Low_Bound => First_Choice_Node_Id,
65 Table_Initial => Choices_Initial,
66 Table_Increment => Choices_Increment,
67 Table_Name => "Prj.Strt.Choices");
68 -- Used to store the case labels and check that there is no duplicate
70 package Choice_Lasts is
72 (Table_Component_Type => Choice_Node_Id,
73 Table_Index_Type => Nat,
76 Table_Increment => 100,
77 Table_Name => "Prj.Strt.Choice_Lasts");
78 -- Used to store the indices of the choices in table Choices,
79 -- to distinguish nested case constructions.
81 Choice_First : Choice_Node_Id := 0;
82 -- Index in table Choices of the first case label of the current
83 -- case construction. Zero means no current case construction.
85 type Name_Location is record
86 Name : Name_Id := No_Name;
87 Location : Source_Ptr := No_Location;
89 -- Store the identifier and the location of a simple name
93 (Table_Component_Type => Name_Location,
94 Table_Index_Type => Nat,
97 Table_Increment => 100,
98 Table_Name => "Prj.Strt.Names");
99 -- Used to accumulate the single names of a name
101 procedure Add (This_String : Name_Id);
102 -- Add a string to the case label list, indicating that it has not
105 procedure Add_To_Names (NL : Name_Location);
106 -- Add one single names to table Names
108 procedure External_Reference
109 (In_Tree : Project_Node_Tree_Ref;
110 Current_Project : Project_Node_Id;
111 Current_Package : Project_Node_Id;
112 External_Value : out Project_Node_Id);
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 -- Parse an attribute reference. Current token is an apostrophe
124 (In_Tree : Project_Node_Tree_Ref;
125 Term : out Project_Node_Id;
126 Expr_Kind : in out Variable_Kind;
127 Current_Project : Project_Node_Id;
128 Current_Package : Project_Node_Id;
129 Optional_Index : Boolean);
130 -- Recursive procedure to parse one term or several terms concatenated
137 procedure Add (This_String : Name_Id) is
139 Choices.Increment_Last;
140 Choices.Table (Choices.Last) :=
141 (The_String => This_String,
142 Already_Used => False);
149 procedure Add_To_Names (NL : Name_Location) is
151 Names.Increment_Last;
152 Names.Table (Names.Last) := NL;
155 -------------------------
156 -- Attribute_Reference --
157 -------------------------
159 procedure Attribute_Reference
160 (In_Tree : Project_Node_Tree_Ref;
161 Reference : out Project_Node_Id;
162 First_Attribute : Attribute_Node_Id;
163 Current_Project : Project_Node_Id;
164 Current_Package : Project_Node_Id)
166 Current_Attribute : Attribute_Node_Id := First_Attribute;
169 -- Declare the node of the attribute reference
173 (Of_Kind => N_Attribute_Reference, In_Tree => In_Tree);
174 Set_Location_Of (Reference, In_Tree, To => Token_Ptr);
175 Scan (In_Tree); -- past apostrophe
177 -- Body may be an attribute name
179 if Token = Tok_Body then
180 Token := Tok_Identifier;
181 Token_Name := Snames.Name_Body;
184 Expect (Tok_Identifier, "identifier");
186 if Token = Tok_Identifier then
187 Set_Name_Of (Reference, In_Tree, To => Token_Name);
189 -- Check if the identifier is one of the attribute identifiers in the
190 -- context (package or project level attributes).
193 Attribute_Node_Id_Of (Token_Name, Starting_At => First_Attribute);
195 -- If the identifier is not allowed, report an error
197 if Current_Attribute = Empty_Attribute then
198 Error_Msg_Name_1 := Token_Name;
199 Error_Msg ("unknown attribute %%", Token_Ptr);
200 Reference := Empty_Node;
202 -- Scan past the attribute name
207 -- Give its characteristics to this attribute reference
209 Set_Project_Node_Of (Reference, In_Tree, To => Current_Project);
210 Set_Package_Node_Of (Reference, In_Tree, To => Current_Package);
211 Set_Expression_Kind_Of
212 (Reference, In_Tree, To => Variable_Kind_Of (Current_Attribute));
215 To => Attribute_Kind_Of (Current_Attribute) in
216 Case_Insensitive_Associative_Array ..
217 Optional_Index_Case_Insensitive_Associative_Array);
219 -- Scan past the attribute name
223 -- If the attribute is an associative array, get the index
225 if Attribute_Kind_Of (Current_Attribute) /= Single then
226 Expect (Tok_Left_Paren, "`(`");
228 if Token = Tok_Left_Paren then
230 Expect (Tok_String_Literal, "literal string");
232 if Token = Tok_String_Literal then
233 Set_Associative_Array_Index_Of
234 (Reference, In_Tree, To => Token_Name);
236 Expect (Tok_Right_Paren, "`)`");
238 if Token = Tok_Right_Paren then
246 -- Change name of obsolete attributes
248 if Reference /= Empty_Node then
249 case Name_Of (Reference, In_Tree) is
250 when Snames.Name_Specification =>
251 Set_Name_Of (Reference, In_Tree, To => Snames.Name_Spec);
253 when Snames.Name_Specification_Suffix =>
255 (Reference, In_Tree, To => Snames.Name_Spec_Suffix);
257 when Snames.Name_Implementation =>
258 Set_Name_Of (Reference, In_Tree, To => Snames.Name_Body);
260 when Snames.Name_Implementation_Suffix =>
262 (Reference, In_Tree, To => Snames.Name_Body_Suffix);
269 end Attribute_Reference;
271 ---------------------------
272 -- End_Case_Construction --
273 ---------------------------
275 procedure End_Case_Construction
276 (Check_All_Labels : Boolean;
277 Case_Location : Source_Ptr)
279 Non_Used : Natural := 0;
280 First_Non_Used : Choice_Node_Id := First_Choice_Node_Id;
282 -- First, if Check_All_Labels is True, check if all values
283 -- of the string type have been used.
285 if Check_All_Labels then
286 for Choice in Choice_First .. Choices.Last loop
287 if not Choices.Table (Choice).Already_Used then
288 Non_Used := Non_Used + 1;
291 First_Non_Used := Choice;
296 -- If only one is not used, report a single warning for this value
299 Error_Msg_Name_1 := Choices.Table (First_Non_Used).The_String;
300 Error_Msg ("?value %% is not used as label", Case_Location);
302 -- If several are not used, report a warning for each one of them
304 elsif Non_Used > 1 then
306 ("?the following values are not used as labels:",
309 for Choice in First_Non_Used .. Choices.Last loop
310 if not Choices.Table (Choice).Already_Used then
311 Error_Msg_Name_1 := Choices.Table (Choice).The_String;
312 Error_Msg ("\?%%", Case_Location);
318 -- If this is the only case construction, empty the tables
320 if Choice_Lasts.Last = 1 then
321 Choice_Lasts.Set_Last (0);
322 Choices.Set_Last (First_Choice_Node_Id);
325 elsif Choice_Lasts.Last = 2 then
327 -- This is the second case construction, set the tables to the first
329 Choice_Lasts.Set_Last (1);
330 Choices.Set_Last (Choice_Lasts.Table (1));
334 -- This is the 3rd or more case construction, set the tables to the
337 Choice_Lasts.Decrement_Last;
338 Choices.Set_Last (Choice_Lasts.Table (Choice_Lasts.Last));
339 Choice_First := Choice_Lasts.Table (Choice_Lasts.Last - 1) + 1;
341 end End_Case_Construction;
343 ------------------------
344 -- External_Reference --
345 ------------------------
347 procedure External_Reference
348 (In_Tree : Project_Node_Tree_Ref;
349 Current_Project : Project_Node_Id;
350 Current_Package : Project_Node_Id;
351 External_Value : out Project_Node_Id)
353 Field_Id : Project_Node_Id := Empty_Node;
358 (Of_Kind => N_External_Value,
360 And_Expr_Kind => Single);
361 Set_Location_Of (External_Value, In_Tree, To => Token_Ptr);
363 -- The current token is External
365 -- Get the left parenthesis
368 Expect (Tok_Left_Paren, "`(`");
370 -- Scan past the left parenthesis
372 if Token = Tok_Left_Paren then
376 -- Get the name of the external reference
378 Expect (Tok_String_Literal, "literal string");
380 if Token = Tok_String_Literal then
383 (Of_Kind => N_Literal_String,
385 And_Expr_Kind => Single);
386 Set_String_Value_Of (Field_Id, In_Tree, To => Token_Name);
387 Set_External_Reference_Of (External_Value, In_Tree, To => Field_Id);
389 -- Scan past the first argument
395 when Tok_Right_Paren =>
396 Scan (In_Tree); -- scan past right paren
399 Scan (In_Tree); -- scan past 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 if Token = Tok_Right_Paren then
425 Scan (In_Tree); -- scan past right paren
429 Error_Msg ("`,` or `)` expected", Token_Ptr);
432 end External_Reference;
434 -----------------------
435 -- Parse_Choice_List --
436 -----------------------
438 procedure Parse_Choice_List
439 (In_Tree : Project_Node_Tree_Ref;
440 First_Choice : out Project_Node_Id)
442 Current_Choice : Project_Node_Id := Empty_Node;
443 Next_Choice : Project_Node_Id := Empty_Node;
444 Choice_String : Name_Id := No_Name;
445 Found : Boolean := False;
448 -- Declare the node of the first choice
452 (Of_Kind => N_Literal_String,
454 And_Expr_Kind => Single);
456 -- Initially Current_Choice is the same as First_Choice
458 Current_Choice := First_Choice;
461 Expect (Tok_String_Literal, "literal string");
462 exit when Token /= Tok_String_Literal;
463 Set_Location_Of (Current_Choice, In_Tree, To => Token_Ptr);
464 Choice_String := Token_Name;
466 -- Give the string value to the current choice
468 Set_String_Value_Of (Current_Choice, In_Tree, To => Choice_String);
470 -- Check if the label is part of the string type and if it has not
471 -- been already used.
474 for Choice in Choice_First .. Choices.Last loop
475 if Choices.Table (Choice).The_String = Choice_String then
477 -- This label is part of the string type
481 if Choices.Table (Choice).Already_Used then
483 -- But it has already appeared in a choice list for this
484 -- case construction so report an error.
486 Error_Msg_Name_1 := Choice_String;
487 Error_Msg ("duplicate case label %%", Token_Ptr);
490 Choices.Table (Choice).Already_Used := True;
497 -- If the label is not part of the string list, report an error
500 Error_Msg_Name_1 := Choice_String;
501 Error_Msg ("illegal case label %%", Token_Ptr);
504 -- Scan past the label
508 -- If there is no '|', we are done
510 if Token = Tok_Vertical_Bar then
512 -- Otherwise, declare the node of the next choice, link it to
513 -- Current_Choice and set Current_Choice to this new node.
517 (Of_Kind => N_Literal_String,
519 And_Expr_Kind => Single);
520 Set_Next_Literal_String
521 (Current_Choice, In_Tree, To => Next_Choice);
522 Current_Choice := Next_Choice;
528 end Parse_Choice_List;
530 ----------------------
531 -- Parse_Expression --
532 ----------------------
534 procedure Parse_Expression
535 (In_Tree : Project_Node_Tree_Ref;
536 Expression : out Project_Node_Id;
537 Current_Project : Project_Node_Id;
538 Current_Package : Project_Node_Id;
539 Optional_Index : Boolean)
541 First_Term : Project_Node_Id := Empty_Node;
542 Expression_Kind : Variable_Kind := Undefined;
545 -- Declare the node of the expression
548 Default_Project_Node (Of_Kind => N_Expression, In_Tree => In_Tree);
549 Set_Location_Of (Expression, In_Tree, To => Token_Ptr);
551 -- Parse the term or terms of the expression
553 Terms (In_Tree => In_Tree,
555 Expr_Kind => Expression_Kind,
556 Current_Project => Current_Project,
557 Current_Package => Current_Package,
558 Optional_Index => Optional_Index);
560 -- Set the first term and the expression kind
562 Set_First_Term (Expression, In_Tree, To => First_Term);
563 Set_Expression_Kind_Of (Expression, In_Tree, To => Expression_Kind);
564 end Parse_Expression;
566 ----------------------------
567 -- Parse_String_Type_List --
568 ----------------------------
570 procedure Parse_String_Type_List
571 (In_Tree : Project_Node_Tree_Ref;
572 First_String : out Project_Node_Id)
574 Last_String : Project_Node_Id := Empty_Node;
575 Next_String : Project_Node_Id := Empty_Node;
576 String_Value : Name_Id := No_Name;
579 -- Declare the node of the first string
583 (Of_Kind => N_Literal_String,
585 And_Expr_Kind => Single);
587 -- Initially, Last_String is the same as First_String
589 Last_String := First_String;
592 Expect (Tok_String_Literal, "literal string");
593 exit when Token /= Tok_String_Literal;
594 String_Value := Token_Name;
596 -- Give its string value to Last_String
598 Set_String_Value_Of (Last_String, In_Tree, To => String_Value);
599 Set_Location_Of (Last_String, In_Tree, To => Token_Ptr);
601 -- Now, check if the string is already part of the string type
604 Current : Project_Node_Id := First_String;
607 while Current /= Last_String loop
608 if String_Value_Of (Current, In_Tree) = String_Value then
610 -- This is a repetition, report an error
612 Error_Msg_Name_1 := String_Value;
613 Error_Msg ("duplicate value %% in type", Token_Ptr);
617 Current := Next_Literal_String (Current, In_Tree);
621 -- Scan past the literal string
625 -- If there is no comma following the literal string, we are done
627 if Token /= Tok_Comma then
631 -- Declare the next string, link it to Last_String and set
632 -- Last_String to its node.
636 (Of_Kind => N_Literal_String,
638 And_Expr_Kind => Single);
639 Set_Next_Literal_String (Last_String, In_Tree, To => Next_String);
640 Last_String := Next_String;
644 end Parse_String_Type_List;
646 ------------------------------
647 -- Parse_Variable_Reference --
648 ------------------------------
650 procedure Parse_Variable_Reference
651 (In_Tree : Project_Node_Tree_Ref;
652 Variable : out Project_Node_Id;
653 Current_Project : Project_Node_Id;
654 Current_Package : Project_Node_Id)
656 Current_Variable : Project_Node_Id := Empty_Node;
658 The_Package : Project_Node_Id := Current_Package;
659 The_Project : Project_Node_Id := Current_Project;
661 Specified_Project : Project_Node_Id := Empty_Node;
662 Specified_Package : Project_Node_Id := Empty_Node;
663 Look_For_Variable : Boolean := True;
664 First_Attribute : Attribute_Node_Id := Empty_Attribute;
665 Variable_Name : Name_Id;
671 Expect (Tok_Identifier, "identifier");
673 if Token /= Tok_Identifier then
674 Look_For_Variable := False;
678 Add_To_Names (NL => (Name => Token_Name, Location => Token_Ptr));
680 exit when Token /= Tok_Dot;
684 if Look_For_Variable then
686 if Token = Tok_Apostrophe then
688 -- Attribute reference
698 -- This may be a project name or a package name.
699 -- Project name have precedence.
701 -- First, look if it can be a package name
705 (Package_Node_Id_Of (Names.Table (1).Name));
707 -- Now, look if it can be a project name
709 if Names.Table (1).Name =
710 Name_Of (Current_Project, In_Tree)
712 The_Project := Current_Project;
716 Imported_Or_Extended_Project_Of
717 (Current_Project, In_Tree, Names.Table (1).Name);
720 if The_Project = Empty_Node then
722 -- If it is neither a project name nor a package name,
725 if First_Attribute = Empty_Attribute then
726 Error_Msg_Name_1 := Names.Table (1).Name;
727 Error_Msg ("unknown project %",
728 Names.Table (1).Location);
729 First_Attribute := Attribute_First;
732 -- If it is a package name, check if the package has
733 -- already been declared in the current project.
736 First_Package_Of (Current_Project, In_Tree);
738 while The_Package /= Empty_Node
739 and then Name_Of (The_Package, In_Tree) /=
743 Next_Package_In_Project (The_Package, In_Tree);
746 -- If it has not been already declared, report an
749 if The_Package = Empty_Node then
750 Error_Msg_Name_1 := Names.Table (1).Name;
751 Error_Msg ("package % not yet defined",
752 Names.Table (1).Location);
757 -- It is a project name
759 First_Attribute := Attribute_First;
760 The_Package := Empty_Node;
765 -- We have either a project name made of several simple
766 -- names (long project), or a project name (short project)
767 -- followed by a package name. The long project name has
771 Short_Project : Name_Id;
772 Long_Project : Name_Id;
779 -- Get the name of the short project
781 for Index in 1 .. Names.Last - 1 loop
783 (Get_Name_String (Names.Table (Index).Name),
784 Buffer, Buffer_Last);
786 if Index /= Names.Last - 1 then
787 Add_To_Buffer (".", Buffer, Buffer_Last);
791 Name_Len := Buffer_Last;
792 Name_Buffer (1 .. Buffer_Last) :=
793 Buffer (1 .. Buffer_Last);
794 Short_Project := Name_Find;
796 -- Now, add the last simple name to get the name of the
799 Add_To_Buffer (".", Buffer, Buffer_Last);
801 (Get_Name_String (Names.Table (Names.Last).Name),
802 Buffer, Buffer_Last);
803 Name_Len := Buffer_Last;
804 Name_Buffer (1 .. Buffer_Last) :=
805 Buffer (1 .. Buffer_Last);
806 Long_Project := Name_Find;
808 -- Check if the long project is imported or extended
810 if Long_Project = Name_Of (Current_Project, In_Tree) then
811 The_Project := Current_Project;
815 Imported_Or_Extended_Project_Of
821 -- If the long project exists, then this is the prefix
824 if The_Project /= Empty_Node then
825 First_Attribute := Attribute_First;
826 The_Package := Empty_Node;
829 -- Otherwise, check if the short project is imported
833 Name_Of (Current_Project, In_Tree)
835 The_Project := Current_Project;
838 The_Project := Imported_Or_Extended_Project_Of
839 (Current_Project, In_Tree,
843 -- If short project does not exist, report an error
845 if The_Project = Empty_Node then
846 Error_Msg_Name_1 := Long_Project;
847 Error_Msg_Name_2 := Short_Project;
848 Error_Msg ("unknown projects % or %",
849 Names.Table (1).Location);
850 The_Package := Empty_Node;
851 First_Attribute := Attribute_First;
854 -- Now, we check if the package has been declared
858 First_Package_Of (The_Project, In_Tree);
859 while The_Package /= Empty_Node
860 and then Name_Of (The_Package, In_Tree) /=
861 Names.Table (Names.Last).Name
864 Next_Package_In_Project (The_Package, In_Tree);
867 -- If it has not, then we report an error
869 if The_Package = Empty_Node then
871 Names.Table (Names.Last).Name;
872 Error_Msg_Name_2 := Short_Project;
873 Error_Msg ("package % not declared in project %",
874 Names.Table (Names.Last).Location);
875 First_Attribute := Attribute_First;
878 -- Otherwise, we have the correct project and
883 (Package_Id_Of (The_Package, In_Tree));
893 Current_Project => The_Project,
894 Current_Package => The_Package,
895 First_Attribute => First_Attribute);
902 (Of_Kind => N_Variable_Reference, In_Tree => In_Tree);
904 if Look_For_Variable then
908 -- Cannot happen (so why null instead of raise PE???)
914 -- Simple variable name
916 Set_Name_Of (Variable, In_Tree, To => Names.Table (1).Name);
920 -- Variable name with a simple name prefix that can be
921 -- a project name or a package name. Project names have
922 -- priority over package names.
924 Set_Name_Of (Variable, In_Tree, To => Names.Table (2).Name);
926 -- Check if it can be a package name
928 The_Package := First_Package_Of (Current_Project, In_Tree);
930 while The_Package /= Empty_Node
931 and then Name_Of (The_Package, In_Tree) /=
935 Next_Package_In_Project (The_Package, In_Tree);
938 -- Now look for a possible project name
940 The_Project := Imported_Or_Extended_Project_Of
941 (Current_Project, In_Tree, Names.Table (1).Name);
943 if The_Project /= Empty_Node then
944 Specified_Project := The_Project;
946 elsif The_Package = Empty_Node then
947 Error_Msg_Name_1 := Names.Table (1).Name;
948 Error_Msg ("unknown package or project %",
949 Names.Table (1).Location);
950 Look_For_Variable := False;
953 Specified_Package := The_Package;
958 -- Variable name with a prefix that is either a project name
959 -- made of several simple names, or a project name followed
960 -- by a package name.
963 (Variable, In_Tree, To => Names.Table (Names.Last).Name);
966 Short_Project : Name_Id;
967 Long_Project : Name_Id;
970 -- First, we get the two possible project names
976 -- Add all the simple names, except the last two
978 for Index in 1 .. Names.Last - 2 loop
980 (Get_Name_String (Names.Table (Index).Name),
981 Buffer, Buffer_Last);
983 if Index /= Names.Last - 2 then
984 Add_To_Buffer (".", Buffer, Buffer_Last);
988 Name_Len := Buffer_Last;
989 Name_Buffer (1 .. Name_Len) := Buffer (1 .. Buffer_Last);
990 Short_Project := Name_Find;
992 -- Add the simple name before the name of the variable
994 Add_To_Buffer (".", Buffer, Buffer_Last);
996 (Get_Name_String (Names.Table (Names.Last - 1).Name),
997 Buffer, Buffer_Last);
998 Name_Len := Buffer_Last;
999 Name_Buffer (1 .. Name_Len) := Buffer (1 .. Buffer_Last);
1000 Long_Project := Name_Find;
1002 -- Check if the prefix is the name of an imported or
1003 -- extended project.
1005 The_Project := Imported_Or_Extended_Project_Of
1006 (Current_Project, In_Tree, Long_Project);
1008 if The_Project /= Empty_Node then
1009 Specified_Project := The_Project;
1012 -- Now check if the prefix may be a project name followed
1013 -- by a package name.
1015 -- First check for a possible project name
1018 Imported_Or_Extended_Project_Of
1019 (Current_Project, In_Tree, Short_Project);
1021 if The_Project = Empty_Node then
1022 -- Unknown prefix, report an error
1024 Error_Msg_Name_1 := Long_Project;
1025 Error_Msg_Name_2 := Short_Project;
1027 ("unknown projects % or %",
1028 Names.Table (1).Location);
1029 Look_For_Variable := False;
1032 Specified_Project := The_Project;
1034 -- Now look for the package in this project
1036 The_Package := First_Package_Of (The_Project, In_Tree);
1038 while The_Package /= Empty_Node
1039 and then Name_Of (The_Package, In_Tree) /=
1040 Names.Table (Names.Last - 1).Name
1043 Next_Package_In_Project (The_Package, In_Tree);
1046 if The_Package = Empty_Node then
1048 -- The package does not exist, report an error
1050 Error_Msg_Name_1 := Names.Table (2).Name;
1051 Error_Msg ("unknown package %",
1052 Names.Table (Names.Last - 1).Location);
1053 Look_For_Variable := False;
1056 Specified_Package := The_Package;
1064 if Look_For_Variable then
1065 Variable_Name := Name_Of (Variable, In_Tree);
1066 Set_Project_Node_Of (Variable, In_Tree, To => Specified_Project);
1067 Set_Package_Node_Of (Variable, In_Tree, To => Specified_Package);
1069 if Specified_Project /= Empty_Node then
1070 The_Project := Specified_Project;
1072 The_Project := Current_Project;
1075 Current_Variable := Empty_Node;
1077 -- Look for this variable
1079 -- If a package was specified, check if the variable has been
1080 -- declared in this package.
1082 if Specified_Package /= Empty_Node then
1084 First_Variable_Of (Specified_Package, In_Tree);
1085 while Current_Variable /= Empty_Node
1087 Name_Of (Current_Variable, In_Tree) /= Variable_Name
1089 Current_Variable := Next_Variable (Current_Variable, In_Tree);
1093 -- Otherwise, if no project has been specified and we are in
1094 -- a package, first check if the variable has been declared in
1097 if Specified_Project = Empty_Node
1098 and then Current_Package /= Empty_Node
1101 First_Variable_Of (Current_Package, In_Tree);
1102 while Current_Variable /= Empty_Node
1103 and then Name_Of (Current_Variable, In_Tree) /= Variable_Name
1106 Next_Variable (Current_Variable, In_Tree);
1110 -- If we have not found the variable in the package, check if the
1111 -- variable has been declared in the project.
1113 if Current_Variable = Empty_Node then
1114 Current_Variable := First_Variable_Of (The_Project, In_Tree);
1115 while Current_Variable /= Empty_Node
1116 and then Name_Of (Current_Variable, In_Tree) /= Variable_Name
1119 Next_Variable (Current_Variable, In_Tree);
1124 -- If the variable was not found, report an error
1126 if Current_Variable = Empty_Node then
1127 Error_Msg_Name_1 := Variable_Name;
1129 ("unknown variable %", Names.Table (Names.Last).Location);
1133 if Current_Variable /= Empty_Node then
1134 Set_Expression_Kind_Of
1136 To => Expression_Kind_Of (Current_Variable, In_Tree));
1138 if Kind_Of (Current_Variable, In_Tree) =
1139 N_Typed_Variable_Declaration
1143 To => String_Type_Of (Current_Variable, In_Tree));
1147 -- If the variable is followed by a left parenthesis, report an error
1148 -- but attempt to scan the index.
1150 if Token = Tok_Left_Paren then
1151 Error_Msg ("\variables cannot be associative arrays", Token_Ptr);
1153 Expect (Tok_String_Literal, "literal string");
1155 if Token = Tok_String_Literal then
1157 Expect (Tok_Right_Paren, "`)`");
1159 if Token = Tok_Right_Paren then
1164 end Parse_Variable_Reference;
1166 ---------------------------------
1167 -- Start_New_Case_Construction --
1168 ---------------------------------
1170 procedure Start_New_Case_Construction
1171 (In_Tree : Project_Node_Tree_Ref;
1172 String_Type : Project_Node_Id)
1174 Current_String : Project_Node_Id;
1177 -- Set Choice_First, depending on whether this is the first case
1178 -- construction or not.
1180 if Choice_First = 0 then
1182 Choices.Set_Last (First_Choice_Node_Id);
1184 Choice_First := Choices.Last + 1;
1187 -- Add the literal of the string type to the Choices table
1189 if String_Type /= Empty_Node then
1190 Current_String := First_Literal_String (String_Type, In_Tree);
1191 while Current_String /= Empty_Node loop
1192 Add (This_String => String_Value_Of (Current_String, In_Tree));
1193 Current_String := Next_Literal_String (Current_String, In_Tree);
1197 -- Set the value of the last choice in table Choice_Lasts
1199 Choice_Lasts.Increment_Last;
1200 Choice_Lasts.Table (Choice_Lasts.Last) := Choices.Last;
1201 end Start_New_Case_Construction;
1208 (In_Tree : Project_Node_Tree_Ref;
1209 Term : out Project_Node_Id;
1210 Expr_Kind : in out Variable_Kind;
1211 Current_Project : Project_Node_Id;
1212 Current_Package : Project_Node_Id;
1213 Optional_Index : Boolean)
1215 Next_Term : Project_Node_Id := Empty_Node;
1216 Term_Id : Project_Node_Id := Empty_Node;
1217 Current_Expression : Project_Node_Id := Empty_Node;
1218 Next_Expression : Project_Node_Id := Empty_Node;
1219 Current_Location : Source_Ptr := No_Location;
1220 Reference : Project_Node_Id := Empty_Node;
1223 -- Declare a new node for the term
1225 Term := Default_Project_Node (Of_Kind => N_Term, In_Tree => In_Tree);
1226 Set_Location_Of (Term, In_Tree, To => Token_Ptr);
1229 when Tok_Left_Paren =>
1231 -- If we have a left parenthesis and we don't know the expression
1232 -- kind, then this is a string list.
1243 -- If we already know that this is a single string, report
1244 -- an error, but set the expression kind to string list to
1245 -- avoid several errors.
1249 ("literal string list cannot appear in a string",
1253 -- Declare a new node for this literal string list
1255 Term_Id := Default_Project_Node
1256 (Of_Kind => N_Literal_String_List,
1258 And_Expr_Kind => List);
1259 Set_Current_Term (Term, In_Tree, To => Term_Id);
1260 Set_Location_Of (Term, In_Tree, To => Token_Ptr);
1262 -- Scan past the left parenthesis
1266 -- If the left parenthesis is immediately followed by a right
1267 -- parenthesis, the literal string list is empty.
1269 if Token = Tok_Right_Paren then
1273 -- Otherwise parse the expression(s) in the literal string list
1276 Current_Location := Token_Ptr;
1278 (In_Tree => In_Tree,
1279 Expression => Next_Expression,
1280 Current_Project => Current_Project,
1281 Current_Package => Current_Package,
1282 Optional_Index => Optional_Index);
1284 -- The expression kind is String list, report an error
1286 if Expression_Kind_Of (Next_Expression, In_Tree) = List then
1287 Error_Msg ("single expression expected",
1291 -- If Current_Expression is empty, it means that the
1292 -- expression is the first in the string list.
1294 if Current_Expression = Empty_Node then
1295 Set_First_Expression_In_List
1296 (Term_Id, In_Tree, To => Next_Expression);
1298 Set_Next_Expression_In_List
1299 (Current_Expression, In_Tree, To => Next_Expression);
1302 Current_Expression := Next_Expression;
1304 -- If there is a comma, continue with the next expression
1306 exit when Token /= Tok_Comma;
1307 Scan (In_Tree); -- past the comma
1310 -- We expect a closing right parenthesis
1312 Expect (Tok_Right_Paren, "`)`");
1314 if Token = Tok_Right_Paren then
1319 when Tok_String_Literal =>
1321 -- If we don't know the expression kind (first term), then it is
1324 if Expr_Kind = Undefined then
1325 Expr_Kind := Single;
1328 -- Declare a new node for the string literal
1331 Default_Project_Node
1332 (Of_Kind => N_Literal_String, In_Tree => In_Tree);
1333 Set_Current_Term (Term, In_Tree, To => Term_Id);
1334 Set_String_Value_Of (Term_Id, In_Tree, To => Token_Name);
1336 -- Scan past the string literal
1340 -- Check for possible index expression
1342 if Token = Tok_At then
1343 if not Optional_Index then
1344 Error_Msg ("index not allowed here", Token_Ptr);
1347 if Token = Tok_Integer_Literal then
1351 -- Set the index value
1355 Expect (Tok_Integer_Literal, "integer literal");
1357 if Token = Tok_Integer_Literal then
1359 Index : constant Int := UI_To_Int (Int_Literal_Value);
1362 Error_Msg ("index cannot be zero", Token_Ptr);
1365 (Term_Id, In_Tree, To => Index);
1374 when Tok_Identifier =>
1375 Current_Location := Token_Ptr;
1377 -- Get the variable or attribute reference
1379 Parse_Variable_Reference
1380 (In_Tree => In_Tree,
1381 Variable => Reference,
1382 Current_Project => Current_Project,
1383 Current_Package => Current_Package);
1384 Set_Current_Term (Term, In_Tree, To => Reference);
1386 if Reference /= Empty_Node then
1388 -- If we don't know the expression kind (first term), then it
1389 -- has the kind of the variable or attribute reference.
1391 if Expr_Kind = Undefined then
1392 Expr_Kind := Expression_Kind_Of (Reference, In_Tree);
1394 elsif Expr_Kind = Single
1395 and then Expression_Kind_Of (Reference, In_Tree) = List
1397 -- If the expression is a single list, and the reference is
1398 -- a string list, report an error, and set the expression
1399 -- kind to string list to avoid multiple errors.
1403 ("list variable cannot appear in single string expression",
1410 -- Project can appear in an expression as the prefix of an
1411 -- attribute reference of the current project.
1413 Current_Location := Token_Ptr;
1415 Expect (Tok_Apostrophe, "`'`");
1417 if Token = Tok_Apostrophe then
1419 (In_Tree => In_Tree,
1420 Reference => Reference,
1421 First_Attribute => Prj.Attr.Attribute_First,
1422 Current_Project => Current_Project,
1423 Current_Package => Empty_Node);
1424 Set_Current_Term (Term, In_Tree, To => Reference);
1427 -- Same checks as above for the expression kind
1429 if Reference /= Empty_Node then
1430 if Expr_Kind = Undefined then
1431 Expr_Kind := Expression_Kind_Of (Reference, In_Tree);
1433 elsif Expr_Kind = Single
1434 and then Expression_Kind_Of (Reference, In_Tree) = List
1437 ("lists cannot appear in single string expression",
1442 when Tok_External =>
1444 -- An external reference is always a single string
1446 if Expr_Kind = Undefined then
1447 Expr_Kind := Single;
1451 (In_Tree => In_Tree,
1452 Current_Project => Current_Project,
1453 Current_Package => Current_Package,
1454 External_Value => Reference);
1455 Set_Current_Term (Term, In_Tree, To => Reference);
1458 Error_Msg ("cannot be part of an expression", Token_Ptr);
1463 -- If there is an '&', call Terms recursively
1465 if Token = Tok_Ampersand then
1466 Scan (In_Tree); -- scan past ampersand
1469 (In_Tree => In_Tree,
1471 Expr_Kind => Expr_Kind,
1472 Current_Project => Current_Project,
1473 Current_Package => Current_Package,
1474 Optional_Index => Optional_Index);
1476 -- And link the next term to this term
1478 Set_Next_Term (Term, In_Tree, To => Next_Term);