Add hppa-openbsd target
[official-gcc.git] / gcc / ada / prj-strt.adb
blob41bfd7367e382619213b3238e13e8a44cf1617a3
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- P R J . S T R T --
6 -- --
7 -- B o d y --
8 -- --
9 -- --
10 -- Copyright (C) 2001-2002 Free Software Foundation, Inc. --
11 -- --
12 -- GNAT is free software; you can redistribute it and/or modify it under --
13 -- terms of the GNU General Public License as published by the Free Soft- --
14 -- ware Foundation; either version 2, or (at your option) any later ver- --
15 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
16 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
17 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
18 -- for more details. You should have received a copy of the GNU General --
19 -- Public License distributed with GNAT; see file COPYING. If not, write --
20 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
21 -- MA 02111-1307, USA. --
22 -- --
23 -- GNAT was originally developed by the GNAT team at New York University. --
24 -- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
25 -- --
26 ------------------------------------------------------------------------------
28 with Errout; use Errout;
29 with Namet; use Namet;
30 with Prj.Attr; use Prj.Attr;
31 with Prj.Tree; use Prj.Tree;
32 with Scans; use Scans;
33 with Sinfo; use Sinfo;
34 with Stringt; use Stringt;
35 with Table;
36 with Types; use Types;
38 package body Prj.Strt is
40 type Name_Location is record
41 Name : Name_Id := No_Name;
42 Location : Source_Ptr := No_Location;
43 end record;
44 -- Store the identifier and the location of a simple name
46 type Name_Range is range 0 .. 3;
47 subtype Name_Index is Name_Range range 1 .. Name_Range'Last;
48 -- A Name may contain up to 3 simple names
50 type Names is array (Name_Index) of Name_Location;
51 -- Used to store 1 to 3 simple_names. 2 simple names are for
52 -- <project>.<package>, <project>.<variable> or <package>.<variable>.
53 -- 3 simple names are for <project>.<package>.<variable>.
55 type Choice_String is record
56 The_String : String_Id;
57 Already_Used : Boolean := False;
58 end record;
59 -- The string of a case label, and an indication that it has already
60 -- been used (to avoid duplicate case labels).
62 Choices_Initial : constant := 10;
63 Choices_Increment : constant := 10;
65 Choice_Node_Low_Bound : constant := 0;
66 Choice_Node_High_Bound : constant := 099_999_999; -- In practice, infinite
68 type Choice_Node_Id is
69 range Choice_Node_Low_Bound .. Choice_Node_High_Bound;
71 First_Choice_Node_Id : constant Choice_Node_Id :=
72 Choice_Node_Low_Bound;
74 package Choices is
75 new Table.Table (Table_Component_Type => Choice_String,
76 Table_Index_Type => Choice_Node_Id,
77 Table_Low_Bound => First_Choice_Node_Id,
78 Table_Initial => Choices_Initial,
79 Table_Increment => Choices_Increment,
80 Table_Name => "Prj.Strt.Choices");
81 -- Used to store the case labels and check that there is no duplicate.
83 package Choice_Lasts is
84 new Table.Table (Table_Component_Type => Choice_Node_Id,
85 Table_Index_Type => Nat,
86 Table_Low_Bound => 1,
87 Table_Initial => 3,
88 Table_Increment => 3,
89 Table_Name => "Prj.Strt.Choice_Lasts");
90 -- Used to store the indices of the choices in table Choices,
91 -- to distinguish nested case constructions.
93 Choice_First : Choice_Node_Id := 0;
94 -- Index in table Choices of the first case label of the current
95 -- case construction.
96 -- 0 means no current case construction.
98 procedure Add (This_String : String_Id);
99 -- Add a string to the case label list, indicating that it has not
100 -- yet been used.
102 procedure External_Reference (External_Value : out Project_Node_Id);
103 -- Parse an external reference. Current token is "external".
105 procedure Attribute_Reference
106 (Reference : out Project_Node_Id;
107 First_Attribute : Attribute_Node_Id;
108 Current_Project : Project_Node_Id;
109 Current_Package : Project_Node_Id);
110 -- Parse an attribute reference. Current token is an apostrophe.
112 procedure Terms
113 (Term : out Project_Node_Id;
114 Expr_Kind : in out Variable_Kind;
115 Current_Project : Project_Node_Id;
116 Current_Package : Project_Node_Id);
117 -- Recursive procedure to parse one term or several terms concatenated
118 -- using "&".
120 ---------
121 -- Add --
122 ---------
124 procedure Add (This_String : String_Id) is
125 begin
126 Choices.Increment_Last;
127 Choices.Table (Choices.Last) :=
128 (The_String => This_String,
129 Already_Used => False);
130 end Add;
132 -------------------------
133 -- Attribute_Reference --
134 -------------------------
136 procedure Attribute_Reference
137 (Reference : out Project_Node_Id;
138 First_Attribute : Attribute_Node_Id;
139 Current_Project : Project_Node_Id;
140 Current_Package : Project_Node_Id)
142 Current_Attribute : Attribute_Node_Id := First_Attribute;
144 begin
145 Reference := Default_Project_Node (Of_Kind => N_Attribute_Reference);
146 Set_Location_Of (Reference, To => Token_Ptr);
147 Scan; -- past apostrophe
148 Expect (Tok_Identifier, "Identifier");
150 if Token = Tok_Identifier then
151 Set_Name_Of (Reference, To => Token_Name);
153 while Current_Attribute /= Empty_Attribute
154 and then
155 Attributes.Table (Current_Attribute).Name /= Token_Name
156 loop
157 Current_Attribute := Attributes.Table (Current_Attribute).Next;
158 end loop;
160 if Current_Attribute = Empty_Attribute then
161 Error_Msg_Name_1 := Token_Name;
162 Error_Msg ("unknown attribute %", Token_Ptr);
163 Reference := Empty_Node;
165 else
166 Set_Project_Node_Of (Reference, To => Current_Project);
167 Set_Package_Node_Of (Reference, To => Current_Package);
168 Set_Expression_Kind_Of
169 (Reference, To => Attributes.Table (Current_Attribute).Kind_1);
170 Set_Case_Insensitive
171 (Reference, To => Attributes.Table (Current_Attribute).Kind_2 =
172 Case_Insensitive_Associative_Array);
173 Scan;
175 if Attributes.Table (Current_Attribute).Kind_2 /= Single then
176 Expect (Tok_Left_Paren, "(");
178 if Token = Tok_Left_Paren then
179 Scan;
180 Expect (Tok_String_Literal, "literal string");
182 if Token = Tok_String_Literal then
183 Set_Associative_Array_Index_Of
184 (Reference, To => Strval (Token_Node));
185 Scan;
186 Expect (Tok_Right_Paren, ")");
188 if Token = Tok_Right_Paren then
189 Scan;
190 end if;
191 end if;
192 end if;
193 end if;
194 end if;
195 end if;
196 end Attribute_Reference;
198 ---------------------------
199 -- End_Case_Construction --
200 ---------------------------
202 procedure End_Case_Construction is
203 begin
204 if Choice_Lasts.Last = 1 then
205 Choice_Lasts.Set_Last (0);
206 Choices.Set_Last (First_Choice_Node_Id);
207 Choice_First := 0;
209 elsif Choice_Lasts.Last = 2 then
210 Choice_Lasts.Set_Last (1);
211 Choices.Set_Last (Choice_Lasts.Table (1));
212 Choice_First := 1;
214 else
215 Choice_Lasts.Decrement_Last;
216 Choices.Set_Last (Choice_Lasts.Table (Choice_Lasts.Last));
217 Choice_First := Choice_Lasts.Table (Choice_Lasts.Last - 1) + 1;
218 end if;
219 end End_Case_Construction;
221 ------------------------
222 -- External_Reference --
223 ------------------------
225 procedure External_Reference (External_Value : out Project_Node_Id) is
226 Field_Id : Project_Node_Id := Empty_Node;
228 begin
229 External_Value :=
230 Default_Project_Node (Of_Kind => N_External_Value,
231 And_Expr_Kind => Single);
232 Set_Location_Of (External_Value, To => Token_Ptr);
234 -- The current token is External
236 -- Get the left parenthesis
238 Scan;
239 Expect (Tok_Left_Paren, "(");
241 -- Scan past the left parenthesis
243 if Token = Tok_Left_Paren then
244 Scan;
245 end if;
247 -- Get the name of the external reference
249 Expect (Tok_String_Literal, "literal string");
251 if Token = Tok_String_Literal then
252 Field_Id :=
253 Default_Project_Node (Of_Kind => N_Literal_String,
254 And_Expr_Kind => Single);
255 Set_String_Value_Of (Field_Id, To => Strval (Token_Node));
256 Set_External_Reference_Of (External_Value, To => Field_Id);
258 -- Scan past the first argument
260 Scan;
262 case Token is
264 when Tok_Right_Paren =>
266 -- Scan past the right parenthesis
267 Scan;
269 when Tok_Comma =>
271 -- Scan past the comma
273 Scan;
275 Expect (Tok_String_Literal, "literal string");
277 -- Get the default
279 if Token = Tok_String_Literal then
280 Field_Id :=
281 Default_Project_Node (Of_Kind => N_Literal_String,
282 And_Expr_Kind => Single);
283 Set_String_Value_Of (Field_Id, To => Strval (Token_Node));
284 Set_External_Default_Of (External_Value, To => Field_Id);
285 Scan;
286 Expect (Tok_Right_Paren, ")");
287 end if;
289 -- Scan past the right parenthesis
290 if Token = Tok_Right_Paren then
291 Scan;
292 end if;
294 when others =>
295 Error_Msg ("',' or ')' expected", Token_Ptr);
296 end case;
297 end if;
298 end External_Reference;
300 -----------------------
301 -- Parse_Choice_List --
302 -----------------------
304 procedure Parse_Choice_List (First_Choice : out Project_Node_Id) is
305 Current_Choice : Project_Node_Id := Empty_Node;
306 Next_Choice : Project_Node_Id := Empty_Node;
307 Choice_String : String_Id := No_String;
308 Found : Boolean := False;
310 begin
311 First_Choice :=
312 Default_Project_Node (Of_Kind => N_Literal_String,
313 And_Expr_Kind => Single);
314 Current_Choice := First_Choice;
316 loop
317 Expect (Tok_String_Literal, "literal string");
318 exit when Token /= Tok_String_Literal;
319 Set_Location_Of (Current_Choice, To => Token_Ptr);
320 Choice_String := Strval (Token_Node);
321 Set_String_Value_Of (Current_Choice, To => Choice_String);
323 Found := False;
324 for Choice in Choice_First .. Choices.Last loop
325 if String_Equal (Choices.Table (Choice).The_String,
326 Choice_String)
327 then
328 Found := True;
330 if Choices.Table (Choice).Already_Used then
331 String_To_Name_Buffer (Choice_String);
332 Error_Msg_Name_1 := Name_Find;
333 Error_Msg ("duplicate case label {", Token_Ptr);
334 else
335 Choices.Table (Choice).Already_Used := True;
336 end if;
338 exit;
339 end if;
340 end loop;
342 if not Found then
343 String_To_Name_Buffer (Choice_String);
344 Error_Msg_Name_1 := Name_Find;
345 Error_Msg ("illegal case label {", Token_Ptr);
346 end if;
348 Scan;
350 if Token = Tok_Vertical_Bar then
351 Next_Choice :=
352 Default_Project_Node (Of_Kind => N_Literal_String,
353 And_Expr_Kind => Single);
354 Set_Next_Literal_String (Current_Choice, To => Next_Choice);
355 Current_Choice := Next_Choice;
356 Scan;
357 else
358 exit;
359 end if;
360 end loop;
361 end Parse_Choice_List;
363 ----------------------
364 -- Parse_Expression --
365 ----------------------
367 procedure Parse_Expression
368 (Expression : out Project_Node_Id;
369 Current_Project : Project_Node_Id;
370 Current_Package : Project_Node_Id)
372 First_Term : Project_Node_Id := Empty_Node;
373 Expression_Kind : Variable_Kind := Undefined;
375 begin
376 Expression := Default_Project_Node (Of_Kind => N_Expression);
377 Set_Location_Of (Expression, To => Token_Ptr);
378 Terms (Term => First_Term,
379 Expr_Kind => Expression_Kind,
380 Current_Project => Current_Project,
381 Current_Package => Current_Package);
382 Set_First_Term (Expression, To => First_Term);
383 Set_Expression_Kind_Of (Expression, To => Expression_Kind);
384 end Parse_Expression;
386 ----------------------------
387 -- Parse_String_Type_List --
388 ----------------------------
390 procedure Parse_String_Type_List (First_String : out Project_Node_Id) is
391 Last_String : Project_Node_Id := Empty_Node;
392 Next_String : Project_Node_Id := Empty_Node;
393 String_Value : String_Id := No_String;
395 begin
396 First_String :=
397 Default_Project_Node (Of_Kind => N_Literal_String,
398 And_Expr_Kind => Single);
399 Last_String := First_String;
401 loop
402 Expect (Tok_String_Literal, "literal string");
403 exit when Token /= Tok_String_Literal;
404 String_Value := Strval (Token_Node);
405 Set_String_Value_Of (Last_String, To => String_Value);
406 Set_Location_Of (Last_String, To => Token_Ptr);
408 declare
409 Current : Project_Node_Id := First_String;
411 begin
412 while Current /= Last_String loop
413 if String_Equal (String_Value_Of (Current), String_Value) then
414 String_To_Name_Buffer (String_Value);
415 Error_Msg_Name_1 := Name_Find;
416 Error_Msg ("duplicate value { in type", Token_Ptr);
417 exit;
418 end if;
420 Current := Next_Literal_String (Current);
421 end loop;
422 end;
424 Scan;
426 if Token /= Tok_Comma then
427 exit;
429 else
430 Next_String :=
431 Default_Project_Node (Of_Kind => N_Literal_String,
432 And_Expr_Kind => Single);
433 Set_Next_Literal_String (Last_String, To => Next_String);
434 Last_String := Next_String;
435 Scan;
436 end if;
437 end loop;
438 end Parse_String_Type_List;
440 ------------------------------
441 -- Parse_Variable_Reference --
442 ------------------------------
444 procedure Parse_Variable_Reference
445 (Variable : out Project_Node_Id;
446 Current_Project : Project_Node_Id;
447 Current_Package : Project_Node_Id)
449 The_Names : Names;
450 Last_Name : Name_Range := 0;
451 Current_Variable : Project_Node_Id := Empty_Node;
453 The_Package : Project_Node_Id := Current_Package;
454 The_Project : Project_Node_Id := Current_Project;
456 Specified_Project : Project_Node_Id := Empty_Node;
457 Specified_Package : Project_Node_Id := Empty_Node;
458 Look_For_Variable : Boolean := True;
459 First_Attribute : Attribute_Node_Id := Empty_Attribute;
460 Variable_Name : Name_Id;
462 begin
463 for Index in The_Names'Range loop
464 Expect (Tok_Identifier, "identifier");
466 if Token /= Tok_Identifier then
467 Look_For_Variable := False;
468 exit;
469 end if;
471 Last_Name := Last_Name + 1;
472 The_Names (Last_Name) :=
473 (Name => Token_Name,
474 Location => Token_Ptr);
475 Scan;
476 exit when Token /= Tok_Dot;
477 Scan;
478 end loop;
480 if Look_For_Variable then
481 if Token = Tok_Apostrophe then
483 -- Attribute reference
485 case Last_Name is
486 when 0 =>
488 -- Cannot happen
490 null;
492 when 1 =>
493 for Index in Package_First .. Package_Attributes.Last loop
494 if Package_Attributes.Table (Index).Name =
495 The_Names (1).Name
496 then
497 First_Attribute :=
498 Package_Attributes.Table (Index).First_Attribute;
499 exit;
500 end if;
501 end loop;
503 if First_Attribute /= Empty_Attribute then
504 The_Package := First_Package_Of (Current_Project);
505 while The_Package /= Empty_Node
506 and then Name_Of (The_Package) /= The_Names (1).Name
507 loop
508 The_Package := Next_Package_In_Project (The_Package);
509 end loop;
511 if The_Package = Empty_Node then
512 Error_Msg_Name_1 := The_Names (1).Name;
513 Error_Msg ("package % not yet defined",
514 The_Names (1).Location);
515 end if;
517 else
518 First_Attribute := Attribute_First;
519 The_Package := Empty_Node;
521 declare
522 The_Project_Name_And_Node :
523 constant Tree_Private_Part.Project_Name_And_Node :=
524 Tree_Private_Part.Projects_Htable.Get
525 (The_Names (1).Name);
527 use Tree_Private_Part;
529 begin
530 if The_Project_Name_And_Node =
531 Tree_Private_Part.No_Project_Name_And_Node
532 then
533 Error_Msg_Name_1 := The_Names (1).Name;
534 Error_Msg ("unknown project %",
535 The_Names (1).Location);
536 else
537 The_Project := The_Project_Name_And_Node.Node;
538 end if;
539 end;
540 end if;
542 when 2 =>
543 declare
544 With_Clause : Project_Node_Id :=
545 First_With_Clause_Of (Current_Project);
547 begin
548 while With_Clause /= Empty_Node loop
549 The_Project := Project_Node_Of (With_Clause);
550 exit when Name_Of (The_Project) = The_Names (1).Name;
551 With_Clause := Next_With_Clause_Of (With_Clause);
552 end loop;
554 if With_Clause = Empty_Node then
555 Error_Msg_Name_1 := The_Names (1).Name;
556 Error_Msg ("unknown project %",
557 The_Names (1).Location);
558 The_Project := Empty_Node;
559 The_Package := Empty_Node;
560 First_Attribute := Attribute_First;
562 else
563 The_Package := First_Package_Of (The_Project);
564 while The_Package /= Empty_Node
565 and then Name_Of (The_Package) /= The_Names (2).Name
566 loop
567 The_Package :=
568 Next_Package_In_Project (The_Package);
569 end loop;
571 if The_Package = Empty_Node then
572 Error_Msg_Name_1 := The_Names (2).Name;
573 Error_Msg_Name_2 := The_Names (1).Name;
574 Error_Msg ("package % not declared in project %",
575 The_Names (2).Location);
576 First_Attribute := Attribute_First;
578 else
579 First_Attribute :=
580 Package_Attributes.Table
581 (Package_Id_Of (The_Package)).First_Attribute;
582 end if;
583 end if;
584 end;
586 when 3 =>
587 Error_Msg
588 ("too many single names for an attribute reference",
589 The_Names (1).Location);
590 Scan;
591 Variable := Empty_Node;
592 return;
593 end case;
595 Attribute_Reference
596 (Variable,
597 Current_Project => The_Project,
598 Current_Package => The_Package,
599 First_Attribute => First_Attribute);
600 return;
601 end if;
602 end if;
604 Variable :=
605 Default_Project_Node (Of_Kind => N_Variable_Reference);
607 if Look_For_Variable then
608 case Last_Name is
609 when 0 =>
611 -- Cannot happen
613 null;
615 when 1 =>
616 Set_Name_Of (Variable, To => The_Names (1).Name);
618 -- Header comment needed ???
620 when 2 =>
621 Set_Name_Of (Variable, To => The_Names (2).Name);
622 The_Package := First_Package_Of (Current_Project);
624 while The_Package /= Empty_Node
625 and then Name_Of (The_Package) /= The_Names (1).Name
626 loop
627 The_Package := Next_Package_In_Project (The_Package);
628 end loop;
630 if The_Package /= Empty_Node then
631 Specified_Package := The_Package;
632 The_Project := Empty_Node;
634 else
635 declare
636 With_Clause : Project_Node_Id :=
637 First_With_Clause_Of (Current_Project);
639 begin
640 while With_Clause /= Empty_Node loop
641 The_Project := Project_Node_Of (With_Clause);
642 exit when Name_Of (The_Project) = The_Names (1).Name;
643 With_Clause := Next_With_Clause_Of (With_Clause);
644 end loop;
646 if With_Clause = Empty_Node then
647 The_Project :=
648 Modified_Project_Of
649 (Project_Declaration_Of (Current_Project));
651 if The_Project /= Empty_Node
652 and then
653 Name_Of (The_Project) /= The_Names (1).Name
654 then
655 The_Project := Empty_Node;
656 end if;
657 end if;
659 if The_Project = Empty_Node then
660 Error_Msg_Name_1 := The_Names (1).Name;
661 Error_Msg ("unknown package or project %",
662 The_Names (1).Location);
663 Look_For_Variable := False;
664 else
665 Specified_Project := The_Project;
666 end if;
667 end;
668 end if;
670 -- Header comment needed ???
672 when 3 =>
673 Set_Name_Of (Variable, To => The_Names (3).Name);
675 declare
676 With_Clause : Project_Node_Id :=
677 First_With_Clause_Of (Current_Project);
679 begin
680 while With_Clause /= Empty_Node loop
681 The_Project := Project_Node_Of (With_Clause);
682 exit when Name_Of (The_Project) = The_Names (1).Name;
683 With_Clause := Next_With_Clause_Of (With_Clause);
684 end loop;
686 if With_Clause = Empty_Node then
687 The_Project :=
688 Modified_Project_Of
689 (Project_Declaration_Of (Current_Project));
691 if The_Project /= Empty_Node
692 and then Name_Of (The_Project) /= The_Names (1).Name
693 then
694 The_Project := Empty_Node;
695 end if;
696 end if;
698 if The_Project = Empty_Node then
699 Error_Msg_Name_1 := The_Names (1).Name;
700 Error_Msg ("unknown package or project %",
701 The_Names (1).Location);
702 Look_For_Variable := False;
704 else
705 Specified_Project := The_Project;
706 The_Package := First_Package_Of (The_Project);
708 while The_Package /= Empty_Node
709 and then Name_Of (The_Package) /= The_Names (2).Name
710 loop
711 The_Package := Next_Package_In_Project (The_Package);
712 end loop;
714 if The_Package = Empty_Node then
715 Error_Msg_Name_1 := The_Names (2).Name;
716 Error_Msg ("unknown package %",
717 The_Names (2).Location);
718 Look_For_Variable := False;
720 else
721 Specified_Package := The_Package;
722 The_Project := Empty_Node;
723 end if;
724 end if;
725 end;
727 end case;
728 end if;
730 if Look_For_Variable then
731 Variable_Name := Name_Of (Variable);
732 Set_Project_Node_Of (Variable, To => Specified_Project);
733 Set_Package_Node_Of (Variable, To => Specified_Package);
735 if The_Package /= Empty_Node then
736 Current_Variable := First_Variable_Of (The_Package);
738 while Current_Variable /= Empty_Node
739 and then
740 Name_Of (Current_Variable) /= Variable_Name
741 loop
742 Current_Variable := Next_Variable (Current_Variable);
743 end loop;
744 end if;
746 if Current_Variable = Empty_Node
747 and then The_Project /= Empty_Node
748 then
749 Current_Variable := First_Variable_Of (The_Project);
750 while Current_Variable /= Empty_Node
751 and then Name_Of (Current_Variable) /= Variable_Name
752 loop
753 Current_Variable := Next_Variable (Current_Variable);
754 end loop;
755 end if;
757 if Current_Variable = Empty_Node then
758 Error_Msg_Name_1 := Variable_Name;
759 Error_Msg ("unknown variable %", The_Names (Last_Name).Location);
760 end if;
761 end if;
763 if Current_Variable /= Empty_Node then
764 Set_Expression_Kind_Of
765 (Variable, To => Expression_Kind_Of (Current_Variable));
767 if Kind_Of (Current_Variable) = N_Typed_Variable_Declaration then
768 Set_String_Type_Of
769 (Variable, To => String_Type_Of (Current_Variable));
770 end if;
771 end if;
773 if Token = Tok_Left_Paren then
774 Error_Msg ("\variables cannot be associative arrays", Token_Ptr);
775 Scan;
776 Expect (Tok_String_Literal, "literal string");
778 if Token = Tok_String_Literal then
779 Scan;
780 Expect (Tok_Right_Paren, ")");
782 if Token = Tok_Right_Paren then
783 Scan;
784 end if;
785 end if;
786 end if;
787 end Parse_Variable_Reference;
789 ---------------------------------
790 -- Start_New_Case_Construction --
791 ---------------------------------
793 procedure Start_New_Case_Construction (String_Type : Project_Node_Id) is
794 Current_String : Project_Node_Id;
796 begin
797 if Choice_First = 0 then
798 Choice_First := 1;
799 Choices.Set_Last (First_Choice_Node_Id);
800 else
801 Choice_First := Choices.Last + 1;
802 end if;
804 if String_Type /= Empty_Node then
805 Current_String := First_Literal_String (String_Type);
807 while Current_String /= Empty_Node loop
808 Add (This_String => String_Value_Of (Current_String));
809 Current_String := Next_Literal_String (Current_String);
810 end loop;
811 end if;
813 Choice_Lasts.Increment_Last;
814 Choice_Lasts.Table (Choice_Lasts.Last) := Choices.Last;
816 end Start_New_Case_Construction;
818 -----------
819 -- Terms --
820 -----------
822 procedure Terms (Term : out Project_Node_Id;
823 Expr_Kind : in out Variable_Kind;
824 Current_Project : Project_Node_Id;
825 Current_Package : Project_Node_Id)
827 Next_Term : Project_Node_Id := Empty_Node;
828 Term_Id : Project_Node_Id := Empty_Node;
829 Current_Expression : Project_Node_Id := Empty_Node;
830 Next_Expression : Project_Node_Id := Empty_Node;
831 Current_Location : Source_Ptr := No_Location;
832 Reference : Project_Node_Id := Empty_Node;
834 begin
835 Term := Default_Project_Node (Of_Kind => N_Term);
836 Set_Location_Of (Term, To => Token_Ptr);
838 case Token is
840 when Tok_Left_Paren =>
841 case Expr_Kind is
842 when Undefined =>
843 Expr_Kind := List;
844 when List =>
845 null;
846 when Single =>
847 Expr_Kind := List;
848 Error_Msg
849 ("literal string list cannot appear in a string",
850 Token_Ptr);
851 end case;
853 Term_Id := Default_Project_Node
854 (Of_Kind => N_Literal_String_List,
855 And_Expr_Kind => List);
856 Set_Current_Term (Term, To => Term_Id);
857 Set_Location_Of (Term, To => Token_Ptr);
859 Scan;
860 if Token = Tok_Right_Paren then
861 Scan;
863 else
864 loop
865 Current_Location := Token_Ptr;
866 Parse_Expression (Expression => Next_Expression,
867 Current_Project => Current_Project,
868 Current_Package => Current_Package);
870 if Expression_Kind_Of (Next_Expression) = List then
871 Error_Msg ("single expression expected",
872 Current_Location);
873 end if;
875 if Current_Expression = Empty_Node then
876 Set_First_Expression_In_List
877 (Term_Id, To => Next_Expression);
878 else
879 Set_Next_Expression_In_List
880 (Current_Expression, To => Next_Expression);
881 end if;
883 Current_Expression := Next_Expression;
884 exit when Token /= Tok_Comma;
885 Scan; -- past the comma
886 end loop;
888 Expect (Tok_Right_Paren, "(");
890 if Token = Tok_Right_Paren then
891 Scan;
892 end if;
893 end if;
895 when Tok_String_Literal =>
896 if Expr_Kind = Undefined then
897 Expr_Kind := Single;
898 end if;
900 Term_Id := Default_Project_Node (Of_Kind => N_Literal_String);
901 Set_Current_Term (Term, To => Term_Id);
902 Set_String_Value_Of (Term_Id, To => Strval (Token_Node));
904 Scan;
906 when Tok_Identifier =>
907 Current_Location := Token_Ptr;
908 Parse_Variable_Reference
909 (Variable => Reference,
910 Current_Project => Current_Project,
911 Current_Package => Current_Package);
912 Set_Current_Term (Term, To => Reference);
914 if Reference /= Empty_Node then
915 if Expr_Kind = Undefined then
916 Expr_Kind := Expression_Kind_Of (Reference);
918 elsif Expr_Kind = Single
919 and then Expression_Kind_Of (Reference) = List
920 then
921 Expr_Kind := List;
922 Error_Msg
923 ("list variable cannot appear in single string expression",
924 Current_Location);
925 end if;
926 end if;
928 when Tok_Project =>
929 Current_Location := Token_Ptr;
930 Scan;
931 Expect (Tok_Apostrophe, "'");
933 if Token = Tok_Apostrophe then
934 Attribute_Reference
935 (Reference => Reference,
936 First_Attribute => Prj.Attr.Attribute_First,
937 Current_Project => Current_Project,
938 Current_Package => Empty_Node);
939 Set_Current_Term (Term, To => Reference);
940 end if;
942 if Reference /= Empty_Node then
943 if Expr_Kind = Undefined then
944 Expr_Kind := Expression_Kind_Of (Reference);
946 elsif Expr_Kind = Single
947 and then Expression_Kind_Of (Reference) = List
948 then
949 Error_Msg
950 ("lists cannot appear in single string expression",
951 Current_Location);
952 end if;
953 end if;
955 when Tok_External =>
956 if Expr_Kind = Undefined then
957 Expr_Kind := Single;
958 end if;
960 External_Reference (External_Value => Reference);
961 Set_Current_Term (Term, To => Reference);
963 when others =>
964 Error_Msg ("cannot be part of an expression", Token_Ptr);
965 Term := Empty_Node;
966 return;
967 end case;
969 if Token = Tok_Ampersand then
970 Scan;
972 Terms (Term => Next_Term,
973 Expr_Kind => Expr_Kind,
974 Current_Project => Current_Project,
975 Current_Package => Current_Package);
976 Set_Next_Term (Term, To => Next_Term);
978 end if;
980 end Terms;
982 end Prj.Strt;