home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / gnat-2.06-src.tgz / tar.out / fsf / gnat / ada / par-ch5.adb < prev    next >
Text File  |  1996-09-28  |  71KB  |  1,933 lines

  1. ------------------------------------------------------------------------------
  2. --                                                                          --
  3. --                         GNAT COMPILER COMPONENTS                         --
  4. --                                                                          --
  5. --                              P A R . C H 5                               --
  6. --                                                                          --
  7. --                                 B o d y                                  --
  8. --                                                                          --
  9. --                            $Revision: 1.62 $                             --
  10. --                                                                          --
  11. --           Copyright (c) 1992,1993,1994 NYU, All Rights Reserved          --
  12. --                                                                          --
  13. -- GNAT is free software;  you can  redistribute it  and/or modify it under --
  14. -- terms of the  GNU General Public License as published  by the Free Soft- --
  15. -- ware  Foundation;  either version 2,  or (at your option) any later ver- --
  16. -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
  17. -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
  18. -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
  19. -- for  more details.  You should have  received  a copy of the GNU General --
  20. -- Public License  distributed with GNAT;  see file COPYING.  If not, write --
  21. -- to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. --
  22. --                                                                          --
  23. ------------------------------------------------------------------------------
  24.  
  25. separate (Par)
  26. package body Ch5 is
  27.  
  28.    --  Local functions, used only in this chapter
  29.  
  30.    function P_Case_Statement                     return Node_Id;
  31.    function P_Case_Statement_Alternative         return Node_Id;
  32.    function P_Exit_Statement                     return Node_Id;
  33.    function P_Goto_Statement                     return Node_Id;
  34.    function P_If_Statement                       return Node_Id;
  35.    function P_Label                              return Node_Id;
  36.    function P_Loop_Parameter_Specification       return Node_Id;
  37.    function P_Null_Statement                     return Node_Id;
  38.  
  39.    function P_Assignment_Statement (LHS : Node_Id)  return Node_Id;
  40.    --  Parse assignment statement. On entry, the caller has scanned the left
  41.    --  hand side (passed in as Lhs), and the colon-equal (or some symbol
  42.    --  taken to be an error equivalent such as equal).
  43.  
  44.    function P_Begin_Statement (Block_Name : Node_Id := Empty) return Node_Id;
  45.    --  Parse begin-end statement. If Block_Name is non-Empty on entry, it is
  46.    --  the N_Identifier node for the label on the block. If Block_Name is
  47.    --  Empty on entry (the default), then the block statement is unlabeled.
  48.  
  49.    function P_Declare_Statement (Block_Name : Node_Id := Empty) return Node_Id;
  50.    --  Parse declare block. If Block_Name is non-Empty on entry, it is
  51.    --  the N_Identifier node for the label on the block. If Block_Name is
  52.    --  Empty on entry (the default), then the block statement is unlabeled.
  53.  
  54.    function P_For_Statement (Loop_Name : Node_Id := Empty) return Node_Id;
  55.    --  Parse for statement. If Loop_Name is non-Empty on entry, it is
  56.    --  the N_Identifier node for the label on the loop. If Loop_Name is
  57.    --  Empty on entry (the default), then the for statement is unlabeled.
  58.  
  59.    function P_Loop_Statement (Loop_Name : Node_Id := Empty) return Node_Id;
  60.    --  Parse loop statement. If Loop_Name is non-Empty on entry, it is
  61.    --  the N_Identifier node for the label on the loop. If Loop_Name is
  62.    --  Empty on entry (the default), then the loop statement is unlabeled.
  63.  
  64.    function P_While_Statement (Loop_Name : Node_Id := Empty) return Node_Id;
  65.    --  Parse while statement. If Loop_Name is non-Empty on entry, it is
  66.    --  the N_Identifier node for the label on the loop. If Loop_Name is
  67.    --  Empty on entry (the default), then the while statement is unlabeled.
  68.  
  69.    ---------------------------------
  70.    -- 5.1  Sequence of Statements --
  71.    ---------------------------------
  72.  
  73.    --  SEQUENCE_OF_STATEMENTS ::= STATEMENT {STATEMENT}
  74.  
  75.    --  STATEMENT ::=
  76.    --    {LABEL} SIMPLE_STATEMENT | {LABEL} COMPOUND_STATEMENT
  77.  
  78.    --  SIMPLE_STATEMENT ::=      NULL_STATEMENT
  79.    --  | ASSIGNMENT_STATEMENT  | EXIT_STATEMENT
  80.    --  | GOTO_STATEMENT        | PROCEDURE_CALL_STATEMENT
  81.    --  | RETURN_STATEMENT      | ENTRY_CALL_STATEMENT
  82.    --  | REQUEUE_STATEMENT     | DELAY_STATEMENT
  83.    --  | ABORT_STATEMENT       | RAISE_STATEMENT
  84.    --  | CODE_STATEMENT
  85.  
  86.    --  COMPOUND_STATEMENT ::=
  87.    --    IF_STATEMENT         | CASE_STATEMENT
  88.    --  | LOOP_STATEMENT       | BLOCK_STATEMENT
  89.    --  | ACCEPT_STATEMENT     | SELECT_STATEMENT
  90.  
  91.    --  This procedure scans a sequence of statements. The caller sets SS_Flags
  92.    --  to indicate acceptable termination conditions for the sequenece:
  93.  
  94.    --    SS_Flags.Eftm Terminate on ELSIF
  95.    --    SS_Flags.Eltm Terminate on ELSE
  96.    --    SS_Flags.Extm Terminate on EXCEPTION
  97.    --    SS_Flags.Ortm Terminate on OR
  98.    --    SS_Flags.Tatm Terminate on THEN ABORT (Token = ABORT on return)
  99.    --    SS_Flags.Whtm Terminate on WHEN
  100.    --    SS_Flags.Unco Unconditional terminate after scanning one statement
  101.  
  102.    --  In addition, the scan is always terminated by encountering END or the
  103.    --  end of file (EOF) condition. If one of the six above terminators is
  104.    --  encountered with the corresponding SS_Flags flag not set, then the
  105.    --  action taken is as follows:
  106.  
  107.    --    If the keyword occurs to the left of the expected column of the end
  108.    --    for the current sequence (as recorded in the current end context),
  109.    --    then it is assumed to belong to an outer context, and is considered
  110.    --    to terminate the sequence of statements.
  111.  
  112.    --    If the keyword occurs to the right of, or in the expected column of
  113.    --    the end for the current sequence, then an error message is output,
  114.    --    the keyword together with its associated context is skipped, and
  115.    --    the statement scan continues until another terminator is found.
  116.  
  117.    --  Note that the first action means that control can return to the caller
  118.    --  with Token set to a terminator other than one of those specified by the
  119.    --  SS parameter. The caller should treat such a case as equivalent to END.
  120.  
  121.    --  In addition, the flag SS_Flags.Sreq is set to True to indicate that at
  122.    --  least one real statement (other than a pragma) is required in the
  123.    --  statement sequence. During the processing of the sequence, this
  124.    --  flag is manipulated to indicate the current status of the requirement
  125.    --  for a statement. For example, it is turned off by the occurrence of a
  126.    --  statement, and back on by a label (which requires a following statement)
  127.  
  128.    --  Error recovery: cannot raise Error_Resync. If an error occurs during
  129.    --  parsing a statement, then the scan pointer is advanced past the next
  130.    --  semicolon and the parse continues.
  131.  
  132.    function P_Sequence_Of_Statements (SS_Flags : SS_Rec) return List_Id is
  133.  
  134.       Statement_Required : Boolean;
  135.       --  This flag indicates if a subsequent statement (other than a pragma)
  136.       --  is required. It is initialized from the Sreq flag, and modified as
  137.       --  statements are scanned (a statement turns it off, and a label turns
  138.       --  it back on again since a statement must follow a label).
  139.  
  140.       Scan_State : Saved_Scan_State;
  141.  
  142.       Statement_List : List_Id;
  143.       Statement_Node : Node_Id;
  144.       Block_Label    : Name_Id;
  145.       Id_Node        : Node_Id;
  146.       Name_Node      : Node_Id;
  147.  
  148.       procedure Test_Statement_Required;
  149.       --  Flag error if Statement_Required flag set
  150.  
  151.       procedure Test_Statement_Required is
  152.       begin
  153.          if Statement_Required then
  154.             Error_Msg_BC ("statement expected");
  155.          end if;
  156.       end Test_Statement_Required;
  157.  
  158.    --  Start of processing for P_Sequence_Of_Statements
  159.  
  160.    begin
  161.       Statement_List := New_List;
  162.       Statement_Required := SS_Flags.Sreq;
  163.  
  164.       loop
  165.          while Token = Tok_Semicolon loop
  166.             Error_Msg_SC ("unexpected semicolon ignored");
  167.             Scan; -- past junk semicolon
  168.          end loop;
  169.  
  170.          begin
  171.             if Style_Check then Style.Check_Indentation; end if;
  172.  
  173.             --  If we are checking columns, then if the next statement is at
  174.             --  the start of the line, it must start to the right of the opener
  175.             --  of the enclosing construct. If not, then we terminate the scan
  176.             --  for statements, and the caller will give an error message if
  177.             --  we are not at an appropriate terminating token.
  178.  
  179.             if RM_Column_Check and then Token_Is_At_Start_Of_Line
  180.               and then Start_Column <= Scope.Table (Scope.Last).Ecol
  181.             then
  182.                if Statement_Required then
  183.                   Error_Msg_BC ("incorrect layout for column check mode");
  184.                end if;
  185.  
  186.                exit;
  187.             end if;
  188.  
  189.             --  Deal with reserved identifier (in assignment or call)
  190.  
  191.             if Is_Reserved_Identifier then
  192.                Save_Scan_State (Scan_State); -- at possible bad identifier
  193.                Scan; -- and scan past it
  194.  
  195.                --  We have an reserved word which is spelled in identifier
  196.                --  style, so the question is whether it really is intended
  197.                --  to be an identifier.
  198.  
  199.                if
  200.                   --  If followed by a semicolon, then it is an identifier,
  201.                   --  with the exception of the cases tested for below.
  202.  
  203.                   (Token = Tok_Semicolon
  204.                     and then Prev_Token /= Tok_Return
  205.                     and then Prev_Token /= Tok_Null
  206.                     and then Prev_Token /= Tok_Raise
  207.                     and then Prev_Token /= Tok_End
  208.                     and then Prev_Token /= Tok_Exit)
  209.  
  210.                   --  If followed by colon, colon-equal, or dot, then we
  211.                   --  definitely  have an identifier (could not be reserved)
  212.  
  213.                   or else Token = Tok_Colon
  214.                   or else Token = Tok_Colon_Equal
  215.                   or else Token = Tok_Dot
  216.  
  217.                   --  Left paren means we have an identifier except for those
  218.                   --  reserved words that can legitimately be followed by a
  219.                   --  left paren.
  220.  
  221.                   or else
  222.                     (Token = Tok_Left_Paren
  223.                       and then Prev_Token /= Tok_Case
  224.                       and then Prev_Token /= Tok_Delay
  225.                       and then Prev_Token /= Tok_If
  226.                       and then Prev_Token /= Tok_Elsif
  227.                       and then Prev_Token /= Tok_Return
  228.                       and then Prev_Token /= Tok_When
  229.                       and then Prev_Token /= Tok_While
  230.                       and then Prev_Token /= Tok_Separate)
  231.                then
  232.                   --  Here we have an apparent reserved identifier and the
  233.                   --  token past it is appropriate to this usage (and would
  234.                   --  be a definite error if this is not an identifier). What
  235.                   --  we do is to use P_Identifier to fix up the identifier,
  236.                   --  and then fall into the normal processing.
  237.  
  238.                   Restore_Scan_State (Scan_State); -- back to the ID
  239.                   Scan_Reserved_Identifier (Force_Msg => False);
  240.  
  241.                   --  Not a reserved identifier after all (or at least we can't
  242.                   --  be sure that it is), so reset the scan and continue.
  243.  
  244.                else
  245.                   Restore_Scan_State (Scan_State); -- back to the reserved word
  246.                end if;
  247.             end if;
  248.  
  249.             --  Now look to see what kind of statement we have
  250.  
  251.             case Token is
  252.  
  253.                --  Case of end or EOF
  254.  
  255.                when Tok_End | Tok_EOF =>
  256.  
  257.                   --  These tokens always terminate the statement sequence
  258.  
  259.                   Test_Statement_Required;
  260.                   exit;
  261.  
  262.                --  Case of ELSIF
  263.  
  264.                when Tok_Elsif =>
  265.  
  266.                   --  Terminate if Eftm set or if the ELSIF is to the left
  267.                   --  of the expected column of the end for this sequence
  268.  
  269.                   if SS_Flags.Eftm
  270.                      or else Start_Column < Scope.Table (Scope.Last).Ecol
  271.                   then
  272.                      Test_Statement_Required;
  273.                      exit;
  274.  
  275.                   --  Otherwise complain and skip past ELSIF Condition then
  276.  
  277.                   else
  278.                      Error_Msg_SC ("ELSIF not allowed here");
  279.                      Scan; -- past ELSIF
  280.                      Discard_Junk_Node (P_Expression_No_Right_Paren);
  281.                      TF_Then;
  282.                      Statement_Required := False;
  283.                   end if;
  284.  
  285.                --  Case of ELSE
  286.  
  287.                when Tok_Else =>
  288.  
  289.                   --  Terminate if Eltm set or if the else is to the left
  290.                   --  of the expected column of the end for this sequence
  291.  
  292.                   if SS_Flags.Eltm
  293.                      or else Start_Column < Scope.Table (Scope.Last).Ecol
  294.                   then
  295.                      Test_Statement_Required;
  296.                      exit;
  297.  
  298.                   --  Otherwise complain and skip past else
  299.  
  300.                   else
  301.                      Error_Msg_SC ("ELSE not allowed here");
  302.                      Scan; -- past ELSE
  303.                      Statement_Required := False;
  304.                   end if;
  305.  
  306.                --  Case of exception
  307.  
  308.                when Tok_Exception =>
  309.                   Test_Statement_Required;
  310.  
  311.                   --  If Extm not set and the exception is not to the left
  312.                   --  of the expected column of the end for this sequence, then
  313.                   --  we assume it belongs to the current sequence, even though
  314.                   --  it is not permitted.
  315.  
  316.                   if not SS_Flags.Extm and then
  317.                      Start_Column >= Scope.Table (Scope.Last).Ecol
  318.  
  319.                   then
  320.                      Error_Msg_SC ("exception handler not permitted here");
  321.                      Scan; -- past EXCEPTION
  322.                      Discard_Junk_List (Parse_Exception_Handlers);
  323.                   end if;
  324.  
  325.                   --  Always return, in the case where we scanned out handlers
  326.                   --  that we did not expect, Parse_Exception_Handlers returned
  327.                   --  with Token being either end or EOF, so we are OK
  328.  
  329.                   exit;
  330.  
  331.                --  Case of OR
  332.  
  333.                when Tok_Or =>
  334.  
  335.                   --  Terminate if Ortm set or if the or is to the left
  336.                   --  of the expected column of the end for this sequence
  337.  
  338.                   if SS_Flags.Ortm
  339.                      or else Start_Column < Scope.Table (Scope.Last).Ecol
  340.                   then
  341.                      Test_Statement_Required;
  342.                      exit;
  343.  
  344.                   --  Otherwise complain and skip past or
  345.  
  346.                   else
  347.                      Error_Msg_SC ("OR not allowed here");
  348.                      Scan; -- past or
  349.                      Statement_Required := False;
  350.                   end if;
  351.  
  352.                --  Case of THEN (deal also with THEN ABORT)
  353.  
  354.                when Tok_Then =>
  355.                   Save_Scan_State (Scan_State); -- at THEN
  356.                   Scan; -- past THEN
  357.  
  358.                   --  Terminate if THEN ABORT allowed (ATC case)
  359.  
  360.                   exit when SS_Flags.Tatm and then Token = Tok_Abort;
  361.  
  362.                   --  Otherwise we treat then as some kind of mess where we
  363.                   --  did not see the associated IF, but we pick up assuming
  364.                   --  it had been there!
  365.  
  366.                   Restore_Scan_State (Scan_State); -- to THEN
  367.                   Append_To (Statement_List, P_If_Statement);
  368.                   Statement_Required := False;
  369.  
  370.                --  Case of WHEN (error because we are not in a case)
  371.  
  372.                when Tok_When | Tok_Others =>
  373.  
  374.                   --  Terminate if Whtm set or if the WHEN is to the left
  375.                   --  of the expected column of the end for this sequence
  376.  
  377.                   if SS_Flags.Whtm
  378.                      or else Start_Column < Scope.Table (Scope.Last).Ecol
  379.                   then
  380.                      Test_Statement_Required;
  381.                      exit;
  382.  
  383.                   --  Otherwise complain and skip when Choice {| Choice} =>
  384.  
  385.                   else
  386.                      Error_Msg_SC ("WHEN not allowed here");
  387.                      Scan; -- past when
  388.                      Discard_Junk_List (P_Discrete_Choice_List);
  389.                      TF_Arrow;
  390.                      Statement_Required := False;
  391.                   end if;
  392.  
  393.                --  Cases of statements starting with an identifier
  394.  
  395.                when Tok_Identifier =>
  396.  
  397.                   --  Save scan pointers and line number in case block label
  398.  
  399.                   Id_Node := Token_Node;
  400.                   Block_Label := Token_Name;
  401.                   Save_Scan_State (Scan_State); -- at Id
  402.                   Scan; -- past Id
  403.  
  404.                   --  Check for common case of assignment, since it occurs
  405.                   --  frequently, and we want to process it efficiently.
  406.  
  407.                   if Token = Tok_Colon_Equal then
  408.                      Scan; -- past the colon-equal
  409.                      Append_To (Statement_List,
  410.                        P_Assignment_Statement (Id_Node));
  411.                      Statement_Required := False;
  412.  
  413.                   --  Check common case of procedure call, another case that
  414.                   --  we want to speed up as much as possible.
  415.  
  416.                   elsif Token = Tok_Semicolon then
  417.                      Append_To (Statement_List,
  418.                        P_Statement_Name (Id_Node));
  419.                      Scan; -- past semicolon
  420.                      Statement_Required := False;
  421.  
  422.                   --  Check for case of "go to" in place of "goto"
  423.  
  424.                   elsif Token = Tok_Identifier
  425.                     and then Block_Label = Name_Go
  426.                     and then Token_Name = Name_To
  427.                   then
  428.                      Error_Msg_SP ("goto is one word");
  429.                      Append_To (Statement_List, P_Goto_Statement);
  430.                      Statement_Required := False;
  431.  
  432.                   --  Check common case of = used instead of :=, just so we
  433.                   --  give a better error message for this special misuse.
  434.  
  435.                   elsif Token = Tok_Equal then
  436.                      T_Colon_Equal; -- give := expected message
  437.                      Append_To (Statement_List,
  438.                        P_Assignment_Statement (Id_Node));
  439.                      Statement_Required := False;
  440.  
  441.                   --  Check case of loop label or block label
  442.  
  443.                   elsif Token = Tok_Colon
  444.                     or else (Token in Token_Class_Labeled_Stmt
  445.                               and then not Token_Is_At_Start_Of_Line)
  446.                   then
  447.                      T_Colon; -- past colon (if there, or msg for missing one)
  448.  
  449.                      --  Test for more than one label
  450.  
  451.                      loop
  452.                         exit when Token /= Tok_Identifier;
  453.                         Save_Scan_State (Scan_State); -- at Id
  454.                         Scan; -- past Id
  455.  
  456.                         if Token = Tok_Colon then
  457.                            Error_Msg_SP
  458.                               ("only one label allowed on block or loop");
  459.                            Scan; -- past colon on extra label
  460.  
  461.                            --  We will set Error_name as the Block_Label since
  462.                            --  we really don't know which of the labels might
  463.                            --  be used at the end of the loop or block!
  464.  
  465.                            Block_Label := Error_Name;
  466.  
  467.                         --  If Id with no colon, then backup to point to the
  468.                         --  Id and we will issue the message below when we try
  469.                         --  to scan out the statement as some other form.
  470.  
  471.                         else
  472.                            Restore_Scan_State (Scan_State); -- to Id
  473.                            exit;
  474.                         end if;
  475.                      end loop;
  476.  
  477.                      --  Loop_Statement (labeled Loop_Statement)
  478.  
  479.                      if Token = Tok_Loop then
  480.                         Append_To (Statement_List,
  481.                           P_Loop_Statement (Id_Node));
  482.  
  483.                      --  While statement (labeled loop statement with WHILE)
  484.  
  485.                      elsif Token = Tok_While then
  486.                         Append_To (Statement_List,
  487.                           P_While_Statement (Id_Node));
  488.  
  489.                      --  Declare statement (labeled block statement with
  490.                      --  DECLARE part)
  491.  
  492.                      elsif Token = Tok_Declare then
  493.                         Append_To (Statement_List,
  494.                           P_Declare_Statement (Id_Node));
  495.  
  496.                      --  Begin statement (labeled block statement with no
  497.                      --  DECLARE part)
  498.  
  499.                      elsif Token = Tok_Begin then
  500.                         Append_To (Statement_List,
  501.                           P_Begin_Statement (Id_Node));
  502.  
  503.                      --  For statement (labeled loop statement with FOR)
  504.  
  505.                      elsif Token = Tok_For then
  506.                         Append_To (Statement_List,
  507.                           P_For_Statement (Id_Node));
  508.  
  509.                      --  Improper statement follows label. If we have an
  510.                      --  expression token, then assume the colon was a
  511.                      --  malformed attempt at an assignment symbol.
  512.  
  513.                      elsif Token not in Token_Class_Eterm then
  514.                         Error_Msg_SP ("assignment symbol is "":=""");
  515.                         Append_To (Statement_List,
  516.                           P_Assignment_Statement (Id_Node));
  517.  
  518.                      --  Otherwise complain we have inappropriate statement
  519.  
  520.                      else
  521.                         Error_Msg_AP
  522.                           ("loop or block statement must follow label");
  523.                      end if;
  524.  
  525.                      Statement_Required := False;
  526.  
  527.                   --  Here we have an identifier followed by something
  528.                   --  other than a colon, semicolon or assignment symbol.
  529.                   --  The only valid possibility is a name extension symbol
  530.  
  531.                   elsif Token in Token_Class_Namext then
  532.                      Restore_Scan_State (Scan_State); -- to Id
  533.                      Name_Node := P_Name;
  534.  
  535.                      --  Skip junk right parens in this context
  536.  
  537.                      while Token = Tok_Right_Paren loop
  538.                         Error_Msg_SC ("extra right paren");
  539.                         Scan; -- past )
  540.                      end loop;
  541.  
  542.                      --  Check context following call
  543.  
  544.                      if Token = Tok_Colon_Equal then
  545.                         Scan; -- past colon equal
  546.                         Append_To (Statement_List,
  547.                           P_Assignment_Statement (Name_Node));
  548.                         Statement_Required := False;
  549.  
  550.                      --  Check common case of = used instead of :=
  551.  
  552.                      elsif Token = Tok_Equal then
  553.                         T_Colon_Equal; -- give := expected message
  554.                         Append_To (Statement_List,
  555.                           P_Assignment_Statement (Name_Node));
  556.                         Statement_Required := False;
  557.  
  558.                      --  Check apostrophe cases
  559.  
  560.                      elsif Token = Tok_Apostrophe then
  561.                         Append_To (Statement_List,
  562.                           P_Code_Statement (Name_Node));
  563.                         Statement_Required := False;
  564.  
  565.                      --  The only other valid item after a name is ; which
  566.                      --  means that the item we just scanned was a call.
  567.  
  568.                      elsif Token = Tok_Semicolon then
  569.                         Append_To (Statement_List,
  570.                           P_Statement_Name (Name_Node));
  571.                         Scan; -- past semicolon
  572.                         Statement_Required := False;
  573.  
  574.                         --  Else we have a missing semicolon
  575.  
  576.                      else
  577.                         TF_Semicolon;
  578.                         Statement_Required := False;
  579.                      end if;
  580.  
  581.                   --  If junk after identifier, check if identifier is an
  582.                   --  instance of an incorrectly spelled keyword. If so, we
  583.                   --  do nothing. The Bad_Spelling_Of will have reset Token
  584.                   --  to the appropriate keyword, so the next time round the
  585.                   --  loop we will process the modified token. Note that we
  586.                   --  check for ELSIF before ELSE here. That's not accidental.
  587.                   --  We don't want to identify a misspelling of ELSE as
  588.                   --  ELSIF, and in particular we do not want to treat ELSEIF
  589.                   --  as ELSE IF.
  590.  
  591.                   else
  592.                      Restore_Scan_State (Scan_State); -- to identifier
  593.  
  594.                      if Bad_Spelling_Of (Tok_Abort)
  595.                        or else Bad_Spelling_Of (Tok_Accept)
  596.                        or else Bad_Spelling_Of (Tok_Case)
  597.                        or else Bad_Spelling_Of (Tok_Declare)
  598.                        or else Bad_Spelling_Of (Tok_Delay)
  599.                        or else Bad_Spelling_Of (Tok_Elsif)
  600.                        or else Bad_Spelling_Of (Tok_Else)
  601.                        or else Bad_Spelling_Of (Tok_End)
  602.                        or else Bad_Spelling_Of (Tok_Exception)
  603.                        or else Bad_Spelling_Of (Tok_Exit)
  604.                        or else Bad_Spelling_Of (Tok_For)
  605.                        or else Bad_Spelling_Of (Tok_Goto)
  606.                        or else Bad_Spelling_Of (Tok_If)
  607.                        or else Bad_Spelling_Of (Tok_Loop)
  608.                        or else Bad_Spelling_Of (Tok_Or)
  609.                        or else Bad_Spelling_Of (Tok_Pragma)
  610.                        or else Bad_Spelling_Of (Tok_Raise)
  611.                        or else Bad_Spelling_Of (Tok_Requeue)
  612.                        or else Bad_Spelling_Of (Tok_Return)
  613.                        or else Bad_Spelling_Of (Tok_Select)
  614.                        or else Bad_Spelling_Of (Tok_When)
  615.                        or else Bad_Spelling_Of (Tok_While)
  616.                      then
  617.                         null;
  618.  
  619.                      --  If not a bad spelling, then we really have junk
  620.  
  621.                      else
  622.                         Scan; -- past identifier again
  623.  
  624.                         --  If next token is first token on line, then we
  625.                         --  consider that we were missing a semicolon after
  626.                         --  the identifier, and process it as a procedure
  627.                         --  call with no parameters.
  628.  
  629.                         if Token_Is_At_Start_Of_Line then
  630.                            Append_To (Statement_List,
  631.                              P_Statement_Name (Id_Node));
  632.                            T_Semicolon; -- to give error message
  633.                            Statement_Required := False;
  634.  
  635.                         --  Otherwise we give a missing := message and
  636.                         --  simply abandon the junk that is there now.
  637.  
  638.                         else
  639.                            T_Colon_Equal; -- give := expected message
  640.                            raise Error_Resync;
  641.                         end if;
  642.  
  643.                      end if;
  644.                   end if;
  645.  
  646.                --  Statement starting with operator symbol. This could be
  647.                --  a call, a name starting an assignment, or a qualified
  648.                --  expression.
  649.  
  650.                when Tok_Operator_Symbol =>
  651.                   Name_Node := P_Name;
  652.  
  653.                   --  An attempt at a range attribute or a qualified expression
  654.                   --  must be illegal here (a code statement cannot possibly
  655.                   --  allow qualification by a function name).
  656.  
  657.                   if Token = Tok_Apostrophe then
  658.                      Error_Msg_SC ("apostrophe illegal here");
  659.                      raise Error_Resync;
  660.                   end if;
  661.  
  662.                   --  Scan possible assignment if we have a name
  663.  
  664.                   if Expr_Form /= EF_Name
  665.                     and then Token = Tok_Colon_Equal
  666.                   then
  667.                      Scan; -- past colon equal
  668.                      Append_To (Statement_List,
  669.                        P_Assignment_Statement (Name_Node));
  670.                   else
  671.                      Append_To (Statement_List,
  672.                        P_Statement_Name (Name_Node));
  673.                   end if;
  674.  
  675.                   TF_Semicolon;
  676.                   Statement_Required := False;
  677.  
  678.                --  Label starting with << which must precede real statement
  679.  
  680.                when Tok_Less_Less =>
  681.                   Append_To (Statement_List, P_Label);
  682.                   Statement_Required := True;
  683.  
  684.                --  Pragma appearing as a statement in a statement sequence
  685.  
  686.                when Tok_Pragma =>
  687.                   Append_To (Statement_List, P_Pragma);
  688.  
  689.                --  Abort_Statement
  690.  
  691.                when Tok_Abort =>
  692.                   Append_To (Statement_List, P_Abort_Statement);
  693.                   Statement_Required := False;
  694.  
  695.                --  Accept_Statement
  696.  
  697.                when Tok_Accept =>
  698.                   Append_To (Statement_List, P_Accept_Statement);
  699.                   Statement_Required := False;
  700.  
  701.                --  Begin_Statement (Block_Statement with no declare, no label)
  702.  
  703.                when Tok_Begin =>
  704.                   Append_To (Statement_List, P_Begin_Statement);
  705.                   Statement_Required := False;
  706.  
  707.                --  Case_Statement
  708.  
  709.                when Tok_Case =>
  710.                   Append_To (Statement_List, P_Case_Statement);
  711.                   Statement_Required := False;
  712.  
  713.                --  Block_Statement with DECLARE and no label
  714.  
  715.                when Tok_Declare =>
  716.                   Append_To (Statement_List, P_Declare_Statement);
  717.                   Statement_Required := False;
  718.  
  719.                --  Delay_Statement
  720.  
  721.                when Tok_Delay =>
  722.                   Append_To (Statement_List, P_Delay_Statement);
  723.                   Statement_Required := False;
  724.  
  725.                --  Exit_Statement
  726.  
  727.                when Tok_Exit =>
  728.                   Append_To (Statement_List, P_Exit_Statement);
  729.                   Statement_Required := False;
  730.  
  731.                --  Loop_Statement with FOR and no label
  732.  
  733.                when Tok_For =>
  734.                   Append_To (Statement_List, P_For_Statement);
  735.                   Statement_Required := False;
  736.  
  737.                --  Goto_Statement
  738.  
  739.                when Tok_Goto =>
  740.                   Append_To (Statement_List, P_Goto_Statement);
  741.                   Statement_Required := False;
  742.  
  743.                --  If_Statement
  744.  
  745.                when Tok_If =>
  746.                   Append_To (Statement_List, P_If_Statement);
  747.                   Statement_Required := False;
  748.  
  749.                --  Loop_Statement
  750.  
  751.                when Tok_Loop =>
  752.                   Append_To (Statement_List, P_Loop_Statement);
  753.                   Statement_Required := False;
  754.  
  755.                --  Null_Statement
  756.  
  757.                when Tok_Null =>
  758.                   Append_To (Statement_List, P_Null_Statement);
  759.                   Statement_Required := False;
  760.  
  761.                --  Raise_Statement
  762.  
  763.                when Tok_Raise =>
  764.                   Append_To (Statement_List, P_Raise_Statement);
  765.                   Statement_Required := False;
  766.  
  767.                --  Requeue_Statement
  768.  
  769.                when Tok_Requeue =>
  770.                   Append_To (Statement_List, P_Requeue_Statement);
  771.                   Statement_Required := False;
  772.  
  773.                --  Return_Statement
  774.  
  775.                when Tok_Return =>
  776.                   Append_To (Statement_List, P_Return_Statement);
  777.                   Statement_Required := False;
  778.  
  779.                --  Select_Statement
  780.  
  781.                when Tok_Select =>
  782.                   Append_To (Statement_List, P_Select_Statement);
  783.                   Statement_Required := False;
  784.  
  785.                --  While_Statement (Block_Statement with while and no loop)
  786.  
  787.                when Tok_While =>
  788.                   Append_To (Statement_List, P_While_Statement);
  789.                   Statement_Required := False;
  790.  
  791.                --  Anything else is some kind of junk, signal an error message
  792.                --  and then raise Error_Resync, to merge with the normal
  793.                --  handling of a bad statement.
  794.  
  795.                when others =>
  796.                   Error_Msg_BC ("statement expected");
  797.                   raise Error_Resync;
  798.  
  799.             end case;
  800.  
  801.          --  On error resynchronization, skip past next semicolon, and, since
  802.          --  we are still in the statement loop, look for next statement. We
  803.          --  set Statement_Required False to avoid an unnecessary error message
  804.          --  complaining that no statement was found (i.e. we consider the
  805.          --  junk to satisfy the requirement for a statement being present).
  806.  
  807.          exception
  808.             when Error_Resync =>
  809.                Resync_Past_Semicolon_Or_To_Loop_Or_Then;
  810.                Statement_Required := False;
  811.          end;
  812.  
  813.          exit when SS_Flags.Unco;
  814.  
  815.       end loop;
  816.  
  817.       return Statement_List;
  818.  
  819.    end P_Sequence_Of_Statements;
  820.  
  821.    --------------------
  822.    -- 5.1  Statement --
  823.    --------------------
  824.  
  825.    --  Parsed by P_Sequence_Of_Statements (5.1), except for the case
  826.    --  of a statement of the form of a name, which is handled here. The
  827.    --  argument passed in is the tree for the name which has been scanned
  828.    --  The returned value is the corresponding statement form.
  829.  
  830.    --  This routine is also used by Par.Prag for processing the procedure
  831.    --  call that appears as the second argument of a pragma Assert.
  832.  
  833.    --  Error recovery: cannot raise Error_Resync
  834.  
  835.    function P_Statement_Name (Name_Node : Node_Id) return Node_Id is
  836.       Stmt_Node : Node_Id;
  837.  
  838.    begin
  839.       --  Case of Indexed component, which is a procedure call with arguments
  840.  
  841.       if Nkind (Name_Node) = N_Indexed_Component then
  842.          declare
  843.             Prefix_Node : Node_Id := Prefix (Name_Node);
  844.             Exprs_Node  : List_Id := Expressions (Name_Node);
  845.          begin
  846.             Change_Node (Name_Node, N_Procedure_Call_Statement);
  847.             Set_Name (Name_Node, Prefix_Node);
  848.             Set_Parameter_Associations (Name_Node, Exprs_Node);
  849.             return Name_Node;
  850.          end;
  851.  
  852.       --  Case of function call node, which is a really a procedure call
  853.  
  854.       elsif Nkind (Name_Node) = N_Function_Call then
  855.          declare
  856.             Fname_Node  : Node_Id := Name (Name_Node);
  857.             Params_List : List_Id := Parameter_Associations (Name_Node);
  858.  
  859.          begin
  860.             Change_Node (Name_Node, N_Procedure_Call_Statement);
  861.             Set_Name (Name_Node, Fname_Node);
  862.             Set_Parameter_Associations (Name_Node, Params_List);
  863.             return Name_Node;
  864.          end;
  865.  
  866.       --  All other cases of names are parameterless procedure calls
  867.  
  868.       else
  869.          Stmt_Node :=
  870.            New_Node (N_Procedure_Call_Statement, Sloc (Name_Node));
  871.          Set_Name (Stmt_Node, Name_Node);
  872.          return Stmt_Node;
  873.       end if;
  874.  
  875.    end P_Statement_Name;
  876.  
  877.    ---------------------------
  878.    -- 5.1  Simple Statement --
  879.    ---------------------------
  880.  
  881.    --  Parsed by P_Sequence_Of_Statements (5.1)
  882.  
  883.    -----------------------------
  884.    -- 5.1  Compound Statement --
  885.    -----------------------------
  886.  
  887.    --  Parsed by P_Sequence_Of_Statements (5.1)
  888.  
  889.    -------------------------
  890.    -- 5.1  Null Statement --
  891.    -------------------------
  892.  
  893.    --  NULL_STATEMENT ::= null;
  894.  
  895.    --  The caller has already checked that the current token is null
  896.  
  897.    --  Error recovery: cannot raise Error_Resync
  898.  
  899.    function P_Null_Statement return Node_Id is
  900.       Null_Stmt_Node : Node_Id;
  901.  
  902.    begin
  903.       Null_Stmt_Node := New_Node (N_Null_Statement, Token_Ptr);
  904.       Scan; -- past NULL
  905.       TF_Semicolon;
  906.       return Null_Stmt_Node;
  907.    end P_Null_Statement;
  908.  
  909.    ----------------
  910.    -- 5.1  Label --
  911.    ----------------
  912.  
  913.    --  LABEL ::= <<label_STATEMENT_IDENTIFIER>>
  914.  
  915.    --  STATEMENT_INDENTIFIER ::= DIRECT_NAME
  916.  
  917.    --  The IDENTIFIER of a STATEMENT_IDENTIFIER shall be an identifier
  918.    --  (not an OPERATOR_SYMBOL)
  919.  
  920.    --  The caller has already checked that the current token is <<
  921.  
  922.    --  Error recovery: can raise Error_Resync
  923.  
  924.    function P_Label return Node_Id is
  925.       Label_Node : Node_Id;
  926.  
  927.    begin
  928.       Label_Node := New_Node (N_Label, Token_Ptr);
  929.       Scan; -- past <<
  930.       Set_Identifier (Label_Node, P_Identifier);
  931.       T_Greater_Greater;
  932.       Append_Elmt (Label_Node, Label_List);
  933.       return Label_Node;
  934.    end P_Label;
  935.  
  936.    -------------------------------
  937.    -- 5.1  Statement Identifier --
  938.    -------------------------------
  939.  
  940.    --  Statement label is parsed by P_Label (5.1)
  941.  
  942.    --  Loop label is parsed by P_Loop_Statement (5.5), P_For_Statement (5.5)
  943.    --   or P_While_Statement (5.5)
  944.  
  945.    --  Block label is parsed by P_Begin_Statement (5.6) or
  946.    --   P_Declare_Statement (5.6)
  947.  
  948.    -------------------------------
  949.    -- 5.2  Assignment Statement --
  950.    -------------------------------
  951.  
  952.    --  ASSIGNMENT_STATEMENT ::=
  953.    --    variable_NAME := EXPRESSION;
  954.  
  955.    --  Error recovery: can raise Error_Resync
  956.  
  957.    function P_Assignment_Statement (Lhs : Node_Id) return Node_Id is
  958.       Assign_Node : Node_Id;
  959.  
  960.    begin
  961.       Assign_Node := New_Node (N_Assignment_Statement, Prev_Token_Ptr);
  962.       Set_Name (Assign_Node, LHS);
  963.       Set_Expression (Assign_Node, P_Expression_No_Right_Paren);
  964.       TF_Semicolon;
  965.       return Assign_Node;
  966.    end P_Assignment_Statement;
  967.  
  968.    -----------------------
  969.    -- 5.3  If Statement --
  970.    -----------------------
  971.  
  972.    --  IF_STATEMENT ::=
  973.    --    if CONDITION then
  974.    --      SEQUENCE_OF_STATEMENTS
  975.    --    {elsif CONDITION then
  976.    --      SEQUENCE_OF_STATEMENTS}
  977.    --    [else
  978.    --      SEQUENCE_OF_STATEMENTS]
  979.    --    end if;
  980.  
  981.    --  CONDITION ::= boolean_EXPRESSION
  982.  
  983.    --  The caller has checked that the initial token is IF (or in the error
  984.    --  case of a mysterious THEN, the initial token may simply be THEN, in
  985.    --  which case, no condition (or IF) was scanned).
  986.  
  987.    --  Error recovery: can raise Error_Resync
  988.  
  989.    function P_If_Statement return Node_Id is
  990.       If_Node    : Node_Id;
  991.       Elsif_Node : Node_Id;
  992.       Loc        : Source_Ptr;
  993.  
  994.       procedure Add_Elsif_Part;
  995.       --  An internal procedure used to scan out a single ELSIF part. On entry
  996.       --  the ELSIF (or an ELSE which has been determined should be ELSIF) is
  997.       --  scanned out and is in Prev_Token.
  998.  
  999.       procedure Check_If_Column;
  1000.       --  An internal procedure used to check that THEN, ELSE ELSE, or ELSIF
  1001.       --  appear in the right place if column checking is enabled (i.e. if
  1002.       --  they are the first token on the line, then they must appear in
  1003.       --  the same column as the opening IF).
  1004.  
  1005.       procedure Check_Then_Column;
  1006.       --  This procedure carries out the style checks for a THEN token
  1007.       --  Note that the caller has set Loc to the Source_Ptr value for
  1008.       --  the previous IF or ELSIF token. These checks apply only to a
  1009.       --  THEN at the start of a line.
  1010.  
  1011.       function Else_Should_Be_Elsif return Boolean;
  1012.       --  An internal routine used to do a special error recovery check when
  1013.       --  an ELSE is encountered. It determines if the ELSE should be treated
  1014.       --  as an ELSIF. A positive decision (TRUE returned, is made if the ELSE
  1015.       --  is followed by a sequence of tokens, starting on the same line as
  1016.       --  the ELSE, which are not expression terminators, followed by a THEN.
  1017.       --  On entry, the ELSE has been scanned out.
  1018.  
  1019.       procedure Add_Elsif_Part is
  1020.       begin
  1021.          if No (Elsif_Parts (If_Node)) then
  1022.             Set_Elsif_Parts (If_Node, New_List);
  1023.          end if;
  1024.  
  1025.          Elsif_Node := New_Node (N_Elsif_Part, Prev_Token_Ptr);
  1026.          Loc := Prev_Token_Ptr;
  1027.          Set_Condition (Elsif_Node, P_Expression_No_Right_Paren);
  1028.          Check_Then_Column;
  1029.          TF_Then;
  1030.          Set_Then_Statements
  1031.            (Elsif_Node, P_Sequence_Of_Statements (SS_Eftm_Eltm_Sreq));
  1032.          Append (Elsif_Node, Elsif_Parts (If_Node));
  1033.       end Add_Elsif_Part;
  1034.  
  1035.       procedure Check_If_Column is
  1036.       begin
  1037.          if RM_Column_Check and then Token_Is_At_Start_Of_Line
  1038.            and then Start_Column /= Scope.Table (Scope.Last).Ecol
  1039.          then
  1040.             Error_Msg_Col := Scope.Table (Scope.Last).Ecol;
  1041.             Error_Msg_SC ("this token should be@");
  1042.          end if;
  1043.       end Check_If_Column;
  1044.  
  1045.       procedure Check_Then_Column is
  1046.       begin
  1047.          if Token_Is_At_Start_Of_Line and then Token = Tok_Then then
  1048.             Check_If_Column;
  1049.             if Style_Check then Style.Check_Then (Loc); end if;
  1050.          end if;
  1051.       end Check_Then_Column;
  1052.  
  1053.       function Else_Should_Be_Elsif return Boolean is
  1054.          Scan_State : Saved_Scan_State;
  1055.  
  1056.       begin
  1057.          if Token_Is_At_Start_Of_Line then
  1058.             return False;
  1059.  
  1060.          else
  1061.             Save_Scan_State (Scan_State);
  1062.  
  1063.             loop
  1064.                if Token in Token_Class_Eterm then
  1065.                   Restore_Scan_State (Scan_State);
  1066.                   return False;
  1067.                else
  1068.                   Scan; -- past non-expression terminating token
  1069.  
  1070.                   if Token = Tok_Then then
  1071.                      Restore_Scan_State (Scan_State);
  1072.                      return True;
  1073.                   end if;
  1074.                end if;
  1075.             end loop;
  1076.          end if;
  1077.       end Else_Should_Be_Elsif;
  1078.  
  1079.    --  Start of processing for P_If_Statement
  1080.  
  1081.    begin
  1082.       Push_Scope_Stack;
  1083.       Scope.Table (Scope.Last).Etyp := E_If;
  1084.       Scope.Table (Scope.Last).Ecol := Start_Column;
  1085.       Scope.Table (Scope.Last).Sloc := Token_Ptr;
  1086.       Scope.Table (Scope.Last).Labl := Error;
  1087.  
  1088.       If_Node := New_Node (N_If_Statement, Token_Ptr);
  1089.  
  1090.       if Token = Tok_If then
  1091.          Loc := Token_Ptr;
  1092.          Scan; -- past IF
  1093.          Set_Condition (If_Node, P_Expression_No_Right_Paren);
  1094.  
  1095.          --  Deal with misuse of IF expression => used instead
  1096.          --  of WHEN expression =>
  1097.  
  1098.          if Token = Tok_Arrow then
  1099.             Error_Msg_SC ("THEN expected");
  1100.             Scan; -- past the arrow
  1101.             Pop_Scope_Stack; -- remove unneeded entry
  1102.             raise Error_Resync;
  1103.          end if;
  1104.  
  1105.          Check_Then_Column;
  1106.  
  1107.       else
  1108.          Error_Msg_SC ("no IF for this THEN");
  1109.          Set_Condition (If_Node, Error);
  1110.       end if;
  1111.  
  1112.       TF_Then;
  1113.  
  1114.       while Token = Tok_Then loop
  1115.          Error_Msg_SC ("redundant THEN");
  1116.          Scan; -- past junk THEN
  1117.       end loop;
  1118.  
  1119.       Set_Then_Statements
  1120.         (If_Node, P_Sequence_Of_Statements (SS_Eftm_Eltm_Sreq));
  1121.  
  1122.       --  This loop scans out else and elsif parts
  1123.  
  1124.       loop
  1125.          if Token = Tok_Elsif then
  1126.             Check_If_Column;
  1127.  
  1128.             if Present (Else_Statements (If_Node)) then
  1129.                Error_Msg_SP ("ELSIF cannot appear after ELSE");
  1130.             end if;
  1131.  
  1132.             Scan; -- past ELSIF
  1133.             Add_Elsif_Part;
  1134.  
  1135.          elsif Token = Tok_Else then
  1136.             Check_If_Column;
  1137.             Scan; -- past ELSE
  1138.  
  1139.             if Else_Should_Be_Elsif then
  1140.                Error_Msg_SP ("ELSE should be ELSIF");
  1141.                Add_Elsif_Part;
  1142.  
  1143.             else
  1144.                --  Here we have an else that really is an else
  1145.  
  1146.                if Present (Else_Statements (If_Node)) then
  1147.                   Error_Msg_SP ("Only one ELSE part allowed");
  1148.                   Append_List
  1149.                     (P_Sequence_Of_Statements (SS_Eftm_Eltm_Sreq),
  1150.                      Else_Statements (If_Node));
  1151.                else
  1152.                   Set_Else_Statements
  1153.                     (If_Node, P_Sequence_Of_Statements (SS_Eftm_Eltm_Sreq));
  1154.                end if;
  1155.             end if;
  1156.  
  1157.          --  If anything other than ELSE or ELSIF, exit the loop. The token
  1158.          --  had better be END (and in fact it had better be END IF), but
  1159.          --  we will let End_Statements take care of checking that.
  1160.  
  1161.          else
  1162.             exit;
  1163.          end if;
  1164.       end loop;
  1165.  
  1166.       End_Statements;
  1167.       return If_Node;
  1168.  
  1169.    end P_If_Statement;
  1170.  
  1171.    --------------------
  1172.    -- 5.3  Condition --
  1173.    --------------------
  1174.  
  1175.    --  Condition is always parsed (as an expression) by its parent construct
  1176.  
  1177.  
  1178.    -------------------------
  1179.    -- 5.4  Case Statement --
  1180.    -------------------------
  1181.  
  1182.    --  CASE_STATEMENT ::=
  1183.    --    case EXPRESSION is
  1184.    --      CASE_STATEMENT_ALTERNATIVE
  1185.    --      {CASE_STATEMENT_ALTERNATIVE}
  1186.    --    end case;
  1187.  
  1188.    --  The caller has checked that the first token is CASE
  1189.  
  1190.    --  Can raise Error_Resync
  1191.  
  1192.    function P_Case_Statement return Node_Id is
  1193.       Case_Node         : Node_Id;
  1194.       Alternatives_List : List_Id;
  1195.       First_When_Loc    : Source_Ptr;
  1196.  
  1197.    begin
  1198.       Push_Scope_Stack;
  1199.       Scope.Table (Scope.Last).Etyp := E_Case;
  1200.       Scope.Table (Scope.Last).Ecol := Start_Column;
  1201.       Scope.Table (Scope.Last).Sloc := Token_Ptr;
  1202.       Scope.Table (Scope.Last).Labl := Error;
  1203.  
  1204.       Case_Node := New_Node (N_Case_Statement, Token_Ptr);
  1205.       Scan; -- past CASE
  1206.       Set_Expression (Case_Node, P_Expression_No_Right_Paren);
  1207.       TF_Is;
  1208.  
  1209.       --  Prepare to parse case statement alternatives
  1210.  
  1211.       Alternatives_List := New_List;
  1212.       P_Pragmas_Misplaced;
  1213.       First_When_Loc := Token_Ptr;
  1214.  
  1215.       --  Loop through case statement alternatives
  1216.  
  1217.       loop
  1218.          --  If we have a WHEN or OTHERS, then that's fine keep going. Note
  1219.          --  that it is a semantic check to ensure the proper use of OTHERS
  1220.  
  1221.          if Token = Tok_When or else Token = Tok_Others then
  1222.             Append (P_Case_Statement_Alternative, Alternatives_List);
  1223.  
  1224.          --  If we have an END, then probably we are at the end of the case
  1225.          --  but we only exit if Check_End thinks the END was reasonable.
  1226.  
  1227.          elsif Token = Tok_End then
  1228.             exit when Check_End;
  1229.  
  1230.          --  Here if token is other than WHEN, OTHERS or END. We definitely
  1231.          --  have an error, but the question is whether or not to get out of
  1232.          --  the case statement. We don't want to get out early, or we will
  1233.          --  get a slew of junk error messages for subsequent when tokens.
  1234.  
  1235.          --  If the token is not at the start of the line, or if it is indented
  1236.          --  with respect to the current case statement, then the best guess is
  1237.          --  that we are still supposed to be inside the case statement. We
  1238.          --  complain about the missing WHEN, and discard the junk statements.
  1239.  
  1240.          elsif not Token_Is_At_Start_Of_Line
  1241.            or else Start_Column > Scope.Table (Scope.Last).Ecol
  1242.          then
  1243.             Error_Msg_BC ("WHEN (case statement alternative) expected");
  1244.             Discard_Junk_List (P_Sequence_Of_Statements (SS_Whtm));
  1245.  
  1246.          --  Here we have a junk token at the start of the line and it is
  1247.          --  not indented. If Check_End thinks there is a missing END, then
  1248.          --  we will get out of the case, otherwise we keep going.
  1249.  
  1250.          else
  1251.             exit when Check_End;
  1252.          end if;
  1253.       end loop;
  1254.  
  1255.       --  Make sure we have at least one alternative
  1256.  
  1257.       if Is_Empty_List (Alternatives_List) then
  1258.          Error_Msg
  1259.             ("WHEN expected, must have at least one alternative in case",
  1260.              First_When_Loc);
  1261.          return Error;
  1262.  
  1263.       else
  1264.          Set_Alternatives (Case_Node, Alternatives_List);
  1265.          return Case_Node;
  1266.       end if;
  1267.    end P_Case_Statement;
  1268.  
  1269.    -------------------------------------
  1270.    -- 5.4  Case Statement Alternative --
  1271.    -------------------------------------
  1272.  
  1273.    --  CASE_STATEMENT_ALTERNATIVE ::=
  1274.    --    when DISCRETE_CHOICE_LIST =>
  1275.    --      SEQUENCE_OF_STATEMENTS
  1276.  
  1277.    --  The caller has checked that the initial token is WHEN or OTHERS
  1278.    --  Error recovery: can raise Error_Resync
  1279.  
  1280.    function P_Case_Statement_Alternative return Node_Id is
  1281.       Case_Alt_Node : Node_Id;
  1282.  
  1283.    begin
  1284.       if Style_Check then Style.Check_Indentation; end if;
  1285.       Case_Alt_Node := New_Node (N_Case_Statement_Alternative, Token_Ptr);
  1286.       T_When; -- past WHEN (or give error in OTHERS case)
  1287.       Set_Discrete_Choices (Case_Alt_Node, P_Discrete_Choice_List);
  1288.       TF_Arrow;
  1289.       Set_Statements (Case_Alt_Node, P_Sequence_Of_Statements (SS_Sreq_Whtm));
  1290.       return Case_Alt_Node;
  1291.    end P_Case_Statement_Alternative;
  1292.  
  1293.    -------------------------
  1294.    -- 5.5  Loop Statement --
  1295.    -------------------------
  1296.  
  1297.    --  LOOP_STATEMENT ::=
  1298.    --    [LOOP_STATEMENT_IDENTIFIER:]
  1299.    --      [ITERATION_SCHEME] loop
  1300.    --        SEQUENCE_OF_STATEMENTS
  1301.    --      end loop [loop_IDENTIFIER];
  1302.  
  1303.    --  ITERATION_SCHEME ::=
  1304.    --    while CONDITION
  1305.    --  | for LOOP_PARAMETER_SPECIFICATION
  1306.  
  1307.    --  The parsing of loop statements is handled by one of three functions
  1308.    --  P_Loop_Statement, P_For_Statement or P_While_Statement depending
  1309.    --  on the initial keyword in the construct (excluding the identifier)
  1310.  
  1311.    --  P_Loop_Statement
  1312.  
  1313.    --  This function parses the case where no iteration scheme is present
  1314.  
  1315.    --  The caller has checked that the initial token is LOOP. The parameter
  1316.    --  is the node identifiers for the loop label if any (or is set to Empty
  1317.    --  if there is no loop label).
  1318.  
  1319.    --  Error recovery : can not raise Error_Resync
  1320.  
  1321.    function P_Loop_Statement (Loop_Name : Node_Id := Empty) return Node_Id is
  1322.       Loop_Node : Node_Id;
  1323.  
  1324.    begin
  1325.       Push_Scope_Stack;
  1326.       Scope.Table (Scope.Last).Labl := Loop_Name;
  1327.       Scope.Table (Scope.Last).Ecol := Start_Column;
  1328.       Scope.Table (Scope.Last).Sloc := Token_Ptr;
  1329.       Scope.Table (Scope.Last).Etyp := E_Loop;
  1330.  
  1331.       Loop_Node := New_Node (N_Loop_Statement, Token_Ptr);
  1332.       TF_Loop;
  1333.  
  1334.       if No (Loop_Name) then
  1335.          Set_Has_Created_Identifier (Loop_Node, True);
  1336.          Set_Identifier (Loop_Node,
  1337.            Make_Identifier (Sloc (Loop_Node), New_Internal_Name ('L')));
  1338.       else
  1339.          Set_Identifier (Loop_Node, Loop_Name);
  1340.       end if;
  1341.  
  1342.       Append_Elmt (Loop_Node, Label_List);
  1343.  
  1344.       Set_Statements (Loop_Node, P_Sequence_Of_Statements (SS_Sreq));
  1345.       End_Statements;
  1346.       return Loop_Node;
  1347.    end P_Loop_Statement;
  1348.  
  1349.    --  P_For_Statement
  1350.  
  1351.    --  This function parses a loop statement with a FOR iteration scheme
  1352.  
  1353.    --  The caller has checked that the initial token is FOR. The parameter
  1354.    --  is the node identifier for the block label if any (or is set to Empty
  1355.    --  if there is no block label).
  1356.  
  1357.    --  Note: the caller fills in the Identifier field if a label was present
  1358.  
  1359.    --  Error recovery: can raise Error_Resync
  1360.  
  1361.    function P_For_Statement (Loop_Name : Node_Id := Empty) return Node_Id is
  1362.       Loop_Node        : Node_Id;
  1363.       Iter_Scheme_Node : Node_Id;
  1364.       Loop_For_Flag    : Boolean;
  1365.  
  1366.    begin
  1367.       Push_Scope_Stack;
  1368.       Scope.Table (Scope.Last).Labl := Loop_Name;
  1369.       Scope.Table (Scope.Last).Ecol := Start_Column;
  1370.       Scope.Table (Scope.Last).Sloc := Token_Ptr;
  1371.       Scope.Table (Scope.Last).Etyp := E_Loop;
  1372.  
  1373.       Loop_For_Flag := (Prev_Token = Tok_Loop);
  1374.       Scan; -- past FOR
  1375.       Iter_Scheme_Node := New_Node (N_Iteration_Scheme, Token_Ptr);
  1376.       Set_Loop_Parameter_Specification
  1377.          (Iter_Scheme_Node, P_Loop_Parameter_Specification);
  1378.  
  1379.       --  The following is a special test so that a miswritten for loop such
  1380.       --  as "loop for I in 1..10;" is handled nicely, without making an extra
  1381.       --  entry in the scope stack. We don't bother to actually fix up the
  1382.       --  tree in this case since it's not worth the effort. Instead we just
  1383.       --  eat up the loop junk, leaving the entry for what now looks like an
  1384.       --  unmodified loop intact.
  1385.  
  1386.       if Loop_For_Flag and then Token = Tok_Semicolon then
  1387.          Error_Msg_SC ("LOOP belongs here, not before FOR");
  1388.          Pop_Scope_Stack;
  1389.          return Error;
  1390.  
  1391.       --  Normal case
  1392.  
  1393.       else
  1394.          Loop_Node := New_Node (N_Loop_Statement, Token_Ptr);
  1395.          TF_Loop;
  1396.          Set_Statements (Loop_Node, P_Sequence_Of_Statements (SS_Sreq));
  1397.          End_Statements;
  1398.          Set_Iteration_Scheme (Loop_Node, Iter_Scheme_Node);
  1399.  
  1400.          if No (Loop_Name) then
  1401.             Set_Has_Created_Identifier (Loop_Node, True);
  1402.             Set_Identifier (Loop_Node,
  1403.               Make_Identifier (Sloc (Loop_Node), New_Internal_Name ('L')));
  1404.          else
  1405.             Set_Identifier (Loop_Node, Loop_Name);
  1406.          end if;
  1407.  
  1408.          Append_Elmt (Loop_Node, Label_List);
  1409.  
  1410.          return Loop_Node;
  1411.       end if;
  1412.  
  1413.    end P_For_Statement;
  1414.  
  1415.    --  P_While_Statement
  1416.  
  1417.    --  This procedure scans a loop statement with a WHILE iteration scheme
  1418.  
  1419.    --  The caller has checked that the initial token is WHILE. The parameter
  1420.    --  is the node identifier for the block label if any (or is set to Empty
  1421.    --  if there is no block label).
  1422.  
  1423.    --  Error recovery: cannot raise Error_Resync
  1424.  
  1425.    function P_While_Statement (Loop_Name : Node_Id := Empty) return Node_Id is
  1426.       Loop_Node        : Node_Id;
  1427.       Iter_Scheme_Node : Node_Id;
  1428.       Loop_While_Flag  : Boolean;
  1429.  
  1430.    begin
  1431.       Push_Scope_Stack;
  1432.       Scope.Table (Scope.Last).Labl := Loop_Name;
  1433.       Scope.Table (Scope.Last).Ecol := Start_Column;
  1434.       Scope.Table (Scope.Last).Sloc := Token_Ptr;
  1435.       Scope.Table (Scope.Last).Etyp := E_Loop;
  1436.  
  1437.       Loop_While_Flag := (Prev_Token = Tok_Loop);
  1438.       Iter_Scheme_Node := New_Node (N_Iteration_Scheme, Token_Ptr);
  1439.       Scan; -- past WHILE
  1440.       Set_Condition (Iter_Scheme_Node, P_Expression_No_Right_Paren);
  1441.  
  1442.       --  The following is a special test so that a miswritten for loop such
  1443.       --  as "loop while I > 10;" is handled nicely, without making an extra
  1444.       --  entry in the scope stack. We don't bother to actually fix up the
  1445.       --  tree in this case since it's not worth the effort. Instead we just
  1446.       --  eat up the loop junk, leaving the entry for what now looks like an
  1447.       --  unmodified loop intact.
  1448.  
  1449.       if Loop_While_Flag and then Token = Tok_Semicolon then
  1450.          Error_Msg_SC ("LOOP belongs here, not before WHILE");
  1451.          Pop_Scope_Stack;
  1452.          return Error;
  1453.  
  1454.       --  Normal case
  1455.  
  1456.       else
  1457.          Loop_Node := New_Node (N_Loop_Statement, Token_Ptr);
  1458.          TF_Loop;
  1459.          Set_Statements (Loop_Node, P_Sequence_Of_Statements (SS_Sreq));
  1460.          End_Statements;
  1461.          Set_Iteration_Scheme (Loop_Node, Iter_Scheme_Node);
  1462.  
  1463.          if No (Loop_Name) then
  1464.             Set_Has_Created_Identifier (Loop_Node, True);
  1465.             Set_Identifier (Loop_Node,
  1466.               Make_Identifier (Sloc (Loop_Node), New_Internal_Name ('L')));
  1467.          else
  1468.             Set_Identifier (Loop_Node, Loop_Name);
  1469.          end if;
  1470.  
  1471.          Append_Elmt (Loop_Node, Label_List);
  1472.  
  1473.          return Loop_Node;
  1474.       end if;
  1475.  
  1476.    end P_While_Statement;
  1477.  
  1478.    ---------------------------------------
  1479.    -- 5.5  Loop Parameter Specification --
  1480.    ---------------------------------------
  1481.  
  1482.    --  LOOP_PARAMETER_SPECIFICATION ::=
  1483.    --    DEFINING_IDENTIFIER in [reverse] DISCRETE_SUBTYPE_DEFINITION
  1484.  
  1485.    --  Error recovery: cannot raise Error_Resync
  1486.  
  1487.    function P_Loop_Parameter_Specification return Node_Id is
  1488.       Loop_Param_Specification_Node : Node_Id;
  1489.       ID_Node : Node_Id;
  1490.  
  1491.    begin
  1492.       Loop_Param_Specification_Node :=
  1493.         New_Node (N_Loop_Parameter_Specification, Token_Ptr);
  1494.       ID_Node := P_Defining_Identifier;
  1495.       Set_Defining_Identifier (Loop_Param_Specification_Node, ID_Node);
  1496.       T_In;
  1497.  
  1498.       if Token = Tok_Reverse then
  1499.          Scan; -- past REVERSE
  1500.          Set_Reverse_Present (Loop_Param_Specification_Node, True);
  1501.       end if;
  1502.  
  1503.       Set_Discrete_Subtype_Definition
  1504.         (Loop_Param_Specification_Node, P_Discrete_Subtype_Definition);
  1505.       return Loop_Param_Specification_Node;
  1506.  
  1507.    exception
  1508.       when Error_Resync =>
  1509.          return Error;
  1510.    end P_Loop_Parameter_Specification;
  1511.  
  1512.    --------------------------
  1513.    -- 5.6  Block Statement --
  1514.    --------------------------
  1515.  
  1516.    --  BLOCK_STATEMENT ::=
  1517.    --    [block_STATEMENT_IDENTIFIER:]
  1518.    --      [declare
  1519.    --        DECLARATIVE_PART]
  1520.    --      begin
  1521.    --        HANDLED_SEQUENCE_OF_STATEMENTS
  1522.    --      end [block_IDENTIFIER];
  1523.  
  1524.    --  The parsing of block statements is handled by one of the two functions
  1525.    --  P_Declare_Statement or P_Begin_Statement depending on whether or not
  1526.    --  a declare section is present
  1527.  
  1528.    --  P_Declare_Statement
  1529.  
  1530.    --  This function parses a block statement with DECLARE present
  1531.  
  1532.    --  The caller has checked that the initial token is DECLARE.
  1533.  
  1534.    --  Error recovery: cannot raise Error_Resync
  1535.  
  1536.    function P_Declare_Statement
  1537.      (Block_Name : Node_Id := Empty)
  1538.       return       Node_Id
  1539.    is
  1540.       Block_Node : Node_Id;
  1541.  
  1542.    begin
  1543.       Block_Node := New_Node (N_Block_Statement, Token_Ptr);
  1544.  
  1545.       Push_Scope_Stack;
  1546.       Scope.Table (Scope.Last).Etyp := E_Name;
  1547.       Scope.Table (Scope.Last).Lreq := Present (Block_Name);
  1548.       Scope.Table (Scope.Last).Ecol := Start_Column;
  1549.       Scope.Table (Scope.Last).Labl := Block_Name;
  1550.       Scope.Table (Scope.Last).Sloc := Token_Ptr;
  1551.  
  1552.       Scan; -- past DECLARE
  1553.  
  1554.       if No (Block_Name) then
  1555.          Set_Has_Created_Identifier (Block_Node, True);
  1556.          Set_Identifier (Block_Node,
  1557.            Make_Identifier (Sloc (Block_Node), New_Internal_Name ('B')));
  1558.       else
  1559.          Set_Identifier (Block_Node, Block_Name);
  1560.       end if;
  1561.  
  1562.       Append_Elmt (Block_Node, Label_List);
  1563.       Parse_Decls_Begin_End (Block_Node);
  1564.       return Block_Node;
  1565.    end P_Declare_Statement;
  1566.  
  1567.    --  P_Begin_Statement
  1568.  
  1569.    --  This function parses a block statement with no DECLARE present
  1570.  
  1571.    --  The caller has checked that the initial token is BEGIN
  1572.  
  1573.    --  Error recovery: cannot raise Error_Resync
  1574.  
  1575.    function P_Begin_Statement
  1576.      (Block_Name : Node_Id := Empty)
  1577.       return       Node_Id
  1578.    is
  1579.       Block_Node : Node_Id;
  1580.  
  1581.    begin
  1582.       Block_Node := New_Node (N_Block_Statement, Token_Ptr);
  1583.  
  1584.       Push_Scope_Stack;
  1585.       Scope.Table (Scope.Last).Etyp := E_Name;
  1586.       Scope.Table (Scope.Last).Lreq := Present (Block_Name);
  1587.       Scope.Table (Scope.Last).Ecol := Start_Column;
  1588.       Scope.Table (Scope.Last).Labl := Block_Name;
  1589.       Scope.Table (Scope.Last).Sloc := Token_Ptr;
  1590.  
  1591.       if No (Block_Name) then
  1592.          Set_Has_Created_Identifier (Block_Node, True);
  1593.          Set_Identifier (Block_Node,
  1594.            Make_Identifier (Sloc (Block_Node), New_Internal_Name ('B')));
  1595.       else
  1596.          Set_Identifier (Block_Node, Block_Name);
  1597.       end if;
  1598.  
  1599.       Append_Elmt (Block_Node, Label_List);
  1600.  
  1601.       Scope.Table (Scope.Last).Ecol := Start_Column;
  1602.       Scope.Table (Scope.Last).Sloc := Token_Ptr;
  1603.       Scan; -- past BEGIN
  1604.       Set_Handled_Statement_Sequence
  1605.         (Block_Node, P_Handled_Sequence_Of_Statements);
  1606.       End_Statements;
  1607.       return Block_Node;
  1608.    end P_Begin_Statement;
  1609.  
  1610.    -------------------------
  1611.    -- 5.7  Exit Statement --
  1612.    -------------------------
  1613.  
  1614.    --  EXIT_STATEMENT ::=
  1615.    --    exit [loop_NAME] [when CONDITION];
  1616.  
  1617.    --  The caller has checked that the initial token is EXIT
  1618.  
  1619.    --  Error recovery: can raise Error_Resync
  1620.  
  1621.    function P_Exit_Statement return Node_Id is
  1622.       Exit_Node : Node_Id;
  1623.  
  1624.    begin
  1625.       Exit_Node := New_Node (N_Exit_Statement, Token_Ptr);
  1626.       Scan; -- past EXIT
  1627.  
  1628.       if Token = Tok_Identifier then
  1629.          Set_Name (Exit_Node, Token_Node);
  1630.          Scan; -- past Identifier
  1631.       end if;
  1632.  
  1633.       if Token = Tok_When then
  1634.          Scan; -- past WHEN
  1635.          Set_Condition (Exit_Node, P_Expression_No_Right_Paren);
  1636.  
  1637.       --  Allow IF instead of WHEN, giving error message
  1638.  
  1639.       elsif Token = Tok_If then
  1640.          T_When;
  1641.          Scan; -- past IF used in place of WHEN
  1642.          Set_Condition (Exit_Node, P_Expression_No_Right_Paren);
  1643.       end if;
  1644.  
  1645.       TF_Semicolon;
  1646.       return Exit_Node;
  1647.    end P_Exit_Statement;
  1648.  
  1649.    -------------------------
  1650.    -- 5.8  Goto Statement --
  1651.    -------------------------
  1652.  
  1653.    --  GOTO_STATEMENT ::= goto label_NAME;
  1654.  
  1655.    --  The caller has checked that the initial token is GOTO  (or TO in the
  1656.    --  error case where GO and TO were incorrectly separated).
  1657.  
  1658.    --  Error recovery: can raise Error_Resync
  1659.  
  1660.    function P_Goto_Statement return Node_Id is
  1661.       Goto_Node : Node_Id;
  1662.  
  1663.    begin
  1664.       Goto_Node := New_Node (N_Goto_Statement, Token_Ptr);
  1665.       Scan; -- past GOTO (or TO)
  1666.       Set_Name (Goto_Node, P_Qualified_Simple_Name_Resync);
  1667.       No_Constraint;
  1668.       TF_Semicolon;
  1669.       return Goto_Node;
  1670.    end P_Goto_Statement;
  1671.  
  1672.    ---------------------------
  1673.    -- Parse_Decls_Begin_End --
  1674.    ---------------------------
  1675.  
  1676.    --  This function parses the construct:
  1677.  
  1678.    --      DECLARATIVE_PART
  1679.    --    begin
  1680.    --      HANDLED_SEQUENCE_OF_STATEMENTS
  1681.    --    end [NAME];
  1682.  
  1683.    --  The caller has built the scope stack entry, and created the node to
  1684.    --  whose Declarations and Handled_Statement_Sequence fields are to be
  1685.    --  set. On return these fields are filled in (except in the case of a
  1686.    --  task body, where the handled statement sequence is optional, and may
  1687.    --  thus be Empty), and the scan is positioned past the End sequence.
  1688.  
  1689.    --  If the BEGIN is missing, then the parent node is used to help construct
  1690.    --  an appropriate missing BEGIN message. Possibilities for the parent are:
  1691.  
  1692.    --    N_Block_Statement     declare block
  1693.    --    N_Entry_Body          entry body
  1694.    --    N_Package_Body        package body (begin part optional)
  1695.    --    N_Subprogram_Body     procedure or function body
  1696.    --    N_Task_Body           task body
  1697.  
  1698.    --  Note: in the case of a block statement, there is definitely a DECLARE
  1699.    --  present (because a Begin statement without a DECLARE is handled by the
  1700.    --  P_Begin_Statement procedure, which does not call Parse_Decls_Begin_End.
  1701.  
  1702.    --  Error recovery: cannot raise Error_Resync
  1703.  
  1704.    procedure Parse_Decls_Begin_End (Parent : Node_Id) is
  1705.       Body_Decl    : Node_Id;
  1706.       Body_Sloc    : Source_Ptr;
  1707.       Decls        : List_Id;
  1708.       Decl         : Node_Id;
  1709.       Parent_Nkind : Node_Kind;
  1710.       Spec_Node    : Node_Id;
  1711.  
  1712.       procedure Missing_Begin (Msg : String);
  1713.       --  Called to post a missing begin message. In the normal case this is
  1714.       --  posted at the start of the current token. A special case arises when
  1715.       --  P_Declarative_Items has previously found a missing begin, in which
  1716.       --  case we replace the original error message.
  1717.  
  1718.       procedure Missing_Begin (Msg : String) is
  1719.       begin
  1720.          if Missing_Begin_Msg = No_Error_Msg then
  1721.             Error_Msg_BC (Msg);
  1722.          else
  1723.             Change_Error_Text (Missing_Begin_Msg, Msg);
  1724.          end if;
  1725.       end Missing_Begin;
  1726.  
  1727.    --  Start of processing for Parse_Decls_Begin_End
  1728.  
  1729.    begin
  1730.       Decls := P_Declarative_Part;
  1731.  
  1732.       --  Check for misplacement of later vs basic declarations in Ada 83
  1733.       --  Also carry out this check if we are checking for Ada 95 features
  1734.  
  1735.       if Ada_83 or Features_On then
  1736.          Decl := First (Decls);
  1737.  
  1738.          --  Loop through sequence of basic declarative items
  1739.  
  1740.          Outer : while Present (Decl) loop
  1741.             if Nkind (Decl) /= N_Subprogram_Body
  1742.               and then Nkind (Decl) /= N_Package_Body
  1743.               and then Nkind (Decl) /= N_Task_Body
  1744.               and then Nkind (Decl) not in  N_Body_Stub
  1745.             then
  1746.                Decl := Next (Decl);
  1747.  
  1748.             --  Once a body is encountered, we only allow later declarative
  1749.             --  items. The inner loop checks the rest of the list.
  1750.  
  1751.             else
  1752.                Body_Sloc := Sloc (Decl);
  1753.  
  1754.                Inner : while Present (Decl) loop
  1755.                   if Nkind (Decl) not in N_Later_Decl_Item
  1756.                     and then Nkind (Decl) /= N_Pragma
  1757.                   then
  1758.                      Note_Feature (Later_Declaration_Ordering, Sloc (Decl));
  1759.  
  1760.                      if Ada_83 then
  1761.                         Error_Msg_Sloc := Body_Sloc;
  1762.                         Error_Msg_N
  1763.                           ("(Ada 83) decl cannot appear after body#", Decl);
  1764.                      end if;
  1765.                   end if;
  1766.  
  1767.                   Decl := Next (Decl);
  1768.                end loop Inner;
  1769.             end if;
  1770.          end loop Outer;
  1771.       end if;
  1772.  
  1773.       --  Here is where we deal with the case of IS used instead of semicolon.
  1774.       --  Specifically, if the last declaration in the declarative part is a
  1775.       --  subprogram body still marked as having a bad IS, then this is where
  1776.       --  we decide that the IS should really have been a semicolon and that
  1777.       --  the body should have been a declaration. Note that if the bad IS
  1778.       --  had turned out to be OK (i.e. a decent begin/end was found for it),
  1779.       --  then the Bad_Is_Detected flag would have been reset by now.
  1780.  
  1781.       Body_Decl := Last (Decls);
  1782.  
  1783.       if Present (Body_Decl)
  1784.         and then Nkind (Body_Decl) = N_Subprogram_Body
  1785.         and then Bad_Is_Detected (Body_Decl)
  1786.       then
  1787.  
  1788.          --  OK, we have the case of a bad IS, so we need to fix up the tree.
  1789.          --  What we have now is a subprogram body with attached declarations
  1790.          --  and a possible statement sequence.
  1791.  
  1792.          --  First step is to take the declarations that were part of the bogus
  1793.          --  subprogram body and append them to the outer declaration chain.
  1794.          --  In other words we append them past the body (which we will later
  1795.          --  convert into a declaration).
  1796.  
  1797.          Append_List (Declarations (Body_Decl), Decls);
  1798.  
  1799.          --  Now take the handled statement sequence of the bogus body and
  1800.          --  set it as the statement sequence for the outer construct. Note
  1801.          --  that it may be empty (we specially allowed a missing BEGIN for
  1802.          --  a subprogram body marked as having a bad IS -- see below).
  1803.  
  1804.          Set_Handled_Statement_Sequence (Parent,
  1805.            Handled_Statement_Sequence (Body_Decl));
  1806.  
  1807.          --  Next step is to convert the old body node to a declaration node
  1808.  
  1809.          Spec_Node := Specification (Body_Decl);
  1810.          Change_Node (Body_Decl, N_Subprogram_Declaration);
  1811.          Set_Specification (Body_Decl, Spec_Node);
  1812.  
  1813.          --  Final step is to put the declarations for the parent where
  1814.          --  they belong, and then fall through the IF to scan out the
  1815.          --  END statements.
  1816.  
  1817.          Set_Declarations (Parent, Decls);
  1818.  
  1819.       --  This is the normal case (i.e. any case except the bad IS case)
  1820.       --  If we have a BEGIN, then scan out the sequence of statements, and
  1821.       --  also reset the expected column for the END to match the BEGIN.
  1822.  
  1823.       else
  1824.          Set_Declarations (Parent, Decls);
  1825.  
  1826.          if Token = Tok_Begin then
  1827.             if Style_Check then Style.Check_Indentation; end if;
  1828.             Scope.Table (Scope.Last).Ecol := Start_Column;
  1829.             Scope.Table (Scope.Last).Sloc := Token_Ptr;
  1830.             Scan; -- past BEGIN
  1831.             Set_Handled_Statement_Sequence (Parent,
  1832.               P_Handled_Sequence_Of_Statements);
  1833.  
  1834.          --  No BEGIN present
  1835.  
  1836.          else
  1837.             Parent_Nkind := Nkind (Parent);
  1838.  
  1839.             --  A special check for the missing IS case. If we have a
  1840.             --  subprogram body that was marked as having a suspicious
  1841.             --  IS, and the current token is END, then we simply confirm
  1842.             --  the suspicion, and do not require a BEGIN to be present
  1843.  
  1844.             if Parent_Nkind = N_Subprogram_Body
  1845.               and then Token  = Tok_End
  1846.               and then Scope.Table (Scope.Last).Etyp = E_Suspicious_Is
  1847.             then
  1848.                Scope.Table (Scope.Last).Etyp := E_Bad_Is;
  1849.  
  1850.             --  Otherwise BEGIN is not required for a package body.
  1851.             --  However if we have something other than a BEGIN which
  1852.             --  looks like it might be statements, then we signal a missing
  1853.             --  BEGIN for these cases as well. We define "something which
  1854.             --  looks like it might be statements" as a token other than
  1855.             --  END, EOF, or a token which starts declarations.
  1856.  
  1857.             elsif Parent_Nkind = N_Package_Body
  1858.               and then (Token = Tok_End
  1859.                           or else Token = Tok_EOF
  1860.                           or else Token in  Token_Class_Declk)
  1861.             then
  1862.                null; -- BEGIN not required for these cases
  1863.  
  1864.             --  These are cases in which a BEGIN is required and not present
  1865.  
  1866.             else
  1867.                --  Issue error message
  1868.  
  1869.                Error_Msg_Sloc := Scope.Table (Scope.Last).Sloc;
  1870.                Error_Msg_Node_1 := Scope.Table (Scope.Last).Labl;
  1871.  
  1872.                if Parent_Nkind = N_Block_Statement then
  1873.                   Missing_Begin ("missing BEGIN for DECLARE#!");
  1874.  
  1875.                elsif Parent_Nkind = N_Entry_Body then
  1876.                   Missing_Begin ("missing BEGIN for ENTRY#!");
  1877.  
  1878.                elsif Parent_Nkind = N_Subprogram_Body then
  1879.                   if Nkind (Specification (Parent))
  1880.                                = N_Function_Specification
  1881.                   then
  1882.                      Missing_Begin ("missing BEGIN for function&#!");
  1883.                   else
  1884.                      Missing_Begin ("missing BEGIN for procedure&#!");
  1885.                   end if;
  1886.  
  1887.                --  The case for package body arises only when
  1888.                --  we have possible statement junk present.
  1889.  
  1890.                elsif Parent_Nkind = N_Package_Body then
  1891.                   Missing_Begin ("missing BEGIN for package body&#!");
  1892.  
  1893.                else
  1894.                   pragma Assert (Parent_Nkind = N_Task_Body);
  1895.                   Missing_Begin ("missing BEGIN for task body&#!");
  1896.                end if;
  1897.  
  1898.                --  Here we pick up the statements after the BEGIN that
  1899.                --  should have been present but was not. We don't insist
  1900.                --  on statements being present if P_Declarative_Part had
  1901.                --  already found a missing BEGIN, since it might have
  1902.                --  swallowed a lone statement into the declarative part.
  1903.  
  1904.                if Missing_Begin_Msg /= No_Error_Msg
  1905.                  and then Token = Tok_End
  1906.                then
  1907.                   null;
  1908.                else
  1909.                   Set_Handled_Statement_Sequence (Parent,
  1910.                     P_Handled_Sequence_Of_Statements);
  1911.                end if;
  1912.             end if;
  1913.          end if;
  1914.       end if;
  1915.  
  1916.       --  Here with declarations and handled statement sequence scanned
  1917.  
  1918.       End_Statements;
  1919.  
  1920.       --  We know that End_Statements removed an entry from the scope stack
  1921.       --  (because it is required to do so under all circumstances). We can
  1922.       --  therefore reference the entry it removed one past the stack top.
  1923.       --  What we are interested in is whether it was a case of a bad IS.
  1924.  
  1925.       if Scope.Table (Scope.Last + 1).Etyp = E_Bad_Is then
  1926.          Error_Msg ("IS should be "";""", Scope.Table (Scope.Last + 1).S_Is);
  1927.          Set_Bad_Is_Detected (Parent, True);
  1928.       end if;
  1929.  
  1930.    end Parse_Decls_Begin_End;
  1931.  
  1932. end Ch5;
  1933.