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 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 ------------------------------------------------------------------------------
26 with Err_Vars
; use Err_Vars
;
27 with Prj
.Attr
; use Prj
.Attr
;
28 with Prj
.Err
; use Prj
.Err
;
31 with Uintp
; use Uintp
;
33 package body Prj
.Strt
is
35 Buffer
: String_Access
;
36 Buffer_Last
: Natural := 0;
38 type Choice_String
is record
40 Already_Used
: Boolean := False;
42 -- The string of a case label, and an indication that it has already
43 -- been used (to avoid duplicate case labels).
45 Choices_Initial
: constant := 10;
46 Choices_Increment
: constant := 100;
47 -- These should be in alloc.ads
49 Choice_Node_Low_Bound
: constant := 0;
50 Choice_Node_High_Bound
: constant := 099_999_999
;
51 -- In practice, infinite
53 type Choice_Node_Id
is
54 range Choice_Node_Low_Bound
.. Choice_Node_High_Bound
;
56 First_Choice_Node_Id
: constant Choice_Node_Id
:=
57 Choice_Node_Low_Bound
;
61 (Table_Component_Type
=> Choice_String
,
62 Table_Index_Type
=> Choice_Node_Id
'Base,
63 Table_Low_Bound
=> First_Choice_Node_Id
,
64 Table_Initial
=> Choices_Initial
,
65 Table_Increment
=> Choices_Increment
,
66 Table_Name
=> "Prj.Strt.Choices");
67 -- Used to store the case labels and check that there is no duplicate
69 package Choice_Lasts
is
71 (Table_Component_Type
=> Choice_Node_Id
,
72 Table_Index_Type
=> Nat
,
75 Table_Increment
=> 100,
76 Table_Name
=> "Prj.Strt.Choice_Lasts");
77 -- Used to store the indices of the choices in table Choices,
78 -- to distinguish nested case constructions.
80 Choice_First
: Choice_Node_Id
:= 0;
81 -- Index in table Choices of the first case label of the current
82 -- case construction. Zero means no current case construction.
84 type Name_Location
is record
85 Name
: Name_Id
:= No_Name
;
86 Location
: Source_Ptr
:= No_Location
;
88 -- Store the identifier and the location of a simple name
92 (Table_Component_Type
=> Name_Location
,
93 Table_Index_Type
=> Nat
,
96 Table_Increment
=> 100,
97 Table_Name
=> "Prj.Strt.Names");
98 -- Used to accumulate the single names of a name
100 procedure Add
(This_String
: Name_Id
);
101 -- Add a string to the case label list, indicating that it has not
104 procedure Add_To_Names
(NL
: Name_Location
);
105 -- Add one single names to table Names
107 procedure External_Reference
108 (In_Tree
: Project_Node_Tree_Ref
;
109 Current_Project
: Project_Node_Id
;
110 Current_Package
: Project_Node_Id
;
111 External_Value
: out Project_Node_Id
);
112 -- 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
) in
215 Case_Insensitive_Associative_Array
..
216 Optional_Index_Case_Insensitive_Associative_Array
);
218 -- Scan past the attribute name
222 -- If the attribute is an associative array, get the index
224 if Attribute_Kind_Of
(Current_Attribute
) /= Single
then
225 Expect
(Tok_Left_Paren
, "`(`");
227 if Token
= Tok_Left_Paren
then
229 Expect
(Tok_String_Literal
, "literal string");
231 if Token
= Tok_String_Literal
then
232 Set_Associative_Array_Index_Of
233 (Reference
, In_Tree
, To
=> Token_Name
);
235 Expect
(Tok_Right_Paren
, "`)`");
237 if Token
= Tok_Right_Paren
then
245 -- Change name of obsolete attributes
247 if Reference
/= Empty_Node
then
248 case Name_Of
(Reference
, In_Tree
) is
249 when Snames
.Name_Specification
=>
250 Set_Name_Of
(Reference
, In_Tree
, To
=> Snames
.Name_Spec
);
252 when Snames
.Name_Specification_Suffix
=>
254 (Reference
, In_Tree
, To
=> Snames
.Name_Spec_Suffix
);
256 when Snames
.Name_Implementation
=>
257 Set_Name_Of
(Reference
, In_Tree
, To
=> Snames
.Name_Body
);
259 when Snames
.Name_Implementation_Suffix
=>
261 (Reference
, In_Tree
, To
=> Snames
.Name_Body_Suffix
);
268 end Attribute_Reference
;
270 ---------------------------
271 -- End_Case_Construction --
272 ---------------------------
274 procedure End_Case_Construction
275 (Check_All_Labels
: Boolean;
276 Case_Location
: Source_Ptr
)
278 Non_Used
: Natural := 0;
279 First_Non_Used
: Choice_Node_Id
:= First_Choice_Node_Id
;
281 -- First, if Check_All_Labels is True, check if all values
282 -- of the string type have been used.
284 if Check_All_Labels
then
285 for Choice
in Choice_First
.. Choices
.Last
loop
286 if not Choices
.Table
(Choice
).Already_Used
then
287 Non_Used
:= Non_Used
+ 1;
290 First_Non_Used
:= Choice
;
295 -- If only one is not used, report a single warning for this value
298 Error_Msg_Name_1
:= Choices
.Table
(First_Non_Used
).The_String
;
299 Error_Msg
("?value %% is not used as label", Case_Location
);
301 -- If several are not used, report a warning for each one of them
303 elsif Non_Used
> 1 then
305 ("?the following values are not used as labels:",
308 for Choice
in First_Non_Used
.. Choices
.Last
loop
309 if not Choices
.Table
(Choice
).Already_Used
then
310 Error_Msg_Name_1
:= Choices
.Table
(Choice
).The_String
;
311 Error_Msg
("\?%%", Case_Location
);
317 -- If this is the only case construction, empty the tables
319 if Choice_Lasts
.Last
= 1 then
320 Choice_Lasts
.Set_Last
(0);
321 Choices
.Set_Last
(First_Choice_Node_Id
);
324 elsif Choice_Lasts
.Last
= 2 then
326 -- This is the second case construction, set the tables to the first
328 Choice_Lasts
.Set_Last
(1);
329 Choices
.Set_Last
(Choice_Lasts
.Table
(1));
333 -- This is the 3rd or more case construction, set the tables to the
336 Choice_Lasts
.Decrement_Last
;
337 Choices
.Set_Last
(Choice_Lasts
.Table
(Choice_Lasts
.Last
));
338 Choice_First
:= Choice_Lasts
.Table
(Choice_Lasts
.Last
- 1) + 1;
340 end End_Case_Construction
;
342 ------------------------
343 -- External_Reference --
344 ------------------------
346 procedure External_Reference
347 (In_Tree
: Project_Node_Tree_Ref
;
348 Current_Project
: Project_Node_Id
;
349 Current_Package
: Project_Node_Id
;
350 External_Value
: out Project_Node_Id
)
352 Field_Id
: Project_Node_Id
:= Empty_Node
;
357 (Of_Kind
=> N_External_Value
,
359 And_Expr_Kind
=> Single
);
360 Set_Location_Of
(External_Value
, In_Tree
, To
=> Token_Ptr
);
362 -- The current token is External
364 -- Get the left parenthesis
367 Expect
(Tok_Left_Paren
, "`(`");
369 -- Scan past the left parenthesis
371 if Token
= Tok_Left_Paren
then
375 -- Get the name of the external reference
377 Expect
(Tok_String_Literal
, "literal string");
379 if Token
= Tok_String_Literal
then
382 (Of_Kind
=> N_Literal_String
,
384 And_Expr_Kind
=> Single
);
385 Set_String_Value_Of
(Field_Id
, In_Tree
, To
=> Token_Name
);
386 Set_External_Reference_Of
(External_Value
, In_Tree
, To
=> Field_Id
);
388 -- Scan past the first argument
394 when Tok_Right_Paren
=>
395 Scan
(In_Tree
); -- scan past right paren
398 Scan
(In_Tree
); -- scan past comma
400 -- Get the string expression for the default
403 Loc
: constant Source_Ptr
:= Token_Ptr
;
408 Expression
=> Field_Id
,
409 Current_Project
=> Current_Project
,
410 Current_Package
=> Current_Package
,
411 Optional_Index
=> False);
413 if Expression_Kind_Of
(Field_Id
, In_Tree
) = List
then
414 Error_Msg
("expression must be a single string", Loc
);
416 Set_External_Default_Of
417 (External_Value
, In_Tree
, To
=> Field_Id
);
421 Expect
(Tok_Right_Paren
, "`)`");
423 if Token
= Tok_Right_Paren
then
424 Scan
(In_Tree
); -- scan past right paren
428 Error_Msg
("`,` or `)` expected", Token_Ptr
);
431 end External_Reference
;
433 -----------------------
434 -- Parse_Choice_List --
435 -----------------------
437 procedure Parse_Choice_List
438 (In_Tree
: Project_Node_Tree_Ref
;
439 First_Choice
: out Project_Node_Id
)
441 Current_Choice
: Project_Node_Id
:= Empty_Node
;
442 Next_Choice
: Project_Node_Id
:= Empty_Node
;
443 Choice_String
: Name_Id
:= No_Name
;
444 Found
: Boolean := False;
447 -- Declare the node of the first choice
451 (Of_Kind
=> N_Literal_String
,
453 And_Expr_Kind
=> Single
);
455 -- Initially Current_Choice is the same as First_Choice
457 Current_Choice
:= First_Choice
;
460 Expect
(Tok_String_Literal
, "literal string");
461 exit when Token
/= Tok_String_Literal
;
462 Set_Location_Of
(Current_Choice
, In_Tree
, To
=> Token_Ptr
);
463 Choice_String
:= Token_Name
;
465 -- Give the string value to the current choice
467 Set_String_Value_Of
(Current_Choice
, In_Tree
, To
=> Choice_String
);
469 -- Check if the label is part of the string type and if it has not
470 -- been already used.
473 for Choice
in Choice_First
.. Choices
.Last
loop
474 if Choices
.Table
(Choice
).The_String
= Choice_String
then
476 -- This label is part of the string type
480 if Choices
.Table
(Choice
).Already_Used
then
482 -- But it has already appeared in a choice list for this
483 -- case construction so report an error.
485 Error_Msg_Name_1
:= Choice_String
;
486 Error_Msg
("duplicate case label %%", Token_Ptr
);
489 Choices
.Table
(Choice
).Already_Used
:= True;
496 -- If the label is not part of the string list, report an error
499 Error_Msg_Name_1
:= Choice_String
;
500 Error_Msg
("illegal case label %%", Token_Ptr
);
503 -- Scan past the label
507 -- If there is no '|', we are done
509 if Token
= Tok_Vertical_Bar
then
511 -- Otherwise, declare the node of the next choice, link it to
512 -- Current_Choice and set Current_Choice to this new node.
516 (Of_Kind
=> N_Literal_String
,
518 And_Expr_Kind
=> Single
);
519 Set_Next_Literal_String
520 (Current_Choice
, In_Tree
, To
=> Next_Choice
);
521 Current_Choice
:= Next_Choice
;
527 end Parse_Choice_List
;
529 ----------------------
530 -- Parse_Expression --
531 ----------------------
533 procedure Parse_Expression
534 (In_Tree
: Project_Node_Tree_Ref
;
535 Expression
: out Project_Node_Id
;
536 Current_Project
: Project_Node_Id
;
537 Current_Package
: Project_Node_Id
;
538 Optional_Index
: Boolean)
540 First_Term
: Project_Node_Id
:= Empty_Node
;
541 Expression_Kind
: Variable_Kind
:= Undefined
;
544 -- Declare the node of the expression
547 Default_Project_Node
(Of_Kind
=> N_Expression
, In_Tree
=> In_Tree
);
548 Set_Location_Of
(Expression
, In_Tree
, To
=> Token_Ptr
);
550 -- Parse the term or terms of the expression
552 Terms
(In_Tree
=> In_Tree
,
554 Expr_Kind
=> Expression_Kind
,
555 Current_Project
=> Current_Project
,
556 Current_Package
=> Current_Package
,
557 Optional_Index
=> Optional_Index
);
559 -- Set the first term and the expression kind
561 Set_First_Term
(Expression
, In_Tree
, To
=> First_Term
);
562 Set_Expression_Kind_Of
(Expression
, In_Tree
, To
=> Expression_Kind
);
563 end Parse_Expression
;
565 ----------------------------
566 -- Parse_String_Type_List --
567 ----------------------------
569 procedure Parse_String_Type_List
570 (In_Tree
: Project_Node_Tree_Ref
;
571 First_String
: out Project_Node_Id
)
573 Last_String
: Project_Node_Id
:= Empty_Node
;
574 Next_String
: Project_Node_Id
:= Empty_Node
;
575 String_Value
: Name_Id
:= No_Name
;
578 -- Declare the node of the first string
582 (Of_Kind
=> N_Literal_String
,
584 And_Expr_Kind
=> Single
);
586 -- Initially, Last_String is the same as First_String
588 Last_String
:= First_String
;
591 Expect
(Tok_String_Literal
, "literal string");
592 exit when Token
/= Tok_String_Literal
;
593 String_Value
:= Token_Name
;
595 -- Give its string value to Last_String
597 Set_String_Value_Of
(Last_String
, In_Tree
, To
=> String_Value
);
598 Set_Location_Of
(Last_String
, In_Tree
, To
=> Token_Ptr
);
600 -- Now, check if the string is already part of the string type
603 Current
: Project_Node_Id
:= First_String
;
606 while Current
/= Last_String
loop
607 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 if Names
.Table
(1).Name
=
709 Name_Of
(Current_Project
, In_Tree
)
711 The_Project
:= Current_Project
;
715 Imported_Or_Extended_Project_Of
716 (Current_Project
, In_Tree
, Names
.Table
(1).Name
);
719 if The_Project
= Empty_Node
then
721 -- If it is neither a project name nor a package name,
724 if First_Attribute
= Empty_Attribute
then
725 Error_Msg_Name_1
:= Names
.Table
(1).Name
;
726 Error_Msg
("unknown project %",
727 Names
.Table
(1).Location
);
728 First_Attribute
:= Attribute_First
;
731 -- If it is a package name, check if the package has
732 -- already been declared in the current project.
735 First_Package_Of
(Current_Project
, In_Tree
);
737 while The_Package
/= Empty_Node
738 and then Name_Of
(The_Package
, In_Tree
) /=
742 Next_Package_In_Project
(The_Package
, In_Tree
);
745 -- If it has not been already declared, report an
748 if The_Package
= Empty_Node
then
749 Error_Msg_Name_1
:= Names
.Table
(1).Name
;
750 Error_Msg
("package % not yet defined",
751 Names
.Table
(1).Location
);
756 -- It is a project name
758 First_Attribute
:= Attribute_First
;
759 The_Package
:= Empty_Node
;
764 -- We have either a project name made of several simple
765 -- names (long project), or a project name (short project)
766 -- followed by a package name. The long project name has
770 Short_Project
: Name_Id
;
771 Long_Project
: Name_Id
;
778 -- Get the name of the short project
780 for Index
in 1 .. Names
.Last
- 1 loop
782 (Get_Name_String
(Names
.Table
(Index
).Name
),
783 Buffer
, Buffer_Last
);
785 if Index
/= Names
.Last
- 1 then
786 Add_To_Buffer
(".", Buffer
, Buffer_Last
);
790 Name_Len
:= Buffer_Last
;
791 Name_Buffer
(1 .. Buffer_Last
) :=
792 Buffer
(1 .. Buffer_Last
);
793 Short_Project
:= Name_Find
;
795 -- Now, add the last simple name to get the name of the
798 Add_To_Buffer
(".", Buffer
, Buffer_Last
);
800 (Get_Name_String
(Names
.Table
(Names
.Last
).Name
),
801 Buffer
, Buffer_Last
);
802 Name_Len
:= Buffer_Last
;
803 Name_Buffer
(1 .. Buffer_Last
) :=
804 Buffer
(1 .. Buffer_Last
);
805 Long_Project
:= Name_Find
;
807 -- Check if the long project is imported or extended
809 if Long_Project
= Name_Of
(Current_Project
, In_Tree
) then
810 The_Project
:= Current_Project
;
814 Imported_Or_Extended_Project_Of
820 -- If the long project exists, then this is the prefix
823 if The_Project
/= Empty_Node
then
824 First_Attribute
:= Attribute_First
;
825 The_Package
:= Empty_Node
;
828 -- Otherwise, check if the short project is imported
832 Name_Of
(Current_Project
, In_Tree
)
834 The_Project
:= Current_Project
;
837 The_Project
:= Imported_Or_Extended_Project_Of
838 (Current_Project
, In_Tree
,
842 -- If short project does not exist, report an error
844 if The_Project
= Empty_Node
then
845 Error_Msg_Name_1
:= Long_Project
;
846 Error_Msg_Name_2
:= Short_Project
;
847 Error_Msg
("unknown projects % or %",
848 Names
.Table
(1).Location
);
849 The_Package
:= Empty_Node
;
850 First_Attribute
:= Attribute_First
;
853 -- Now, we check if the package has been declared
857 First_Package_Of
(The_Project
, In_Tree
);
858 while The_Package
/= Empty_Node
859 and then Name_Of
(The_Package
, In_Tree
) /=
860 Names
.Table
(Names
.Last
).Name
863 Next_Package_In_Project
(The_Package
, In_Tree
);
866 -- If it has not, then we report an error
868 if The_Package
= Empty_Node
then
870 Names
.Table
(Names
.Last
).Name
;
871 Error_Msg_Name_2
:= Short_Project
;
872 Error_Msg
("package % not declared in project %",
873 Names
.Table
(Names
.Last
).Location
);
874 First_Attribute
:= Attribute_First
;
877 -- Otherwise, we have the correct project and
882 (Package_Id_Of
(The_Package
, In_Tree
));
892 Current_Project
=> The_Project
,
893 Current_Package
=> The_Package
,
894 First_Attribute
=> First_Attribute
);
901 (Of_Kind
=> N_Variable_Reference
, In_Tree
=> In_Tree
);
903 if Look_For_Variable
then
907 -- Cannot happen (so why null instead of raise PE???)
913 -- Simple variable name
915 Set_Name_Of
(Variable
, In_Tree
, To
=> Names
.Table
(1).Name
);
919 -- Variable name with a simple name prefix that can be
920 -- a project name or a package name. Project names have
921 -- priority over package names.
923 Set_Name_Of
(Variable
, In_Tree
, To
=> Names
.Table
(2).Name
);
925 -- Check if it can be a package name
927 The_Package
:= First_Package_Of
(Current_Project
, In_Tree
);
929 while The_Package
/= Empty_Node
930 and then Name_Of
(The_Package
, In_Tree
) /=
934 Next_Package_In_Project
(The_Package
, In_Tree
);
937 -- Now look for a possible project name
939 The_Project
:= Imported_Or_Extended_Project_Of
940 (Current_Project
, In_Tree
, Names
.Table
(1).Name
);
942 if The_Project
/= Empty_Node
then
943 Specified_Project
:= The_Project
;
945 elsif The_Package
= Empty_Node
then
946 Error_Msg_Name_1
:= Names
.Table
(1).Name
;
947 Error_Msg
("unknown package or project %",
948 Names
.Table
(1).Location
);
949 Look_For_Variable
:= False;
952 Specified_Package
:= The_Package
;
957 -- Variable name with a prefix that is either a project name
958 -- made of several simple names, or a project name followed
959 -- by a package name.
962 (Variable
, In_Tree
, To
=> Names
.Table
(Names
.Last
).Name
);
965 Short_Project
: Name_Id
;
966 Long_Project
: Name_Id
;
969 -- First, we get the two possible project names
975 -- Add all the simple names, except the last two
977 for Index
in 1 .. Names
.Last
- 2 loop
979 (Get_Name_String
(Names
.Table
(Index
).Name
),
980 Buffer
, Buffer_Last
);
982 if Index
/= Names
.Last
- 2 then
983 Add_To_Buffer
(".", Buffer
, Buffer_Last
);
987 Name_Len
:= Buffer_Last
;
988 Name_Buffer
(1 .. Name_Len
) := Buffer
(1 .. Buffer_Last
);
989 Short_Project
:= Name_Find
;
991 -- Add the simple name before the name of the variable
993 Add_To_Buffer
(".", Buffer
, Buffer_Last
);
995 (Get_Name_String
(Names
.Table
(Names
.Last
- 1).Name
),
996 Buffer
, Buffer_Last
);
997 Name_Len
:= Buffer_Last
;
998 Name_Buffer
(1 .. Name_Len
) := Buffer
(1 .. Buffer_Last
);
999 Long_Project
:= Name_Find
;
1001 -- Check if the prefix is the name of an imported or
1002 -- extended project.
1004 The_Project
:= Imported_Or_Extended_Project_Of
1005 (Current_Project
, In_Tree
, Long_Project
);
1007 if The_Project
/= Empty_Node
then
1008 Specified_Project
:= The_Project
;
1011 -- Now check if the prefix may be a project name followed
1012 -- by a package name.
1014 -- First check for a possible project name
1017 Imported_Or_Extended_Project_Of
1018 (Current_Project
, In_Tree
, Short_Project
);
1020 if The_Project
= Empty_Node
then
1021 -- Unknown prefix, report an error
1023 Error_Msg_Name_1
:= Long_Project
;
1024 Error_Msg_Name_2
:= Short_Project
;
1026 ("unknown projects % or %",
1027 Names
.Table
(1).Location
);
1028 Look_For_Variable
:= False;
1031 Specified_Project
:= The_Project
;
1033 -- Now look for the package in this project
1035 The_Package
:= First_Package_Of
(The_Project
, In_Tree
);
1037 while The_Package
/= Empty_Node
1038 and then Name_Of
(The_Package
, In_Tree
) /=
1039 Names
.Table
(Names
.Last
- 1).Name
1042 Next_Package_In_Project
(The_Package
, In_Tree
);
1045 if The_Package
= Empty_Node
then
1047 -- The package does not exist, report an error
1049 Error_Msg_Name_1
:= Names
.Table
(2).Name
;
1050 Error_Msg
("unknown package %",
1051 Names
.Table
(Names
.Last
- 1).Location
);
1052 Look_For_Variable
:= False;
1055 Specified_Package
:= The_Package
;
1063 if Look_For_Variable
then
1064 Variable_Name
:= Name_Of
(Variable
, In_Tree
);
1065 Set_Project_Node_Of
(Variable
, In_Tree
, To
=> Specified_Project
);
1066 Set_Package_Node_Of
(Variable
, In_Tree
, To
=> Specified_Package
);
1068 if Specified_Project
/= Empty_Node
then
1069 The_Project
:= Specified_Project
;
1071 The_Project
:= Current_Project
;
1074 Current_Variable
:= Empty_Node
;
1076 -- Look for this variable
1078 -- If a package was specified, check if the variable has been
1079 -- declared in this package.
1081 if Specified_Package
/= Empty_Node
then
1083 First_Variable_Of
(Specified_Package
, In_Tree
);
1084 while Current_Variable
/= Empty_Node
1086 Name_Of
(Current_Variable
, In_Tree
) /= Variable_Name
1088 Current_Variable
:= Next_Variable
(Current_Variable
, In_Tree
);
1092 -- Otherwise, if no project has been specified and we are in
1093 -- a package, first check if the variable has been declared in
1096 if Specified_Project
= Empty_Node
1097 and then Current_Package
/= Empty_Node
1100 First_Variable_Of
(Current_Package
, In_Tree
);
1101 while Current_Variable
/= Empty_Node
1102 and then Name_Of
(Current_Variable
, In_Tree
) /= Variable_Name
1105 Next_Variable
(Current_Variable
, In_Tree
);
1109 -- If we have not found the variable in the package, check if the
1110 -- variable has been declared in the project.
1112 if Current_Variable
= Empty_Node
then
1113 Current_Variable
:= First_Variable_Of
(The_Project
, In_Tree
);
1114 while Current_Variable
/= Empty_Node
1115 and then Name_Of
(Current_Variable
, In_Tree
) /= Variable_Name
1118 Next_Variable
(Current_Variable
, In_Tree
);
1123 -- If the variable was not found, report an error
1125 if Current_Variable
= Empty_Node
then
1126 Error_Msg_Name_1
:= Variable_Name
;
1128 ("unknown variable %", Names
.Table
(Names
.Last
).Location
);
1132 if Current_Variable
/= Empty_Node
then
1133 Set_Expression_Kind_Of
1135 To
=> Expression_Kind_Of
(Current_Variable
, In_Tree
));
1137 if Kind_Of
(Current_Variable
, In_Tree
) =
1138 N_Typed_Variable_Declaration
1142 To
=> String_Type_Of
(Current_Variable
, In_Tree
));
1146 -- If the variable is followed by a left parenthesis, report an error
1147 -- but attempt to scan the index.
1149 if Token
= Tok_Left_Paren
then
1150 Error_Msg
("\variables cannot be associative arrays", Token_Ptr
);
1152 Expect
(Tok_String_Literal
, "literal string");
1154 if Token
= Tok_String_Literal
then
1156 Expect
(Tok_Right_Paren
, "`)`");
1158 if Token
= Tok_Right_Paren
then
1163 end Parse_Variable_Reference
;
1165 ---------------------------------
1166 -- Start_New_Case_Construction --
1167 ---------------------------------
1169 procedure Start_New_Case_Construction
1170 (In_Tree
: Project_Node_Tree_Ref
;
1171 String_Type
: Project_Node_Id
)
1173 Current_String
: Project_Node_Id
;
1176 -- Set Choice_First, depending on whether this is the first case
1177 -- construction or not.
1179 if Choice_First
= 0 then
1181 Choices
.Set_Last
(First_Choice_Node_Id
);
1183 Choice_First
:= Choices
.Last
+ 1;
1186 -- Add the literal of the string type to the Choices table
1188 if String_Type
/= Empty_Node
then
1189 Current_String
:= First_Literal_String
(String_Type
, In_Tree
);
1190 while Current_String
/= Empty_Node
loop
1191 Add
(This_String
=> String_Value_Of
(Current_String
, In_Tree
));
1192 Current_String
:= Next_Literal_String
(Current_String
, In_Tree
);
1196 -- Set the value of the last choice in table Choice_Lasts
1198 Choice_Lasts
.Increment_Last
;
1199 Choice_Lasts
.Table
(Choice_Lasts
.Last
) := Choices
.Last
;
1200 end Start_New_Case_Construction
;
1207 (In_Tree
: Project_Node_Tree_Ref
;
1208 Term
: out Project_Node_Id
;
1209 Expr_Kind
: in out Variable_Kind
;
1210 Current_Project
: Project_Node_Id
;
1211 Current_Package
: Project_Node_Id
;
1212 Optional_Index
: Boolean)
1214 Next_Term
: Project_Node_Id
:= Empty_Node
;
1215 Term_Id
: Project_Node_Id
:= Empty_Node
;
1216 Current_Expression
: Project_Node_Id
:= Empty_Node
;
1217 Next_Expression
: Project_Node_Id
:= Empty_Node
;
1218 Current_Location
: Source_Ptr
:= No_Location
;
1219 Reference
: Project_Node_Id
:= Empty_Node
;
1222 -- Declare a new node for the term
1224 Term
:= Default_Project_Node
(Of_Kind
=> N_Term
, In_Tree
=> In_Tree
);
1225 Set_Location_Of
(Term
, In_Tree
, To
=> Token_Ptr
);
1228 when Tok_Left_Paren
=>
1230 -- If we have a left parenthesis and we don't know the expression
1231 -- kind, then this is a string list.
1242 -- If we already know that this is a single string, report
1243 -- an error, but set the expression kind to string list to
1244 -- avoid several errors.
1248 ("literal string list cannot appear in a string",
1252 -- Declare a new node for this literal string list
1254 Term_Id
:= Default_Project_Node
1255 (Of_Kind
=> N_Literal_String_List
,
1257 And_Expr_Kind
=> List
);
1258 Set_Current_Term
(Term
, In_Tree
, To
=> Term_Id
);
1259 Set_Location_Of
(Term
, In_Tree
, To
=> Token_Ptr
);
1261 -- Scan past the left parenthesis
1265 -- If the left parenthesis is immediately followed by a right
1266 -- parenthesis, the literal string list is empty.
1268 if Token
= Tok_Right_Paren
then
1272 -- Otherwise parse the expression(s) in the literal string list
1275 Current_Location
:= Token_Ptr
;
1277 (In_Tree
=> In_Tree
,
1278 Expression
=> Next_Expression
,
1279 Current_Project
=> Current_Project
,
1280 Current_Package
=> Current_Package
,
1281 Optional_Index
=> Optional_Index
);
1283 -- The expression kind is String list, report an error
1285 if Expression_Kind_Of
(Next_Expression
, In_Tree
) = List
then
1286 Error_Msg
("single expression expected",
1290 -- If Current_Expression is empty, it means that the
1291 -- expression is the first in the string list.
1293 if Current_Expression
= Empty_Node
then
1294 Set_First_Expression_In_List
1295 (Term_Id
, In_Tree
, To
=> Next_Expression
);
1297 Set_Next_Expression_In_List
1298 (Current_Expression
, In_Tree
, To
=> Next_Expression
);
1301 Current_Expression
:= Next_Expression
;
1303 -- If there is a comma, continue with the next expression
1305 exit when Token
/= Tok_Comma
;
1306 Scan
(In_Tree
); -- past the comma
1309 -- We expect a closing right parenthesis
1311 Expect
(Tok_Right_Paren
, "`)`");
1313 if Token
= Tok_Right_Paren
then
1318 when Tok_String_Literal
=>
1320 -- If we don't know the expression kind (first term), then it is
1323 if Expr_Kind
= Undefined
then
1324 Expr_Kind
:= Single
;
1327 -- Declare a new node for the string literal
1330 Default_Project_Node
1331 (Of_Kind
=> N_Literal_String
, In_Tree
=> In_Tree
);
1332 Set_Current_Term
(Term
, In_Tree
, To
=> Term_Id
);
1333 Set_String_Value_Of
(Term_Id
, In_Tree
, To
=> Token_Name
);
1335 -- Scan past the string literal
1339 -- Check for possible index expression
1341 if Token
= Tok_At
then
1342 if not Optional_Index
then
1343 Error_Msg
("index not allowed here", Token_Ptr
);
1346 if Token
= Tok_Integer_Literal
then
1350 -- Set the index value
1354 Expect
(Tok_Integer_Literal
, "integer literal");
1356 if Token
= Tok_Integer_Literal
then
1358 Index
: constant Int
:= UI_To_Int
(Int_Literal_Value
);
1361 Error_Msg
("index cannot be zero", Token_Ptr
);
1364 (Term_Id
, In_Tree
, To
=> Index
);
1373 when Tok_Identifier
=>
1374 Current_Location
:= Token_Ptr
;
1376 -- Get the variable or attribute reference
1378 Parse_Variable_Reference
1379 (In_Tree
=> In_Tree
,
1380 Variable
=> Reference
,
1381 Current_Project
=> Current_Project
,
1382 Current_Package
=> Current_Package
);
1383 Set_Current_Term
(Term
, In_Tree
, To
=> Reference
);
1385 if Reference
/= Empty_Node
then
1387 -- If we don't know the expression kind (first term), then it
1388 -- has the kind of the variable or attribute reference.
1390 if Expr_Kind
= Undefined
then
1391 Expr_Kind
:= Expression_Kind_Of
(Reference
, In_Tree
);
1393 elsif Expr_Kind
= Single
1394 and then Expression_Kind_Of
(Reference
, In_Tree
) = List
1396 -- If the expression is a single list, and the reference is
1397 -- a string list, report an error, and set the expression
1398 -- kind to string list to avoid multiple errors.
1402 ("list variable cannot appear in single string expression",
1409 -- Project can appear in an expression as the prefix of an
1410 -- attribute reference of the current project.
1412 Current_Location
:= Token_Ptr
;
1414 Expect
(Tok_Apostrophe
, "`'`");
1416 if Token
= Tok_Apostrophe
then
1418 (In_Tree
=> In_Tree
,
1419 Reference
=> Reference
,
1420 First_Attribute
=> Prj
.Attr
.Attribute_First
,
1421 Current_Project
=> Current_Project
,
1422 Current_Package
=> Empty_Node
);
1423 Set_Current_Term
(Term
, In_Tree
, To
=> Reference
);
1426 -- Same checks as above for the expression kind
1428 if Reference
/= Empty_Node
then
1429 if Expr_Kind
= Undefined
then
1430 Expr_Kind
:= Expression_Kind_Of
(Reference
, In_Tree
);
1432 elsif Expr_Kind
= Single
1433 and then Expression_Kind_Of
(Reference
, In_Tree
) = List
1436 ("lists cannot appear in single string expression",
1441 when Tok_External
=>
1443 -- An external reference is always a single string
1445 if Expr_Kind
= Undefined
then
1446 Expr_Kind
:= Single
;
1450 (In_Tree
=> In_Tree
,
1451 Current_Project
=> Current_Project
,
1452 Current_Package
=> Current_Package
,
1453 External_Value
=> Reference
);
1454 Set_Current_Term
(Term
, In_Tree
, To
=> Reference
);
1457 Error_Msg
("cannot be part of an expression", Token_Ptr
);
1462 -- If there is an '&', call Terms recursively
1464 if Token
= Tok_Ampersand
then
1465 Scan
(In_Tree
); -- scan past ampersand
1468 (In_Tree
=> In_Tree
,
1470 Expr_Kind
=> Expr_Kind
,
1471 Current_Project
=> Current_Project
,
1472 Current_Package
=> Current_Package
,
1473 Optional_Index
=> Optional_Index
);
1475 -- And link the next term to this term
1477 Set_Next_Term
(Term
, In_Tree
, To
=> Next_Term
);