diff options
author | kenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4> | 2001-10-02 14:23:52 +0000 |
---|---|---|
committer | kenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4> | 2001-10-02 14:23:52 +0000 |
commit | 49d882a7d8c985758c04737e801f6028d5b7240f (patch) | |
tree | 0509e847916fc00cfe5c311617e039600afa9622 /gcc/ada/prj-strt.adb | |
parent | 83cce46b47d48de4c71b02a20f5bf36296a48568 (diff) | |
download | gcc-49d882a7d8c985758c04737e801f6028d5b7240f.tar.gz |
New Language: Ada
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@45956 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ada/prj-strt.adb')
-rw-r--r-- | gcc/ada/prj-strt.adb | 943 |
1 files changed, 943 insertions, 0 deletions
diff --git a/gcc/ada/prj-strt.adb b/gcc/ada/prj-strt.adb new file mode 100644 index 00000000000..790c632c2cf --- /dev/null +++ b/gcc/ada/prj-strt.adb @@ -0,0 +1,943 @@ +------------------------------------------------------------------------------ +-- -- +-- GNAT COMPILER COMPONENTS -- +-- -- +-- P R J . S T R T -- +-- -- +-- B o d y -- +-- -- +-- $Revision: 1.12 $ +-- -- +-- Copyright (C) 2001 Free Software Foundation, Inc. -- +-- -- +-- GNAT is free software; you can redistribute it and/or modify it under -- +-- terms of the GNU General Public License as published by the Free Soft- -- +-- ware Foundation; either version 2, or (at your option) any later ver- -- +-- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- +-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- +-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -- +-- for more details. You should have received a copy of the GNU General -- +-- Public License distributed with GNAT; see file COPYING. If not, write -- +-- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, -- +-- MA 02111-1307, USA. -- +-- -- +-- GNAT was originally developed by the GNAT team at New York University. -- +-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). -- +-- -- +------------------------------------------------------------------------------ + +with Errout; use Errout; +with Prj.Attr; use Prj.Attr; +with Prj.Tree; use Prj.Tree; +with Scans; use Scans; +with Sinfo; use Sinfo; +with Stringt; use Stringt; +with Table; +with Types; use Types; + +package body Prj.Strt is + + Initial_Size : constant := 8; + + type Name_Location is record + Name : Name_Id := No_Name; + Location : Source_Ptr := No_Location; + end record; + -- Store the identifier and the location of a simple name + + type Name_Range is range 0 .. 3; + subtype Name_Index is Name_Range range 1 .. Name_Range'Last; + -- A Name may contain up to 3 simple names + + type Names is array (Name_Index) of Name_Location; + -- Used to store 1 to 3 simple_names. 2 simple names are for + -- <project>.<package>, <project>.<variable> or <package>.<variable>. + -- 3 simple names are for <project>.<package>.<variable>. + + type Choice_String is record + The_String : String_Id; + Already_Used : Boolean := False; + end record; + -- The string of a case label, and an indication that it has already + -- been used (to avoid duplicate case labels). + + Choices_Initial : constant := 10; + Choices_Increment : constant := 10; + + Choice_Node_Low_Bound : constant := 0; + Choice_Node_High_Bound : constant := 099_999_999; -- In practice, infinite + + type Choice_Node_Id is + range Choice_Node_Low_Bound .. Choice_Node_High_Bound; + + First_Choice_Node_Id : constant Choice_Node_Id := + Choice_Node_Low_Bound; + + Empty_Choice : constant Choice_Node_Id := + Choice_Node_Low_Bound; + + First_Choice_Id : constant Choice_Node_Id := First_Choice_Node_Id + 1; + + package Choices is + new Table.Table (Table_Component_Type => Choice_String, + Table_Index_Type => Choice_Node_Id, + Table_Low_Bound => First_Choice_Node_Id, + Table_Initial => Choices_Initial, + Table_Increment => Choices_Increment, + Table_Name => "Prj.Strt.Choices"); + -- Used to store the case labels and check that there is no duplicate. + + package Choice_Lasts is + new Table.Table (Table_Component_Type => Choice_Node_Id, + Table_Index_Type => Nat, + Table_Low_Bound => 1, + Table_Initial => 3, + Table_Increment => 3, + Table_Name => "Prj.Strt.Choice_Lasts"); + -- Used to store the indices of the choices in table Choices, + -- to distinguish nested case constructions. + + Choice_First : Choice_Node_Id := 0; + -- Index in table Choices of the first case label of the current + -- case construction. + -- 0 means no current case construction. + + procedure Add (This_String : String_Id); + -- Add a string to the case label list, indicating that it has not + -- yet been used. + + procedure External_Reference (External_Value : out Project_Node_Id); + -- Parse an external reference. Current token is "external". + + procedure Attribute_Reference + (Reference : out Project_Node_Id; + First_Attribute : Attribute_Node_Id; + Current_Project : Project_Node_Id; + Current_Package : Project_Node_Id); + -- Parse an attribute reference. Current token is an apostrophe. + + procedure Terms + (Term : out Project_Node_Id; + Expr_Kind : in out Variable_Kind; + Current_Project : Project_Node_Id; + Current_Package : Project_Node_Id); + -- Recursive procedure to parse one term or several terms concatenated + -- using "&". + + --------- + -- Add -- + --------- + + procedure Add (This_String : String_Id) is + begin + Choices.Increment_Last; + Choices.Table (Choices.Last) := + (The_String => This_String, + Already_Used => False); + end Add; + + ------------------------- + -- Attribute_Reference -- + ------------------------- + + procedure Attribute_Reference + (Reference : out Project_Node_Id; + First_Attribute : Attribute_Node_Id; + Current_Project : Project_Node_Id; + Current_Package : Project_Node_Id) + is + Current_Attribute : Attribute_Node_Id := First_Attribute; + + begin + Reference := Default_Project_Node (Of_Kind => N_Attribute_Reference); + Set_Location_Of (Reference, To => Token_Ptr); + Scan; -- past apostrophe + Expect (Tok_Identifier, "Identifier"); + + if Token = Tok_Identifier then + Set_Name_Of (Reference, To => Token_Name); + + while Current_Attribute /= Empty_Attribute + and then + Attributes.Table (Current_Attribute).Name /= Token_Name + loop + Current_Attribute := Attributes.Table (Current_Attribute).Next; + end loop; + + if Current_Attribute = Empty_Attribute then + Error_Msg ("unknown attribute", Token_Ptr); + Reference := Empty_Node; + + elsif + Attributes.Table (Current_Attribute).Kind_2 = Associative_Array + then + Error_Msg + ("associative array attribute cannot be referenced", + Token_Ptr); + Reference := Empty_Node; + + else + Set_Project_Node_Of (Reference, To => Current_Project); + Set_Package_Node_Of (Reference, To => Current_Package); + Set_Expression_Kind_Of + (Reference, To => Attributes.Table (Current_Attribute).Kind_1); + Scan; + end if; + end if; + end Attribute_Reference; + + --------------------------- + -- End_Case_Construction -- + --------------------------- + + procedure End_Case_Construction is + begin + if Choice_Lasts.Last = 1 then + Choice_Lasts.Set_Last (0); + Choices.Set_Last (First_Choice_Node_Id); + Choice_First := 0; + + elsif Choice_Lasts.Last = 2 then + Choice_Lasts.Set_Last (1); + Choices.Set_Last (Choice_Lasts.Table (1)); + Choice_First := 1; + + else + Choice_Lasts.Decrement_Last; + Choices.Set_Last (Choice_Lasts.Table (Choice_Lasts.Last)); + Choice_First := Choice_Lasts.Table (Choice_Lasts.Last - 1) + 1; + end if; + end End_Case_Construction; + + ------------------------ + -- External_Reference -- + ------------------------ + + procedure External_Reference (External_Value : out Project_Node_Id) is + Field_Id : Project_Node_Id := Empty_Node; + + begin + External_Value := + Default_Project_Node (Of_Kind => N_External_Value, + And_Expr_Kind => Single); + Set_Location_Of (External_Value, To => Token_Ptr); + + -- The current token is External + + -- Get the left parenthesis + + Scan; + Expect (Tok_Left_Paren, "("); + + -- Scan past the left parenthesis + + if Token = Tok_Left_Paren then + Scan; + end if; + + -- Get the name of the external reference + + Expect (Tok_String_Literal, "literal string"); + + if Token = Tok_String_Literal then + Field_Id := + Default_Project_Node (Of_Kind => N_Literal_String, + And_Expr_Kind => Single); + Set_String_Value_Of (Field_Id, To => Strval (Token_Node)); + Set_External_Reference_Of (External_Value, To => Field_Id); + + -- Scan past the first argument + + Scan; + + case Token is + + when Tok_Right_Paren => + + -- Scan past the right parenthesis + Scan; + + when Tok_Comma => + + -- Scan past the comma + + Scan; + + Expect (Tok_String_Literal, "literal string"); + + -- Get the default + + if Token = Tok_String_Literal then + Field_Id := + Default_Project_Node (Of_Kind => N_Literal_String, + And_Expr_Kind => Single); + Set_String_Value_Of (Field_Id, To => Strval (Token_Node)); + Set_External_Default_Of (External_Value, To => Field_Id); + Scan; + Expect (Tok_Right_Paren, ")"); + end if; + + -- Scan past the right parenthesis + if Token = Tok_Right_Paren then + Scan; + end if; + + when others => + Error_Msg ("',' or ')' expected", Token_Ptr); + end case; + end if; + end External_Reference; + + ----------------------- + -- Parse_Choice_List -- + ----------------------- + + procedure Parse_Choice_List (First_Choice : out Project_Node_Id) is + Current_Choice : Project_Node_Id := Empty_Node; + Next_Choice : Project_Node_Id := Empty_Node; + Choice_String : String_Id := No_String; + Found : Boolean := False; + + begin + First_Choice := + Default_Project_Node (Of_Kind => N_Literal_String, + And_Expr_Kind => Single); + Current_Choice := First_Choice; + + loop + Expect (Tok_String_Literal, "literal string"); + exit when Token /= Tok_String_Literal; + Set_Location_Of (Current_Choice, To => Token_Ptr); + Choice_String := Strval (Token_Node); + Set_String_Value_Of (Current_Choice, To => Choice_String); + + Found := False; + for Choice in Choice_First .. Choices.Last loop + if String_Equal (Choices.Table (Choice).The_String, + Choice_String) + then + Found := True; + + if Choices.Table (Choice).Already_Used then + Error_Msg ("duplicate case label", Token_Ptr); + else + Choices.Table (Choice).Already_Used := True; + end if; + + exit; + end if; + end loop; + + if not Found then + Error_Msg ("illegal case label", Token_Ptr); + end if; + + Scan; + + if Token = Tok_Vertical_Bar then + Next_Choice := + Default_Project_Node (Of_Kind => N_Literal_String, + And_Expr_Kind => Single); + Set_Next_Literal_String (Current_Choice, To => Next_Choice); + Current_Choice := Next_Choice; + Scan; + else + exit; + end if; + end loop; + end Parse_Choice_List; + + ---------------------- + -- Parse_Expression -- + ---------------------- + + procedure Parse_Expression + (Expression : out Project_Node_Id; + Current_Project : Project_Node_Id; + Current_Package : Project_Node_Id) + is + First_Term : Project_Node_Id := Empty_Node; + Expression_Kind : Variable_Kind := Undefined; + + begin + Expression := Default_Project_Node (Of_Kind => N_Expression); + Set_Location_Of (Expression, To => Token_Ptr); + Terms (Term => First_Term, + Expr_Kind => Expression_Kind, + Current_Project => Current_Project, + Current_Package => Current_Package); + Set_First_Term (Expression, To => First_Term); + Set_Expression_Kind_Of (Expression, To => Expression_Kind); + end Parse_Expression; + + ---------------------------- + -- Parse_String_Type_List -- + ---------------------------- + + procedure Parse_String_Type_List (First_String : out Project_Node_Id) is + Last_String : Project_Node_Id := Empty_Node; + Next_String : Project_Node_Id := Empty_Node; + String_Value : String_Id := No_String; + + begin + First_String := + Default_Project_Node (Of_Kind => N_Literal_String, + And_Expr_Kind => Single); + Last_String := First_String; + + loop + Expect (Tok_String_Literal, "literal string"); + exit when Token /= Tok_String_Literal; + String_Value := Strval (Token_Node); + Set_String_Value_Of (Last_String, To => String_Value); + Set_Location_Of (Last_String, To => Token_Ptr); + + declare + Current : Project_Node_Id := First_String; + + begin + while Current /= Last_String loop + if String_Equal (String_Value_Of (Current), String_Value) then + Error_Msg ("duplicate value in type", Token_Ptr); + exit; + end if; + + Current := Next_Literal_String (Current); + end loop; + end; + + Scan; + + if Token /= Tok_Comma then + exit; + + else + Next_String := + Default_Project_Node (Of_Kind => N_Literal_String, + And_Expr_Kind => Single); + Set_Next_Literal_String (Last_String, To => Next_String); + Last_String := Next_String; + Scan; + end if; + end loop; + end Parse_String_Type_List; + + ------------------------------ + -- Parse_Variable_Reference -- + ------------------------------ + + procedure Parse_Variable_Reference + (Variable : out Project_Node_Id; + Current_Project : Project_Node_Id; + Current_Package : Project_Node_Id) + is + The_Names : Names; + Last_Name : Name_Range := 0; + Current_Variable : Project_Node_Id := Empty_Node; + + The_Package : Project_Node_Id := Current_Package; + The_Project : Project_Node_Id := Current_Project; + + Specified_Project : Project_Node_Id := Empty_Node; + Specified_Package : Project_Node_Id := Empty_Node; + Look_For_Variable : Boolean := True; + First_Attribute : Attribute_Node_Id := Empty_Attribute; + Variable_Name : Name_Id; + + begin + for Index in The_Names'Range loop + Expect (Tok_Identifier, "identifier"); + + if Token /= Tok_Identifier then + Look_For_Variable := False; + exit; + end if; + + Last_Name := Last_Name + 1; + The_Names (Last_Name) := + (Name => Token_Name, + Location => Token_Ptr); + Scan; + exit when Token /= Tok_Dot; + Scan; + end loop; + + if Look_For_Variable then + if Token = Tok_Apostrophe then + + -- Attribute reference + + case Last_Name is + when 0 => + + -- Cannot happen + + null; + + when 1 => + for Index in Package_First .. Package_Attributes.Last loop + if Package_Attributes.Table (Index).Name = + The_Names (1).Name + then + First_Attribute := + Package_Attributes.Table (Index).First_Attribute; + exit; + end if; + end loop; + + if First_Attribute /= Empty_Attribute then + The_Package := First_Package_Of (Current_Project); + while The_Package /= Empty_Node + and then Name_Of (The_Package) /= The_Names (1).Name + loop + The_Package := Next_Package_In_Project (The_Package); + end loop; + + if The_Package = Empty_Node then + Error_Msg ("package not yet defined", + The_Names (1).Location); + end if; + + else + First_Attribute := Attribute_First; + The_Package := Empty_Node; + + declare + The_Project_Name_And_Node : + constant Tree_Private_Part.Project_Name_And_Node := + Tree_Private_Part.Projects_Htable.Get + (The_Names (1).Name); + + use Tree_Private_Part; + + begin + if The_Project_Name_And_Node = + Tree_Private_Part.No_Project_Name_And_Node + then + Error_Msg ("unknown project", + The_Names (1).Location); + else + The_Project := The_Project_Name_And_Node.Node; + end if; + end; + end if; + + when 2 => + declare + With_Clause : Project_Node_Id := + First_With_Clause_Of (Current_Project); + + begin + while With_Clause /= Empty_Node loop + The_Project := Project_Node_Of (With_Clause); + exit when Name_Of (The_Project) = The_Names (1).Name; + With_Clause := Next_With_Clause_Of (With_Clause); + end loop; + + if With_Clause = Empty_Node then + Error_Msg ("unknown project", + The_Names (1).Location); + The_Project := Empty_Node; + The_Package := Empty_Node; + First_Attribute := Attribute_First; + + else + The_Package := First_Package_Of (The_Project); + while The_Package /= Empty_Node + and then Name_Of (The_Package) /= The_Names (2).Name + loop + The_Package := + Next_Package_In_Project (The_Package); + end loop; + + if The_Package = Empty_Node then + Error_Msg ("package not declared in project", + The_Names (2).Location); + First_Attribute := Attribute_First; + + else + First_Attribute := + Package_Attributes.Table + (Package_Id_Of (The_Package)).First_Attribute; + end if; + end if; + end; + + when 3 => + Error_Msg + ("too many single names for an attribute reference", + The_Names (1).Location); + Scan; + Variable := Empty_Node; + return; + end case; + + Attribute_Reference + (Variable, + Current_Project => The_Project, + Current_Package => The_Package, + First_Attribute => First_Attribute); + return; + end if; + end if; + + Variable := + Default_Project_Node (Of_Kind => N_Variable_Reference); + + if Look_For_Variable then + case Last_Name is + when 0 => + + -- Cannot happen + + null; + + when 1 => + Set_Name_Of (Variable, To => The_Names (1).Name); + + -- Header comment needed ??? + + when 2 => + Set_Name_Of (Variable, To => The_Names (2).Name); + The_Package := First_Package_Of (Current_Project); + + while The_Package /= Empty_Node + and then Name_Of (The_Package) /= The_Names (1).Name + loop + The_Package := Next_Package_In_Project (The_Package); + end loop; + + if The_Package /= Empty_Node then + Specified_Package := The_Package; + The_Project := Empty_Node; + + else + declare + With_Clause : Project_Node_Id := + First_With_Clause_Of (Current_Project); + + begin + while With_Clause /= Empty_Node loop + The_Project := Project_Node_Of (With_Clause); + exit when Name_Of (The_Project) = The_Names (1).Name; + With_Clause := Next_With_Clause_Of (With_Clause); + end loop; + + if With_Clause = Empty_Node then + The_Project := + Modified_Project_Of + (Project_Declaration_Of (Current_Project)); + + if The_Project /= Empty_Node + and then + Name_Of (The_Project) /= The_Names (1).Name + then + The_Project := Empty_Node; + end if; + end if; + + if The_Project = Empty_Node then + Error_Msg ("unknown package or project", + The_Names (1).Location); + Look_For_Variable := False; + else + Specified_Project := The_Project; + end if; + end; + end if; + + -- Header comment needed ??? + + when 3 => + Set_Name_Of (Variable, To => The_Names (3).Name); + + declare + With_Clause : Project_Node_Id := + First_With_Clause_Of (Current_Project); + + begin + while With_Clause /= Empty_Node loop + The_Project := Project_Node_Of (With_Clause); + exit when Name_Of (The_Project) = The_Names (1).Name; + With_Clause := Next_With_Clause_Of (With_Clause); + end loop; + + if With_Clause = Empty_Node then + The_Project := + Modified_Project_Of + (Project_Declaration_Of (Current_Project)); + + if The_Project /= Empty_Node + and then Name_Of (The_Project) /= The_Names (1).Name + then + The_Project := Empty_Node; + end if; + end if; + + if The_Project = Empty_Node then + Error_Msg ("unknown package or project", + The_Names (1).Location); + Look_For_Variable := False; + + else + Specified_Project := The_Project; + The_Package := First_Package_Of (The_Project); + + while The_Package /= Empty_Node + and then Name_Of (The_Package) /= The_Names (2).Name + loop + The_Package := Next_Package_In_Project (The_Package); + end loop; + + if The_Package = Empty_Node then + Error_Msg ("unknown package", + The_Names (2).Location); + Look_For_Variable := False; + + else + Specified_Package := The_Package; + The_Project := Empty_Node; + end if; + end if; + end; + + end case; + end if; + + if Look_For_Variable then + Variable_Name := Name_Of (Variable); + Set_Project_Node_Of (Variable, To => Specified_Project); + Set_Package_Node_Of (Variable, To => Specified_Package); + + if The_Package /= Empty_Node then + Current_Variable := First_Variable_Of (The_Package); + + while Current_Variable /= Empty_Node + and then + Name_Of (Current_Variable) /= Variable_Name + loop + Current_Variable := Next_Variable (Current_Variable); + end loop; + end if; + + if Current_Variable = Empty_Node + and then The_Project /= Empty_Node + then + Current_Variable := First_Variable_Of (The_Project); + while Current_Variable /= Empty_Node + and then Name_Of (Current_Variable) /= Variable_Name + loop + Current_Variable := Next_Variable (Current_Variable); + end loop; + end if; + + if Current_Variable = Empty_Node then + Error_Msg ("unknown variable", The_Names (Last_Name).Location); + end if; + end if; + + if Current_Variable /= Empty_Node then + Set_Expression_Kind_Of + (Variable, To => Expression_Kind_Of (Current_Variable)); + + if Kind_Of (Current_Variable) = N_Typed_Variable_Declaration then + Set_String_Type_Of + (Variable, To => String_Type_Of (Current_Variable)); + end if; + end if; + end Parse_Variable_Reference; + + --------------------------------- + -- Start_New_Case_Construction -- + --------------------------------- + + procedure Start_New_Case_Construction (String_Type : Project_Node_Id) is + Current_String : Project_Node_Id; + + begin + if Choice_First = 0 then + Choice_First := 1; + Choices.Set_Last (First_Choice_Node_Id); + else + Choice_First := Choices.Last + 1; + end if; + + if String_Type /= Empty_Node then + Current_String := First_Literal_String (String_Type); + + while Current_String /= Empty_Node loop + Add (This_String => String_Value_Of (Current_String)); + Current_String := Next_Literal_String (Current_String); + end loop; + end if; + + Choice_Lasts.Increment_Last; + Choice_Lasts.Table (Choice_Lasts.Last) := Choices.Last; + + end Start_New_Case_Construction; + + ----------- + -- Terms -- + ----------- + + procedure Terms (Term : out Project_Node_Id; + Expr_Kind : in out Variable_Kind; + Current_Project : Project_Node_Id; + Current_Package : Project_Node_Id) + is + Next_Term : Project_Node_Id := Empty_Node; + Term_Id : Project_Node_Id := Empty_Node; + Current_Expression : Project_Node_Id := Empty_Node; + Next_Expression : Project_Node_Id := Empty_Node; + Current_Location : Source_Ptr := No_Location; + Reference : Project_Node_Id := Empty_Node; + + begin + Term := Default_Project_Node (Of_Kind => N_Term); + Set_Location_Of (Term, To => Token_Ptr); + + case Token is + + when Tok_Left_Paren => + case Expr_Kind is + when Undefined => + Expr_Kind := List; + when List => + null; + when Single => + Expr_Kind := List; + Error_Msg + ("literal string list cannot appear in a string", + Token_Ptr); + end case; + + Term_Id := Default_Project_Node + (Of_Kind => N_Literal_String_List, + And_Expr_Kind => List); + Set_Current_Term (Term, To => Term_Id); + Set_Location_Of (Term, To => Token_Ptr); + + Scan; + if Token = Tok_Right_Paren then + Scan; + + else + loop + Current_Location := Token_Ptr; + Parse_Expression (Expression => Next_Expression, + Current_Project => Current_Project, + Current_Package => Current_Package); + + if Expression_Kind_Of (Next_Expression) = List then + Error_Msg ("single expression expected", + Current_Location); + end if; + + if Current_Expression = Empty_Node then + Set_First_Expression_In_List + (Term_Id, To => Next_Expression); + else + Set_Next_Expression_In_List + (Current_Expression, To => Next_Expression); + end if; + + Current_Expression := Next_Expression; + exit when Token /= Tok_Comma; + Scan; -- past the comma + end loop; + + Expect (Tok_Right_Paren, "("); + + if Token = Tok_Right_Paren then + Scan; + end if; + end if; + + when Tok_String_Literal => + if Expr_Kind = Undefined then + Expr_Kind := Single; + end if; + + Term_Id := Default_Project_Node (Of_Kind => N_Literal_String); + Set_Current_Term (Term, To => Term_Id); + Set_String_Value_Of (Term_Id, To => Strval (Token_Node)); + + Scan; + + when Tok_Identifier => + Current_Location := Token_Ptr; + Parse_Variable_Reference + (Variable => Reference, + Current_Project => Current_Project, + Current_Package => Current_Package); + Set_Current_Term (Term, To => Reference); + + if Reference /= Empty_Node then + if Expr_Kind = Undefined then + Expr_Kind := Expression_Kind_Of (Reference); + + elsif Expr_Kind = Single + and then Expression_Kind_Of (Reference) = List + then + Expr_Kind := List; + Error_Msg + ("list variable cannot appear in single string expression", + Current_Location); + end if; + end if; + + when Tok_Project => + Current_Location := Token_Ptr; + Scan; + Expect (Tok_Apostrophe, "'"); + + if Token = Tok_Apostrophe then + Attribute_Reference + (Reference => Reference, + First_Attribute => Prj.Attr.Attribute_First, + Current_Project => Current_Project, + Current_Package => Empty_Node); + Set_Current_Term (Term, To => Reference); + end if; + + if Reference /= Empty_Node then + if Expr_Kind = Undefined then + Expr_Kind := Expression_Kind_Of (Reference); + + elsif Expr_Kind = Single + and then Expression_Kind_Of (Reference) = List + then + Error_Msg + ("lists cannot appear in single string expression", + Current_Location); + end if; + end if; + + when Tok_External => + if Expr_Kind = Undefined then + Expr_Kind := Single; + end if; + + External_Reference (External_Value => Reference); + Set_Current_Term (Term, To => Reference); + + when others => + Error_Msg ("cannot be part of an expression", Token_Ptr); + Term := Empty_Node; + return; + end case; + + if Token = Tok_Ampersand then + Scan; + + Terms (Term => Next_Term, + Expr_Kind => Expr_Kind, + Current_Project => Current_Project, + Current_Package => Current_Package); + Set_Next_Term (Term, To => Next_Term); + + end if; + + end Terms; + +end Prj.Strt; |