OSDN Git Service

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