--------------------------------------- ----------------------------------------- -- -- -- OCARINA COMPONENTS -- -- -- -- OCARINA.AADL.PARSER.COMPONENTS.FLOWS -- -- -- -- 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.Lexer; with Ocarina.AADL.Tokens; with Ocarina.AADL.Parser.Identifiers; with Ocarina.AADL.Parser.Components.Modes; with Ocarina.AADL.Parser.Properties; with Ocarina.Builder.Components.Flows; with Ocarina.Entities.Components.Flows; package body Ocarina.AADL.Parser.Components.Flows is function P_Flow_Identifier (Container : Types.Node_Id) return Node_Id; pragma Inline (P_Flow_Identifier); pragma Unreferenced (P_Flow_Identifier); -- Call P_Identifier_Identifier (T_Dot, True, PC_Flow_Identifier) function P_Flow_Implementation (Identifier : Node_Id; Container : Node_Id; Is_Refinement : Boolean; Is_End_To_End : Boolean; Category : Ocarina.Entities.Components.Flows.Flow_Category) return Node_Id; -- Parse Flow_Implementation, Flow_Implementation_Refinement -- End_To_End_Flow_Spec and End_To_End_Flow_Refinement function P_Flow_Spec (Identifier : Node_Id; Container : Types.Node_Id; Is_Refinement : Boolean; Category : Ocarina.Entities.Components.Flows.Flow_Category) return Node_Id; -- This function is called in P_Flow_Spec (Boolean) to make this function -- body shorter and easier to read ----------------------- -- P_Flow_Identifier -- ----------------------- function P_Flow_Identifier (Container : Types.Node_Id) return Node_Id is use Tokens; use Ocarina.AADL.Parser.Identifiers; pragma Unreferenced (Container); begin return P_Entity_Reference (PC_Flow_Identifier); end P_Flow_Identifier; --------------------------- -- P_Flow_Implementation -- --------------------------- -- flow_source_implementation ::= flow_identifier : flow source -- { subcomponent_flow_identifier -> connection_identifier -> }* -- flow_feature_identifier -- flow_sink_implementation ::= flow_identifier : flow sink -- flow_feature_identifier -- { -> connection_identifier -> subcomponent_flow_identifier }* -- flow_path_implementation ::= flow_identifier : flow path -- source_flow_feature_identifier -- [ { -> connection_identifier -> subcomponent_flow_identifier }+ -- -> connection_identifier ] -- -> sink_flow_feature_identifier -- end_to_end_flow_spec ::= flow_identifier : end to end flow -- start_subcomponent_flow_identifier -- { -> connection_identifier -- -> flow_path_subcomponent_flow_identifier }* -- -> connection_identifier -> end_subcomponent_flow_identifier -- [ { ( property_association }+ } ] -- [ in_modes_and_transitions ] ; -- flow_source_implementation_refinement ::= -- flow_identifier : refined to flow source -- ( { { property_association }+ } [ in_modes_and_transitions ] -- | in_modes_and_transitions ) ; -- flow_sink_implementation_refinement ::= -- flow_identifier : refined to flow sink -- ( { { property_association }+ } [ in_modes_and_transitions ] -- | in_modes_and_transitions ) ; -- flow_path_implementation_refinement ::= -- flow_identifier : refined to flow path -- ( { { property_association }+ } [ in_modes_and_transitions ] -- | in_modes_and_transitions ) ; -- end_to_end_flow_refinement ::= -- defining_identifier : refined to end to end flow -- ( { { property_association }+ } [ in_modes_and_transitions ] -- | in_modes_and_transitions ) ; -- subcomponent_flow_identifier ::= -- subcomponent_identifier . flow_spec_identifier function P_Flow_Implementation (Identifier : Node_Id; Container : Node_Id; Is_Refinement : Boolean; Is_End_To_End : Boolean; Category : Ocarina.Entities.Components.Flows.Flow_Category) return Node_Id is use Ocarina.Builder.Components.Flows; use Locations; use Ocarina.Nodes; use Ocarina.Nutils; use Lexer; use Tokens; use Parser.Components.Modes; use Parser.Properties; use Parser.Identifiers; use Ocarina.Entities.Components.Flows; Flow_Impl : Node_Id; Connections : List_Id; Modes_Trans : Node_Id := No_Node; -- modes and transitions Code : Parsing_Code; Loc : Location; OK : Boolean; Item : Node_Id; begin if Is_End_To_End then if Is_Refinement then Code := PC_End_To_End_Flow_Refinement; else Code := PC_End_To_End_Flow_Spec; end if; else if Category = FC_Source then if Is_Refinement then Code := PC_Flow_Source_Implementation_Refinement; else Code := PC_Flow_Source_Implementation; end if; elsif Category = FC_Sink then if Is_Refinement then Code := PC_Flow_Sink_Implementation_Refinement; else Code := PC_Flow_Sink_Implementation; end if; else if Is_Refinement then Code := PC_Flow_Path_Implementation_Refinement; else Code := PC_Flow_Path_Implementation; end if; end if; end if; if not Is_Refinement then -- Parse connections Connections := New_List (K_List_Id, Token_Location); loop Save_Lexer (Loc); Scan_Token; if Token = T_Semicolon or else Token = T_Left_Curly_Bracket then Restore_Lexer (Loc); exit; end if; Restore_Lexer (Loc); Item := P_Entity_Reference (Code); if Present (Item) then Append_Node_To_List (Item, Connections); else -- Error when parsing item, ignores tokens ---> Delimiter; quit Skip_Tokens (T_Semicolon, False); Connections := No_List; end if; Save_Lexer (Loc); Scan_Token; if Token = T_Semicolon or else Token = T_Left_Curly_Bracket then Restore_Lexer (Loc); exit; end if; if Token /= T_Connection then Skip_Tokens (T_Semicolon, False); Connections := No_List; exit; end if; end loop; if No (Connections) or else Is_Empty (Connections) then Skip_Tokens (T_Semicolon); return No_Node; else Set_Loc (Node_Id (Connections), Ocarina.Nodes.Loc (First_Node (Connections))); end if; end if; if Is_End_To_End then Flow_Impl := Add_New_End_To_End_Flow_Spec (Loc => Ocarina.Nodes.Loc (Identifier), Container => Container, Name => Identifier, Is_Refinement => Is_Refinement, In_Modes => Modes_Trans); else Flow_Impl := Add_New_Flow_Implementation (Loc => Ocarina.Nodes.Loc (Identifier), Container => Container, Name => Identifier, Category => Category, Is_Refinement => Is_Refinement, In_Modes => Modes_Trans); end if; OK := P_Property_Associations (Flow_Impl, True, PAT_Simple, Code); if not OK then -- Property_Associations are not defined, -- In_Modes_And_Transitions must exist if Is_Refinement = TRUE- if Is_Refinement and then Token /= T_In then DPE (Code, (T_In, T_Left_Curly_Bracket)); Skip_Tokens (T_Semicolon); return No_Node; end if; end if; Save_Lexer (Loc); Scan_Token; if Token = T_In then Modes_Trans := P_In_Modes (Code => PC_In_Modes_And_Transitions); if No (Modes_Trans) then Skip_Tokens (T_Semicolon); return No_Node; end if; else Restore_Lexer (Loc); end if; Save_Lexer (Loc); Scan_Token; if Token /= T_Semicolon then DPE (Code, T_Semicolon); Restore_Lexer (Loc); return No_Node; end if; if Flow_Impl /= No_Node and then not Is_Refinement then Set_Connections (Flow_Impl, Connections); end if; Set_In_Modes (Flow_Impl, Modes_Trans); return Flow_Impl; end P_Flow_Implementation; --------------------------------------------------- -- P_Flow_Implementation_Or_End_To_End_Flow_Spec -- --------------------------------------------------- -- flow_implementation ::= -- ( flow_source_implementation -- | flow_sink_implementation -- | flow_path_implementation ) -- [ { { property_association }+ } ] -- [ in_modes_and_transitions ] ; -- flow_implementation_refinement ::= -- flow_source_implementation_refinement -- | flow_sink_implementation_refinement -- | flow_path_implementation_refinement function P_Flow_Implementation_Or_End_To_End_Flow_Spec (Container : Types.Node_Id; Refinable : Boolean) return Node_Id is use Ocarina.Builder.Components.Flows; use Ocarina.Entities.Components.Flows; use Tokens; use Lexer; use Ocarina.AADL.Parser.Identifiers; Identifier : Node_Id; Is_Refinement : Boolean; Category : Flow_Category; Code : Parsing_Code; OK : Boolean; begin P_Identifier_Refined_To (Refinable_To_RT (Refinable), False, PC_Flow_Implementation, PC_Flow_Implementation_Refinement, T_Semicolon, Identifier, Is_Refinement, OK); if not OK then return No_Node; end if; if Is_Refinement then Code := PC_Flow_Implementation_Refinement; else Code := PC_Flow_Implementation; end if; Scan_Token; case Token is when T_Flow => -- Flow_Implementation or Flow_Implementation_Refinement Scan_Token; case Token is when T_Source => Category := FC_Source; when T_Sink => Category := FC_Sink; when T_Path => Category := FC_Path; when others => DPE (Code, (T_Source, T_Sink, T_Path)); Skip_Tokens (T_Semicolon); return No_Node; end case; return P_Flow_Implementation (Identifier => Identifier, Container => Container, Is_Refinement => Is_Refinement, Is_End_To_End => False, Category => Category); when T_End => -- End_To_End_Flow_Spec or End_To_End_Flow_Refinement if Is_Refinement then Code := PC_End_To_End_Flow_Refinement; else Code := PC_End_To_End_Flow_Spec; end if; Scan_Token; -- parse 'to' if Token /= T_To then DPE (Code, T_To); Skip_Tokens (T_Semicolon); return No_Node; end if; Scan_Token; -- parse 'end' if Token /= T_End then DPE (Code, T_End); Skip_Tokens (T_Semicolon); return No_Node; end if; Scan_Token; -- parse 'flow' if Token /= T_Flow then DPE (Code, T_Flow); Skip_Tokens (T_Semicolon); return No_Node; end if; return P_Flow_Implementation (Identifier => Identifier, Container => Container, Is_Refinement => Is_Refinement, Is_End_To_End => True, Category => Category); when others => DPE (Code, (T_Flow, T_End)); Skip_Tokens (T_Semicolon); return No_Node; end case; end P_Flow_Implementation_Or_End_To_End_Flow_Spec; ----------------- -- P_Flow_Spec -- ----------------- -- flow_spec ::= flow_source_spec | flow_sink_spec | flow_path_spec -- flow_spec_refinement ::= flow_source_spec_refinement -- | flow_sink_spec_refinement -- | flow_path_spec_refinement -- flow_source_spec ::= -- defining_identifier : flow source flow_feature_identifier -- [ { { property_association }+ } ] ; -- flow_sink_spec ::= -- defining_identifier : flow sink flow_feature_identifier -- [ { { property_association }+ } ] ; -- flow_path_spec ::= -- defining_identifier : flow path -- source_flow_feature_identifier -> sink_flow_feature_identifier -- [ { { property_association }+ } ] ; -- flow_source_spec_refinement ::= -- defining_identifier : refined to flow source -- { { property_association }+ } ; -- flow_sink_spec_refinement ::= -- defining_identifier : refined to flow sink -- { { property_association }+ } ; -- flow_path_spec_refinement ::= -- defining_identifier : refined to flow path -- { { property_association }+ } ; function P_Flow_Spec (Container : Types.Node_Id; Refinable : Boolean) return Node_Id is use Ocarina.Builder.Components.Flows; use Ocarina.Entities.Components.Flows; use Lexer; use Tokens; use Ocarina.AADL.Parser.Identifiers; Identifier : Node_Id; Is_Refinement : Boolean; OK : Boolean; Category : Flow_Category; Code : Parsing_Code; begin P_Identifier_Refined_To (Refinable_To_RT (Refinable), False, PC_Flow_Spec, PC_Flow_Spec_Refinement, T_Semicolon, Identifier, Is_Refinement, OK); if not OK then return No_Node; end if; if Is_Refinement then Code := PC_Flow_Spec_Refinement; else Code := PC_Flow_Spec; end if; Scan_Token; if Token = T_Flow then Scan_Token; case Token is when T_Source => Category := FC_Source; when T_Sink => Category := FC_Sink; when T_Path => Category := FC_Path; when others => DPE (Code, (T_Source, T_Sink, T_Path)); Skip_Tokens (T_Semicolon); return No_Node; end case; else DPE (Code, T_Flow); Skip_Tokens (T_Semicolon); return No_Node; end if; return P_Flow_Spec (Identifier => Identifier, Container => Container, Is_Refinement => Is_Refinement, Category => Category); end P_Flow_Spec; ----------------- -- P_Flow_Spec -- ----------------- -- flow_feature_identifier ::= port_identifier -- | parameter_identifier -- | port_group_identifier -- | port_group_identifier . port_identifier function P_Flow_Spec (Identifier : Node_Id; Container : Types.Node_Id; Is_Refinement : Boolean; Category : Ocarina.Entities.Components.Flows.Flow_Category) return Node_Id is use Locations; use Ocarina.Nodes; use Tokens; use Lexer; use Parser.Properties; use Parser.Identifiers; use Ocarina.Builder.Components.Flows; use Ocarina.Entities.Components.Flows; Flow_Spec : Node_Id; Source_Flow : Node_Id := No_Node; Sink_Flow : Node_Id := No_Node; Code : Parsing_Code; OK : Boolean; Loc : Location; -- Sub-function determining parsing code to display error messages function Flow_Parsing_Code return Parsing_Code; pragma Inline (Flow_Parsing_Code); function Flow_Parsing_Code return Parsing_Code is begin if Is_Refinement then case Category is when FC_Source => return PC_Flow_Source_Spec_Refinement; when FC_Sink => return PC_Flow_Sink_Spec_Refinement; when FC_Path => return PC_Flow_Path_Spec_Refinement; end case; else case Category is when FC_Source => return PC_Flow_Source_Spec; when FC_Sink => return PC_Flow_Sink_Spec; when FC_Path => return PC_Flow_Path_Spec; end case; end if; end Flow_Parsing_Code; begin Code := Flow_Parsing_Code; if not Is_Refinement then -- Parse flow_feature_identifier(s) case Category is when FC_Source => Source_Flow := P_Entity_Reference (Code); if No (Source_Flow) then Skip_Tokens (T_Semicolon); return No_Node; end if; when FC_Sink => Sink_Flow := P_Entity_Reference (Code); if No (Sink_Flow) then Skip_Tokens (T_Semicolon); return No_Node; end if; when FC_Path => Source_Flow := P_Entity_Reference (Code); if No (Source_Flow) then Skip_Tokens (T_Semicolon); return No_Node; end if; Scan_Token; if Token /= T_Connection then DPE (Code, T_Connection); Skip_Tokens (T_Semicolon); return No_Node; end if; Sink_Flow := P_Entity_Reference (Code); if No (Sink_Flow) then Skip_Tokens (T_Semicolon); return No_Node; end if; end case; end if; Flow_Spec := Add_New_Flow_Spec (Loc => Ocarina.Nodes.Loc (Identifier), Comp_Type => Container, Name => Identifier, Category => Category, Is_Refinement => Is_Refinement, Sink_Flow => Sink_Flow, Source_Flow => Source_Flow); OK := P_Property_Associations (Flow_Spec, not Is_Refinement, PAT_Simple, Code); Save_Lexer (Loc); Scan_Token; if Token /= T_Semicolon then DPE (Code, T_Semicolon); Restore_Lexer (Loc); return No_Node; end if; if not OK then return No_Node; end if; return Flow_Spec; end P_Flow_Spec; end Ocarina.AADL.Parser.Components.Flows;