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-sync.adb < prev    next >
Text File  |  1996-09-28  |  9KB  |  326 lines

  1. ------------------------------------------------------------------------------
  2. --                                                                          --
  3. --                         GNAT COMPILER COMPONENTS                         --
  4. --                                                                          --
  5. --                             P A R . S Y N C                              --
  6. --                                                                          --
  7. --                                 B o d y                                  --
  8. --                                                                          --
  9. --                            $Revision: 1.15 $                             --
  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 Sync is
  27.  
  28.    procedure Resync_Init;
  29.    --  This routine is called on initiating a resyncrhonization action
  30.  
  31.    procedure Resync_Resume;
  32.    --  This routine is called on completing a resynchronization action
  33.  
  34.    -----------------
  35.    -- Resync_Init --
  36.    -----------------
  37.  
  38.    procedure Resync_Init is
  39.    begin
  40.       --  The following check makes sure we do not get stuck in an infinite
  41.       --  loop resynchonizing and getting nowhere. If we are called to do a
  42.       --  resynchronize and we are exactly at the same point that we left off
  43.       --  on the last resynchronize call, then we force at least one token to
  44.       --  be skipped so that we make progress!
  45.  
  46.       if Token_Ptr = Last_Resync_Point then
  47.          Scan; -- to skip at least one token
  48.       end if;
  49.  
  50.       --  Output extra error message if debug R flag is set
  51.  
  52.       if Debug_Flag_R then
  53.          Error_Msg_SC ("resynchronizing!");
  54.       end if;
  55.    end Resync_Init;
  56.  
  57.    -------------------
  58.    -- Resync_Resume --
  59.    -------------------
  60.  
  61.    procedure Resync_Resume is
  62.    begin
  63.       --  Save resync point (see special test in Resync_Init)
  64.  
  65.       Last_Resync_Point := Token_Ptr;
  66.  
  67.       if Debug_Flag_R then
  68.          Error_Msg_SC ("resuming here!");
  69.       end if;
  70.    end Resync_Resume;
  71.  
  72.    -------------------
  73.    -- Resync_Choice --
  74.    -------------------
  75.  
  76.    procedure Resync_Choice is
  77.    begin
  78.       Resync_Init;
  79.  
  80.       --  Loop till we get a token that terminates a choice. Note that EOF is
  81.       --  one such token, so we are sure to get out of this loop eventually!
  82.  
  83.       while Token not in Token_Class_Cterm loop
  84.          Scan;
  85.       end loop;
  86.  
  87.       Resync_Resume;
  88.    end Resync_Choice;
  89.  
  90.    ------------------
  91.    -- Resync_Cunit --
  92.    ------------------
  93.  
  94.    procedure Resync_Cunit is
  95.    begin
  96.       Resync_Init;
  97.  
  98.       while Token not in Token_Class_Cunit
  99.         and then Token /= Tok_EOF
  100.       loop
  101.          Scan;
  102.       end loop;
  103.  
  104.       Resync_Resume;
  105.    end Resync_Cunit;
  106.  
  107.    -----------------------
  108.    -- Resync_Expression --
  109.    -----------------------
  110.  
  111.    procedure Resync_Expression is
  112.       Paren_Count : Int;
  113.  
  114.    begin
  115.       Resync_Init;
  116.       Paren_Count := 0;
  117.  
  118.       loop
  119.          --  Terminating tokens are those in class Eterm and also RANGE,
  120.          --  DIGITS or DELTA if not preceded by an apostrophe (if they are
  121.          --  preceded by an apostrophe, then they are attributes). In addiion,
  122.          --  at the outer parentheses level only, we also consider a comma,
  123.          --  right parenthesis or vertical bar to terminate an expression.
  124.  
  125.          if Token in Token_Class_Eterm
  126.  
  127.            or else (Token in Token_Class_Atkwd
  128.                      and then Prev_Token /= Tok_Apostrophe)
  129.  
  130.            or else (Paren_Count = 0
  131.                      and then
  132.                        (Token = Tok_Comma
  133.                          or else Token = Tok_Right_Paren
  134.                          or else Token = Tok_Vertical_Bar))
  135.          then
  136.             --  A special check: if we stop on the ELSE of OR ELSE or the
  137.             --  THEN of AND THEN, keep going, because this is not really an
  138.             --  expression terminator after all. Also, keep going past WITH
  139.             --  since this can be part of an extension aggregate
  140.  
  141.             if (Token = Tok_Else and then Prev_Token = Tok_Or)
  142.                or else (Token = Tok_Then and then Prev_Token = Tok_And)
  143.                or else Token = Tok_With
  144.             then
  145.                null;
  146.             else
  147.                exit;
  148.             end if;
  149.          end if;
  150.  
  151.          if Token = Tok_Left_Paren then
  152.             Paren_Count := Paren_Count + 1;
  153.  
  154.          elsif Token = Tok_Right_Paren then
  155.             Paren_Count := Paren_Count - 1;
  156.  
  157.          end if;
  158.  
  159.          Scan; -- past token to be skipped
  160.       end loop;
  161.  
  162.       Resync_Resume;
  163.    end Resync_Expression;
  164.  
  165.    ------------------------------------
  166.    -- Resync_Past_Right_Paren_Or_Eol --
  167.    ------------------------------------
  168.  
  169.    procedure Resync_Past_Right_Paren_Or_EOL is
  170.    begin
  171.       Resync_Init;
  172.  
  173.       while Prev_Token /= Tok_Right_Paren
  174.         and then Token_Ptr /= First_Non_Blank_Location
  175.       loop
  176.          Scan;
  177.       end loop;
  178.  
  179.       Resync_Resume;
  180.    end Resync_Past_Right_Paren_Or_EOL;
  181.  
  182.    ---------------------------
  183.    -- Resync_Past_Semicolon --
  184.    ---------------------------
  185.  
  186.    procedure Resync_Past_Semicolon is
  187.    begin
  188.       Resync_Init;
  189.  
  190.       loop
  191.          --  Done if we are at a semicolon
  192.  
  193.          if Token = Tok_Semicolon then
  194.             Scan; -- past semicolon
  195.             exit;
  196.  
  197.          --  Done if we are at a token which normally appears only after
  198.          --  a semicolon. One special glitch is that the keyword private is
  199.          --  in this category only if it does NOT appear after WITH.
  200.  
  201.          elsif Token in Token_Class_After_SM
  202.             and then (Token /= Tok_Private or else Prev_Token /= Tok_With)
  203.          then
  204.             exit;
  205.  
  206.          --  Otherwise keep going
  207.  
  208.          else
  209.             Scan;
  210.          end if;
  211.       end loop;
  212.  
  213.       --  Fall out of loop with resyncrhonization complete
  214.  
  215.       Resync_Resume;
  216.    end Resync_Past_Semicolon;
  217.  
  218.    ----------------------------------------------
  219.    -- Resync_Past_Semicolon_Or_To_Loop_Or_Then --
  220.    ----------------------------------------------
  221.  
  222.    procedure Resync_Past_Semicolon_Or_To_Loop_Or_Then is
  223.    begin
  224.       Resync_Init;
  225.  
  226.       loop
  227.          --  Done if at semicolon
  228.  
  229.          if Token = Tok_Semicolon then
  230.             Scan; -- past the semicolon
  231.             exit;
  232.  
  233.          --  Done if we are at a token which normally appears only after
  234.          --  a semicolon. One special glitch is that the keyword private is
  235.          --  in this category only if it does NOT appear after WITH.
  236.  
  237.          elsif (Token in Token_Class_After_SM
  238.                   and then (Token /= Tok_Private
  239.                               or else Prev_Token /= Tok_With))
  240.          then
  241.             exit;
  242.  
  243.          --  Done if we are at THEN or LOOP
  244.  
  245.          elsif Token = Tok_Then or else Token = Tok_Loop then
  246.             exit;
  247.  
  248.          --  Otherwise keep going
  249.  
  250.          else
  251.             Scan;
  252.          end if;
  253.       end loop;
  254.  
  255.       --  Fall out of loop with resyncrhonization complete
  256.  
  257.       Resync_Resume;
  258.    end Resync_Past_Semicolon_Or_To_Loop_Or_Then;
  259.  
  260.    --------------------
  261.    -- Resync_To_When --
  262.    --------------------
  263.  
  264.    procedure Resync_To_When is
  265.    begin
  266.       Resync_Init;
  267.  
  268.       loop
  269.          --  Done if at semicolon, WHEN or IS
  270.  
  271.          if Token = Tok_Semicolon
  272.            or else Token = Tok_When
  273.            or else Token = Tok_Is
  274.          then
  275.             exit;
  276.  
  277.          --  Otherwise keep going
  278.  
  279.          else
  280.             Scan;
  281.          end if;
  282.       end loop;
  283.  
  284.       --  Fall out of loop with resyncrhonization complete
  285.  
  286.       Resync_Resume;
  287.    end Resync_To_When;
  288.  
  289.    ---------------------------
  290.    -- Resync_Semicolon_List --
  291.    ---------------------------
  292.  
  293.    procedure Resync_Semicolon_List is
  294.       Paren_Count : Int;
  295.  
  296.    begin
  297.       Resync_Init;
  298.       Paren_Count := 0;
  299.  
  300.       loop
  301.          if Token = Tok_EOF
  302.            or else Token = Tok_Semicolon
  303.            or else Token = Tok_Is
  304.            or else Token in Token_Class_After_SM
  305.          then
  306.             exit;
  307.  
  308.          elsif Token = Tok_Left_Paren then
  309.             Paren_Count := Paren_Count + 1;
  310.  
  311.          elsif Token = Tok_Right_Paren then
  312.             if Paren_Count = 0 then
  313.                exit;
  314.             else
  315.                Paren_Count := Paren_Count - 1;
  316.             end if;
  317.          end if;
  318.  
  319.          Scan;
  320.       end loop;
  321.  
  322.       Resync_Resume;
  323.    end Resync_Semicolon_List;
  324.  
  325. end Sync;
  326.