1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 ------------------------------------------------------------------------------
29 procedure Resync_Init
;
30 -- This routine is called on initiating a resynchronization action
32 procedure Resync_Resume
;
33 -- This routine is called on completing a resynchronization action
39 procedure Resync_Choice
is
43 -- Loop till we get a token that terminates a choice. Note that EOF is
44 -- one such token, so we are sure to get out of this loop eventually.
46 while Token
not in Token_Class_Cterm
loop
57 procedure Resync_Cunit
is
61 while Token
not in Token_Class_Cunit
62 and then Token
/= Tok_EOF
70 -----------------------
71 -- Resync_Expression --
72 -----------------------
74 procedure Resync_Expression
is
82 -- Terminating tokens are those in class Eterm and also RANGE,
83 -- DIGITS or DELTA if not preceded by an apostrophe (if they are
84 -- preceded by an apostrophe, then they are attributes). In addition,
85 -- at the outer parentheses level only, we also consider a comma,
86 -- right parenthesis or vertical bar to terminate an expression.
88 if Token
in Token_Class_Eterm
90 or else (Token
in Token_Class_Atkwd
91 and then Prev_Token
/= Tok_Apostrophe
)
93 or else (Paren_Count
= 0
96 or else Token
= Tok_Right_Paren
97 or else Token
= Tok_Vertical_Bar
))
99 -- A special check: if we stop on the ELSE of OR ELSE or the
100 -- THEN of AND THEN, keep going, because this is not really an
101 -- expression terminator after all. Also, keep going past WITH
102 -- since this can be part of an extension aggregate
104 if (Token
= Tok_Else
and then Prev_Token
= Tok_Or
)
105 or else (Token
= Tok_Then
and then Prev_Token
= Tok_And
)
106 or else Token
= Tok_With
114 if Token
= Tok_Left_Paren
then
115 Paren_Count
:= Paren_Count
+ 1;
117 elsif Token
= Tok_Right_Paren
then
118 Paren_Count
:= Paren_Count
- 1;
122 Scan
; -- past token to be skipped
126 end Resync_Expression
;
132 procedure Resync_Init
is
134 -- The following check makes sure we do not get stuck in an infinite
135 -- loop resynchronizing and getting nowhere. If we are called to do a
136 -- resynchronize and we are exactly at the same point that we left off
137 -- on the last resynchronize call, then we force at least one token to
138 -- be skipped so that we make progress.
140 if Token_Ptr
= Last_Resync_Point
then
141 Scan
; -- to skip at least one token
144 -- Output extra error message if debug R flag is set
147 Error_Msg_SC
("resynchronizing!");
151 ----------------------------------
152 -- Resync_Past_Malformed_Aspect --
153 ----------------------------------
155 procedure Resync_Past_Malformed_Aspect
is
160 -- A comma may separate two aspect specifications, but it may also
161 -- delimit multiple arguments of a single aspect.
163 if Token
= Tok_Comma
then
165 Scan_State
: Saved_Scan_State
;
168 Save_Scan_State
(Scan_State
);
171 -- The identifier following the comma is a valid aspect, the
172 -- current malformed aspect has been successfully skipped.
174 if Token
= Tok_Identifier
175 and then Get_Aspect_Id
(Token_Name
) /= No_Aspect
177 Restore_Scan_State
(Scan_State
);
180 -- The comma is delimiting multiple arguments of an aspect
183 Restore_Scan_State
(Scan_State
);
187 -- An IS signals the last aspect specification when the related
188 -- context is a body.
190 elsif Token
= Tok_Is
then
193 -- A semicolon signals the last aspect specification
195 elsif Token
= Tok_Semicolon
then
198 -- In the case of a mistyped semicolon, any token which follows a
199 -- semicolon signals the last aspect specification.
201 elsif Token
in Token_Class_After_SM
then
210 -- Fall out of loop with resynchronization complete
213 end Resync_Past_Malformed_Aspect
;
215 ---------------------------
216 -- Resync_Past_Semicolon --
217 ---------------------------
219 procedure Resync_Past_Semicolon
is
224 -- Done if we are at a semicolon
226 if Token
= Tok_Semicolon
then
227 Scan
; -- past semicolon
230 -- Done if we are at a token which normally appears only after
231 -- a semicolon. One special glitch is that the keyword private is
232 -- in this category only if it does NOT appear after WITH.
234 elsif Token
in Token_Class_After_SM
235 and then (Token
/= Tok_Private
or else Prev_Token
/= Tok_With
)
239 -- Otherwise keep going
246 -- Fall out of loop with resynchronization complete
249 end Resync_Past_Semicolon
;
251 ----------------------------------------------
252 -- Resync_Past_Semicolon_Or_To_Loop_Or_Then --
253 ----------------------------------------------
255 procedure Resync_Past_Semicolon_Or_To_Loop_Or_Then
is
260 -- Done if at semicolon
262 if Token
= Tok_Semicolon
then
263 Scan
; -- past the semicolon
266 -- Done if we are at a token which normally appears only after
267 -- a semicolon. One special glitch is that the keyword private is
268 -- in this category only if it does NOT appear after WITH.
270 elsif Token
in Token_Class_After_SM
271 and then (Token
/= Tok_Private
or else Prev_Token
/= Tok_With
)
275 -- Done if we are at THEN or LOOP
277 elsif Token
= Tok_Then
or else Token
= Tok_Loop
then
280 -- Otherwise keep going
287 -- Fall out of loop with resynchronization complete
290 end Resync_Past_Semicolon_Or_To_Loop_Or_Then
;
296 procedure Resync_Resume
is
298 -- Save resync point (see special test in Resync_Init)
300 Last_Resync_Point
:= Token_Ptr
;
303 Error_Msg_SC
("resuming here!");
307 ---------------------------
308 -- Resync_Semicolon_List --
309 ---------------------------
311 procedure Resync_Semicolon_List
is
320 or else Token
= Tok_Semicolon
321 or else Token
= Tok_Is
322 or else Token
in Token_Class_After_SM
326 elsif Token
= Tok_Left_Paren
then
327 Paren_Count
:= Paren_Count
+ 1;
329 elsif Token
= Tok_Right_Paren
then
330 if Paren_Count
= 0 then
333 Paren_Count
:= Paren_Count
- 1;
341 end Resync_Semicolon_List
;
343 -------------------------
344 -- Resync_To_Semicolon --
345 -------------------------
347 procedure Resync_To_Semicolon
is
352 -- Done if we are at a semicolon
354 if Token
= Tok_Semicolon
then
357 -- Done if we are at a token which normally appears only after
358 -- a semicolon. One special glitch is that the keyword private is
359 -- in this category only if it does NOT appear after WITH.
361 elsif Token
in Token_Class_After_SM
362 and then (Token
/= Tok_Private
or else Prev_Token
/= Tok_With
)
366 -- Otherwise keep going
373 -- Fall out of loop with resynchronization complete
376 end Resync_To_Semicolon
;
382 procedure Resync_To_When
is
387 -- Done if at semicolon, WHEN or IS
389 if Token
= Tok_Semicolon
390 or else Token
= Tok_When
391 or else Token
= Tok_Is
395 -- Otherwise keep going
402 -- Fall out of loop with resynchronization complete