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, 59 Temple Place - Suite 330, Boston, --
20 -- MA 02111-1307, 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
;
31 with Prj
.Tree
; use Prj
.Tree
;
32 with Scans
; use Scans
;
35 with Types
; use Types
;
36 with Uintp
; use Uintp
;
38 package body Prj
.Strt
is
40 Buffer
: String_Access
;
41 Buffer_Last
: Natural := 0;
43 type Choice_String
is record
45 Already_Used
: Boolean := False;
47 -- The string of a case label, and an indication that it has already
48 -- been used (to avoid duplicate case labels).
50 Choices_Initial
: constant := 10;
51 Choices_Increment
: constant := 50;
53 Choice_Node_Low_Bound
: constant := 0;
54 Choice_Node_High_Bound
: constant := 099_999_999
;
55 -- In practice, infinite
57 type Choice_Node_Id
is
58 range Choice_Node_Low_Bound
.. Choice_Node_High_Bound
;
60 First_Choice_Node_Id
: constant Choice_Node_Id
:=
61 Choice_Node_Low_Bound
;
64 new Table
.Table
(Table_Component_Type
=> Choice_String
,
65 Table_Index_Type
=> Choice_Node_Id
,
66 Table_Low_Bound
=> First_Choice_Node_Id
,
67 Table_Initial
=> Choices_Initial
,
68 Table_Increment
=> Choices_Increment
,
69 Table_Name
=> "Prj.Strt.Choices");
70 -- Used to store the case labels and check that there is no duplicate.
72 package Choice_Lasts
is
73 new Table
.Table
(Table_Component_Type
=> Choice_Node_Id
,
74 Table_Index_Type
=> Nat
,
77 Table_Increment
=> 100,
78 Table_Name
=> "Prj.Strt.Choice_Lasts");
79 -- Used to store the indices of the choices in table Choices,
80 -- to distinguish nested case constructions.
82 Choice_First
: Choice_Node_Id
:= 0;
83 -- Index in table Choices of the first case label of the current
84 -- case construction. Zero means no current case construction.
86 type Name_Location
is record
87 Name
: Name_Id
:= No_Name
;
88 Location
: Source_Ptr
:= No_Location
;
90 -- Store the identifier and the location of a simple name
93 new Table
.Table
(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 External_Value
: out Project_Node_Id
);
111 -- Parse an external reference. Current token is "external".
113 procedure Attribute_Reference
114 (In_Tree
: Project_Node_Tree_Ref
;
115 Reference
: out Project_Node_Id
;
116 First_Attribute
: Attribute_Node_Id
;
117 Current_Project
: Project_Node_Id
;
118 Current_Package
: Project_Node_Id
);
119 -- Parse an attribute reference. Current token is an apostrophe.
122 (In_Tree
: Project_Node_Tree_Ref
;
123 Term
: out Project_Node_Id
;
124 Expr_Kind
: in out Variable_Kind
;
125 Current_Project
: Project_Node_Id
;
126 Current_Package
: Project_Node_Id
;
127 Optional_Index
: Boolean);
128 -- Recursive procedure to parse one term or several terms concatenated
135 procedure Add
(This_String
: Name_Id
) is
137 Choices
.Increment_Last
;
138 Choices
.Table
(Choices
.Last
) :=
139 (The_String
=> This_String
,
140 Already_Used
=> False);
147 procedure Add_To_Names
(NL
: Name_Location
) is
149 Names
.Increment_Last
;
150 Names
.Table
(Names
.Last
) := NL
;
153 -------------------------
154 -- Attribute_Reference --
155 -------------------------
157 procedure Attribute_Reference
158 (In_Tree
: Project_Node_Tree_Ref
;
159 Reference
: out Project_Node_Id
;
160 First_Attribute
: Attribute_Node_Id
;
161 Current_Project
: Project_Node_Id
;
162 Current_Package
: Project_Node_Id
)
164 Current_Attribute
: Attribute_Node_Id
:= First_Attribute
;
167 -- Declare the node of the attribute reference
171 (Of_Kind
=> N_Attribute_Reference
, In_Tree
=> In_Tree
);
172 Set_Location_Of
(Reference
, In_Tree
, To
=> Token_Ptr
);
173 Scan
(In_Tree
); -- past apostrophe
175 -- Body may be an attribute name
177 if Token
= Tok_Body
then
178 Token
:= Tok_Identifier
;
179 Token_Name
:= Snames
.Name_Body
;
182 Expect
(Tok_Identifier
, "identifier");
184 if Token
= Tok_Identifier
then
185 Set_Name_Of
(Reference
, In_Tree
, To
=> Token_Name
);
187 -- Check if the identifier is one of the attribute identifiers in the
188 -- context (package or project level attributes).
191 Attribute_Node_Id_Of
(Token_Name
, Starting_At
=> First_Attribute
);
193 -- If the identifier is not allowed, report an error
195 if Current_Attribute
= Empty_Attribute
then
196 Error_Msg_Name_1
:= Token_Name
;
197 Error_Msg
("unknown attribute %", Token_Ptr
);
198 Reference
:= Empty_Node
;
200 -- Scan past the attribute name
205 -- Give its characteristics to this attribute reference
207 Set_Project_Node_Of
(Reference
, In_Tree
, To
=> Current_Project
);
208 Set_Package_Node_Of
(Reference
, In_Tree
, To
=> Current_Package
);
209 Set_Expression_Kind_Of
210 (Reference
, In_Tree
, To
=> Variable_Kind_Of
(Current_Attribute
));
213 To
=> Attribute_Kind_Of
(Current_Attribute
) =
214 Case_Insensitive_Associative_Array
);
216 -- Scan past the attribute name
220 -- If the attribute is an associative array, get the index
222 if Attribute_Kind_Of
(Current_Attribute
) /= Single
then
223 Expect
(Tok_Left_Paren
, "`(`");
225 if Token
= Tok_Left_Paren
then
227 Expect
(Tok_String_Literal
, "literal string");
229 if Token
= Tok_String_Literal
then
230 Set_Associative_Array_Index_Of
231 (Reference
, In_Tree
, To
=> Token_Name
);
233 Expect
(Tok_Right_Paren
, "`)`");
235 if Token
= Tok_Right_Paren
then
243 -- Change name of obsolete attributes
245 if Reference
/= Empty_Node
then
246 case Name_Of
(Reference
, In_Tree
) is
247 when Snames
.Name_Specification
=>
248 Set_Name_Of
(Reference
, In_Tree
, To
=> Snames
.Name_Spec
);
250 when Snames
.Name_Specification_Suffix
=>
252 (Reference
, In_Tree
, To
=> Snames
.Name_Spec_Suffix
);
254 when Snames
.Name_Implementation
=>
255 Set_Name_Of
(Reference
, In_Tree
, To
=> Snames
.Name_Body
);
257 when Snames
.Name_Implementation_Suffix
=>
259 (Reference
, In_Tree
, To
=> Snames
.Name_Body_Suffix
);
266 end Attribute_Reference
;
268 ---------------------------
269 -- End_Case_Construction --
270 ---------------------------
272 procedure End_Case_Construction
273 (Check_All_Labels
: Boolean;
274 Case_Location
: Source_Ptr
)
276 Non_Used
: Natural := 0;
277 First_Non_Used
: Choice_Node_Id
:= First_Choice_Node_Id
;
279 -- First, if Check_All_Labels is True, check if all values
280 -- of the string type have been used.
282 if Check_All_Labels
then
283 for Choice
in Choice_First
.. Choices
.Last
loop
284 if not Choices
.Table
(Choice
).Already_Used
then
285 Non_Used
:= Non_Used
+ 1;
288 First_Non_Used
:= Choice
;
293 -- If only one is not used, report a single warning for this value
296 Error_Msg_Name_1
:= Choices
.Table
(First_Non_Used
).The_String
;
297 Error_Msg
("?value { is not used as label", Case_Location
);
299 -- If several are not used, report a warning for each one of them
301 elsif Non_Used
> 1 then
303 ("?the following values are not used as labels:",
306 for Choice
in First_Non_Used
.. Choices
.Last
loop
307 if not Choices
.Table
(Choice
).Already_Used
then
308 Error_Msg_Name_1
:= Choices
.Table
(Choice
).The_String
;
309 Error_Msg
("\?{", Case_Location
);
315 -- If this is the only case construction, empty the tables
317 if Choice_Lasts
.Last
= 1 then
318 Choice_Lasts
.Set_Last
(0);
319 Choices
.Set_Last
(First_Choice_Node_Id
);
322 elsif Choice_Lasts
.Last
= 2 then
323 -- This is the second case onstruction, set the tables to the first
325 Choice_Lasts
.Set_Last
(1);
326 Choices
.Set_Last
(Choice_Lasts
.Table
(1));
330 -- This is the 3rd or more case construction, set the tables to the
333 Choice_Lasts
.Decrement_Last
;
334 Choices
.Set_Last
(Choice_Lasts
.Table
(Choice_Lasts
.Last
));
335 Choice_First
:= Choice_Lasts
.Table
(Choice_Lasts
.Last
- 1) + 1;
337 end End_Case_Construction
;
339 ------------------------
340 -- External_Reference --
341 ------------------------
343 procedure External_Reference
344 (In_Tree
: Project_Node_Tree_Ref
;
345 External_Value
: out Project_Node_Id
)
347 Field_Id
: Project_Node_Id
:= Empty_Node
;
352 (Of_Kind
=> N_External_Value
,
354 And_Expr_Kind
=> Single
);
355 Set_Location_Of
(External_Value
, In_Tree
, To
=> Token_Ptr
);
357 -- The current token is External
359 -- Get the left parenthesis
362 Expect
(Tok_Left_Paren
, "`(`");
364 -- Scan past the left parenthesis
366 if Token
= Tok_Left_Paren
then
370 -- Get the name of the external reference
372 Expect
(Tok_String_Literal
, "literal string");
374 if Token
= Tok_String_Literal
then
377 (Of_Kind
=> N_Literal_String
,
379 And_Expr_Kind
=> Single
);
380 Set_String_Value_Of
(Field_Id
, In_Tree
, To
=> Token_Name
);
381 Set_External_Reference_Of
(External_Value
, In_Tree
, To
=> Field_Id
);
383 -- Scan past the first argument
389 when Tok_Right_Paren
=>
391 -- Scan past the right parenthesis
396 -- Scan past the comma
400 Expect
(Tok_String_Literal
, "literal string");
404 if Token
= Tok_String_Literal
then
407 (Of_Kind
=> N_Literal_String
,
409 And_Expr_Kind
=> Single
);
410 Set_String_Value_Of
(Field_Id
, In_Tree
, To
=> Token_Name
);
411 Set_External_Default_Of
412 (External_Value
, In_Tree
, To
=> Field_Id
);
414 Expect
(Tok_Right_Paren
, "`)`");
417 -- Scan past the right parenthesis
418 if Token
= Tok_Right_Paren
then
423 Error_Msg
("`,` or `)` expected", Token_Ptr
);
426 end External_Reference
;
428 -----------------------
429 -- Parse_Choice_List --
430 -----------------------
432 procedure Parse_Choice_List
433 (In_Tree
: Project_Node_Tree_Ref
;
434 First_Choice
: out Project_Node_Id
)
436 Current_Choice
: Project_Node_Id
:= Empty_Node
;
437 Next_Choice
: Project_Node_Id
:= Empty_Node
;
438 Choice_String
: Name_Id
:= No_Name
;
439 Found
: Boolean := False;
442 -- Declare the node of the first choice
446 (Of_Kind
=> N_Literal_String
,
448 And_Expr_Kind
=> Single
);
450 -- Initially Current_Choice is the same as First_Choice
452 Current_Choice
:= First_Choice
;
455 Expect
(Tok_String_Literal
, "literal string");
456 exit when Token
/= Tok_String_Literal
;
457 Set_Location_Of
(Current_Choice
, In_Tree
, To
=> Token_Ptr
);
458 Choice_String
:= Token_Name
;
460 -- Give the string value to the current choice
462 Set_String_Value_Of
(Current_Choice
, In_Tree
, To
=> Choice_String
);
464 -- Check if the label is part of the string type and if it has not
465 -- been already used.
468 for Choice
in Choice_First
.. Choices
.Last
loop
469 if Choices
.Table
(Choice
).The_String
= Choice_String
then
470 -- This label is part of the string type
474 if Choices
.Table
(Choice
).Already_Used
then
475 -- But it has already appeared in a choice list for this
476 -- case construction; report an error.
478 Error_Msg_Name_1
:= Choice_String
;
479 Error_Msg
("duplicate case label {", Token_Ptr
);
481 Choices
.Table
(Choice
).Already_Used
:= True;
488 -- If the label is not part of the string list, report an error
491 Error_Msg_Name_1
:= Choice_String
;
492 Error_Msg
("illegal case label {", Token_Ptr
);
495 -- Scan past the label
499 -- If there is no '|', we are done
501 if Token
= Tok_Vertical_Bar
then
502 -- Otherwise, declare the node of the next choice, link it to
503 -- Current_Choice and set Current_Choice to this new node.
507 (Of_Kind
=> N_Literal_String
,
509 And_Expr_Kind
=> Single
);
510 Set_Next_Literal_String
511 (Current_Choice
, In_Tree
, To
=> Next_Choice
);
512 Current_Choice
:= Next_Choice
;
518 end Parse_Choice_List
;
520 ----------------------
521 -- Parse_Expression --
522 ----------------------
524 procedure Parse_Expression
525 (In_Tree
: Project_Node_Tree_Ref
;
526 Expression
: out Project_Node_Id
;
527 Current_Project
: Project_Node_Id
;
528 Current_Package
: Project_Node_Id
;
529 Optional_Index
: Boolean)
531 First_Term
: Project_Node_Id
:= Empty_Node
;
532 Expression_Kind
: Variable_Kind
:= Undefined
;
535 -- Declare the node of the expression
538 Default_Project_Node
(Of_Kind
=> N_Expression
, In_Tree
=> In_Tree
);
539 Set_Location_Of
(Expression
, In_Tree
, To
=> Token_Ptr
);
541 -- Parse the term or terms of the expression
543 Terms
(In_Tree
=> In_Tree
,
545 Expr_Kind
=> Expression_Kind
,
546 Current_Project
=> Current_Project
,
547 Current_Package
=> Current_Package
,
548 Optional_Index
=> Optional_Index
);
550 -- Set the first term and the expression kind
552 Set_First_Term
(Expression
, In_Tree
, To
=> First_Term
);
553 Set_Expression_Kind_Of
(Expression
, In_Tree
, To
=> Expression_Kind
);
554 end Parse_Expression
;
556 ----------------------------
557 -- Parse_String_Type_List --
558 ----------------------------
560 procedure Parse_String_Type_List
561 (In_Tree
: Project_Node_Tree_Ref
;
562 First_String
: out Project_Node_Id
)
564 Last_String
: Project_Node_Id
:= Empty_Node
;
565 Next_String
: Project_Node_Id
:= Empty_Node
;
566 String_Value
: Name_Id
:= No_Name
;
569 -- Declare the node of the first string
573 (Of_Kind
=> N_Literal_String
,
575 And_Expr_Kind
=> Single
);
577 -- Initially, Last_String is the same as First_String
579 Last_String
:= First_String
;
582 Expect
(Tok_String_Literal
, "literal string");
583 exit when Token
/= Tok_String_Literal
;
584 String_Value
:= Token_Name
;
586 -- Give its string value to Last_String
588 Set_String_Value_Of
(Last_String
, In_Tree
, To
=> String_Value
);
589 Set_Location_Of
(Last_String
, In_Tree
, To
=> Token_Ptr
);
591 -- Now, check if the string is already part of the string type
594 Current
: Project_Node_Id
:= First_String
;
597 while Current
/= Last_String
loop
598 if String_Value_Of
(Current
, In_Tree
) = String_Value
then
599 -- This is a repetition, report an error
601 Error_Msg_Name_1
:= String_Value
;
602 Error_Msg
("duplicate value { in type", Token_Ptr
);
606 Current
:= Next_Literal_String
(Current
, In_Tree
);
610 -- Scan past the literal string
614 -- If there is no comma following the literal string, we are done
616 if Token
/= Tok_Comma
then
620 -- Declare the next string, link it to Last_String and set
621 -- Last_String to its node.
625 (Of_Kind
=> N_Literal_String
,
627 And_Expr_Kind
=> Single
);
628 Set_Next_Literal_String
(Last_String
, In_Tree
, To
=> Next_String
);
629 Last_String
:= Next_String
;
633 end Parse_String_Type_List
;
635 ------------------------------
636 -- Parse_Variable_Reference --
637 ------------------------------
639 procedure Parse_Variable_Reference
640 (In_Tree
: Project_Node_Tree_Ref
;
641 Variable
: out Project_Node_Id
;
642 Current_Project
: Project_Node_Id
;
643 Current_Package
: Project_Node_Id
)
645 Current_Variable
: Project_Node_Id
:= Empty_Node
;
647 The_Package
: Project_Node_Id
:= Current_Package
;
648 The_Project
: Project_Node_Id
:= Current_Project
;
650 Specified_Project
: Project_Node_Id
:= Empty_Node
;
651 Specified_Package
: Project_Node_Id
:= Empty_Node
;
652 Look_For_Variable
: Boolean := True;
653 First_Attribute
: Attribute_Node_Id
:= Empty_Attribute
;
654 Variable_Name
: Name_Id
;
660 Expect
(Tok_Identifier
, "identifier");
662 if Token
/= Tok_Identifier
then
663 Look_For_Variable
:= False;
667 Add_To_Names
(NL
=> (Name
=> Token_Name
, Location
=> Token_Ptr
));
669 exit when Token
/= Tok_Dot
;
673 if Look_For_Variable
then
675 if Token
= Tok_Apostrophe
then
677 -- Attribute reference
687 -- This may be a project name or a package name.
688 -- Project name have precedence.
690 -- First, look if it can be a package name
694 (Package_Node_Id_Of
(Names
.Table
(1).Name
));
696 -- Now, look if it can be a project name
698 The_Project
:= Imported_Or_Extended_Project_Of
699 (Current_Project
, In_Tree
, Names
.Table
(1).Name
);
701 if The_Project
= Empty_Node
then
702 -- If it is neither a project name nor a package name,
705 if First_Attribute
= Empty_Attribute
then
706 Error_Msg_Name_1
:= Names
.Table
(1).Name
;
707 Error_Msg
("unknown project %",
708 Names
.Table
(1).Location
);
709 First_Attribute
:= Attribute_First
;
712 -- If it is a package name, check if the package
713 -- has already been declared in the current project.
716 First_Package_Of
(Current_Project
, In_Tree
);
718 while The_Package
/= Empty_Node
719 and then Name_Of
(The_Package
, In_Tree
) /=
723 Next_Package_In_Project
(The_Package
, In_Tree
);
726 -- If it has not been already declared, report an
729 if The_Package
= Empty_Node
then
730 Error_Msg_Name_1
:= Names
.Table
(1).Name
;
731 Error_Msg
("package % not yet defined",
732 Names
.Table
(1).Location
);
737 -- It is a project name
739 First_Attribute
:= Attribute_First
;
740 The_Package
:= Empty_Node
;
745 -- We have either a project name made of several simple
746 -- names (long project), or a project name (short project)
747 -- followed by a package name. The long project name has
751 Short_Project
: Name_Id
;
752 Long_Project
: Name_Id
;
759 -- Get the name of the short project
761 for Index
in 1 .. Names
.Last
- 1 loop
763 (Get_Name_String
(Names
.Table
(Index
).Name
),
764 Buffer
, Buffer_Last
);
766 if Index
/= Names
.Last
- 1 then
767 Add_To_Buffer
(".", Buffer
, Buffer_Last
);
771 Name_Len
:= Buffer_Last
;
772 Name_Buffer
(1 .. Buffer_Last
) :=
773 Buffer
(1 .. Buffer_Last
);
774 Short_Project
:= Name_Find
;
776 -- Now, add the last simple name to get the name of the
779 Add_To_Buffer
(".", Buffer
, Buffer_Last
);
781 (Get_Name_String
(Names
.Table
(Names
.Last
).Name
),
782 Buffer
, Buffer_Last
);
783 Name_Len
:= Buffer_Last
;
784 Name_Buffer
(1 .. Buffer_Last
) :=
785 Buffer
(1 .. Buffer_Last
);
786 Long_Project
:= Name_Find
;
788 -- Check if the long project is imported or extended
790 The_Project
:= Imported_Or_Extended_Project_Of
791 (Current_Project
, In_Tree
, Long_Project
);
793 -- If the long project exists, then this is the prefix
796 if The_Project
/= Empty_Node
then
797 First_Attribute
:= Attribute_First
;
798 The_Package
:= Empty_Node
;
801 -- Otherwise, check if the short project is imported
804 The_Project
:= Imported_Or_Extended_Project_Of
805 (Current_Project
, In_Tree
,
808 -- If the short project does not exist, we report an
811 if The_Project
= Empty_Node
then
812 Error_Msg_Name_1
:= Long_Project
;
813 Error_Msg_Name_2
:= Short_Project
;
814 Error_Msg
("unknown projects % or %",
815 Names
.Table
(1).Location
);
816 The_Package
:= Empty_Node
;
817 First_Attribute
:= Attribute_First
;
820 -- Now, we check if the package has been declared
824 First_Package_Of
(The_Project
, In_Tree
);
825 while The_Package
/= Empty_Node
826 and then Name_Of
(The_Package
, In_Tree
) /=
827 Names
.Table
(Names
.Last
).Name
830 Next_Package_In_Project
(The_Package
, In_Tree
);
833 -- If it has not, then we report an error
835 if The_Package
= Empty_Node
then
837 Names
.Table
(Names
.Last
).Name
;
838 Error_Msg_Name_2
:= Short_Project
;
839 Error_Msg
("package % not declared in project %",
840 Names
.Table
(Names
.Last
).Location
);
841 First_Attribute
:= Attribute_First
;
844 -- Otherwise, we have the correct project and
849 (Package_Id_Of
(The_Package
, In_Tree
));
859 Current_Project
=> The_Project
,
860 Current_Package
=> The_Package
,
861 First_Attribute
=> First_Attribute
);
868 (Of_Kind
=> N_Variable_Reference
, In_Tree
=> In_Tree
);
870 if Look_For_Variable
then
880 -- Simple variable name
882 Set_Name_Of
(Variable
, In_Tree
, To
=> Names
.Table
(1).Name
);
886 -- Variable name with a simple name prefix that can be
887 -- a project name or a package name. Project names have
888 -- priority over package names.
890 Set_Name_Of
(Variable
, In_Tree
, To
=> Names
.Table
(2).Name
);
892 -- Check if it can be a package name
894 The_Package
:= First_Package_Of
(Current_Project
, In_Tree
);
896 while The_Package
/= Empty_Node
897 and then Name_Of
(The_Package
, In_Tree
) /=
901 Next_Package_In_Project
(The_Package
, In_Tree
);
904 -- Now look for a possible project name
906 The_Project
:= Imported_Or_Extended_Project_Of
907 (Current_Project
, In_Tree
, Names
.Table
(1).Name
);
909 if The_Project
/= Empty_Node
then
910 Specified_Project
:= The_Project
;
912 elsif The_Package
= Empty_Node
then
913 Error_Msg_Name_1
:= Names
.Table
(1).Name
;
914 Error_Msg
("unknown package or project %",
915 Names
.Table
(1).Location
);
916 Look_For_Variable
:= False;
919 Specified_Package
:= The_Package
;
924 -- Variable name with a prefix that is either a project name
925 -- made of several simple names, or a project name followed
926 -- by a package name.
929 (Variable
, In_Tree
, To
=> Names
.Table
(Names
.Last
).Name
);
932 Short_Project
: Name_Id
;
933 Long_Project
: Name_Id
;
936 -- First, we get the two possible project names
942 -- Add all the simple names, except the last two
944 for Index
in 1 .. Names
.Last
- 2 loop
946 (Get_Name_String
(Names
.Table
(Index
).Name
),
947 Buffer
, Buffer_Last
);
949 if Index
/= Names
.Last
- 2 then
950 Add_To_Buffer
(".", Buffer
, Buffer_Last
);
954 Name_Len
:= Buffer_Last
;
955 Name_Buffer
(1 .. Name_Len
) := Buffer
(1 .. Buffer_Last
);
956 Short_Project
:= Name_Find
;
958 -- Add the simple name before the name of the variable
960 Add_To_Buffer
(".", Buffer
, Buffer_Last
);
962 (Get_Name_String
(Names
.Table
(Names
.Last
- 1).Name
),
963 Buffer
, Buffer_Last
);
964 Name_Len
:= Buffer_Last
;
965 Name_Buffer
(1 .. Name_Len
) := Buffer
(1 .. Buffer_Last
);
966 Long_Project
:= Name_Find
;
968 -- Check if the prefix is the name of an imported or
971 The_Project
:= Imported_Or_Extended_Project_Of
972 (Current_Project
, In_Tree
, Long_Project
);
974 if The_Project
/= Empty_Node
then
975 Specified_Project
:= The_Project
;
978 -- Now check if the prefix may be a project name followed
979 -- by a package name.
981 -- First check for a possible project name
983 The_Project
:= Imported_Or_Extended_Project_Of
984 (Current_Project
, In_Tree
, Short_Project
);
986 if The_Project
= Empty_Node
then
987 -- Unknown prefix, report an error
989 Error_Msg_Name_1
:= Long_Project
;
990 Error_Msg_Name_2
:= Short_Project
;
991 Error_Msg
("unknown projects % or %",
992 Names
.Table
(1).Location
);
993 Look_For_Variable
:= False;
996 Specified_Project
:= The_Project
;
998 -- Now look for the package in this project
1000 The_Package
:= First_Package_Of
(The_Project
, In_Tree
);
1002 while The_Package
/= Empty_Node
1003 and then Name_Of
(The_Package
, In_Tree
) /=
1004 Names
.Table
(Names
.Last
- 1).Name
1007 Next_Package_In_Project
(The_Package
, In_Tree
);
1010 if The_Package
= Empty_Node
then
1011 -- The package does not vexist, report an error
1013 Error_Msg_Name_1
:= Names
.Table
(2).Name
;
1014 Error_Msg
("unknown package %",
1015 Names
.Table
(Names
.Last
- 1).Location
);
1016 Look_For_Variable
:= False;
1019 Specified_Package
:= The_Package
;
1027 if Look_For_Variable
then
1028 Variable_Name
:= Name_Of
(Variable
, In_Tree
);
1029 Set_Project_Node_Of
(Variable
, In_Tree
, To
=> Specified_Project
);
1030 Set_Package_Node_Of
(Variable
, In_Tree
, To
=> Specified_Package
);
1032 if Specified_Project
/= Empty_Node
then
1033 The_Project
:= Specified_Project
;
1036 The_Project
:= Current_Project
;
1039 Current_Variable
:= Empty_Node
;
1041 -- Look for this variable
1043 -- If a package was specified, check if the variable has been
1044 -- declared in this package.
1046 if Specified_Package
/= Empty_Node
then
1048 First_Variable_Of
(Specified_Package
, In_Tree
);
1050 while Current_Variable
/= Empty_Node
1052 Name_Of
(Current_Variable
, In_Tree
) /= Variable_Name
1054 Current_Variable
:= Next_Variable
(Current_Variable
, In_Tree
);
1058 -- Otherwise, if no project has been specified and we are in
1059 -- a package, first check if the variable has been declared in
1062 if Specified_Project
= Empty_Node
1063 and then Current_Package
/= Empty_Node
1066 First_Variable_Of
(Current_Package
, In_Tree
);
1068 while Current_Variable
/= Empty_Node
1069 and then Name_Of
(Current_Variable
, In_Tree
) /= Variable_Name
1072 Next_Variable
(Current_Variable
, In_Tree
);
1076 -- If we have not found the variable in the package, check if the
1077 -- variable has been declared in the project.
1079 if Current_Variable
= Empty_Node
then
1080 Current_Variable
:= First_Variable_Of
(The_Project
, In_Tree
);
1082 while Current_Variable
/= Empty_Node
1083 and then Name_Of
(Current_Variable
, In_Tree
) /= Variable_Name
1086 Next_Variable
(Current_Variable
, In_Tree
);
1091 -- If the variable was not found, report an error
1093 if Current_Variable
= Empty_Node
then
1094 Error_Msg_Name_1
:= Variable_Name
;
1096 ("unknown variable %", Names
.Table
(Names
.Last
).Location
);
1100 if Current_Variable
/= Empty_Node
then
1101 Set_Expression_Kind_Of
1103 To
=> Expression_Kind_Of
(Current_Variable
, In_Tree
));
1106 Kind_Of
(Current_Variable
, In_Tree
) = N_Typed_Variable_Declaration
1110 To
=> String_Type_Of
(Current_Variable
, In_Tree
));
1114 -- If the variable is followed by a left parenthesis, report an error
1115 -- but attempt to scan the index.
1117 if Token
= Tok_Left_Paren
then
1118 Error_Msg
("\variables cannot be associative arrays", Token_Ptr
);
1120 Expect
(Tok_String_Literal
, "literal string");
1122 if Token
= Tok_String_Literal
then
1124 Expect
(Tok_Right_Paren
, "`)`");
1126 if Token
= Tok_Right_Paren
then
1131 end Parse_Variable_Reference
;
1133 ---------------------------------
1134 -- Start_New_Case_Construction --
1135 ---------------------------------
1137 procedure Start_New_Case_Construction
1138 (In_Tree
: Project_Node_Tree_Ref
;
1139 String_Type
: Project_Node_Id
)
1141 Current_String
: Project_Node_Id
;
1144 -- Set Choice_First, depending on whether is the first case
1145 -- construction or not.
1147 if Choice_First
= 0 then
1149 Choices
.Set_Last
(First_Choice_Node_Id
);
1151 Choice_First
:= Choices
.Last
+ 1;
1154 -- Add to table Choices the literal of the string type
1156 if String_Type
/= Empty_Node
then
1157 Current_String
:= First_Literal_String
(String_Type
, In_Tree
);
1159 while Current_String
/= Empty_Node
loop
1160 Add
(This_String
=> String_Value_Of
(Current_String
, In_Tree
));
1161 Current_String
:= Next_Literal_String
(Current_String
, In_Tree
);
1165 -- Set the value of the last choice in table Choice_Lasts
1167 Choice_Lasts
.Increment_Last
;
1168 Choice_Lasts
.Table
(Choice_Lasts
.Last
) := Choices
.Last
;
1170 end Start_New_Case_Construction
;
1177 (In_Tree
: Project_Node_Tree_Ref
;
1178 Term
: out Project_Node_Id
;
1179 Expr_Kind
: in out Variable_Kind
;
1180 Current_Project
: Project_Node_Id
;
1181 Current_Package
: Project_Node_Id
;
1182 Optional_Index
: Boolean)
1184 Next_Term
: Project_Node_Id
:= Empty_Node
;
1185 Term_Id
: Project_Node_Id
:= Empty_Node
;
1186 Current_Expression
: Project_Node_Id
:= Empty_Node
;
1187 Next_Expression
: Project_Node_Id
:= Empty_Node
;
1188 Current_Location
: Source_Ptr
:= No_Location
;
1189 Reference
: Project_Node_Id
:= Empty_Node
;
1192 -- Declare a new node for the term
1194 Term
:= Default_Project_Node
(Of_Kind
=> N_Term
, In_Tree
=> In_Tree
);
1195 Set_Location_Of
(Term
, In_Tree
, To
=> Token_Ptr
);
1198 when Tok_Left_Paren
=>
1200 -- If we have a left parenthesis and we don't know the expression
1201 -- kind, then this is a string list.
1212 -- If we already know that this is a single string, report
1213 -- an error, but set the expression kind to string list to
1214 -- avoid several errors.
1218 ("literal string list cannot appear in a string",
1222 -- Declare a new node for this literal string list
1224 Term_Id
:= Default_Project_Node
1225 (Of_Kind
=> N_Literal_String_List
,
1227 And_Expr_Kind
=> List
);
1228 Set_Current_Term
(Term
, In_Tree
, To
=> Term_Id
);
1229 Set_Location_Of
(Term
, In_Tree
, To
=> Token_Ptr
);
1231 -- Scan past the left parenthesis
1235 -- If the left parenthesis is immediately followed by a right
1236 -- parenthesis, the literal string list is empty.
1238 if Token
= Tok_Right_Paren
then
1242 -- Otherwise, we parse the expression(s) in the literal string
1246 Current_Location
:= Token_Ptr
;
1248 (In_Tree
=> In_Tree
,
1249 Expression
=> Next_Expression
,
1250 Current_Project
=> Current_Project
,
1251 Current_Package
=> Current_Package
,
1252 Optional_Index
=> Optional_Index
);
1254 -- The expression kind is String list, report an error
1256 if Expression_Kind_Of
(Next_Expression
, In_Tree
) = List
then
1257 Error_Msg
("single expression expected",
1261 -- If Current_Expression is empty, it means that the
1262 -- expression is the first in the string list.
1264 if Current_Expression
= Empty_Node
then
1265 Set_First_Expression_In_List
1266 (Term_Id
, In_Tree
, To
=> Next_Expression
);
1268 Set_Next_Expression_In_List
1269 (Current_Expression
, In_Tree
, To
=> Next_Expression
);
1272 Current_Expression
:= Next_Expression
;
1274 -- If there is a comma, continue with the next expression
1276 exit when Token
/= Tok_Comma
;
1277 Scan
(In_Tree
); -- past the comma
1280 -- We expect a closing right parenthesis
1282 Expect
(Tok_Right_Paren
, "`)`");
1284 if Token
= Tok_Right_Paren
then
1289 when Tok_String_Literal
=>
1291 -- If we don't know the expression kind (first term), then it is
1294 if Expr_Kind
= Undefined
then
1295 Expr_Kind
:= Single
;
1298 -- Declare a new node for the string literal
1301 Default_Project_Node
1302 (Of_Kind
=> N_Literal_String
, In_Tree
=> In_Tree
);
1303 Set_Current_Term
(Term
, In_Tree
, To
=> Term_Id
);
1304 Set_String_Value_Of
(Term_Id
, In_Tree
, To
=> Token_Name
);
1306 -- Scan past the string literal
1310 -- Check for possible index expression
1312 if Token
= Tok_At
then
1313 if not Optional_Index
then
1314 Error_Msg
("index not allowed here", Token_Ptr
);
1317 if Token
= Tok_Integer_Literal
then
1321 -- Set the index value
1325 Expect
(Tok_Integer_Literal
, "integer literal");
1327 if Token
= Tok_Integer_Literal
then
1329 Index
: constant Int
:= UI_To_Int
(Int_Literal_Value
);
1332 Error_Msg
("index cannot be zero", Token_Ptr
);
1335 (Term_Id
, In_Tree
, To
=> Index
);
1344 when Tok_Identifier
=>
1345 Current_Location
:= Token_Ptr
;
1347 -- Get the variable or attribute reference
1349 Parse_Variable_Reference
1350 (In_Tree
=> In_Tree
,
1351 Variable
=> Reference
,
1352 Current_Project
=> Current_Project
,
1353 Current_Package
=> Current_Package
);
1354 Set_Current_Term
(Term
, In_Tree
, To
=> Reference
);
1356 if Reference
/= Empty_Node
then
1358 -- If we don't know the expression kind (first term), then it
1359 -- has the kind of the variable or attribute reference.
1361 if Expr_Kind
= Undefined
then
1362 Expr_Kind
:= Expression_Kind_Of
(Reference
, In_Tree
);
1364 elsif Expr_Kind
= Single
1365 and then Expression_Kind_Of
(Reference
, In_Tree
) = List
1367 -- If the expression is a single list, and the reference is
1368 -- a string list, report an error, and set the expression
1369 -- kind to string list to avoid multiple errors.
1373 ("list variable cannot appear in single string expression",
1380 -- project can appear in an expression as the prefix of an
1381 -- attribute reference of the current project.
1383 Current_Location
:= Token_Ptr
;
1385 Expect
(Tok_Apostrophe
, "`'`");
1387 if Token
= Tok_Apostrophe
then
1389 (In_Tree
=> In_Tree
,
1390 Reference
=> Reference
,
1391 First_Attribute
=> Prj
.Attr
.Attribute_First
,
1392 Current_Project
=> Current_Project
,
1393 Current_Package
=> Empty_Node
);
1394 Set_Current_Term
(Term
, In_Tree
, To
=> Reference
);
1397 -- Same checks as above for the expression kind
1399 if Reference
/= Empty_Node
then
1400 if Expr_Kind
= Undefined
then
1401 Expr_Kind
:= Expression_Kind_Of
(Reference
, In_Tree
);
1403 elsif Expr_Kind
= Single
1404 and then Expression_Kind_Of
(Reference
, In_Tree
) = List
1407 ("lists cannot appear in single string expression",
1412 when Tok_External
=>
1413 -- An external reference is always a single string
1415 if Expr_Kind
= Undefined
then
1416 Expr_Kind
:= Single
;
1420 (In_Tree
=> In_Tree
, External_Value
=> Reference
);
1421 Set_Current_Term
(Term
, In_Tree
, To
=> Reference
);
1424 Error_Msg
("cannot be part of an expression", Token_Ptr
);
1429 -- If there is an '&', call Terms recursively
1431 if Token
= Tok_Ampersand
then
1433 -- Scan past the '&'
1438 (In_Tree
=> In_Tree
,
1440 Expr_Kind
=> Expr_Kind
,
1441 Current_Project
=> Current_Project
,
1442 Current_Package
=> Current_Package
,
1443 Optional_Index
=> Optional_Index
);
1445 -- And link the next term to this term
1447 Set_Next_Term
(Term
, In_Tree
, To
=> Next_Term
);