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;
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 -- Parse an external reference. Current token is "external"
114 procedure Attribute_Reference
115 (In_Tree : Project_Node_Tree_Ref;
116 Reference : out Project_Node_Id;
117 First_Attribute : Attribute_Node_Id;
118 Current_Project : Project_Node_Id;
119 Current_Package : Project_Node_Id);
120 -- Parse an attribute reference. Current token is an apostrophe
123 (In_Tree : Project_Node_Tree_Ref;
124 Term : out Project_Node_Id;
125 Expr_Kind : in out Variable_Kind;
126 Current_Project : Project_Node_Id;
127 Current_Package : Project_Node_Id;
128 Optional_Index : Boolean);
129 -- Recursive procedure to parse one term or several terms concatenated
136 procedure Add (This_String : Name_Id) is
138 Choices.Increment_Last;
139 Choices.Table (Choices.Last) :=
140 (The_String => This_String,
141 Already_Used => False);
148 procedure Add_To_Names (NL : Name_Location) is
150 Names.Increment_Last;
151 Names.Table (Names.Last) := NL;
154 -------------------------
155 -- Attribute_Reference --
156 -------------------------
158 procedure Attribute_Reference
159 (In_Tree : Project_Node_Tree_Ref;
160 Reference : out Project_Node_Id;
161 First_Attribute : Attribute_Node_Id;
162 Current_Project : Project_Node_Id;
163 Current_Package : Project_Node_Id)
165 Current_Attribute : Attribute_Node_Id := First_Attribute;
168 -- Declare the node of the attribute reference
172 (Of_Kind => N_Attribute_Reference, In_Tree => In_Tree);
173 Set_Location_Of (Reference, In_Tree, To => Token_Ptr);
174 Scan (In_Tree); -- past apostrophe
176 -- Body may be an attribute name
178 if Token = Tok_Body then
179 Token := Tok_Identifier;
180 Token_Name := Snames.Name_Body;
183 Expect (Tok_Identifier, "identifier");
185 if Token = Tok_Identifier then
186 Set_Name_Of (Reference, In_Tree, To => Token_Name);
188 -- Check if the identifier is one of the attribute identifiers in the
189 -- context (package or project level attributes).
192 Attribute_Node_Id_Of (Token_Name, Starting_At => First_Attribute);
194 -- If the identifier is not allowed, report an error
196 if Current_Attribute = Empty_Attribute then
197 Error_Msg_Name_1 := Token_Name;
198 Error_Msg ("unknown attribute %%", Token_Ptr);
199 Reference := Empty_Node;
201 -- Scan past the attribute name
206 -- Give its characteristics to this attribute reference
208 Set_Project_Node_Of (Reference, In_Tree, To => Current_Project);
209 Set_Package_Node_Of (Reference, In_Tree, To => Current_Package);
210 Set_Expression_Kind_Of
211 (Reference, In_Tree, To => Variable_Kind_Of (Current_Attribute));
214 To => Attribute_Kind_Of (Current_Attribute) =
215 Case_Insensitive_Associative_Array);
217 -- Scan past the attribute name
221 -- If the attribute is an associative array, get the index
223 if Attribute_Kind_Of (Current_Attribute) /= Single then
224 Expect (Tok_Left_Paren, "`(`");
226 if Token = Tok_Left_Paren then
228 Expect (Tok_String_Literal, "literal string");
230 if Token = Tok_String_Literal then
231 Set_Associative_Array_Index_Of
232 (Reference, In_Tree, To => Token_Name);
234 Expect (Tok_Right_Paren, "`)`");
236 if Token = Tok_Right_Paren then
244 -- Change name of obsolete attributes
246 if Reference /= Empty_Node then
247 case Name_Of (Reference, In_Tree) is
248 when Snames.Name_Specification =>
249 Set_Name_Of (Reference, In_Tree, To => Snames.Name_Spec);
251 when Snames.Name_Specification_Suffix =>
253 (Reference, In_Tree, To => Snames.Name_Spec_Suffix);
255 when Snames.Name_Implementation =>
256 Set_Name_Of (Reference, In_Tree, To => Snames.Name_Body);
258 when Snames.Name_Implementation_Suffix =>
260 (Reference, In_Tree, To => Snames.Name_Body_Suffix);
267 end Attribute_Reference;
269 ---------------------------
270 -- End_Case_Construction --
271 ---------------------------
273 procedure End_Case_Construction
274 (Check_All_Labels : Boolean;
275 Case_Location : Source_Ptr)
277 Non_Used : Natural := 0;
278 First_Non_Used : Choice_Node_Id := First_Choice_Node_Id;
280 -- First, if Check_All_Labels is True, check if all values
281 -- of the string type have been used.
283 if Check_All_Labels then
284 for Choice in Choice_First .. Choices.Last loop
285 if not Choices.Table (Choice).Already_Used then
286 Non_Used := Non_Used + 1;
289 First_Non_Used := Choice;
294 -- If only one is not used, report a single warning for this value
297 Error_Msg_Name_1 := Choices.Table (First_Non_Used).The_String;
298 Error_Msg ("?value %% is not used as label", Case_Location);
300 -- If several are not used, report a warning for each one of them
302 elsif Non_Used > 1 then
304 ("?the following values are not used as labels:",
307 for Choice in First_Non_Used .. Choices.Last loop
308 if not Choices.Table (Choice).Already_Used then
309 Error_Msg_Name_1 := Choices.Table (Choice).The_String;
310 Error_Msg ("\?%%", Case_Location);
316 -- If this is the only case construction, empty the tables
318 if Choice_Lasts.Last = 1 then
319 Choice_Lasts.Set_Last (0);
320 Choices.Set_Last (First_Choice_Node_Id);
323 elsif Choice_Lasts.Last = 2 then
324 -- This is the second case onstruction, set the tables to the first
326 Choice_Lasts.Set_Last (1);
327 Choices.Set_Last (Choice_Lasts.Table (1));
331 -- This is the 3rd or more case construction, set the tables to the
334 Choice_Lasts.Decrement_Last;
335 Choices.Set_Last (Choice_Lasts.Table (Choice_Lasts.Last));
336 Choice_First := Choice_Lasts.Table (Choice_Lasts.Last - 1) + 1;
338 end End_Case_Construction;
340 ------------------------
341 -- External_Reference --
342 ------------------------
344 procedure External_Reference
345 (In_Tree : Project_Node_Tree_Ref;
346 Current_Project : Project_Node_Id;
347 Current_Package : Project_Node_Id;
348 External_Value : out Project_Node_Id)
350 Field_Id : Project_Node_Id := Empty_Node;
355 (Of_Kind => N_External_Value,
357 And_Expr_Kind => Single);
358 Set_Location_Of (External_Value, In_Tree, To => Token_Ptr);
360 -- The current token is External
362 -- Get the left parenthesis
365 Expect (Tok_Left_Paren, "`(`");
367 -- Scan past the left parenthesis
369 if Token = Tok_Left_Paren then
373 -- Get the name of the external reference
375 Expect (Tok_String_Literal, "literal string");
377 if Token = Tok_String_Literal then
380 (Of_Kind => N_Literal_String,
382 And_Expr_Kind => Single);
383 Set_String_Value_Of (Field_Id, In_Tree, To => Token_Name);
384 Set_External_Reference_Of (External_Value, In_Tree, To => Field_Id);
386 -- Scan past the first argument
392 when Tok_Right_Paren =>
394 -- Scan past the right parenthesis
399 -- Scan past the comma
403 -- Get the string expression for the default
406 Loc : constant Source_Ptr := Token_Ptr;
411 Expression => Field_Id,
412 Current_Project => Current_Project,
413 Current_Package => Current_Package,
414 Optional_Index => False);
416 if Expression_Kind_Of (Field_Id, In_Tree) = List then
417 Error_Msg ("expression must be a single string", Loc);
419 Set_External_Default_Of
420 (External_Value, In_Tree, To => Field_Id);
424 Expect (Tok_Right_Paren, "`)`");
426 -- Scan past the right parenthesis
428 if Token = Tok_Right_Paren then
433 Error_Msg ("`,` or `)` expected", Token_Ptr);
436 end External_Reference;
438 -----------------------
439 -- Parse_Choice_List --
440 -----------------------
442 procedure Parse_Choice_List
443 (In_Tree : Project_Node_Tree_Ref;
444 First_Choice : out Project_Node_Id)
446 Current_Choice : Project_Node_Id := Empty_Node;
447 Next_Choice : Project_Node_Id := Empty_Node;
448 Choice_String : Name_Id := No_Name;
449 Found : Boolean := False;
452 -- Declare the node of the first choice
456 (Of_Kind => N_Literal_String,
458 And_Expr_Kind => Single);
460 -- Initially Current_Choice is the same as First_Choice
462 Current_Choice := First_Choice;
465 Expect (Tok_String_Literal, "literal string");
466 exit when Token /= Tok_String_Literal;
467 Set_Location_Of (Current_Choice, In_Tree, To => Token_Ptr);
468 Choice_String := Token_Name;
470 -- Give the string value to the current choice
472 Set_String_Value_Of (Current_Choice, In_Tree, To => Choice_String);
474 -- Check if the label is part of the string type and if it has not
475 -- been already used.
478 for Choice in Choice_First .. Choices.Last loop
479 if Choices.Table (Choice).The_String = Choice_String then
480 -- This label is part of the string type
484 if Choices.Table (Choice).Already_Used then
485 -- But it has already appeared in a choice list for this
486 -- case construction; report an error.
488 Error_Msg_Name_1 := Choice_String;
489 Error_Msg ("duplicate case label %%", Token_Ptr);
491 Choices.Table (Choice).Already_Used := True;
498 -- If the label is not part of the string list, report an error
501 Error_Msg_Name_1 := Choice_String;
502 Error_Msg ("illegal case label %%", Token_Ptr);
505 -- Scan past the label
509 -- If there is no '|', we are done
511 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
609 -- This is a repetition, report an error
611 Error_Msg_Name_1 := String_Value;
612 Error_Msg ("duplicate value %% in type", Token_Ptr);
616 Current := Next_Literal_String (Current, In_Tree);
620 -- Scan past the literal string
624 -- If there is no comma following the literal string, we are done
626 if Token /= Tok_Comma then
630 -- Declare the next string, link it to Last_String and set
631 -- Last_String to its node.
635 (Of_Kind => N_Literal_String,
637 And_Expr_Kind => Single);
638 Set_Next_Literal_String (Last_String, In_Tree, To => Next_String);
639 Last_String := Next_String;
643 end Parse_String_Type_List;
645 ------------------------------
646 -- Parse_Variable_Reference --
647 ------------------------------
649 procedure Parse_Variable_Reference
650 (In_Tree : Project_Node_Tree_Ref;
651 Variable : out Project_Node_Id;
652 Current_Project : Project_Node_Id;
653 Current_Package : Project_Node_Id)
655 Current_Variable : Project_Node_Id := Empty_Node;
657 The_Package : Project_Node_Id := Current_Package;
658 The_Project : Project_Node_Id := Current_Project;
660 Specified_Project : Project_Node_Id := Empty_Node;
661 Specified_Package : Project_Node_Id := Empty_Node;
662 Look_For_Variable : Boolean := True;
663 First_Attribute : Attribute_Node_Id := Empty_Attribute;
664 Variable_Name : Name_Id;
670 Expect (Tok_Identifier, "identifier");
672 if Token /= Tok_Identifier then
673 Look_For_Variable := False;
677 Add_To_Names (NL => (Name => Token_Name, Location => Token_Ptr));
679 exit when Token /= Tok_Dot;
683 if Look_For_Variable then
685 if Token = Tok_Apostrophe then
687 -- Attribute reference
697 -- This may be a project name or a package name.
698 -- Project name have precedence.
700 -- First, look if it can be a package name
704 (Package_Node_Id_Of (Names.Table (1).Name));
706 -- Now, look if it can be a project name
708 The_Project := Imported_Or_Extended_Project_Of
709 (Current_Project, In_Tree, Names.Table (1).Name);
711 if The_Project = Empty_Node then
712 -- If it is neither a project name nor a package name,
715 if First_Attribute = Empty_Attribute then
716 Error_Msg_Name_1 := Names.Table (1).Name;
717 Error_Msg ("unknown project %",
718 Names.Table (1).Location);
719 First_Attribute := Attribute_First;
722 -- If it is a package name, check if the package
723 -- has already been declared in the current project.
726 First_Package_Of (Current_Project, In_Tree);
728 while The_Package /= Empty_Node
729 and then Name_Of (The_Package, In_Tree) /=
733 Next_Package_In_Project (The_Package, In_Tree);
736 -- If it has not been already declared, report an
739 if The_Package = Empty_Node then
740 Error_Msg_Name_1 := Names.Table (1).Name;
741 Error_Msg ("package % not yet defined",
742 Names.Table (1).Location);
747 -- It is a project name
749 First_Attribute := Attribute_First;
750 The_Package := Empty_Node;
755 -- We have either a project name made of several simple
756 -- names (long project), or a project name (short project)
757 -- followed by a package name. The long project name has
761 Short_Project : Name_Id;
762 Long_Project : Name_Id;
769 -- Get the name of the short project
771 for Index in 1 .. Names.Last - 1 loop
773 (Get_Name_String (Names.Table (Index).Name),
774 Buffer, Buffer_Last);
776 if Index /= Names.Last - 1 then
777 Add_To_Buffer (".", Buffer, Buffer_Last);
781 Name_Len := Buffer_Last;
782 Name_Buffer (1 .. Buffer_Last) :=
783 Buffer (1 .. Buffer_Last);
784 Short_Project := Name_Find;
786 -- Now, add the last simple name to get the name of the
789 Add_To_Buffer (".", Buffer, Buffer_Last);
791 (Get_Name_String (Names.Table (Names.Last).Name),
792 Buffer, Buffer_Last);
793 Name_Len := Buffer_Last;
794 Name_Buffer (1 .. Buffer_Last) :=
795 Buffer (1 .. Buffer_Last);
796 Long_Project := Name_Find;
798 -- Check if the long project is imported or extended
800 The_Project := Imported_Or_Extended_Project_Of
801 (Current_Project, In_Tree, Long_Project);
803 -- If the long project exists, then this is the prefix
806 if The_Project /= Empty_Node then
807 First_Attribute := Attribute_First;
808 The_Package := Empty_Node;
811 -- Otherwise, check if the short project is imported
814 The_Project := Imported_Or_Extended_Project_Of
815 (Current_Project, In_Tree,
818 -- If the short project does not exist, we report an
821 if The_Project = Empty_Node then
822 Error_Msg_Name_1 := Long_Project;
823 Error_Msg_Name_2 := Short_Project;
824 Error_Msg ("unknown projects % or %",
825 Names.Table (1).Location);
826 The_Package := Empty_Node;
827 First_Attribute := Attribute_First;
830 -- Now, we check if the package has been declared
834 First_Package_Of (The_Project, In_Tree);
835 while The_Package /= Empty_Node
836 and then Name_Of (The_Package, In_Tree) /=
837 Names.Table (Names.Last).Name
840 Next_Package_In_Project (The_Package, In_Tree);
843 -- If it has not, then we report an error
845 if The_Package = Empty_Node then
847 Names.Table (Names.Last).Name;
848 Error_Msg_Name_2 := Short_Project;
849 Error_Msg ("package % not declared in project %",
850 Names.Table (Names.Last).Location);
851 First_Attribute := Attribute_First;
854 -- Otherwise, we have the correct project and
859 (Package_Id_Of (The_Package, In_Tree));
869 Current_Project => The_Project,
870 Current_Package => The_Package,
871 First_Attribute => First_Attribute);
878 (Of_Kind => N_Variable_Reference, In_Tree => In_Tree);
880 if Look_For_Variable then
890 -- Simple variable name
892 Set_Name_Of (Variable, In_Tree, To => Names.Table (1).Name);
896 -- Variable name with a simple name prefix that can be
897 -- a project name or a package name. Project names have
898 -- priority over package names.
900 Set_Name_Of (Variable, In_Tree, To => Names.Table (2).Name);
902 -- Check if it can be a package name
904 The_Package := First_Package_Of (Current_Project, In_Tree);
906 while The_Package /= Empty_Node
907 and then Name_Of (The_Package, In_Tree) /=
911 Next_Package_In_Project (The_Package, In_Tree);
914 -- Now look for a possible project name
916 The_Project := Imported_Or_Extended_Project_Of
917 (Current_Project, In_Tree, Names.Table (1).Name);
919 if The_Project /= Empty_Node then
920 Specified_Project := The_Project;
922 elsif The_Package = Empty_Node then
923 Error_Msg_Name_1 := Names.Table (1).Name;
924 Error_Msg ("unknown package or project %",
925 Names.Table (1).Location);
926 Look_For_Variable := False;
929 Specified_Package := The_Package;
934 -- Variable name with a prefix that is either a project name
935 -- made of several simple names, or a project name followed
936 -- by a package name.
939 (Variable, In_Tree, To => Names.Table (Names.Last).Name);
942 Short_Project : Name_Id;
943 Long_Project : Name_Id;
946 -- First, we get the two possible project names
952 -- Add all the simple names, except the last two
954 for Index in 1 .. Names.Last - 2 loop
956 (Get_Name_String (Names.Table (Index).Name),
957 Buffer, Buffer_Last);
959 if Index /= Names.Last - 2 then
960 Add_To_Buffer (".", Buffer, Buffer_Last);
964 Name_Len := Buffer_Last;
965 Name_Buffer (1 .. Name_Len) := Buffer (1 .. Buffer_Last);
966 Short_Project := Name_Find;
968 -- Add the simple name before the name of the variable
970 Add_To_Buffer (".", Buffer, Buffer_Last);
972 (Get_Name_String (Names.Table (Names.Last - 1).Name),
973 Buffer, Buffer_Last);
974 Name_Len := Buffer_Last;
975 Name_Buffer (1 .. Name_Len) := Buffer (1 .. Buffer_Last);
976 Long_Project := Name_Find;
978 -- Check if the prefix is the name of an imported or
981 The_Project := Imported_Or_Extended_Project_Of
982 (Current_Project, In_Tree, Long_Project);
984 if The_Project /= Empty_Node then
985 Specified_Project := The_Project;
988 -- Now check if the prefix may be a project name followed
989 -- by a package name.
991 -- First check for a possible project name
993 The_Project := Imported_Or_Extended_Project_Of
994 (Current_Project, In_Tree, Short_Project);
996 if The_Project = Empty_Node then
997 -- Unknown prefix, report an error
999 Error_Msg_Name_1 := Long_Project;
1000 Error_Msg_Name_2 := Short_Project;
1001 Error_Msg ("unknown projects % or %",
1002 Names.Table (1).Location);
1003 Look_For_Variable := False;
1006 Specified_Project := The_Project;
1008 -- Now look for the package in this project
1010 The_Package := First_Package_Of (The_Project, In_Tree);
1012 while The_Package /= Empty_Node
1013 and then Name_Of (The_Package, In_Tree) /=
1014 Names.Table (Names.Last - 1).Name
1017 Next_Package_In_Project (The_Package, In_Tree);
1020 if The_Package = Empty_Node then
1021 -- The package does not vexist, report an error
1023 Error_Msg_Name_1 := Names.Table (2).Name;
1024 Error_Msg ("unknown package %",
1025 Names.Table (Names.Last - 1).Location);
1026 Look_For_Variable := False;
1029 Specified_Package := The_Package;
1037 if Look_For_Variable then
1038 Variable_Name := Name_Of (Variable, In_Tree);
1039 Set_Project_Node_Of (Variable, In_Tree, To => Specified_Project);
1040 Set_Package_Node_Of (Variable, In_Tree, To => Specified_Package);
1042 if Specified_Project /= Empty_Node then
1043 The_Project := Specified_Project;
1046 The_Project := Current_Project;
1049 Current_Variable := Empty_Node;
1051 -- Look for this variable
1053 -- If a package was specified, check if the variable has been
1054 -- declared in this package.
1056 if Specified_Package /= Empty_Node then
1058 First_Variable_Of (Specified_Package, In_Tree);
1060 while Current_Variable /= Empty_Node
1062 Name_Of (Current_Variable, In_Tree) /= Variable_Name
1064 Current_Variable := Next_Variable (Current_Variable, In_Tree);
1068 -- Otherwise, if no project has been specified and we are in
1069 -- a package, first check if the variable has been declared in
1072 if Specified_Project = Empty_Node
1073 and then Current_Package /= Empty_Node
1076 First_Variable_Of (Current_Package, In_Tree);
1078 while Current_Variable /= Empty_Node
1079 and then Name_Of (Current_Variable, In_Tree) /= Variable_Name
1082 Next_Variable (Current_Variable, In_Tree);
1086 -- If we have not found the variable in the package, check if the
1087 -- variable has been declared in the project.
1089 if Current_Variable = Empty_Node then
1090 Current_Variable := First_Variable_Of (The_Project, In_Tree);
1092 while Current_Variable /= Empty_Node
1093 and then Name_Of (Current_Variable, In_Tree) /= Variable_Name
1096 Next_Variable (Current_Variable, In_Tree);
1101 -- If the variable was not found, report an error
1103 if Current_Variable = Empty_Node then
1104 Error_Msg_Name_1 := Variable_Name;
1106 ("unknown variable %", Names.Table (Names.Last).Location);
1110 if Current_Variable /= Empty_Node then
1111 Set_Expression_Kind_Of
1113 To => Expression_Kind_Of (Current_Variable, In_Tree));
1116 Kind_Of (Current_Variable, In_Tree) = N_Typed_Variable_Declaration
1120 To => String_Type_Of (Current_Variable, In_Tree));
1124 -- If the variable is followed by a left parenthesis, report an error
1125 -- but attempt to scan the index.
1127 if Token = Tok_Left_Paren then
1128 Error_Msg ("\variables cannot be associative arrays", Token_Ptr);
1130 Expect (Tok_String_Literal, "literal string");
1132 if Token = Tok_String_Literal then
1134 Expect (Tok_Right_Paren, "`)`");
1136 if Token = Tok_Right_Paren then
1141 end Parse_Variable_Reference;
1143 ---------------------------------
1144 -- Start_New_Case_Construction --
1145 ---------------------------------
1147 procedure Start_New_Case_Construction
1148 (In_Tree : Project_Node_Tree_Ref;
1149 String_Type : Project_Node_Id)
1151 Current_String : Project_Node_Id;
1154 -- Set Choice_First, depending on whether is the first case
1155 -- construction or not.
1157 if Choice_First = 0 then
1159 Choices.Set_Last (First_Choice_Node_Id);
1161 Choice_First := Choices.Last + 1;
1164 -- Add to table Choices the literal of the string type
1166 if String_Type /= Empty_Node then
1167 Current_String := First_Literal_String (String_Type, In_Tree);
1169 while Current_String /= Empty_Node loop
1170 Add (This_String => String_Value_Of (Current_String, In_Tree));
1171 Current_String := Next_Literal_String (Current_String, In_Tree);
1175 -- Set the value of the last choice in table Choice_Lasts
1177 Choice_Lasts.Increment_Last;
1178 Choice_Lasts.Table (Choice_Lasts.Last) := Choices.Last;
1180 end Start_New_Case_Construction;
1187 (In_Tree : Project_Node_Tree_Ref;
1188 Term : out Project_Node_Id;
1189 Expr_Kind : in out Variable_Kind;
1190 Current_Project : Project_Node_Id;
1191 Current_Package : Project_Node_Id;
1192 Optional_Index : Boolean)
1194 Next_Term : Project_Node_Id := Empty_Node;
1195 Term_Id : Project_Node_Id := Empty_Node;
1196 Current_Expression : Project_Node_Id := Empty_Node;
1197 Next_Expression : Project_Node_Id := Empty_Node;
1198 Current_Location : Source_Ptr := No_Location;
1199 Reference : Project_Node_Id := Empty_Node;
1202 -- Declare a new node for the term
1204 Term := Default_Project_Node (Of_Kind => N_Term, In_Tree => In_Tree);
1205 Set_Location_Of (Term, In_Tree, To => Token_Ptr);
1208 when Tok_Left_Paren =>
1210 -- If we have a left parenthesis and we don't know the expression
1211 -- kind, then this is a string list.
1222 -- If we already know that this is a single string, report
1223 -- an error, but set the expression kind to string list to
1224 -- avoid several errors.
1228 ("literal string list cannot appear in a string",
1232 -- Declare a new node for this literal string list
1234 Term_Id := Default_Project_Node
1235 (Of_Kind => N_Literal_String_List,
1237 And_Expr_Kind => List);
1238 Set_Current_Term (Term, In_Tree, To => Term_Id);
1239 Set_Location_Of (Term, In_Tree, To => Token_Ptr);
1241 -- Scan past the left parenthesis
1245 -- If the left parenthesis is immediately followed by a right
1246 -- parenthesis, the literal string list is empty.
1248 if Token = Tok_Right_Paren then
1252 -- Otherwise, we parse the expression(s) in the literal string
1256 Current_Location := Token_Ptr;
1258 (In_Tree => In_Tree,
1259 Expression => Next_Expression,
1260 Current_Project => Current_Project,
1261 Current_Package => Current_Package,
1262 Optional_Index => Optional_Index);
1264 -- The expression kind is String list, report an error
1266 if Expression_Kind_Of (Next_Expression, In_Tree) = List then
1267 Error_Msg ("single expression expected",
1271 -- If Current_Expression is empty, it means that the
1272 -- expression is the first in the string list.
1274 if Current_Expression = Empty_Node then
1275 Set_First_Expression_In_List
1276 (Term_Id, In_Tree, To => Next_Expression);
1278 Set_Next_Expression_In_List
1279 (Current_Expression, In_Tree, To => Next_Expression);
1282 Current_Expression := Next_Expression;
1284 -- If there is a comma, continue with the next expression
1286 exit when Token /= Tok_Comma;
1287 Scan (In_Tree); -- past the comma
1290 -- We expect a closing right parenthesis
1292 Expect (Tok_Right_Paren, "`)`");
1294 if Token = Tok_Right_Paren then
1299 when Tok_String_Literal =>
1301 -- If we don't know the expression kind (first term), then it is
1304 if Expr_Kind = Undefined then
1305 Expr_Kind := Single;
1308 -- Declare a new node for the string literal
1311 Default_Project_Node
1312 (Of_Kind => N_Literal_String, In_Tree => In_Tree);
1313 Set_Current_Term (Term, In_Tree, To => Term_Id);
1314 Set_String_Value_Of (Term_Id, In_Tree, To => Token_Name);
1316 -- Scan past the string literal
1320 -- Check for possible index expression
1322 if Token = Tok_At then
1323 if not Optional_Index then
1324 Error_Msg ("index not allowed here", Token_Ptr);
1327 if Token = Tok_Integer_Literal then
1331 -- Set the index value
1335 Expect (Tok_Integer_Literal, "integer literal");
1337 if Token = Tok_Integer_Literal then
1339 Index : constant Int := UI_To_Int (Int_Literal_Value);
1342 Error_Msg ("index cannot be zero", Token_Ptr);
1345 (Term_Id, In_Tree, To => Index);
1354 when Tok_Identifier =>
1355 Current_Location := Token_Ptr;
1357 -- Get the variable or attribute reference
1359 Parse_Variable_Reference
1360 (In_Tree => In_Tree,
1361 Variable => Reference,
1362 Current_Project => Current_Project,
1363 Current_Package => Current_Package);
1364 Set_Current_Term (Term, In_Tree, To => Reference);
1366 if Reference /= Empty_Node then
1368 -- If we don't know the expression kind (first term), then it
1369 -- has the kind of the variable or attribute reference.
1371 if Expr_Kind = Undefined then
1372 Expr_Kind := Expression_Kind_Of (Reference, In_Tree);
1374 elsif Expr_Kind = Single
1375 and then Expression_Kind_Of (Reference, In_Tree) = List
1377 -- If the expression is a single list, and the reference is
1378 -- a string list, report an error, and set the expression
1379 -- kind to string list to avoid multiple errors.
1383 ("list variable cannot appear in single string expression",
1390 -- project can appear in an expression as the prefix of an
1391 -- attribute reference of the current project.
1393 Current_Location := Token_Ptr;
1395 Expect (Tok_Apostrophe, "`'`");
1397 if Token = Tok_Apostrophe then
1399 (In_Tree => In_Tree,
1400 Reference => Reference,
1401 First_Attribute => Prj.Attr.Attribute_First,
1402 Current_Project => Current_Project,
1403 Current_Package => Empty_Node);
1404 Set_Current_Term (Term, In_Tree, To => Reference);
1407 -- Same checks as above for the expression kind
1409 if Reference /= Empty_Node then
1410 if Expr_Kind = Undefined then
1411 Expr_Kind := Expression_Kind_Of (Reference, In_Tree);
1413 elsif Expr_Kind = Single
1414 and then Expression_Kind_Of (Reference, In_Tree) = List
1417 ("lists cannot appear in single string expression",
1422 when Tok_External =>
1423 -- An external reference is always a single string
1425 if Expr_Kind = Undefined then
1426 Expr_Kind := Single;
1430 (In_Tree => In_Tree,
1431 Current_Project => Current_Project,
1432 Current_Package => Current_Package,
1433 External_Value => Reference);
1434 Set_Current_Term (Term, In_Tree, To => Reference);
1437 Error_Msg ("cannot be part of an expression", Token_Ptr);
1442 -- If there is an '&', call Terms recursively
1444 if Token = Tok_Ampersand then
1446 -- Scan past the '&'
1451 (In_Tree => In_Tree,
1453 Expr_Kind => Expr_Kind,
1454 Current_Project => Current_Project,
1455 Current_Package => Current_Package,
1456 Optional_Index => Optional_Index);
1458 -- And link the next term to this term
1460 Set_Next_Term (Term, In_Tree, To => Next_Term);