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-util.adb < prev    next >
Text File  |  1996-09-28  |  17KB  |  520 lines

  1. ------------------------------------------------------------------------------
  2. --                                                                          --
  3. --                         GNAT COMPILER COMPONENTS                         --
  4. --                                                                          --
  5. --                             P A R . U T I L                              --
  6. --                                                                          --
  7. --                                 B o d y                                  --
  8. --                                                                          --
  9. --                            $Revision: 1.45 $                             --
  10. --                                                                          --
  11. --        Copyright (c) 1992,1993,1994,1995 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. with Uintp; use Uintp;
  26.  
  27. separate (Par)
  28. package body Util is
  29.  
  30.    -----------------------
  31.    -- Local Subprograms --
  32.    -----------------------
  33.  
  34.    procedure Set_Keyword_Name;
  35.    --  Builds a names table entry for the current token and stores the Name_Id
  36.    --  in Error_Msg_Name_1, ready for incorporation into an error message.
  37.  
  38.    ---------------------
  39.    -- Bad_Spelling_Of --
  40.    ---------------------
  41.  
  42.    function Bad_Spelling_Of (T : Token_Type) return Boolean is
  43.       Tname : constant String := Token_Type'Image (T);
  44.       --  Characters of token name
  45.  
  46.       S : String (1 .. Tname'Last - 4);
  47.       --  Characters of token name folded to lowe case, omitting TOK_ at start
  48.  
  49.       M : String (1 .. 42) := "Incorrect spelling of keyword ************";
  50.       --  Buffer used to construct error message
  51.  
  52.       P : constant := 30;
  53.       --  Starting subscript in M for keyword name
  54.  
  55.       SL : constant Natural := S'Length;
  56.       --  Length of token name excluding TOK_ at start
  57.  
  58.    begin
  59.       if Token /= Tok_Identifier then
  60.          return False;
  61.       end if;
  62.  
  63.       for J in S'Range loop
  64.          S (J) := Fold_Lower (Tname (Integer (J) + 4));
  65.       end loop;
  66.  
  67.       Get_Name_String (Token_Name);
  68.  
  69.       --  Never consider something a misspelling if either the actual or
  70.       --  expected string is less than 3 characters (before this check we
  71.       --  used to consider i to be a misspelled if in some cases!)
  72.  
  73.       if SL < 3 or else Name_Len < 3 then
  74.          return False;
  75.  
  76.       --  Special case: prefix matches, i.e. the leading characters of the
  77.       --  token that we have exactly match the required keyword. If there
  78.       --  are at least two characters left over, assume that we have a case
  79.       --  of two keywords joined together which should not be joined.
  80.  
  81.       elsif Name_Len > SL + 1
  82.         and then S = Name_Buffer (1 .. SL)
  83.       then
  84.          Scan_Ptr := Token_Ptr + S'Length;
  85.          Error_Msg_S ("missing space");
  86.          Token := T;
  87.          return True;
  88.       end if;
  89.  
  90.       --  If first character does not match, then definitely not misspelling
  91.  
  92.       if S (1) /= Name_Buffer (1) then
  93.          return False;
  94.       end if;
  95.  
  96.       --  Lengths match. Execute loop to check for a single error, single
  97.       --  transposition or exact match (we only fall through this loop if
  98.       --  one of these three conditions is found).
  99.  
  100.       if Name_Len = SL then
  101.  
  102.          --  Loop to check for single mismatch or exact match (we only fall
  103.          --  through this loop if one of these two conditions is met).
  104.  
  105.          for J in 2 .. Name_Len - 1 loop
  106.             if Name_Buffer (J) /= S (J) then
  107.  
  108.                exit when Name_Buffer (J + 1) = S (J + 1)
  109.                  and then Name_Buffer (J + 2 .. Name_Len) = S (J + 2 .. SL);
  110.  
  111.                exit when Name_Buffer (J) = S (J + 1)
  112.                  and then Name_Buffer (J + 1) = S (J)
  113.                  and then Name_Buffer (J + 2 .. Name_Len) = S (J + 2 .. SL);
  114.  
  115.                return False;
  116.             end if;
  117.          end loop;
  118.  
  119.       --  Length is 1 too short. Execute loop to check for single deletion
  120.       --  (we only fall through this loop if a single insertion is found)
  121.  
  122.       elsif Name_Len = S'Last - 1 then
  123.          for J in 2 .. Name_Len loop
  124.             if Name_Buffer (J) /= S (J) then
  125.                exit when Name_Buffer (J .. Name_Len) = S (J + 1 .. SL);
  126.                return False;
  127.             end if;
  128.          end loop;
  129.  
  130.       --  Length is 1 too long. Execute loop to check for single insertion
  131.       --  (we only fall through this loop if a single insertion is found)
  132.  
  133.       elsif Name_Len = S'Last + 1 then
  134.          for J in 2 .. S'Last loop
  135.             if Name_Buffer (J) /= S (J) then
  136.                exit when Name_Buffer (J + 1 .. Name_Len) = S (J .. SL);
  137.                return False;
  138.             end if;
  139.          end loop;
  140.  
  141.       --  Length is completely wrong
  142.  
  143.       else
  144.          return False;
  145.       end if;
  146.  
  147.       --  Fall through to here if we have a bad spelling
  148.  
  149.       for J in 1 .. S'Last loop
  150.          M (P + J - 1) := Fold_Upper (S (J));
  151.       end loop;
  152.  
  153.       Error_Msg_SC (M (1 .. 29 + S'Last));
  154.       Token := T;
  155.       return True;
  156.  
  157.    end Bad_Spelling_Of;
  158.  
  159.    ----------------------
  160.    -- Check_95_Keyword --
  161.    ----------------------
  162.  
  163.    --  On entry, the caller has checked that current token is an identifier
  164.    --  whose name matches the name of the 95 keyword New_Tok.
  165.  
  166.    procedure Check_95_Keyword (Token_95, Next : Token_Type) is
  167.       Scan_State : Saved_Scan_State;
  168.  
  169.    begin
  170.       Save_Scan_State (Scan_State); -- at identifier/keyword
  171.       Scan; -- past identifier/keyword
  172.  
  173.       if Token = Next then
  174.          Restore_Scan_State (Scan_State); -- to identifier
  175.          Error_Msg_Name_1 := Token_Name;
  176.          Error_Msg_SC ("(Ada 83) keyword* cannot be used!");
  177.          Token := Token_95;
  178.       else
  179.          Restore_Scan_State (Scan_State); -- to identifier
  180.       end if;
  181.    end Check_95_Keyword;
  182.  
  183.    -----------------------------
  184.    -- Check_Simple_Expression --
  185.    -----------------------------
  186.  
  187.    procedure Check_Simple_Expression (E : Node_Id) is
  188.    begin
  189.       if Expr_Form = EF_Non_Simple then
  190.          Error_Msg_N ("this expression must be parenthesized", E);
  191.       end if;
  192.    end Check_Simple_Expression;
  193.  
  194.    ---------------------------------------
  195.    -- Check_Simple_Expression_In_Ada_83 --
  196.    ---------------------------------------
  197.  
  198.    procedure Check_Simple_Expression_In_Ada_83 (E : Node_Id) is
  199.    begin
  200.       if Expr_Form = EF_Non_Simple then
  201.          Note_Feature (Non_Simple_Expressions, Sloc (E));
  202.  
  203.          if Ada_83 then
  204.             Error_Msg_N ("(Ada 83) this expression must be parenthesized!", E);
  205.          end if;
  206.       end if;
  207.    end Check_Simple_Expression_In_Ada_83;
  208.  
  209.    ------------------------
  210.    -- Check_Subtype_Mark --
  211.    ------------------------
  212.  
  213.    function Check_Subtype_Mark (Mark : Node_Id) return Node_Id is
  214.    begin
  215.       if Nkind (Mark) = N_Identifier
  216.         or else Nkind (Mark) = N_Selected_Component
  217.         or else (Nkind (Mark) = N_Attribute_Reference
  218.                   and then Is_Type_Attribute_Name (Attribute_Name (Mark)))
  219.         or else Mark = Error
  220.       then
  221.          return Mark;
  222.       else
  223.          Error_Msg ("subtype mark expected", Sloc (Mark));
  224.          return Error;
  225.       end if;
  226.    end Check_Subtype_Mark;
  227.  
  228.    -------------------
  229.    -- Comma_Present --
  230.    -------------------
  231.  
  232.    function Comma_Present return Boolean is
  233.       Scan_State  : Saved_Scan_State;
  234.       Paren_Count : Nat;
  235.  
  236.    begin
  237.       --  First check, if a comma is present, then a comma is present!
  238.  
  239.       if Token = Tok_Comma then
  240.          T_Comma;
  241.          return True;
  242.  
  243.       --  If we have a right paren, then that is taken as ending the list
  244.       --  i.e. no comma is present.
  245.  
  246.       elsif Token = Tok_Right_Paren then
  247.          return False;
  248.  
  249.       --  If pragmas, then get rid of them and make a recursive call
  250.       --  to process what follows these pragmas.
  251.  
  252.       elsif Token = Tok_Pragma then
  253.          P_Pragmas_Misplaced;
  254.          return Comma_Present;
  255.  
  256.       --  At this stage we have an error, and the goal is to decide on whether
  257.       --  or not we should diagnose an error and report a (non-existent)
  258.       --  comma as being present, or simply to report no comma is present
  259.  
  260.       --  If we are a semicolon, then the question is whether we have a missing
  261.       --  right paren, or whether the semicolon should have been a comma. To
  262.       --  guess the right answer, we scan ahead keeping track of the paren
  263.       --  level, looking for a clue that helps us make the right decision.
  264.  
  265.       --  This approach is highly accurate in the single error case, and does
  266.       --  not make bad mistakes in the multiple error case (indeed we can't
  267.       --  really make a very bad decision at this point in any case).
  268.  
  269.       elsif Token = Tok_Semicolon then
  270.          Save_Scan_State (Scan_State);
  271.          Scan; -- past semicolon
  272.  
  273.          --  Check for being followed by identifier => which almost certainly
  274.          --  means we are still in a parameter list and the comma should have
  275.          --  been a semicolon (such a sequence could not follow a semicolon)
  276.  
  277.          if Token = Tok_Identifier then
  278.             Scan;
  279.  
  280.             if Token = Tok_Arrow then
  281.                goto Assume_Comma;
  282.             end if;
  283.          end if;
  284.  
  285.          --  If that test didn't work, loop ahead looking for a comma or
  286.          --  semicolon at the same parenthesis level. Always remember that
  287.          --  we can't go badly wrong in an error situation like this!
  288.  
  289.          Paren_Count := 0;
  290.  
  291.          --  Here is the look ahead loop, Paren_Count tells us whether the
  292.          --  token we are looking at is at the same paren level as the
  293.          --  suspicious semicolon that we are trying to figure out.
  294.  
  295.          loop
  296.  
  297.             --  If we hit another semicolon or an end of file, and we have
  298.             --  not seen a right paren or another comma on the way, then
  299.             --  probably the semicolon did end the list. Indeed that is
  300.             --  certainly the only single error correction possible here.
  301.  
  302.             if Token = Tok_Semicolon or else Token = Tok_EOF then
  303.                Restore_Scan_State (Scan_State);
  304.                return False;
  305.  
  306.             --  A comma at the same paren level as the semicolon is a strong
  307.             --  indicator that the semicolon should have been a comma, indeed
  308.             --  again this is the only possible single error correction.
  309.  
  310.             elsif Token = Tok_Comma then
  311.                exit when Paren_Count = 0;
  312.  
  313.             --  A left paren just bumps the paren count
  314.  
  315.             elsif Token = Tok_Left_Paren then
  316.                Paren_Count := Paren_Count + 1;
  317.  
  318.             --  A right paren that is at the same paren level as the semicolon
  319.             --  also means that the only possible single error correction is
  320.             --  to assume that the semicolon should have been a comma. If we
  321.             --  are not at the same paren level, then adjust the paren level.
  322.  
  323.             elsif Token = Tok_Right_Paren then
  324.                exit when Paren_Count = 0;
  325.                Paren_Count := Paren_Count - 1;
  326.             end if;
  327.  
  328.             --  Keep going, we haven't made a decision yet
  329.  
  330.             Scan;
  331.          end loop;
  332.  
  333.          --  If we fall through the loop, it means that we found a terminating
  334.          --  right paren or another comma. In either case it is reasonable to
  335.          --  assume that the semicolon was really intended to be a comma. Also
  336.          --  come here for the identifier arrow case.
  337.  
  338.          <<Assume_Comma>>
  339.             Restore_Scan_State (Scan_State);
  340.             Error_Msg_SC (""";"" illegal here, replaced by "",""");
  341.             Scan; -- past the semicolon
  342.             return True;
  343.  
  344.       --  If we are not at semicolon or a right paren, then we base the
  345.       --  decision on whether or not the next token can be part of an
  346.       --  expression. If not, then decide that no comma is present (the
  347.       --  caller will eventually generate a missing right parent message)
  348.  
  349.       elsif Token in Token_Class_Eterm then
  350.          return False;
  351.  
  352.       --  Otherwise we assume a comma is present, even if none is present,
  353.       --  since the next token must be part of an expression, so if we were
  354.       --  at the end of the list, then there is more than one error present.
  355.  
  356.       else
  357.          T_Comma; -- to give error
  358.          return True;
  359.       end if;
  360.    end Comma_Present;
  361.  
  362.    -----------------------
  363.    -- Discard_Junk_List --
  364.    -----------------------
  365.  
  366.    procedure Discard_Junk_List (L : List_Id) is
  367.    begin
  368.       null;
  369.    end Discard_Junk_List;
  370.  
  371.    -----------------------
  372.    -- Discard_Junk_Node --
  373.    -----------------------
  374.  
  375.    procedure Discard_Junk_Node (N : Node_Id) is
  376.    begin
  377.       null;
  378.    end Discard_Junk_Node;
  379.  
  380.    ------------
  381.    -- Ignore --
  382.    ------------
  383.  
  384.    procedure Ignore (T : Token_Type) is
  385.    begin
  386.       if Token = T then
  387.          Set_Keyword_Name;
  388.          Error_Msg_SC ("unexpected keyword% ignored");
  389.          Scan;
  390.       end if;
  391.    end Ignore;
  392.  
  393.    ----------------------------
  394.    -- Is_Reserved_Identifier --
  395.    ----------------------------
  396.  
  397.    function Is_Reserved_Identifier return Boolean is
  398.       Ident_Casing : constant Casing_Type :=
  399.                        Identifier_Casing (Current_Source_File);
  400.  
  401.    begin
  402.       if not Is_Reserved_Keyword (Token) then
  403.          return False;
  404.  
  405.       --  If we have a reserved word, check its casing with the default
  406.       --  identifier casing. A match is an exact equality of case styles,
  407.       --  or a case in which the current identifier case mode is unknown.
  408.  
  409.       else
  410.          if Determine_Token_Casing = Ident_Casing then
  411.             return True;
  412.  
  413.          elsif Ident_Casing = Unknown then
  414.             return True;
  415.  
  416.          else
  417.             return False;
  418.          end if;
  419.       end if;
  420.    end Is_Reserved_Identifier;
  421.  
  422.    -------------------
  423.    -- No_Constraint --
  424.    -------------------
  425.  
  426.    procedure No_Constraint is
  427.    begin
  428.       if Token in Token_Class_Consk then
  429.          Error_Msg_SC ("constraint not allowed here");
  430.          Discard_Junk_Node (P_Constraint_Opt);
  431.       end if;
  432.    end No_Constraint;
  433.  
  434.    ---------------------
  435.    -- Pop_Scope_Stack --
  436.    ---------------------
  437.  
  438.    procedure Pop_Scope_Stack is
  439.    begin
  440.       pragma Assert (Scope.Last > 0);
  441.       Scope.Decrement_Last;
  442.  
  443.       if Debug_Flag_P then
  444.          Error_Msg_Uint_1 := UI_From_Int (Scope.Last);
  445.          Error_Msg_SC ("decrement scope stack ptr, new value = ^!");
  446.       end if;
  447.    end Pop_Scope_Stack;
  448.  
  449.    ----------------------
  450.    -- Push_Scope_Stack --
  451.    ----------------------
  452.  
  453.    procedure Push_Scope_Stack is
  454.    begin
  455.       Scope.Increment_Last;
  456.  
  457.       if Debug_Flag_P then
  458.          Error_Msg_Uint_1 := UI_From_Int (Scope.Last);
  459.          Error_Msg_SC ("increment scope stack ptr, new value = ^!");
  460.       end if;
  461.    end Push_Scope_Stack;
  462.  
  463.    ----------------------
  464.    -- Separate_Present --
  465.    ----------------------
  466.  
  467.    function Separate_Present return Boolean is
  468.       Scan_State : Saved_Scan_State;
  469.  
  470.    begin
  471.       if Token = Tok_Separate then
  472.          return True;
  473.  
  474.       elsif Token /= Tok_Identifier then
  475.          return False;
  476.  
  477.       else
  478.          Save_Scan_State (Scan_State);
  479.          Scan; -- past identifier
  480.  
  481.          if Token = Tok_Semicolon then
  482.             Restore_Scan_State (Scan_State);
  483.             return Bad_Spelling_Of (Tok_Separate);
  484.  
  485.          else
  486.             Restore_Scan_State (Scan_State);
  487.             return False;
  488.          end if;
  489.       end if;
  490.    end Separate_Present;
  491.  
  492.    ----------------------
  493.    -- Set_Keyword_Name --
  494.    ----------------------
  495.  
  496.    procedure Set_Keyword_Name is
  497.       Tname : constant String := Token_Type'Image (Token);
  498.       --  Characters of token name (note we omit TOK_ at the start)
  499.  
  500.    begin
  501.       Name_Len := Tname'Last - 4;
  502.  
  503.       for J in 1 .. Name_Len loop
  504.          Name_Buffer (J) := Fold_Lower (Tname (J + 4));
  505.       end loop;
  506.  
  507.       Error_Msg_Name_1 := Name_Find;
  508.    end Set_Keyword_Name;
  509.  
  510.    -------------------------------
  511.    -- Token_Is_At_Start_Of_Line --
  512.    -------------------------------
  513.  
  514.    function Token_Is_At_Start_Of_Line return Boolean is
  515.    begin
  516.       return (Token_Ptr = First_Non_Blank_Location);
  517.    end Token_Is_At_Start_Of_Line;
  518.  
  519. end Util;
  520.