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);