blob: 33c668d3c256a12dadf1957383ffbe53c0d02f74 [file] [log] [blame]
------------------------------------------------------------------------------
-- --
-- GNAT COMPILER COMPONENTS --
-- --
-- P A R . C H 1 1 --
-- --
-- B o d y --
-- --
-- Copyright (C) 1992-2022, 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 3, 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 COPYING3. If not, go to --
-- http://www.gnu.org/licenses for a complete copy of the license. --
-- --
-- GNAT was originally developed by the GNAT team at New York University. --
-- Extensive contributions were provided by Ada Core Technologies Inc. --
-- --
------------------------------------------------------------------------------
pragma Style_Checks (All_Checks);
-- Turn off subprogram body ordering check. Subprograms are in order
-- by RM section rather than alphabetical
with Sinfo.CN; use Sinfo.CN;
separate (Par)
package body Ch11 is
-- Local functions, used only in this chapter
function P_Exception_Handler return Node_Id;
function P_Exception_Choice return Node_Id;
---------------------------------
-- 11.1 Exception Declaration --
---------------------------------
-- Parsed by P_Identifier_Declaration (3.3.1)
------------------------------------------
-- 11.2 Handled Sequence Of Statements --
------------------------------------------
-- HANDLED_SEQUENCE_OF_STATEMENTS ::=
-- SEQUENCE_OF_STATEMENTS
-- [exception
-- EXCEPTION_HANDLER
-- {EXCEPTION_HANDLER}]
-- Error_Recovery : Cannot raise Error_Resync
function P_Handled_Sequence_Of_Statements return Node_Id is
Handled_Stmt_Seq_Node : Node_Id;
begin
Handled_Stmt_Seq_Node :=
New_Node (N_Handled_Sequence_Of_Statements, Token_Ptr);
Set_Statements
(Handled_Stmt_Seq_Node,
P_Sequence_Of_Statements (SS_Extm_Sreq, Handled => True));
if Token = Tok_Exception then
Scan; -- past EXCEPTION
Set_Exception_Handlers
(Handled_Stmt_Seq_Node, Parse_Exception_Handlers);
end if;
return Handled_Stmt_Seq_Node;
end P_Handled_Sequence_Of_Statements;
-----------------------------
-- 11.2 Exception Handler --
-----------------------------
-- EXCEPTION_HANDLER ::=
-- when [CHOICE_PARAMETER_SPECIFICATION :]
-- EXCEPTION_CHOICE {| EXCEPTION_CHOICE} =>
-- SEQUENCE_OF_STATEMENTS
-- CHOICE_PARAMETER_SPECIFICATION ::= DEFINING_IDENTIFIER
-- Error recovery: cannot raise Error_Resync
function P_Exception_Handler return Node_Id is
Scan_State : Saved_Scan_State;
Handler_Node : Node_Id;
Choice_Param_Node : Node_Id;
begin
Exception_Handler_Encountered := True;
Handler_Node := New_Node (N_Exception_Handler, Token_Ptr);
Set_Local_Raise_Statements (Handler_Node, No_Elist);
if Style_Check then
Style.Check_Indentation;
end if;
T_When;
-- Test for possible choice parameter present
if Token = Tok_Identifier then
Choice_Param_Node := Token_Node;
Save_Scan_State (Scan_State); -- at identifier
Scan; -- past identifier
if Token = Tok_Colon then
if Ada_Version = Ada_83 then
Error_Msg_SP ("(Ada 83) choice parameter not allowed!");
end if;
Scan; -- past :
Change_Identifier_To_Defining_Identifier (Choice_Param_Node);
Warn_If_Standard_Redefinition (Choice_Param_Node);
Set_Choice_Parameter (Handler_Node, Choice_Param_Node);
elsif Token = Tok_Others then
Error_Msg_AP -- CODEFIX
("missing "":""");
Change_Identifier_To_Defining_Identifier (Choice_Param_Node);
Warn_If_Standard_Redefinition (Choice_Param_Node);
Set_Choice_Parameter (Handler_Node, Choice_Param_Node);
else
Restore_Scan_State (Scan_State); -- to identifier
end if;
end if;
-- Loop through exception choices
Set_Exception_Choices (Handler_Node, New_List);
loop
Append (P_Exception_Choice, Exception_Choices (Handler_Node));
exit when Token /= Tok_Vertical_Bar;
Scan; -- past vertical bar
end loop;
TF_Arrow;
Set_Statements (Handler_Node, P_Sequence_Of_Statements (SS_Sreq_Whtm));
return Handler_Node;
end P_Exception_Handler;
------------------------------------------
-- 11.2 Choice Parameter Specification --
------------------------------------------
-- Parsed by P_Exception_Handler (11.2)
----------------------------
-- 11.2 Exception Choice --
----------------------------
-- EXCEPTION_CHOICE ::= exception_NAME | others
-- Error recovery: cannot raise Error_Resync. If an error occurs, then the
-- scan pointer is advanced to the next arrow or vertical bar or semicolon.
function P_Exception_Choice return Node_Id is
begin
if Token = Tok_Others then
Scan; -- past OTHERS
return New_Node (N_Others_Choice, Prev_Token_Ptr);
else
return P_Name; -- exception name
end if;
exception
when Error_Resync =>
Resync_Choice;
return Error;
end P_Exception_Choice;
----------------------------
-- 11.3 Raise Expression --
----------------------------
-- RAISE_EXPRESSION ::= raise [exception_NAME [with string_EXPRESSION]]
-- The caller has verified that the initial token is RAISE
-- Error recovery: can raise Error_Resync
function P_Raise_Expression return Node_Id is
Raise_Node : Node_Id;
begin
Error_Msg_Ada_2012_Feature ("raise expression", Token_Ptr);
Raise_Node := New_Node (N_Raise_Expression, Token_Ptr);
Scan; -- past RAISE
Set_Name (Raise_Node, P_Name);
if Token = Tok_With then
Scan; -- past WITH
Set_Expression (Raise_Node, P_Expression);
end if;
return Raise_Node;
end P_Raise_Expression;
---------------------------
-- 11.3 Raise Statement --
---------------------------
-- RAISE_STATEMENT ::= raise [exception_NAME with string_EXPRESSION];
-- The caller has verified that the initial token is RAISE
-- Error recovery: can raise Error_Resync
function P_Raise_Statement return Node_Id is
Raise_Node : Node_Id;
begin
Raise_Node := New_Node (N_Raise_Statement, Token_Ptr);
Scan; -- past RAISE
if Token /= Tok_Semicolon then
Set_Name (Raise_Node, P_Name);
end if;
if Token = Tok_With then
Error_Msg_Ada_2005_Extension ("string expression in raise");
Scan; -- past WITH
Set_Expression (Raise_Node, P_Expression);
end if;
if Token = Tok_When then
Error_Msg_GNAT_Extension ("raise when statement", Token_Ptr);
Mutate_Nkind (Raise_Node, N_Raise_When_Statement);
if Token = Tok_When and then not Missing_Semicolon_On_When then
Scan; -- past WHEN
Set_Condition (Raise_Node, P_Expression_No_Right_Paren);
-- Allow IF instead of WHEN, giving error message
elsif Token = Tok_If then
T_When;
Scan; -- past IF used in place of WHEN
Set_Condition (Raise_Node, P_Expression_No_Right_Paren);
end if;
end if;
TF_Semicolon;
return Raise_Node;
end P_Raise_Statement;
------------------------------
-- Parse_Exception_Handlers --
------------------------------
-- This routine scans out a list of exception handlers appearing in a
-- construct as:
-- exception
-- EXCEPTION_HANDLER {EXCEPTION_HANDLER}
-- The caller has scanned out the EXCEPTION keyword
-- Control returns after scanning the last exception handler, presumably
-- at the keyword END, but this is not checked in this routine.
-- Error recovery: cannot raise Error_Resync
function Parse_Exception_Handlers return List_Id is
Handler : Node_Id;
Handlers_List : List_Id;
begin
Handlers_List := New_List;
P_Pragmas_Opt (Handlers_List);
if Token = Tok_End then
Error_Msg_SC ("must have at least one exception handler!");
else
loop
Handler := P_Exception_Handler;
Append (Handler, Handlers_List);
-- Note: no need to check for pragmas here. Although the
-- syntax officially allows them in this position, they
-- will have been swallowed up as part of the statement
-- sequence of the handler we just scanned out.
exit when Token /= Tok_When;
end loop;
end if;
return Handlers_List;
end Parse_Exception_Handlers;
end Ch11;