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-tchk.adb < prev    next >
Text File  |  1996-09-28  |  18KB  |  775 lines

  1. ------------------------------------------------------------------------------
  2. --                                                                          --
  3. --                         GNAT COMPILER COMPONENTS                         --
  4. --                                                                          --
  5. --                             P A R . T C H K                              --
  6. --                                                                          --
  7. --                                 B o d y                                  --
  8. --                                                                          --
  9. --                            $Revision: 1.23 $                             --
  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. --  Token scan routines.
  26.  
  27. --  Error recovery: none of the T_xxx or TF_xxx routines raise Error_Resync
  28.  
  29. separate (Par)
  30. package body Tchk is
  31.  
  32.    type Position is (SC, BC, AP);
  33.    --  Specify position of error message (see Error_Msg_SC/BC/AP)
  34.  
  35.    -----------------------
  36.    -- Local Subprograms --
  37.    -----------------------
  38.  
  39.    procedure Check_Token (T : Token_Type; P : Position);
  40.    pragma Inline (Check_Token);
  41.    --  Called by T_xx routines to check for reserved keyword token. P is the
  42.    --  position of the error message if the token is missing (see Wrong_Token)
  43.  
  44.    procedure Wrong_Token (T : Token_Type; P : Position);
  45.    --  Called when scanning a reserved keyword when the keyword is not
  46.    --  present. T is the token type for the keyword, and P indicates the
  47.    --  position to be used to place a message relative to the current
  48.    --  token if the keyword is not located nearby.
  49.  
  50.    -----------------
  51.    -- Check_Token --
  52.    -----------------
  53.  
  54.    procedure Check_Token (T : Token_Type; P : Position) is
  55.    begin
  56.       if Token = T then
  57.          Scan;
  58.          return;
  59.       else
  60.          Wrong_Token (T, P);
  61.       end if;
  62.    end Check_Token;
  63.  
  64.    -------------
  65.    -- T_Abort --
  66.    -------------
  67.  
  68.    procedure T_Abort is
  69.    begin
  70.       Check_Token (Tok_Abort, SC);
  71.    end T_Abort;
  72.  
  73.    -------------
  74.    -- T_Arrow --
  75.    -------------
  76.  
  77.    procedure T_Arrow is
  78.    begin
  79.       if Token = Tok_Arrow then
  80.          Scan;
  81.  
  82.       --  A little recovery helper, accept then in place of =>
  83.  
  84.       elsif Token = Tok_Then then
  85.          Error_Msg_BC ("missing ""=>""");
  86.          Scan; -- past then used in place of =>
  87.  
  88.       else
  89.          Error_Msg_AP ("missing ""=>""");
  90.       end if;
  91.    end T_Arrow;
  92.  
  93.    ----------
  94.    -- T_At --
  95.    ----------
  96.  
  97.    procedure T_At is
  98.    begin
  99.       Check_Token (Tok_At, SC);
  100.    end T_At;
  101.  
  102.    -------------
  103.    -- T_Begin --
  104.    -------------
  105.  
  106.    procedure T_Begin is
  107.    begin
  108.       Check_Token (Tok_Begin, SC);
  109.    end T_Begin;
  110.  
  111.    ------------
  112.    -- T_Body --
  113.    ------------
  114.  
  115.    procedure T_Body is
  116.    begin
  117.       Check_Token (Tok_Body, BC);
  118.    end T_Body;
  119.  
  120.    -----------
  121.    -- T_Box --
  122.    -----------
  123.  
  124.    procedure T_Box is
  125.    begin
  126.       if Token = Tok_Box then
  127.          Scan;
  128.       else
  129.          Error_Msg_AP ("missing ""<>""");
  130.       end if;
  131.    end T_Box;
  132.  
  133.    -------------
  134.    -- T_Colon --
  135.    -------------
  136.  
  137.    procedure T_Colon is
  138.    begin
  139.       if Token = Tok_Colon then
  140.          Scan;
  141.       else
  142.          Error_Msg_AP ("missing "":""");
  143.       end if;
  144.    end T_Colon;
  145.  
  146.    -------------------
  147.    -- T_Colon_Equal --
  148.    -------------------
  149.  
  150.    procedure T_Colon_Equal is
  151.    begin
  152.       if Token = Tok_Colon_Equal then
  153.          Scan;
  154.  
  155.       elsif Token = Tok_Equal then
  156.          Error_Msg_SC ("""="" should be "":=""");
  157.  
  158.       elsif Token = Tok_Colon then
  159.          Error_Msg_SC (""":"" should be "":=""");
  160.  
  161.       elsif Token = Tok_Is then
  162.          Error_Msg_SC ("IS should be "":=""");
  163.  
  164.       else
  165.          Error_Msg_AP ("missing "":=""");
  166.       end if;
  167.    end T_Colon_Equal;
  168.  
  169.    -------------
  170.    -- T_Comma --
  171.    -------------
  172.  
  173.    procedure T_Comma is
  174.    begin
  175.       if Token = Tok_Comma then
  176.          Scan;
  177.  
  178.       else
  179.          if Token = Tok_Pragma then
  180.             P_Pragmas_Misplaced;
  181.          end if;
  182.  
  183.          if Token = Tok_Comma then
  184.             Scan;
  185.          else
  186.             Error_Msg_AP ("missing "",""");
  187.          end if;
  188.       end if;
  189.  
  190.       if Token = Tok_Pragma then
  191.          P_Pragmas_Misplaced;
  192.       end if;
  193.    end T_Comma;
  194.  
  195.    ---------------
  196.    -- T_Dot_Dot --
  197.    ---------------
  198.  
  199.    procedure T_Dot_Dot is
  200.    begin
  201.       if Token = Tok_Dot_Dot then
  202.          Scan;
  203.       else
  204.          Error_Msg_AP ("missing ""..""");
  205.       end if;
  206.    end T_Dot_Dot;
  207.  
  208.    -----------
  209.    -- T_For --
  210.    -----------
  211.  
  212.    procedure T_For is
  213.    begin
  214.       Check_Token (Tok_For, AP);
  215.    end T_For;
  216.  
  217.    -----------------------
  218.    -- T_Greater_Greater --
  219.    -----------------------
  220.  
  221.    procedure T_Greater_Greater is
  222.    begin
  223.       if Token = Tok_Greater_Greater then
  224.          Scan;
  225.       else
  226.          Error_Msg_AP ("missing "">>""");
  227.       end if;
  228.    end T_Greater_Greater;
  229.  
  230.    ------------------
  231.    -- T_Identifier --
  232.    ------------------
  233.  
  234.    procedure T_Identifier is
  235.    begin
  236.       if Token = Tok_Identifier then
  237.          Scan;
  238.       elsif Token in Token_Class_Literal then
  239.          Error_Msg_SC ("identifier expected");
  240.          Scan;
  241.       else
  242.          Error_Msg_AP ("identifier expected");
  243.       end if;
  244.    end T_Identifier;
  245.  
  246.    ----------
  247.    -- T_In --
  248.    ----------
  249.  
  250.    procedure T_In is
  251.    begin
  252.       Check_Token (Tok_In, AP);
  253.    end T_In;
  254.  
  255.    ----------
  256.    -- T_Is --
  257.    ----------
  258.  
  259.    procedure T_Is is
  260.    begin
  261.       if Token = Tok_Is then
  262.          Scan;
  263.  
  264.       --  Allow OF, => or = to substitute for IS with complaint
  265.  
  266.       elsif Token = Tok_Arrow
  267.         or else Token = Tok_Of
  268.         or else Token = Tok_Equal
  269.       then
  270.          Error_Msg_SC ("missing IS");
  271.          Scan; -- token used in place of IS
  272.       else
  273.          Wrong_Token (Tok_Is, AP);
  274.       end if;
  275.  
  276.       while Token = Tok_Is loop
  277.          Error_Msg_SC ("extra IS ignored");
  278.          Scan;
  279.       end loop;
  280.    end T_Is;
  281.  
  282.    ------------------
  283.    -- T_Left_Paren --
  284.    ------------------
  285.  
  286.    procedure T_Left_Paren is
  287.    begin
  288.       if Token = Tok_Left_Paren then
  289.          Scan;
  290.       else
  291.          Error_Msg_AP ("missing ""(""");
  292.       end if;
  293.    end T_Left_Paren;
  294.  
  295.    ------------
  296.    -- T_Loop --
  297.    ------------
  298.  
  299.    procedure T_Loop is
  300.    begin
  301.       Check_Token (Tok_Loop, SC);
  302.    end T_Loop;
  303.  
  304.    -----------
  305.    -- T_Mod --
  306.    -----------
  307.  
  308.    procedure T_Mod is
  309.    begin
  310.       Check_Token (Tok_Mod, AP);
  311.    end T_Mod;
  312.  
  313.    -----------
  314.    -- T_New --
  315.    -----------
  316.  
  317.    procedure T_New is
  318.    begin
  319.       Check_Token (Tok_New, AP);
  320.    end T_New;
  321.  
  322.    ----------
  323.    -- T_Of --
  324.    ----------
  325.  
  326.    procedure T_Of is
  327.    begin
  328.       Check_Token (Tok_Of, AP);
  329.    end T_Of;
  330.  
  331.    ----------
  332.    -- T_Or --
  333.    ----------
  334.  
  335.    procedure T_Or is
  336.    begin
  337.       Check_Token (Tok_Or, AP);
  338.    end T_Or;
  339.  
  340.    ---------------
  341.    -- T_Private --
  342.    ---------------
  343.  
  344.    procedure T_Private is
  345.    begin
  346.       Check_Token (Tok_Private, SC);
  347.    end T_Private;
  348.  
  349.    -------------
  350.    -- T_Range --
  351.    -------------
  352.  
  353.    procedure T_Range is
  354.    begin
  355.       Check_Token (Tok_Range, AP);
  356.    end T_Range;
  357.  
  358.    -------------------
  359.    -- T_Right_Paren --
  360.    -------------------
  361.  
  362.    procedure T_Right_Paren is
  363.    begin
  364.       if Token = Tok_Right_Paren then
  365.          Scan;
  366.       else
  367.          Error_Msg_AP ("missing "")""");
  368.       end if;
  369.    end T_Right_Paren;
  370.  
  371.    --------------
  372.    -- T_Record --
  373.    --------------
  374.  
  375.    procedure T_Record is
  376.    begin
  377.       Check_Token (Tok_Record, AP);
  378.    end T_Record;
  379.  
  380.    -----------------
  381.    -- T_Semicolon --
  382.    -----------------
  383.  
  384.    procedure T_Semicolon is
  385.    begin
  386.  
  387.       if Token = Tok_Semicolon then
  388.          Scan;
  389.  
  390.       --  An interesting little kludge here. If the previous token is a
  391.       --  semicolon, then there is no way that we can legitimately need
  392.       --  another semicolon. This could only arise in an error situation
  393.       --  where an error has already been signalled. By simply ignoring
  394.       --  the request for a semicolon in this case, we avoid some spurious
  395.       --  missing semicolon messages.
  396.  
  397.       elsif Prev_Token = Tok_Semicolon then
  398.          return;
  399.  
  400.       --  Otherwise we really do have a missing semicolon
  401.  
  402.       else
  403.          Error_Msg_AP ("missing "";""");
  404.       end if;
  405.    end T_Semicolon;
  406.  
  407.    ------------
  408.    -- T_Then --
  409.    ------------
  410.  
  411.    procedure T_Then is
  412.    begin
  413.       Check_Token (Tok_Then, AP);
  414.    end T_Then;
  415.  
  416.    ------------
  417.    -- T_Type --
  418.    ------------
  419.  
  420.    procedure T_Type is
  421.    begin
  422.       Check_Token (Tok_Type, BC);
  423.    end T_Type;
  424.  
  425.    -----------
  426.    -- T_Use --
  427.    -----------
  428.  
  429.    procedure T_Use is
  430.    begin
  431.       Check_Token (Tok_Use, SC);
  432.    end T_Use;
  433.  
  434.    ------------
  435.    -- T_When --
  436.    ------------
  437.  
  438.    procedure T_When is
  439.    begin
  440.       Check_Token (Tok_When, SC);
  441.    end T_When;
  442.  
  443.    ------------
  444.    -- T_With --
  445.    ------------
  446.  
  447.    procedure T_With is
  448.    begin
  449.       Check_Token (Tok_With, BC);
  450.    end T_With;
  451.  
  452.    --------------
  453.    -- TF_Arrow --
  454.    --------------
  455.  
  456.    procedure TF_Arrow is
  457.       Scan_State : Saved_Scan_State;
  458.  
  459.    begin
  460.       if Token = Tok_Arrow then
  461.          Scan; -- skip arrow and we are done
  462.  
  463.       else
  464.          T_Arrow; -- give missing arrow message
  465.          Save_Scan_State (Scan_State); -- at start of junk tokens
  466.  
  467.          loop
  468.             if Prev_Token_Ptr < Current_Line_Start
  469.               or else Token = Tok_Semicolon
  470.               or else Token = Tok_EOF
  471.             then
  472.                Restore_Scan_State (Scan_State); -- to where we were!
  473.                return;
  474.             end if;
  475.  
  476.             Scan; -- continue search!
  477.  
  478.             if Token = Tok_Arrow then
  479.                Scan; -- past arrow
  480.                return;
  481.             end if;
  482.          end loop;
  483.       end if;
  484.    end TF_Arrow;
  485.  
  486.    -----------
  487.    -- TF_Is --
  488.    -----------
  489.  
  490.    procedure TF_Is is
  491.       Scan_State : Saved_Scan_State;
  492.  
  493.    begin
  494.       if Token = Tok_Is then
  495.          T_Is; -- past IS and we are done
  496.  
  497.       --  Allow OF or => or = in place of IS (with error message)
  498.  
  499.       elsif Token = Tok_Of
  500.         or else Token = Tok_Arrow
  501.         or else Token = Tok_Equal
  502.       then
  503.          T_Is; -- give missing IS message and skip bad token
  504.  
  505.       else
  506.          T_Is; -- give missing IS message
  507.          Save_Scan_State (Scan_State); -- at start of junk tokens
  508.  
  509.          loop
  510.             if Prev_Token_Ptr < Current_Line_Start
  511.               or else Token = Tok_Semicolon
  512.               or else Token = Tok_EOF
  513.             then
  514.                Restore_Scan_State (Scan_State); -- to where we were!
  515.                return;
  516.             end if;
  517.  
  518.             Scan; -- continue search!
  519.  
  520.             if Token = Tok_Is
  521.               or else Token = Tok_Of
  522.               or else Token = Tok_Arrow
  523.             then
  524.                Scan; -- past IS or OF or =>
  525.                return;
  526.             end if;
  527.          end loop;
  528.       end if;
  529.    end TF_Is;
  530.  
  531.    -------------
  532.    -- TF_Loop --
  533.    -------------
  534.  
  535.    procedure TF_Loop is
  536.       Scan_State : Saved_Scan_State;
  537.  
  538.    begin
  539.       if Token = Tok_Loop then
  540.          Scan; -- past LOOP and we are done
  541.  
  542.       --  Allow THEN in place of LOOP
  543.  
  544.       elsif Token = Tok_Then then
  545.          T_Loop; -- give missing LOOP message
  546.  
  547.       else
  548.          T_Loop; -- give missing LOOP message
  549.          Save_Scan_State (Scan_State); -- at start of junk tokens
  550.  
  551.          loop
  552.             if Prev_Token_Ptr < Current_Line_Start
  553.               or else Token = Tok_Semicolon
  554.               or else Token = Tok_EOF
  555.             then
  556.                Restore_Scan_State (Scan_State); -- to where we were!
  557.                return;
  558.             end if;
  559.  
  560.             Scan; -- continue search!
  561.  
  562.             if Token = Tok_Loop or else Token = Tok_Then then
  563.                Scan; -- past loop or then (message already generated)
  564.                return;
  565.             end if;
  566.          end loop;
  567.       end if;
  568.    end TF_Loop;
  569.  
  570.    --------------
  571.    -- TF_Return--
  572.    --------------
  573.  
  574.    procedure TF_Return is
  575.       Scan_State : Saved_Scan_State;
  576.  
  577.    begin
  578.       if Token = Tok_Return then
  579.          Scan; -- skip RETURN and we are done
  580.  
  581.       else
  582.          Error_Msg_SC ("missing RETURN");
  583.          Save_Scan_State (Scan_State); -- at start of junk tokens
  584.  
  585.          loop
  586.             if Prev_Token_Ptr < Current_Line_Start
  587.               or else Token = Tok_Semicolon
  588.               or else Token = Tok_EOF
  589.             then
  590.                Restore_Scan_State (Scan_State); -- to where we were!
  591.                return;
  592.             end if;
  593.  
  594.             Scan; -- continue search!
  595.  
  596.             if Token = Tok_Return then
  597.                Scan; -- past RETURN
  598.                return;
  599.             end if;
  600.          end loop;
  601.       end if;
  602.    end TF_Return;
  603.  
  604.    ------------------
  605.    -- TF_Semicolon --
  606.    ------------------
  607.  
  608.    procedure TF_Semicolon is
  609.       Scan_State : Saved_Scan_State;
  610.  
  611.    begin
  612.       if Token = Tok_Semicolon then
  613.          Scan; -- past ; and we are done
  614.          return;
  615.  
  616.       --  An interesting little kludge here. If the previous token is a
  617.       --  semicolon, then there is no way that we can legitimately need
  618.       --  another semicolon. This could only arise in an error situation
  619.       --  where an error has already been signalled. By simply ignoring
  620.       --  the request for a semicolon in this case, we avoid some spurious
  621.       --  missing semicolon messages.
  622.  
  623.       elsif Prev_Token = Tok_Semicolon then
  624.          return;
  625.  
  626.       else
  627.          if Token = Tok_Pragma then
  628.             P_Pragmas_Misplaced;
  629.  
  630.             if Token = Tok_Semicolon then
  631.                Scan; -- past semicolon
  632.                return;
  633.             end if;
  634.          end if;
  635.  
  636.          T_Semicolon; -- give missing semicolon message
  637.          Save_Scan_State (Scan_State); -- at start of junk tokens
  638.  
  639.          loop
  640.             if Prev_Token_Ptr < Current_Line_Start
  641.               or else Token = Tok_EOF
  642.             then
  643.                Restore_Scan_State (Scan_State); -- to where we were
  644.                return;
  645.             end if;
  646.  
  647.             Scan; -- continue search
  648.  
  649.             if Token = Tok_Semicolon then
  650.                Scan; -- past semicolon
  651.                return;
  652.  
  653.             elsif Token in Token_Class_After_SM then
  654.                return;
  655.             end if;
  656.          end loop;
  657.       end if;
  658.    end TF_Semicolon;
  659.  
  660.    -------------
  661.    -- TF_Then --
  662.    -------------
  663.  
  664.    procedure TF_Then is
  665.       Scan_State : Saved_Scan_State;
  666.  
  667.    begin
  668.       if Token = Tok_Then then
  669.          Scan; -- past THEN and we are done
  670.  
  671.       else
  672.          T_Then; -- give missing THEN message
  673.          Save_Scan_State (Scan_State); -- at start of junk tokens
  674.  
  675.          loop
  676.             if Prev_Token_Ptr < Current_Line_Start
  677.               or else Token = Tok_Semicolon
  678.               or else Token = Tok_EOF
  679.             then
  680.                Restore_Scan_State (Scan_State); -- to where we were
  681.                return;
  682.             end if;
  683.  
  684.             Scan; -- continue search!
  685.  
  686.             if Token = Tok_Then then
  687.                Scan; -- past THEN
  688.                return;
  689.             end if;
  690.          end loop;
  691.       end if;
  692.    end TF_Then;
  693.  
  694.    ------------
  695.    -- TF_Use --
  696.    ------------
  697.  
  698.    procedure TF_Use is
  699.       Scan_State : Saved_Scan_State;
  700.  
  701.    begin
  702.       if Token = Tok_Use then
  703.          Scan; -- past USE and we are done
  704.  
  705.       else
  706.          T_Use; -- give USE expected message
  707.          Save_Scan_State (Scan_State); -- at start of junk tokens
  708.  
  709.          loop
  710.             if Prev_Token_Ptr < Current_Line_Start
  711.               or else Token = Tok_Semicolon
  712.               or else Token = Tok_EOF
  713.             then
  714.                Restore_Scan_State (Scan_State); -- to where we were
  715.                return;
  716.             end if;
  717.  
  718.             Scan; -- continue search!
  719.  
  720.             if Token = Tok_Use then
  721.                Scan; -- past use
  722.                return;
  723.             end if;
  724.          end loop;
  725.       end if;
  726.    end TF_Use;
  727.  
  728.    -----------------
  729.    -- Wrong_Token --
  730.    -----------------
  731.  
  732.    procedure Wrong_Token (T : Token_Type; P : Position) is
  733.       Missing : constant String := "missing ";
  734.       Image : constant String := Token_Type'Image (T);
  735.       Tok_Name : constant String := Image (5 .. Image'Length);
  736.       M : String (1 .. Missing'Length + Tok_Name'Length);
  737.  
  738.    begin
  739.       --  Set M to Missing & Tok_Name.
  740.  
  741.       M (1 .. Missing'Length) := Missing;
  742.       M (Missing'Length + 1 .. M'Last) := Tok_Name;
  743.  
  744.       if Token = Tok_Semicolon then
  745.          Scan;
  746.  
  747.          if Token = T then
  748.             Error_Msg_SP ("extra "";"" ignored");
  749.             Scan;
  750.          else
  751.             Error_Msg_SP (M);
  752.          end if;
  753.  
  754.       elsif Token = Tok_Comma then
  755.          Scan;
  756.  
  757.          if Token = T then
  758.             Error_Msg_SP ("extra "","" ignored");
  759.             Scan;
  760.  
  761.          else
  762.             Error_Msg_SP (M);
  763.          end if;
  764.  
  765.       else
  766.          case P is
  767.             when SC => Error_Msg_SC (M);
  768.             when BC => Error_Msg_BC (M);
  769.             when AP => Error_Msg_AP (M);
  770.          end case;
  771.       end if;
  772.    end Wrong_Token;
  773.  
  774. end Tchk;
  775.