----------------------------------------- --------------------------------------- -- -- -- OCARINA COMPONENTS -- -- -- -- OCARINA.AADL.PARSER.COMPONENTS.MODES -- -- -- -- B o d y -- -- -- -- Copyright (C) 2004-2006, GET-Telecom Paris. -- -- -- -- Ocarina is free software; you can redistribute it and/or modify -- -- it under terms of the GNU General Public License as published by the -- -- Free Software Foundation; either version 2, or (at your option) any -- -- later version. Ocarina is distributed in the hope that it will be -- -- useful, but WITHOUT 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 Ocarina; see file COPYING. -- -- If not, write to the Free Software Foundation, 51 Franklin Street, Fifth -- -- Floor, Boston, MA 02111-1301, USA. -- -- -- -- As a special exception, if other files instantiate generics from this -- -- unit, or you link this unit with other files to produce an executable, -- -- this unit does not by itself cause the resulting executable to be -- -- covered by the GNU General Public License. This exception does not -- -- however invalidate any other reasons why the executable file might be -- -- covered by the GNU Public License. -- -- -- -- Ocarina is maintained by the Ocarina team -- -- (ocarina-users@listes.enst.fr) -- -- -- ------------------------------------------------------------------------------ with Locations; with Ocarina.Nodes; with Ocarina.Nutils; with Ocarina.AADL.Tokens; with Ocarina.AADL.Lexer; with Ocarina.AADL.Parser.Properties; with Ocarina.AADL.Parser.Identifiers; with Ocarina.Builder.Components.Modes; package body Ocarina.AADL.Parser.Components.Modes is function P_Mode (Mode : Node_Id; Is_Refinement : Boolean; Is_Initial : Boolean; Refinable : Boolean) return Node_Id; -- Parse Mode and Mode_Refinement -- NOTE: The parameter Refinable is only useful for determining output -- error message (for list of expected tokens) function P_Mode_Transition (Mode_Transition : Types.Node_Id; Source_Modes : List_Id) return Node_Id; -- Current token is '-[' and will be ignored in this function function P_Unique_Port_Identifier (Container : Types.Node_Id) return Node_Id; -- Parse Unique_Port_Identifier ---------------- -- P_In_Modes -- ---------------- -- ( in modes ( ( Item { , Item }* | none ) ) ) function P_In_Modes (Code : Parsing_Code) return Node_Id is use Locations; use Ocarina.Nodes; use Ocarina.Nutils; use Tokens; use Lexer; use Ocarina.AADL.Parser.Identifiers; pragma Assert (Code = PC_In_Modes or else Code = PC_In_Modes_And_Transitions); In_Modes : Node_Id; Mode_List : List_Id; Start_Loc : Location; Loc : Location; Item : Node_Id; -- NOTE: no tokens skipping is necessary because when an error -- occurs this function return No_Node and calling function -- will skip tokens until ';' (in general) is reached begin Save_Lexer (Start_Loc); Scan_Token; -- Consume 'modes' ('in' is already consumed) if Token /= T_Modes then DPE (Code, T_Modes); return No_Node; end if; Scan_Token; -- Consume '(' if Token /= T_Left_Parenthesis then DPE (Code, T_Left_Parenthesis); return No_Node; end if; Save_Lexer (Loc); Scan_Token; if Token = T_None then Mode_List := New_List (K_List_Id, Start_Loc); else Restore_Lexer (Loc); Mode_List := New_List (K_List_Id, Start_Loc); loop Save_Lexer (Loc); Scan_Token; if Token = T_Right_Parenthesis then Restore_Lexer (Loc); exit; end if; Restore_Lexer (Loc); if Code = PC_In_Modes then Item := P_Entity_Reference (Code); else Item := P_Mode_Or_Transition (No_Node); end if; if Present (Item) then Append_Node_To_List (Item, Mode_List); else Skip_Tokens (T_Right_Parenthesis, False); Mode_List := No_List; exit; end if; Save_Lexer (Loc); Scan_Token; if Token = T_Right_Parenthesis then Restore_Lexer (Loc); exit; end if; if Token /= T_Comma then Skip_Tokens (T_Right_Parenthesis, False); Mode_List := No_List; end if; end loop; if Is_Empty (Mode_List) then -- An error message must be displayed because no error -- message is displayed in P_Identifier DPE (Code, T_Identifier); Skip_Tokens (T_Right_Parenthesis); return No_Node; end if; end if; Scan_Token; -- Consume ')' if Token /= T_Right_Parenthesis then DPE (Code, T_Right_Parenthesis); return No_Node; end if; -- Create the In_Mode node In_Modes := New_Node (K_In_Modes, Start_Loc); Set_Modes (In_Modes, Mode_List); return In_Modes; end P_In_Modes; ------------ -- P_Mode -- ------------ -- mode ::= defining_mode_identifier : [ initial ] mode -- [ { { mode_property_assocation }+ } ] ; -- mode_refinement ::= defining_mode_identifier : refined to mode -- { { mode_property_assocation }+ } ; function P_Mode (Mode : Node_Id; Is_Refinement : Boolean; Is_Initial : Boolean; Refinable : Boolean) return Node_Id is use Locations; use Ocarina.Nodes; use Ocarina.Nutils; use Parser.Properties; use Tokens; use Lexer; Code : Parsing_Code; OK : Boolean; Loc : Location; begin if Is_Refinement then Code := PC_Mode_Refinement; else Code := PC_Mode; end if; Scan_Token; if Token /= T_Mode then if Is_Initial or else Is_Refinement then DPE (Code, T_Mode); else if Refinable then DPE (PC_Mode, (T_Mode, T_Initial, T_Refined)); else DPE (PC_Mode, (T_Mode, T_Initial)); end if; end if; Skip_Tokens (T_Semicolon); return No_Node; end if; OK := P_Property_Associations (Mode, not Is_Refinement, PAT_Simple, Code); if not OK then return No_Node; end if; Save_Lexer (Loc); Scan_Token; if Token /= T_Semicolon then DPE (Code, T_Semicolon); Restore_Lexer (Loc); return No_Node; end if; Set_Is_Refinement (Mode, Is_Refinement); Set_Is_Initial (Mode, Is_Initial); return Mode; end P_Mode; ------------------------------- -- P_Mode_Or_Mode_Transition -- ------------------------------- -- mode ::= defining_mode_identifier : [ initial ] mode -- [ { { mode_property_assocation }+ } ] ; -- mode_transition ::= -- source_mode_identifier { , source_mode_identifier }* -- -[ unique_port_identifier { , unique_port_identifier }* ]-> -- destination_mode_identifier ; -- mode_refinement ::= defining_mode_identifier : refined to mode -- { { mode_property_assocation }+ } ; function P_Mode_Or_Mode_Transition (Container : Node_Id; Refinable : Boolean) return Node_Id is use Locations; use Ocarina.Nodes; use Ocarina.Nutils; use Tokens; use Lexer; use Ocarina.AADL.Parser.Identifiers; use Ocarina.Builder.Components.Modes; Identifier : Node_Id; Identifiers_List : List_Id; Source_Modes : List_Id; Is_Refinement : Boolean := False; Is_Initial : Boolean := False; Loc : Location; Node : Node_Id; begin Identifier := P_Identifier (No_Node); if No (Identifier) then -- Error when parsing identifier, quit return No_Node; end if; Scan_Token; case Token is when T_Colon => -- parsing Mode or Mode_Refinement Save_Lexer (Loc); Scan_Token; if Token = T_Refined then if not Refinable then DPE (PC_Mode, EMC_Refinement_Is_Not_Allowed); Skip_Tokens (T_Semicolon); return No_Node; end if; Scan_Token; -- parsing 'to' if Token /= T_To then DPE (PC_Mode_Refinement, T_To); Skip_Tokens (T_Semicolon); return No_Node; end if; Is_Refinement := True; elsif Token = T_Initial then Is_Initial := True; else Restore_Lexer (Loc); end if; Node := Add_New_Mode (Loc => Ocarina.Nodes.Loc (Identifier), Identifier => Identifier, Component => Container); return P_Mode (Node, Is_Refinement, Is_Initial, Refinable); when T_Left_Step_Bracket | T_Comma => -- parse Mode_Transition Source_Modes := New_List (K_Identifiers_List, Ocarina.Nodes.Loc (Identifier)); Append_Node_To_List (Identifier, Source_Modes); if Token = T_Comma then -- parse next source modes Identifiers_List := P_Items_List (P_Identifier'Access, No_Node, T_Comma, False); if No (Identifiers_List) then DPE (PC_Mode_Transition, T_Identifier); Skip_Tokens (T_Semicolon); return No_Node; end if; Append_Node_To_List (First_Node (Identifiers_List), Source_Modes); Scan_Token; -- parse '-[' if Token /= T_Left_Step_Bracket then DPE (PC_Mode_Transition, T_Left_Step_Bracket); Skip_Tokens (T_Semicolon); return No_Node; end if; end if; Node := Add_New_Mode_Transition (Loc => Ocarina.Nodes.Loc (Identifier), Component => Container); return P_Mode_Transition (Node, Source_Modes); when others => DPE (PC_Mode_Or_Mode_Transition, (T_Colon, T_Left_Step_Bracket)); Skip_Tokens (T_Semicolon); return No_Node; end case; end P_Mode_Or_Mode_Transition; -------------------------- -- P_Mode_Or_Transition -- -------------------------- -- mode_or_transition ::= -- mode_identifier | ( old_mode_identifier -> new_mode_identifier ) function P_Mode_Or_Transition (Container : Types.Node_Id) return Node_Id is use Locations; use Ocarina.Nodes; use Ocarina.Nutils; use Lexer; use Tokens; use Ocarina.AADL.Parser.Identifiers; pragma Unreferenced (Container); Mode_Tran : Node_Id; Loc : Location; begin Save_Lexer (Loc); Scan_Token; if Token = T_Left_Parenthesis then Mode_Tran := New_Node (K_Pair_Of_Entity_References, Token_Location); Set_First_Reference (Mode_Tran, P_Entity_Reference (PC_Mode_Or_Mode_Transition)); Scan_Token; if Token /= T_Connection then DPE (PC_Mode_Or_Transition, (T_Right_Parenthesis)); return No_Node; end if; Set_Second_Reference (Mode_Tran, P_Entity_Reference (PC_Mode_Or_Mode_Transition)); Scan_Token; if Token /= T_Right_Parenthesis then Mode_Tran := No_Node; DPE (PC_Mode_Or_Transition, (T_Right_Parenthesis)); end if; else Restore_Lexer (Loc); Mode_Tran := P_Entity_Reference (PC_Mode_Or_Transition); end if; return Mode_Tran; end P_Mode_Or_Transition; ----------------------- -- P_Mode_Transition -- ----------------------- -- mode_transition ::= -- source_mode_identifier { , source_mode_identifier }* -- -[ unique_port_identifier { , unique_port_identifier }* ]-> -- destination_mode_identifier ; function P_Mode_Transition (Mode_Transition : Node_Id; Source_Modes : List_Id) return Node_Id is use Locations; use Ocarina.Nodes; use Ocarina.Nutils; use Tokens; use Lexer; use Ocarina.AADL.Parser.Identifiers; pragma Assert (Mode_Transition /= No_Node); Unique_Ports : List_Id; Destination : Node_Id; Loc : Location; begin Unique_Ports := P_Items_List (P_Unique_Port_Identifier'Access, No_Node, T_Comma, False); if No (Unique_Ports) then DPE (PC_Mode_Transition, T_Identifier); Skip_Tokens (T_Semicolon); return No_Node; end if; Scan_Token; if Token /= T_Right_Step_Bracket then DPE (PC_Mode_Transition, T_Right_Step_Bracket); Skip_Tokens (T_Semicolon); return No_Node; end if; Scan_Token; if Token /= T_Identifier then DPE (PC_Mode_Transition, T_Identifier); Skip_Tokens (T_Semicolon); return No_Node; end if; Destination := Make_Current_Identifier (No_Node); Save_Lexer (Loc); Scan_Token; if Token /= T_Semicolon then DPE (PC_Mode_Transition, T_Semicolon); Restore_Lexer (Loc); return No_Node; end if; Set_Source_Modes (Mode_Transition, Source_Modes); Set_Unique_Ports (Mode_Transition, Unique_Ports); Set_Destination_Mode (Mode_Transition, Destination); return Mode_Transition; end P_Mode_Transition; ------------------------------ -- P_Unique_Port_Identifier -- ------------------------------ function P_Unique_Port_Identifier (Container : Types.Node_Id) return Node_Id is use Ocarina.Nodes; use Tokens; use Ocarina.AADL.Parser.Identifiers; pragma Unreferenced (Container); begin return P_Entity_Reference (PC_Unique_Port_Identifier); end P_Unique_Port_Identifier; end Ocarina.AADL.Parser.Components.Modes;