1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
11 -- Copyright (C) 1992-2001 Free Software Foundation, Inc. --
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. --
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). --
27 ------------------------------------------------------------------------------
29 -- Token scan routines.
31 -- Error recovery: none of the T_xxx or TF_xxx routines raise Error_Resync
36 type Position
is (SC
, BC
, AP
);
37 -- Specify position of error message (see Error_Msg_SC/BC/AP)
39 -----------------------
40 -- Local Subprograms --
41 -----------------------
43 procedure Check_Token
(T
: Token_Type
; P
: Position
);
44 pragma Inline
(Check_Token
);
45 -- Called by T_xx routines to check for reserved keyword token. P is the
46 -- position of the error message if the token is missing (see Wrong_Token)
48 procedure Wrong_Token
(T
: Token_Type
; P
: Position
);
49 -- Called when scanning a reserved keyword when the keyword is not
50 -- present. T is the token type for the keyword, and P indicates the
51 -- position to be used to place a message relative to the current
52 -- token if the keyword is not located nearby.
58 procedure Check_Token
(T
: Token_Type
; P
: Position
) is
74 Check_Token
(Tok_Abort
, SC
);
83 if Token
= Tok_Arrow
then
86 -- A little recovery helper, accept then in place of =>
88 elsif Token
= Tok_Then
then
89 Error_Msg_BC
("missing ""=>""");
90 Scan
; -- past THEN used in place of =>
92 elsif Token
= Tok_Colon_Equal
then
93 Error_Msg_SC
(""":="" should be ""=>""");
94 Scan
; -- past := used in place of =>
97 Error_Msg_AP
("missing ""=>""");
107 Check_Token
(Tok_At
, SC
);
116 Check_Token
(Tok_Body
, BC
);
125 if Token
= Tok_Box
then
128 Error_Msg_AP
("missing ""<>""");
138 if Token
= Tok_Colon
then
141 Error_Msg_AP
("missing "":""");
149 procedure T_Colon_Equal
is
151 if Token
= Tok_Colon_Equal
then
154 elsif Token
= Tok_Equal
then
155 Error_Msg_SC
("""="" should be "":=""");
158 elsif Token
= Tok_Colon
then
159 Error_Msg_SC
(""":"" should be "":=""");
162 elsif Token
= Tok_Is
then
163 Error_Msg_SC
("IS should be "":=""");
167 Error_Msg_AP
("missing "":=""");
177 if Token
= Tok_Comma
then
181 if Token
= Tok_Pragma
then
185 if Token
= Tok_Comma
then
188 Error_Msg_AP
("missing "",""");
192 if Token
= Tok_Pragma
then
201 procedure T_Dot_Dot
is
203 if Token
= Tok_Dot_Dot
then
206 Error_Msg_AP
("missing ""..""");
216 Check_Token
(Tok_For
, AP
);
219 -----------------------
220 -- T_Greater_Greater --
221 -----------------------
223 procedure T_Greater_Greater
is
225 if Token
= Tok_Greater_Greater
then
228 Error_Msg_AP
("missing "">>""");
230 end T_Greater_Greater
;
236 procedure T_Identifier
is
238 if Token
= Tok_Identifier
then
240 elsif Token
in Token_Class_Literal
then
241 Error_Msg_SC
("identifier expected");
244 Error_Msg_AP
("identifier expected");
254 Check_Token
(Tok_In
, AP
);
263 if Token
= Tok_Is
then
266 Ignore
(Tok_Semicolon
);
268 -- Allow OF, => or = to substitute for IS with complaint
270 elsif Token
= Tok_Arrow
271 or else Token
= Tok_Of
272 or else Token
= Tok_Equal
274 Error_Msg_SC
("missing IS");
275 Scan
; -- token used in place of IS
277 Wrong_Token
(Tok_Is
, AP
);
280 while Token
= Tok_Is
loop
281 Error_Msg_SC
("extra IS ignored");
290 procedure T_Left_Paren
is
292 if Token
= Tok_Left_Paren
then
295 Error_Msg_AP
("missing ""(""");
305 if Token
= Tok_Do
then
306 Error_Msg_SC
("LOOP expected");
309 Check_Token
(Tok_Loop
, AP
);
319 Check_Token
(Tok_Mod
, AP
);
328 Check_Token
(Tok_New
, AP
);
337 Check_Token
(Tok_Of
, AP
);
346 Check_Token
(Tok_Or
, AP
);
353 procedure T_Private
is
355 Check_Token
(Tok_Private
, SC
);
364 Check_Token
(Tok_Range
, AP
);
371 procedure T_Record
is
373 Check_Token
(Tok_Record
, AP
);
380 procedure T_Right_Paren
is
382 if Token
= Tok_Right_Paren
then
385 Error_Msg_AP
("missing "")""");
393 procedure T_Semicolon
is
396 if Token
= Tok_Semicolon
then
399 if Token
= Tok_Semicolon
then
400 Error_Msg_SC
("extra "";"" ignored");
404 elsif Token
= Tok_Colon
then
405 Error_Msg_SC
(""":"" should be "";""");
408 elsif Token
= Tok_Comma
then
409 Error_Msg_SC
(""","" should be "";""");
412 elsif Token
= Tok_Dot
then
413 Error_Msg_SC
("""."" should be "";""");
416 -- An interesting little kludge here. If the previous token is a
417 -- semicolon, then there is no way that we can legitimately need
418 -- another semicolon. This could only arise in an error situation
419 -- where an error has already been signalled. By simply ignoring
420 -- the request for a semicolon in this case, we avoid some spurious
421 -- missing semicolon messages.
423 elsif Prev_Token
= Tok_Semicolon
then
426 -- If the current token is | then this is a reasonable
427 -- place to suggest the possibility of a "C" confusion :-)
429 elsif Token
= Tok_Vertical_Bar
then
430 Error_Msg_SC
("unexpected occurrence of ""|"", did you mean OR'?");
431 Resync_Past_Semicolon
;
433 -- Otherwise we really do have a missing semicolon
436 Error_Msg_AP
("missing "";""");
448 Check_Token
(Tok_Then
, AP
);
457 Check_Token
(Tok_Type
, BC
);
466 Check_Token
(Tok_Use
, SC
);
475 Check_Token
(Tok_When
, SC
);
484 Check_Token
(Tok_With
, BC
);
491 procedure TF_Arrow
is
492 Scan_State
: Saved_Scan_State
;
495 if Token
= Tok_Arrow
then
496 Scan
; -- skip arrow and we are done
498 elsif Token
= Tok_Colon_Equal
then
499 T_Arrow
; -- Let T_Arrow give the message
502 T_Arrow
; -- give missing arrow message
503 Save_Scan_State
(Scan_State
); -- at start of junk tokens
506 if Prev_Token_Ptr
< Current_Line_Start
507 or else Token
= Tok_Semicolon
508 or else Token
= Tok_EOF
510 Restore_Scan_State
(Scan_State
); -- to where we were!
514 Scan
; -- continue search!
516 if Token
= Tok_Arrow
then
529 Scan_State
: Saved_Scan_State
;
532 if Token
= Tok_Is
then
533 T_Is
; -- past IS and we are done
535 -- Allow OF or => or = in place of IS (with error message)
538 or else Token
= Tok_Arrow
539 or else Token
= Tok_Equal
541 T_Is
; -- give missing IS message and skip bad token
544 T_Is
; -- give missing IS message
545 Save_Scan_State
(Scan_State
); -- at start of junk tokens
548 if Prev_Token_Ptr
< Current_Line_Start
549 or else Token
= Tok_Semicolon
550 or else Token
= Tok_EOF
552 Restore_Scan_State
(Scan_State
); -- to where we were!
556 Scan
; -- continue search!
559 or else Token
= Tok_Of
560 or else Token
= Tok_Arrow
562 Scan
; -- past IS or OF or =>
574 Scan_State
: Saved_Scan_State
;
577 if Token
= Tok_Loop
then
578 Scan
; -- past LOOP and we are done
580 -- Allow DO or THEN in place of LOOP
582 elsif Token
= Tok_Then
or else Token
= Tok_Do
then
583 T_Loop
; -- give missing LOOP message
586 T_Loop
; -- give missing LOOP message
587 Save_Scan_State
(Scan_State
); -- at start of junk tokens
590 if Prev_Token_Ptr
< Current_Line_Start
591 or else Token
= Tok_Semicolon
592 or else Token
= Tok_EOF
594 Restore_Scan_State
(Scan_State
); -- to where we were!
598 Scan
; -- continue search!
600 if Token
= Tok_Loop
or else Token
= Tok_Then
then
601 Scan
; -- past loop or then (message already generated)
612 procedure TF_Return
is
613 Scan_State
: Saved_Scan_State
;
616 if Token
= Tok_Return
then
617 Scan
; -- skip RETURN and we are done
620 Error_Msg_SC
("missing RETURN");
621 Save_Scan_State
(Scan_State
); -- at start of junk tokens
624 if Prev_Token_Ptr
< Current_Line_Start
625 or else Token
= Tok_Semicolon
626 or else Token
= Tok_EOF
628 Restore_Scan_State
(Scan_State
); -- to where we were!
632 Scan
; -- continue search!
634 if Token
= Tok_Return
then
646 procedure TF_Semicolon
is
647 Scan_State
: Saved_Scan_State
;
650 if Token
= Tok_Semicolon
then
654 -- An interesting little kludge here. If the previous token is a
655 -- semicolon, then there is no way that we can legitimately need
656 -- another semicolon. This could only arise in an error situation
657 -- where an error has already been signalled. By simply ignoring
658 -- the request for a semicolon in this case, we avoid some spurious
659 -- missing semicolon messages.
661 elsif Prev_Token
= Tok_Semicolon
then
665 if Token
= Tok_Pragma
then
668 if Token
= Tok_Semicolon
then
674 T_Semicolon
; -- give missing semicolon message
675 Save_Scan_State
(Scan_State
); -- at start of junk tokens
678 if Prev_Token_Ptr
< Current_Line_Start
679 or else Token
= Tok_EOF
681 Restore_Scan_State
(Scan_State
); -- to where we were
685 Scan
; -- continue search
687 if Token
= Tok_Semicolon
then
691 elsif Token
in Token_Class_After_SM
then
703 Scan_State
: Saved_Scan_State
;
706 if Token
= Tok_Then
then
707 Scan
; -- past THEN and we are done
710 T_Then
; -- give missing THEN message
711 Save_Scan_State
(Scan_State
); -- at start of junk tokens
714 if Prev_Token_Ptr
< Current_Line_Start
715 or else Token
= Tok_Semicolon
716 or else Token
= Tok_EOF
718 Restore_Scan_State
(Scan_State
); -- to where we were
722 Scan
; -- continue search!
724 if Token
= Tok_Then
then
737 Scan_State
: Saved_Scan_State
;
740 if Token
= Tok_Use
then
741 Scan
; -- past USE and we are done
744 T_Use
; -- give USE expected message
745 Save_Scan_State
(Scan_State
); -- at start of junk tokens
748 if Prev_Token_Ptr
< Current_Line_Start
749 or else Token
= Tok_Semicolon
750 or else Token
= Tok_EOF
752 Restore_Scan_State
(Scan_State
); -- to where we were
756 Scan
; -- continue search!
758 if Token
= Tok_Use
then
770 procedure Wrong_Token
(T
: Token_Type
; P
: Position
) is
771 Missing
: constant String := "missing ";
772 Image
: constant String := Token_Type
'Image (T
);
773 Tok_Name
: constant String := Image
(5 .. Image
'Length);
774 M
: String (1 .. Missing
'Length + Tok_Name
'Length);
777 -- Set M to Missing & Tok_Name.
779 M
(1 .. Missing
'Length) := Missing
;
780 M
(Missing
'Length + 1 .. M
'Last) := Tok_Name
;
782 if Token
= Tok_Semicolon
then
786 Error_Msg_SP
("extra "";"" ignored");
792 elsif Token
= Tok_Comma
then
796 Error_Msg_SP
("extra "","" ignored");
805 when SC
=> Error_Msg_SC
(M
);
806 when BC
=> Error_Msg_BC
(M
);
807 when AP
=> Error_Msg_AP
(M
);