--------------------------------------- ----------------------------------------- -- -- -- 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;