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