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-endh.adb < prev    next >
Text File  |  1996-09-28  |  35KB  |  933 lines

  1. ------------------------------------------------------------------------------
  2. --                                                                          --
  3. --                         GNAT COMPILER COMPONENTS                         --
  4. --                                                                          --
  5. --                             P A R . E N D H                              --
  6. --                                                                          --
  7. --                                 B o d y                                  --
  8. --                                                                          --
  9. --                            $Revision: 1.33 $                             --
  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 Endh is
  27.  
  28.    ----------------
  29.    -- Local Data --
  30.    ----------------
  31.  
  32.    End_Sloc : Source_Ptr;
  33.    --  Source location of END token
  34.  
  35.    End_OK : Boolean;
  36.    --  Set False if error is found in END line
  37.  
  38.    End_Column : Column_Number;
  39.    --  Column of END line
  40.  
  41.    End_Type : SS_End_Type;
  42.    --  Type of END expected. The special value E_Dummy is set to indicate that
  43.    --  no END token was present (so a missing END inserted message is needed)
  44.  
  45.    End_Labl : Node_Id;
  46.    --  Node_Id value for name on END line, or Empty if no name appeared. If
  47.    --  this is non-empty, then it is either an N_Designator node for a child
  48.    --  unit or a node with a Chars field that identifies the actual label.
  49.  
  50.    Syntax_OK : Boolean;
  51.    --  Set True if the entry is syntactically correct
  52.  
  53.    Token_OK : Boolean;
  54.    --  Set True if the keyword in the END sequence matches, or if neither
  55.    --  the END sequence nor the END stack entry has a keyword.
  56.  
  57.    Label_OK : Boolean;
  58.    --  Set True if both the END sequence and the END stack entry contained
  59.    --  labels (other than No_Name or Error_Name) and the labels matched.
  60.    --  This is a stronger condition than SYNTAX_OK, since it means that a
  61.    --  label was present, even in a case where it was optional. Note that
  62.    --  the case of no label required, and no label present does NOT set
  63.    --  Label_OK to True, it is True only if a positive label match is found
  64.    --  or (a special case added in version 1.3) if we have the END RECORD
  65.    --  case. Since RECORD cannot nest, this is as good as a matching label
  66.    --  for being sure that we have the right one!
  67.  
  68.    Column_OK : Boolean;
  69.    --  Column_OK is set True if the END sequence appears in the expected column
  70.  
  71.    Scan_State : Saved_Scan_State;
  72.    --  Save state at start of END sequence, in case we decide not to eat it up
  73.  
  74.    -----------------------
  75.    -- Local Subprograms --
  76.    -----------------------
  77.  
  78.    procedure Check_Label (Label1, Label2 : Node_Id);
  79.    --  Given two labels, which are known to match, i.e. a call to Same_Label
  80.    --  for Label1, Label2 previously returned True, determines if the spelling
  81.    --  meets the style checking rules. Check_Label is called only if the
  82.    --  Style_Check mode is set on.
  83.  
  84.    procedure Evaluate_End_Entry (SS_Index : Int);
  85.    --  Compare scanned END entry (as recorded by a prior call to P_End_Scan)
  86.    --  with a specified entry in the scope stack (the single parameter is the
  87.    --  entry index in the scope stack). Note that Scan is not called. The above
  88.    --  variables xxx_OK are set to indicate the result of the evaluation.
  89.  
  90.    procedure Output_End_Deleted;
  91.    --  Output a message complaining that the current END structure does not
  92.    --  match anything and is being deleted.
  93.  
  94.    procedure Output_End_Expected;
  95.    --  Output a message at the start of the current token which is always an
  96.    --  END, complaining that the END is not of the right form. The message
  97.    --  indicates the expected form. The information for the message is taken
  98.    --  from the top entry in the scope stack. Note that in the case of a
  99.    --  suspicious IS, we do not output the message, but instead simply mark
  100.    --  the scope stack entry as being a case of a bad IS.
  101.  
  102.    procedure Output_End_Missing;
  103.    --  Output a message just before the current token, complaining that the
  104.    --  END is not of the right form. The message indicates the expected form.
  105.    --  The information for the message is taken from the top entry in the
  106.    --  scope stack. Note that in the case of a suspicious IS, we do not output
  107.    --  the message, but instead simply mark the scope stack entry as a bad IS.
  108.  
  109.    function Same_Label (Label1, Label2 : Node_Id) return Boolean;
  110.    --  This function compares the two names associated with the given nodes.
  111.    --  If they are both simple (i.e. have Chars fields), then they have to
  112.    --  be the same name. Otherwise they must both be N_Selected_Component
  113.    --  nodes, referring to the same set of names, or Label1 is an N_Designator
  114.    --  referring to the same set of names as the N_Defining_Program_Unit_Name
  115.    --  in Label2. Any other combination returns False. This routine is used
  116.    --  to compare the End_Labl scanned from the End line with the saved label
  117.    --  value in the scope stack.
  118.  
  119.    ---------------
  120.    -- Check_End --
  121.    ---------------
  122.  
  123.    function Check_End return Boolean is
  124.       Name_On_Separate_Line : Boolean;
  125.       --  Set True if the name on an END line is on a separate source line
  126.       --  from the END. This is highly suspicious, but is allowed. The point
  127.       --  is that we want to make sure that we don't just have a missing
  128.       --  semicolon misleading us into swallowing an identifier from the
  129.       --  following line.
  130.  
  131.       Name_Scan_State : Saved_Scan_State;
  132.       --  Save state at start of name if Name_On_Separate_Line is TRUE
  133.  
  134.    begin
  135.       --  Our first task is to scan out the END sequence if one is present.
  136.       --  If none is present, signal by setting End_Type to E_Dummy.
  137.  
  138.       if Token /= Tok_End then
  139.          End_Type := E_Dummy;
  140.  
  141.       else
  142.          Save_Scan_State (Scan_State); -- at END
  143.          End_Sloc := Token_Ptr;
  144.          End_Column := Start_Column;
  145.          End_OK := True;
  146.          Scan; -- past END
  147.  
  148.          --  Cases of keywords where no label is allowed
  149.  
  150.          if Token = Tok_Case then
  151.             End_Type := E_Case;
  152.             End_Labl := Empty;
  153.             Scan; -- past CASE
  154.  
  155.          elsif Token = Tok_If then
  156.             End_Type := E_If;
  157.             End_Labl := Empty;
  158.             Scan; -- past IF
  159.  
  160.          elsif Token = Tok_Record then
  161.             End_Type := E_Record;
  162.             End_Labl := Empty;
  163.             Scan; -- past RECORD
  164.  
  165.          elsif Token = Tok_Select then
  166.             End_Type := E_Select;
  167.             End_Labl := Empty;
  168.             Scan; -- past SELECT
  169.  
  170.          --  Cases which do allow labels
  171.  
  172.          else
  173.             --  LOOP
  174.  
  175.             if Token = Tok_Loop then
  176.                Scan; -- past LOOP
  177.                End_Type := E_Loop;
  178.  
  179.             --  FOR or WHILE allowed (signalling error) to substitute for LOOP
  180.  
  181.             elsif Token = Tok_For or else Token = Tok_While then
  182.                Scan; -- past FOR or WHILE
  183.                End_Type := E_Loop;
  184.                End_OK := False;
  185.  
  186.             --  Cases with no keyword
  187.  
  188.             else
  189.                End_Type := E_Name;
  190.             end if;
  191.  
  192.             --  Now see if a name is present
  193.  
  194.             if Token = Tok_Identifier or else
  195.                Token = Tok_String_Literal or else
  196.                Token = Tok_Operator_Symbol
  197.             then
  198.                if Token_Is_At_Start_Of_Line then
  199.                   Name_On_Separate_Line := True;
  200.                   Save_Scan_State (Name_Scan_State);
  201.                else
  202.                   Name_On_Separate_Line := False;
  203.                end if;
  204.  
  205.                End_Labl := P_Designator;
  206.  
  207.                --  We have now scanned out a name. Here is where we do a check
  208.                --  to catch the cases like:
  209.                --
  210.                --    end loop
  211.                --    X := 3;
  212.                --
  213.                --  where the missing semicolon might make us swallow up the X
  214.                --  as a bogus end label. In a situation like this, where the
  215.                --  apparent name is on a separate line, we accept it only if
  216.                --  it matches the label and is followed by a semicolon.
  217.  
  218.                if Name_On_Separate_Line then
  219.                   if Token /= Tok_Semicolon or else
  220.                     not Same_Label (End_Labl, Scope.Table (Scope.Last).Labl)
  221.                   then
  222.                      Restore_Scan_State (Name_Scan_State);
  223.                      End_Labl := Empty;
  224.                   end if;
  225.                end if;
  226.  
  227.             --  Here for case of name allowed, but no name present
  228.  
  229.             else
  230.                End_Labl := Empty;
  231.  
  232.                if Style_Check
  233.                  and then End_Type = E_Name
  234.                  and then Present (Scope.Table (Scope.Last).Labl)
  235.                then
  236.                   Style.No_End (Scope.Table (Scope.Last).Labl);
  237.                end if;
  238.             end if;
  239.          end if;
  240.  
  241.          --  Except in case of END RECORD, semicolon must follow. For END
  242.          --  RECORD, a semicolon does follow, but it is part of a higher level
  243.          --  construct. In any case, a missing semicolon is not serious enough
  244.          --  to consider the END statement to be bad in the sense that we
  245.          --  are dealing with (i.e. to be suspicious that it is not in fact
  246.          --  the END statement we are looking for!)
  247.  
  248.          if End_Type /= E_Record then
  249.             T_Semicolon;
  250.          end if;
  251.       end if;
  252.  
  253.       --  Now we call the Pop_End_Context routine to get a recommendation
  254.       --  as to what should be done with the END sequence we have scanned.
  255.  
  256.       Pop_End_Context;
  257.  
  258.       --  Remaining action depends on End_Action set by Pop_End_Context
  259.  
  260.       case End_Action is
  261.  
  262.          --  Accept_As_Scanned. In this case, Pop_End_Context left Token
  263.          --  pointing past the last token of a syntactically correct END
  264.  
  265.          when Accept_As_Scanned =>
  266.  
  267.             --  Syntactically correct included the possibility of a missing
  268.             --  semicolon. If we do have a missing semicolon, then we have
  269.             --  already given a message, but now we scan out possible rubbish
  270.             --  on the same line as the END
  271.  
  272.             while not Token_Is_At_Start_Of_Line
  273.               and then Prev_Token /= Tok_Record
  274.               and then Prev_Token /= Tok_Semicolon
  275.               and then Token /= Tok_End
  276.               and then Token /= Tok_EOF
  277.             loop
  278.                Scan; -- past junk
  279.             end loop;
  280.  
  281.             return True;
  282.  
  283.          --  Insert_And_Accept. In this case, Pop_End_Context has reset Token
  284.          --  to point to the start of the END sequence, and recommends that it
  285.          --  be left in place to satisfy an outer scope level END. This means
  286.          --  that we proceed as though an END were present, and leave the scan
  287.          --  pointer unchanged.
  288.  
  289.          when Insert_And_Accept =>
  290.             return True;
  291.  
  292.          --  Skip_And_Accept. In this case, Pop_End_Context has reset Token
  293.          --  to point to the start of the END sequence. This END sequence is
  294.          --  syntactically incorrect, and an appropriate error message has
  295.          --  already been posted. Pop_End_Context recommends accepting the
  296.          --  END sequence as the one we want, so we skip past it and then
  297.          --  proceed as though an END were present.
  298.  
  299.          when Skip_And_Accept =>
  300.             End_Skip;
  301.             return True;
  302.  
  303.          --  Skip_And_Reject. In this case, Pop_End_Context has reset Token
  304.          --  to point to the start of the END sequence. This END sequence is
  305.          --  syntactically incorrect, and an appropriate error message has
  306.          --  already been posted. Pop_End_Context recommends entirely ignoring
  307.          --  this END sequence, so we skip past it and then return False, since
  308.          --  as far as the caller is concerned, no END sequence is present.
  309.  
  310.          when Skip_And_Reject =>
  311.             End_Skip;
  312.             return False;
  313.       end case;
  314.    end Check_End;
  315.  
  316.    -----------------
  317.    -- Check_Label --
  318.    -----------------
  319.  
  320.    --  This is a simple recursive routine that checks the separate components
  321.    --  of a child unit label one by one. Compare coding to Same_Label, but
  322.    --  note that tests can be simplified because we know that Label1 and
  323.    --  Label2 have already passed the Same_Label test, since Check_Label
  324.    --  is only called if Label_OK is set to True.
  325.  
  326.    procedure Check_Label (Label1, Label2 : Node_Id) is
  327.    begin
  328.       if Nkind (Label1) in N_Has_Chars then
  329.          if Nkind (Label1) = N_Identifier then
  330.             Style.Check_Identifier (Label1, Label2);
  331.          end if;
  332.  
  333.       elsif Nkind (Label1) = N_Selected_Component then
  334.          Check_Label (Prefix (Label1), Prefix (Label2));
  335.          Check_Label (Selector_Name (Label1), Selector_Name (Label2));
  336.  
  337.       else
  338.          Check_Label (Name (Label1), Name (Label2));
  339.          Check_Label (Identifier (Label1), Defining_Identifier (Label2));
  340.       end if;
  341.    end Check_Label;
  342.  
  343.    --------------
  344.    -- End Skip --
  345.    --------------
  346.  
  347.    --  This procedure skips past an END sequence. On entry Token contains
  348.    --  Tok_End, and we know that the END sequence is syntactically incorrect,
  349.    --  and that an appropriate error message has already been posted. The
  350.    --  mission is simply to position the scan pointer to be the best guess of
  351.    --  the position after the END sequence. We do not issue any additional
  352.    --  error messages while carrying this out.
  353.  
  354.    --  Error recovery: does not raise Error_Resync
  355.  
  356.    procedure End_Skip is
  357.    begin
  358.       Scan; -- past END
  359.  
  360.       --  If the scan past the END leaves us on the next line, that's probably
  361.       --  where we should quit the scan, since it is likely that what we have
  362.       --  is a missing semicolon. Consider the following:
  363.  
  364.       --       END
  365.       --       Process_Input;
  366.  
  367.       --  This will have looked like a syntactically valid END sequence to the
  368.       --  initial scan of the END, but subsequent checking will have determined
  369.       --  that the label Process_Input is not an appropriate label. The real
  370.       --  error is a missing semicolon after the END, and by leaving the scan
  371.       --  pointer just past the END, we will improve the error recovery.
  372.  
  373.       if Token_Is_At_Start_Of_Line then
  374.          return;
  375.       end if;
  376.  
  377.       --  If there is a semicolon after the END, scan it out and we are done
  378.  
  379.       if Token = Tok_Semicolon then
  380.          Scan; -- past semicolon
  381.          return;
  382.       end if;
  383.  
  384.       --  Otherwise skip past a token after the END. Note that we skip past
  385.       --  for or while, to allow END for and END while to substitute for
  386.       --  END loop (of course an error message has already been issued).
  387.  
  388.       if Token = Tok_Case
  389.          or else Token = Tok_For
  390.          or else Token = Tok_If
  391.          or else Token = Tok_Loop
  392.          or else Token = Tok_Record
  393.          or else Token = Tok_Select
  394.          or else Token = Tok_While
  395.       then
  396.          Scan; -- past token after END
  397.  
  398.          --  If that leaves us on the next line, then we are done. This is the
  399.          --  same principle described above for the case of END at line end
  400.  
  401.          if Token_Is_At_Start_Of_Line then
  402.             return;
  403.  
  404.          --  If we just scanned out record, then we are done, since the
  405.          --  semicolon after END RECORD is not part of the END sequence
  406.  
  407.          elsif Prev_Token = Tok_Record then
  408.             return;
  409.  
  410.          --  If we have a semicolon, scan it out and we are done
  411.  
  412.          elsif Token = Tok_Semicolon then
  413.             Scan; -- past semicolon
  414.             return;
  415.          end if;
  416.       end if;
  417.  
  418.       --  Check for a label present on the same line
  419.  
  420.       loop
  421.          if Token_Is_At_Start_Of_Line then
  422.             return;
  423.          end if;
  424.  
  425.          if Token /= Tok_Identifier
  426.            and then Token /= Tok_Operator_Symbol
  427.            and then Token /= Tok_String_Literal
  428.          then
  429.             exit;
  430.          end if;
  431.  
  432.          Scan; -- past identifier, operator symbol or string literal
  433.  
  434.          if Token_Is_At_Start_Of_Line then
  435.             return;
  436.          elsif Token = Tok_Dot then
  437.             Scan; -- past dot
  438.          end if;
  439.       end loop;
  440.  
  441.       --  Skip final semicolon
  442.  
  443.       if Token = Tok_Semicolon then
  444.          Scan; -- past semicolon
  445.  
  446.       --  If we don't have a final semicolon, skip until we either encounter
  447.       --  an END token, or a semicolon or the start of the next line. This
  448.       --  allows general junk to follow the end line (normally it is hard to
  449.       --  think that anyone will put anything deliberate here, and remember
  450.       --  that we know there is a missing semicolon in any case). We also
  451.       --  quite on an EOF (or else we would get stuck in an infinite loop
  452.       --  if there is no line end at the end of the last line of the file)
  453.  
  454.       else
  455.          while Token /= Tok_End
  456.            and then Token /= Tok_EOF
  457.            and then Token /= Tok_Semicolon
  458.            and then not Token_Is_At_Start_Of_Line
  459.          loop
  460.             Scan; -- past junk token on same line
  461.          end loop;
  462.       end if;
  463.  
  464.       return;
  465.    end End_Skip;
  466.  
  467.    --------------------
  468.    -- End Statements --
  469.    --------------------
  470.  
  471.    --  This procedure is called when END is required or expected to terminate
  472.    --  a sequence of statements. The caller has already made an appropriate
  473.    --  entry on the scope stack to describe the expected form of the END.
  474.    --  End_Statements should only be used in cases where the only appropriate
  475.    --  terminator is END.
  476.  
  477.    --  Error recovery: cannot raise Error_Resync;
  478.  
  479.    procedure End_Statements is
  480.    begin
  481.  
  482.       --  This loop runs more than once in the case where Check_End rejects
  483.       --  the END sequence, as indicated by Check_End returning False.
  484.  
  485.       loop
  486.          if Check_End then
  487.             return;
  488.          end if;
  489.  
  490.          --  Extra statements past the bogus END are discarded. This is not
  491.          --  ideal for maximum error recovery, but it's too much trouble to
  492.          --  find an appropriate place to put them!
  493.  
  494.          Discard_Junk_List (P_Sequence_Of_Statements (SS_None));
  495.       end loop;
  496.    end End_Statements;
  497.  
  498.    ------------------------
  499.    -- Evaluate End Entry --
  500.    ------------------------
  501.  
  502.    procedure Evaluate_End_Entry (SS_Index : Int) is
  503.    begin
  504.       Column_OK := (End_Column = Scope.Table (SS_Index).Ecol);
  505.  
  506.       Token_OK  := (End_Type = Scope.Table (SS_Index).Etyp or else
  507.                      (End_Type = E_Name and then
  508.                        Scope.Table (SS_Index).Etyp >= E_Name));
  509.  
  510.       Label_OK  := (Token_OK and then End_Type = E_Record) or else
  511.                      (Present (End_Labl) and then
  512.                        (Same_Label (End_Labl, Scope.Table (SS_Index).Labl)
  513.                          or else Scope.Table (SS_Index).Labl = Error));
  514.  
  515.       --  Compute setting of Syntax_OK. We definitely have a syntax error
  516.       --  if the Token does not match properly or if P_End_Scan detected
  517.       --  a syntax error such as a missing semicolon.
  518.  
  519.       if not Token_OK or not End_OK then
  520.          Syntax_OK := False;
  521.          return;
  522.       end if;
  523.  
  524.       --  Final check is that label is OK. Certainly it is OK if there
  525.       --  was an exact match on the label (the END label = the stack label)
  526.  
  527.       if Label_OK then
  528.          Syntax_OK := True;
  529.          return;
  530.       end if;
  531.  
  532.       --  If there was a label and it did not match, then we definitely
  533.       --  do have a syntax error.
  534.  
  535.       if Present (End_Labl) then
  536.          Syntax_OK := False;
  537.          return;
  538.       end if;
  539.  
  540.       --  Otherwise we have cases of no label on the END line. For the loop
  541.       --  case, this is acceptable only if the loop is unlabeled.
  542.  
  543.       if End_Type = E_Loop then
  544.          Syntax_OK := (Scope.Table (SS_Index).Labl = Empty);
  545.          return;
  546.  
  547.       --  Cases where a label is definitely allowed on the END line
  548.  
  549.       elsif End_Type = E_Name then
  550.          Syntax_OK := (Scope.Table (SS_Index).Labl = Empty or else
  551.                          not Scope.Table (SS_Index).Lreq);
  552.          return;
  553.  
  554.       --  Otherwise we have cases which don't allow labels anyway, so we
  555.       --  certainly accept an END which does not have a label.
  556.  
  557.       else
  558.          Syntax_OK := True;
  559.          return;
  560.       end if;
  561.    end Evaluate_End_Entry;
  562.  
  563.    ------------------------
  564.    -- Output End Deleted --
  565.    ------------------------
  566.  
  567.    procedure Output_End_Deleted is
  568.    begin
  569.  
  570.       if End_Type = E_Loop then
  571.          Error_Msg_SC ("no LOOP for this `END LOOP`!");
  572.  
  573.       elsif End_Type = E_Case then
  574.          Error_Msg_SC ("no CASE for this `END CASE`");
  575.  
  576.       elsif End_Type = E_If then
  577.          Error_Msg_SC ("no IF for this `END IF`!");
  578.  
  579.       elsif End_Type = E_Record then
  580.          Error_Msg_SC ("no RECORD for this `END RECORD`!");
  581.  
  582.       elsif End_Type = E_Select then
  583.          Error_Msg_SC ("no SELECT for this `END SELECT`!");
  584.  
  585.       else
  586.          Error_Msg_SC ("no BEGIN for this END!");
  587.       end if;
  588.    end Output_End_Deleted;
  589.  
  590.    -------------------------
  591.    -- Output End Expected --
  592.    -------------------------
  593.  
  594.    procedure Output_End_Expected is
  595.       End_Type : SS_End_Type;
  596.  
  597.    begin
  598.       End_Type := Scope.Table (Scope.Last).Etyp;
  599.       Error_Msg_Col    := Scope.Table (Scope.Last).Ecol;
  600.       Error_Msg_Node_1 := Scope.Table (Scope.Last).Labl;
  601.       Error_Msg_Sloc   := Scope.Table (Scope.Last).Sloc;
  602.  
  603.       if End_Type = E_Case then
  604.          Error_Msg_SC ("`END CASE;` expected@ for CASE#!");
  605.  
  606.       elsif End_Type = E_If then
  607.          Error_Msg_SC ("`END IF;` expected@ for IF#!");
  608.  
  609.       elsif End_Type = E_Loop then
  610.          if Error_Msg_Node_1 = Empty then
  611.             Error_Msg_SC
  612.               ("`END LOOP;` expected@ for LOOP#!");
  613.          else
  614.             Error_Msg_SC ("`END LOOP&;` expected@!");
  615.          end if;
  616.  
  617.       elsif End_Type = E_Record then
  618.          Error_Msg_SC
  619.            ("`END RECORD;` expected@ for RECORD#!");
  620.  
  621.       elsif End_Type = E_Select then
  622.          Error_Msg_SC
  623.            ("`END SELECT;` expected@ for SELECT#!");
  624.  
  625.       elsif End_Type = E_Name then
  626.          if Error_Msg_Node_1 = Empty then
  627.             Error_Msg_SC ("`END;` expected@ for BEGIN#!");
  628.          else
  629.             Error_Msg_SC ("`END&;` expected@!");
  630.          end if;
  631.  
  632.       --  The other possibility is a missing END for a subprogram with a
  633.       --  suspicious IS (that probably should have been a semicolon). The
  634.       --  Missing IS confirms the suspicion!
  635.  
  636.       else -- End_Type = E_Suspicious_Is or E_Bad_Is
  637.          Scope.Table (Scope.Last).Etyp := E_Bad_Is;
  638.       end if;
  639.    end Output_End_Expected;
  640.  
  641.    ------------------------
  642.    -- Output End Missing --
  643.    ------------------------
  644.  
  645.    procedure Output_End_Missing is
  646.       End_Type : SS_End_Type;
  647.  
  648.    begin
  649.       End_Type := Scope.Table (Scope.Last).Etyp;
  650.       Error_Msg_Node_1 := Scope.Table (Scope.Last).Labl;
  651.       Error_Msg_Sloc   := Scope.Table (Scope.Last).Sloc;
  652.  
  653.       if End_Type = E_Case then
  654.          Error_Msg_BC ("missing `END CASE;` for CASE#!");
  655.  
  656.       elsif End_Type = E_If then
  657.          Error_Msg_BC ("missing `END IF;` for IF#!");
  658.  
  659.       elsif End_Type = E_Loop then
  660.          if Error_Msg_Node_1 = Empty then
  661.             Error_Msg_BC ("missing `END LOOP;` for LOOP#!");
  662.          else
  663.             Error_Msg_BC ("missing `END LOOP&;`!");
  664.          end if;
  665.  
  666.       elsif End_Type = E_Record then
  667.          Error_Msg_SC
  668.            ("missing `END RECORD;` for RECORD#!");
  669.  
  670.       elsif End_Type = E_Select then
  671.          Error_Msg_BC
  672.            ("missing `END SELECT;` for SELECT#!");
  673.  
  674.       elsif End_Type = E_Name then
  675.          if Error_Msg_Node_1 = Empty then
  676.             Error_Msg_BC ("missing `END;` for BEGIN#!");
  677.          else
  678.             Error_Msg_BC ("missing `END&;`!");
  679.          end if;
  680.  
  681.       else -- End_Type = E_Suspicious_Is or E_Bad_Is
  682.          Scope.Table (Scope.Last).Etyp := E_Bad_Is;
  683.       end if;
  684.    end Output_End_Missing;
  685.  
  686.    ----------------
  687.    -- Same_Label --
  688.    ----------------
  689.  
  690.    function Same_Label (Label1, Label2 : Node_Id) return Boolean is
  691.    begin
  692.       if Nkind (Label1) in N_Has_Chars
  693.         and then Nkind (Label2) in N_Has_Chars
  694.       then
  695.          return Chars (Label1) = Chars (Label2);
  696.  
  697.       elsif Nkind (Label1) = N_Selected_Component
  698.         and then Nkind (Label2) = N_Selected_Component
  699.       then
  700.          return Same_Label (Prefix (Label1), Prefix (Label2)) and then
  701.            Same_Label (Selector_Name (Label1), Selector_Name (Label2));
  702.  
  703.       elsif Nkind (Label1) = N_Designator
  704.         and then Nkind (Label2) = N_Defining_Program_Unit_Name
  705.       then
  706.          return Same_Label (Name (Label1), Name (Label2)) and then
  707.            Same_Label (Identifier (Label1), Defining_Identifier (Label2));
  708.  
  709.       else
  710.          return False;
  711.       end if;
  712.    end Same_Label;
  713.  
  714.    ---------------------
  715.    -- Pop End Context --
  716.    ---------------------
  717.  
  718.    procedure Pop_End_Context is
  719.  
  720.       Pretty_Good : Boolean;
  721.       --  This flag is set True if the END sequence is syntactically incorrect,
  722.       --  but has the right token type and the right column (this means that
  723.       --  it is wrong only in lacking a semicolon or having the wrong label)
  724.  
  725.       Outer_Match : Boolean;
  726.       --  This flag is set True if we decide that the current END sequence
  727.       --  belongs to some outer level entry in the scope stack, and thus
  728.       --  we will NOT eat it up in matching the current expected END.
  729.  
  730.    begin
  731.       --  If not at END, then output END expected message
  732.  
  733.       if End_Type = E_Dummy then
  734.          Output_End_Missing;
  735.          Pop_Scope_Stack;
  736.          End_Action := Insert_And_Accept;
  737.          return;
  738.  
  739.       --  Otherwise we do have an END present
  740.  
  741.       else
  742.          --  A special check. If we have END; followed by an end of file,
  743.          --  WITH or SEPARATE, then if we are not at the outer level, then
  744.          --  we have a sytax error. Consider the example:
  745.  
  746.          --   ...
  747.          --      declare
  748.          --         X : Integer;
  749.          --      begin
  750.          --         X := Father (A);
  751.          --         Process (X, X);
  752.          --   end;
  753.          --   with Package1;
  754.          --   ...
  755.  
  756.          --  Now the END; here is a syntactically correct closer for the
  757.          --  declare block, but if we eat it up, then we obviously have
  758.          --  a missing END for the outer context (since WITH can only appear
  759.          --  at the outer level.
  760.  
  761.          --  In this situation, we always reserve the END; for the outer level,
  762.          --  even if it is in the wrong column. This is because it's much more
  763.          --  useful to have the error message point to the DECLARE than to the
  764.          --  package header in this case.
  765.  
  766.          if (Token = Tok_EOF or else
  767.              Token = Tok_With or else
  768.              Token = Tok_Separate)
  769.            and then End_Type >= E_Name
  770.            and then No (End_Labl)
  771.            and then Scope.Last > 1
  772.          then
  773.             Restore_Scan_State (Scan_State); -- to END
  774.             Output_End_Expected;
  775.             Pop_Scope_Stack;
  776.             End_Action := Insert_And_Accept;
  777.             return;
  778.          end if;
  779.  
  780.          --  Otherwise we go through the normal END evaluation procedure
  781.  
  782.          Evaluate_End_Entry (Scope.Last);
  783.  
  784.          --  If top entry in stack is syntactically correct, then we have
  785.          --  scanned it out and everything is fine. This is the required
  786.          --  action to properly process correct Ada programs.
  787.  
  788.          if Syntax_OK then
  789.  
  790.             --  Complain if checking columns and END is not in right column.
  791.             --  Right in this context means exactly right, or on the same
  792.             --  line as the opener.
  793.  
  794.             if RM_Column_Check then
  795.                if End_Column /= Scope.Table (Scope.Last).Ecol
  796.                  and then Current_Line_Start > Scope.Table (Scope.Last).Sloc
  797.                then
  798.                   Error_Msg_Col := Scope.Table (Scope.Last).Ecol;
  799.                   Error_Msg
  800.                     ("END in wrong column, should be@", End_Sloc);
  801.                end if;
  802.             end if;
  803.  
  804.             --  If label was present, check its spelling
  805.  
  806.             if (Style_Check and Label_OK) and then Present (End_Labl) then
  807.                Check_Label (End_Labl, Scope.Table (Scope.Last).Labl);
  808.             end if;
  809.  
  810.             --  All OK, so return to caller indicating END is OK
  811.  
  812.             Pop_Scope_Stack;
  813.             End_Action := Accept_As_Scanned;
  814.             return;
  815.          end if;
  816.  
  817.          --  If that check failed, then we definitely have an error. The issue
  818.          --  is how to choose among three possible courses of action:
  819.  
  820.          --   1. Ignore the current END text completely, scanning past it,
  821.          --      deciding that it belongs neither to the current context,
  822.          --      nor to any outer context.
  823.  
  824.          --   2. Accept the current END text, scanning past it, and issuing
  825.          --      an error message that it does not have the right form.
  826.  
  827.          --   3. Leave the current END text in place, NOT scanning past it,
  828.          --      issuing an error message indicating the END expected for the
  829.          --      current context. In this case, the END is available to match
  830.          --      some outer END context.
  831.  
  832.          --  From a correct functioning point of view, it does not make any
  833.          --  difference which of these three approaches we take, the program
  834.          --  will work correctly in any case. However, making an accurate
  835.          --  choice among these alternatives, i.e. choosing the one that
  836.          --  corresponds to what the programmer had in mind, does make a
  837.          --  significant difference in the quality of error recovery.
  838.  
  839.          Restore_Scan_State (Scan_State); -- to END
  840.  
  841.          --  First we see how good the current END entry is with respect to
  842.          --  what we expect. It is considered pretty good if the token is OK,
  843.          --  and either the label or the column matches.
  844.  
  845.          Pretty_Good := Token_OK and (Column_OK or Label_OK);
  846.  
  847.          --  Next check, if there is a deeper entry in the stack which
  848.          --  has a very high probability of being acceptable, then insert
  849.          --  the END entry we want, leaving the higher level entry for later
  850.  
  851.          for J in reverse 1 .. Scope.Last - 1 loop
  852.             Evaluate_End_Entry (J);
  853.  
  854.             --  To even consider the deeper entry to be immediately acceptable,
  855.             --  it must be syntactically correct. Furthermore it must either
  856.             --  have a correct label, or the correct column. If the current
  857.             --  entry was a close match (Pretty_Good set), then we are even
  858.             --  more strict in accepting the outer level one: even if it has
  859.             --  the right label, it must have the right column as well.
  860.  
  861.             if Syntax_OK then
  862.                if Pretty_Good then
  863.                   Outer_Match := Label_OK and Column_OK;
  864.                else
  865.                   Outer_Match := Label_OK or Column_OK;
  866.                end if;
  867.             else
  868.                Outer_Match := False;
  869.             end if;
  870.  
  871.             --  If the outer entry does convincingly match the END text, then
  872.             --  back up the scan to the start of the END sequence, issue an
  873.             --  error message indicating the END we expected, and return with
  874.             --  Token pointing to the END (case 3 from above discussion).
  875.  
  876.             if Outer_Match then
  877.                Output_End_Missing;
  878.                Pop_Scope_Stack;
  879.                End_Action := Insert_And_Accept;
  880.                return;
  881.             end if;
  882.          end loop;
  883.  
  884.          --  Here we have a situation in which the current END entry is
  885.          --  syntactically incorrect, but there is no deeper entry in the
  886.          --  END stack which convincingly matches it.
  887.  
  888.          --  If the END text was judged to be a Pretty_Good match for the
  889.          --  expected token or if it appears left of the expected column,
  890.          --  then we will accept it as the one we want, scanning past it, even
  891.          --  though it is not completely right (we issue a message showing what
  892.          --  we expected it to be). This is action 2 from the discussion above.
  893.          --  There is one other special case to consider: the LOOP case.
  894.          --  Consider the example:
  895.  
  896.          --     Lbl: loop
  897.          --             null;
  898.          --          end loop;
  899.  
  900.          --  Here the column lines up with Lbl, so END LOOP is to the right,
  901.          --  but it is still acceptable. LOOP is the one case where alignment
  902.          --  practices vary substantially in practice.
  903.  
  904.          if Pretty_Good
  905.             or else End_Column <= Scope.Table (Scope.Last).Ecol
  906.             or else (End_Type = Scope.Table (Scope.Last).Etyp
  907.                         and then End_Type = E_Loop)
  908.          then
  909.             Output_End_Expected;
  910.             Pop_Scope_Stack;
  911.             End_Action := Skip_And_Accept;
  912.             return;
  913.  
  914.          --  Here we have the case where the END is to the right of the
  915.          --  expected column and does not have a correct label to convince
  916.          --  us that it nevertheless belongs to the current scope. For this
  917.          --  we consider that it probably belongs not to the current context,
  918.          --  but to some inner context that was not properly recognized (due to
  919.          --  other syntax errors), and for which no proper scope stack entry
  920.          --  was made. The proper action in this case is to delete the END text
  921.          --  and return False to the caller as a signal to keep on looking for
  922.          --  an acceptable END. This is action 1 from the discussion above.
  923.  
  924.          else
  925.             Output_End_Deleted;
  926.             End_Action := Skip_And_Reject;
  927.             return;
  928.          end if;
  929.       end if;
  930.    end Pop_End_Context;
  931.  
  932. end Endh;
  933.