PR c++/37276
[official-gcc.git] / gcc / ada / par-tchk.adb
blob6efb1e96697173266b1bc2fb184fb7dc0c69b0ec
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- P A R . T C H K --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 1992-2010, Free Software Foundation, Inc. --
10 -- --
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. --
20 -- --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
23 -- --
24 ------------------------------------------------------------------------------
26 -- Token scan routines
28 -- Error recovery: none of the T_xxx or TF_xxx routines raise Error_Resync
30 separate (Par)
31 package body Tchk is
33 type Position is (SC, BC, AP);
34 -- Specify position of error message (see Error_Msg_SC/BC/AP)
36 -----------------------
37 -- Local Subprograms --
38 -----------------------
40 procedure Check_Token (T : Token_Type; P : Position);
41 pragma Inline (Check_Token);
42 -- Called by T_xx routines to check for reserved keyword token. P is the
43 -- position of the error message if the token is missing (see Wrong_Token)
45 procedure Wrong_Token (T : Token_Type; P : Position);
46 -- Called when scanning a reserved keyword when the keyword is not present.
47 -- T is the token type for the keyword, and P indicates the position to be
48 -- used to place a message relative to the current token if the keyword is
49 -- not located nearby.
51 -----------------
52 -- Check_Token --
53 -----------------
55 procedure Check_Token (T : Token_Type; P : Position) is
56 begin
57 if Token = T then
58 Scan;
59 return;
60 else
61 Wrong_Token (T, P);
62 end if;
63 end Check_Token;
65 -------------
66 -- T_Abort --
67 -------------
69 procedure T_Abort is
70 begin
71 Check_Token (Tok_Abort, SC);
72 end T_Abort;
74 -------------
75 -- T_Arrow --
76 -------------
78 procedure T_Arrow is
79 begin
80 if Token = Tok_Arrow then
81 Scan;
83 -- A little recovery helper, accept then in place of =>
85 elsif Token = Tok_Then then
86 Error_Msg_BC -- CODEFIX
87 ("|THEN should be ""='>""");
88 Scan; -- past THEN used in place of =>
90 elsif Token = Tok_Colon_Equal then
91 Error_Msg_SC -- CODEFIX
92 ("|"":="" should be ""='>""");
93 Scan; -- past := used in place of =>
95 else
96 Error_Msg_AP -- CODEFIX
97 ("missing ""='>""");
98 end if;
99 end T_Arrow;
101 ----------
102 -- T_At --
103 ----------
105 procedure T_At is
106 begin
107 Check_Token (Tok_At, SC);
108 end T_At;
110 ------------
111 -- T_Body --
112 ------------
114 procedure T_Body is
115 begin
116 Check_Token (Tok_Body, BC);
117 end T_Body;
119 -----------
120 -- T_Box --
121 -----------
123 procedure T_Box is
124 begin
125 if Token = Tok_Box then
126 Scan;
127 else
128 Error_Msg_AP -- CODEFIX
129 ("missing ""'<'>""");
130 end if;
131 end T_Box;
133 -------------
134 -- T_Colon --
135 -------------
137 procedure T_Colon is
138 begin
139 if Token = Tok_Colon then
140 Scan;
141 else
142 Error_Msg_AP -- CODEFIX
143 ("missing "":""");
144 end if;
145 end T_Colon;
147 -------------------
148 -- T_Colon_Equal --
149 -------------------
151 procedure T_Colon_Equal is
152 begin
153 if Token = Tok_Colon_Equal then
154 Scan;
156 elsif Token = Tok_Equal then
157 Error_Msg_SC -- CODEFIX
158 ("|""="" should be "":=""");
159 Scan;
161 elsif Token = Tok_Colon then
162 Error_Msg_SC -- CODEFIX
163 ("|"":"" should be "":=""");
164 Scan;
166 elsif Token = Tok_Is then
167 Error_Msg_SC -- CODEFIX
168 ("|IS should be "":=""");
169 Scan;
171 else
172 Error_Msg_AP -- CODEFIX
173 ("missing "":=""");
174 end if;
175 end T_Colon_Equal;
177 -------------
178 -- T_Comma --
179 -------------
181 procedure T_Comma is
182 begin
183 if Token = Tok_Comma then
184 Scan;
186 else
187 if Token = Tok_Pragma then
188 P_Pragmas_Misplaced;
189 end if;
191 if Token = Tok_Comma then
192 Scan;
193 else
194 Error_Msg_AP -- CODEFIX
195 ("missing "",""");
196 end if;
197 end if;
199 if Token = Tok_Pragma then
200 P_Pragmas_Misplaced;
201 end if;
202 end T_Comma;
204 ---------------
205 -- T_Dot_Dot --
206 ---------------
208 procedure T_Dot_Dot is
209 begin
210 if Token = Tok_Dot_Dot then
211 Scan;
212 else
213 Error_Msg_AP -- CODEFIX
214 ("missing ""..""");
215 end if;
216 end T_Dot_Dot;
218 -----------
219 -- T_For --
220 -----------
222 procedure T_For is
223 begin
224 Check_Token (Tok_For, AP);
225 end T_For;
227 -----------------------
228 -- T_Greater_Greater --
229 -----------------------
231 procedure T_Greater_Greater is
232 begin
233 if Token = Tok_Greater_Greater then
234 Scan;
235 else
236 Error_Msg_AP -- CODEFIX
237 ("missing ""'>'>""");
238 end if;
239 end T_Greater_Greater;
241 ------------------
242 -- T_Identifier --
243 ------------------
245 procedure T_Identifier is
246 begin
247 if Token = Tok_Identifier then
248 Scan;
249 elsif Token in Token_Class_Literal then
250 Error_Msg_SC ("identifier expected");
251 Scan;
252 else
253 Error_Msg_AP ("identifier expected");
254 end if;
255 end T_Identifier;
257 ----------
258 -- T_In --
259 ----------
261 procedure T_In is
262 begin
263 Check_Token (Tok_In, AP);
264 end T_In;
266 ----------
267 -- T_Is --
268 ----------
270 procedure T_Is is
271 begin
272 Ignore (Tok_Semicolon);
274 -- If we have IS scan past it
276 if Token = Tok_Is then
277 Scan;
279 -- And ignore any following semicolons
281 Ignore (Tok_Semicolon);
283 -- Allow OF, => or = to substitute for IS with complaint
285 elsif Token = Tok_Arrow then
286 Error_Msg_SC -- CODEFIX
287 ("|""=>"" should be IS");
288 Scan; -- past =>
290 elsif Token = Tok_Of then
291 Error_Msg_SC -- CODEFIX
292 ("|OF should be IS");
293 Scan; -- past OF
295 elsif Token = Tok_Equal then
296 Error_Msg_SC -- CODEFIX
297 ("|""="" should be IS");
298 Scan; -- past =
300 else
301 Wrong_Token (Tok_Is, AP);
302 end if;
304 -- Ignore extra IS keywords
306 while Token = Tok_Is loop
307 Error_Msg_SC -- CODEFIX
308 ("|extra IS ignored");
309 Scan;
310 end loop;
311 end T_Is;
313 ------------------
314 -- T_Left_Paren --
315 ------------------
317 procedure T_Left_Paren is
318 begin
319 if Token = Tok_Left_Paren then
320 Scan;
321 else
322 Error_Msg_AP -- CODEFIX
323 ("missing ""(""");
324 end if;
325 end T_Left_Paren;
327 ------------
328 -- T_Loop --
329 ------------
331 procedure T_Loop is
332 begin
333 if Token = Tok_Do then
334 Error_Msg_SC -- CODEFIX
335 ("LOOP expected");
336 Scan;
337 else
338 Check_Token (Tok_Loop, AP);
339 end if;
340 end T_Loop;
342 -----------
343 -- T_Mod --
344 -----------
346 procedure T_Mod is
347 begin
348 Check_Token (Tok_Mod, AP);
349 end T_Mod;
351 -----------
352 -- T_New --
353 -----------
355 procedure T_New is
356 begin
357 Check_Token (Tok_New, AP);
358 end T_New;
360 ----------
361 -- T_Of --
362 ----------
364 procedure T_Of is
365 begin
366 Check_Token (Tok_Of, AP);
367 end T_Of;
369 ----------
370 -- T_Or --
371 ----------
373 procedure T_Or is
374 begin
375 Check_Token (Tok_Or, AP);
376 end T_Or;
378 ---------------
379 -- T_Private --
380 ---------------
382 procedure T_Private is
383 begin
384 Check_Token (Tok_Private, SC);
385 end T_Private;
387 -------------
388 -- T_Range --
389 -------------
391 procedure T_Range is
392 begin
393 Check_Token (Tok_Range, AP);
394 end T_Range;
396 --------------
397 -- T_Record --
398 --------------
400 procedure T_Record is
401 begin
402 Check_Token (Tok_Record, AP);
403 end T_Record;
405 -------------------
406 -- T_Right_Paren --
407 -------------------
409 procedure T_Right_Paren is
410 begin
411 if Token = Tok_Right_Paren then
412 Scan;
413 else
414 Error_Msg_AP -- CODEFIX
415 ("|missing "")""");
416 end if;
417 end T_Right_Paren;
419 -----------------
420 -- T_Semicolon --
421 -----------------
423 procedure T_Semicolon is
424 begin
426 if Token = Tok_Semicolon then
427 Scan;
429 if Token = Tok_Semicolon then
430 Error_Msg_SC -- CODEFIX
431 ("|extra "";"" ignored");
432 Scan;
433 end if;
435 return;
437 elsif Token = Tok_Colon then
438 Error_Msg_SC -- CODEFIX
439 ("|"":"" should be "";""");
440 Scan;
441 return;
443 elsif Token = Tok_Comma then
444 Error_Msg_SC -- CODEFIX
445 ("|"","" should be "";""");
446 Scan;
447 return;
449 elsif Token = Tok_Dot then
450 Error_Msg_SC -- CODEFIX
451 ("|""."" should be "";""");
452 Scan;
453 return;
455 -- An interesting little kludge here. If the previous token is a
456 -- semicolon, then there is no way that we can legitimately need another
457 -- semicolon. This could only arise in an error situation where an error
458 -- has already been signalled. By simply ignoring the request for a
459 -- semicolon in this case, we avoid some spurious missing semicolon
460 -- messages.
462 elsif Prev_Token = Tok_Semicolon then
463 return;
465 -- If the current token is | then this is a reasonable place to suggest
466 -- the possibility of a "C" confusion.
468 elsif Token = Tok_Vertical_Bar then
469 Error_Msg_SC -- CODEFIX
470 ("unexpected occurrence of ""'|"", did you mean OR'?");
471 Resync_Past_Semicolon;
472 return;
474 -- Deal with pragma. If pragma is not at start of line, it is considered
475 -- misplaced otherwise we treat it as a normal missing semicolon case.
477 elsif Token = Tok_Pragma
478 and then not Token_Is_At_Start_Of_Line
479 then
480 P_Pragmas_Misplaced;
482 if Token = Tok_Semicolon then
483 Scan;
484 return;
485 end if;
486 end if;
488 -- If none of those tests return, we really have a missing semicolon
490 Error_Msg_AP -- CODEFIX
491 ("|missing "";""");
492 return;
493 end T_Semicolon;
495 ------------
496 -- T_Then --
497 ------------
499 procedure T_Then is
500 begin
501 Check_Token (Tok_Then, AP);
502 end T_Then;
504 ------------
505 -- T_Type --
506 ------------
508 procedure T_Type is
509 begin
510 Check_Token (Tok_Type, BC);
511 end T_Type;
513 -----------
514 -- T_Use --
515 -----------
517 procedure T_Use is
518 begin
519 Check_Token (Tok_Use, SC);
520 end T_Use;
522 ------------
523 -- T_When --
524 ------------
526 procedure T_When is
527 begin
528 Check_Token (Tok_When, SC);
529 end T_When;
531 ------------
532 -- T_With --
533 ------------
535 procedure T_With is
536 begin
537 Check_Token (Tok_With, BC);
538 end T_With;
540 --------------
541 -- TF_Arrow --
542 --------------
544 procedure TF_Arrow is
545 Scan_State : Saved_Scan_State;
547 begin
548 if Token = Tok_Arrow then
549 Scan; -- skip arrow and we are done
551 elsif Token = Tok_Colon_Equal then
552 T_Arrow; -- Let T_Arrow give the message
554 else
555 T_Arrow; -- give missing arrow message
556 Save_Scan_State (Scan_State); -- at start of junk tokens
558 loop
559 if Prev_Token_Ptr < Current_Line_Start
560 or else Token = Tok_Semicolon
561 or else Token = Tok_EOF
562 then
563 Restore_Scan_State (Scan_State); -- to where we were!
564 return;
565 end if;
567 Scan; -- continue search!
569 if Token = Tok_Arrow then
570 Scan; -- past arrow
571 return;
572 end if;
573 end loop;
574 end if;
575 end TF_Arrow;
577 -----------
578 -- TF_Is --
579 -----------
581 procedure TF_Is is
582 Scan_State : Saved_Scan_State;
584 begin
585 if Token = Tok_Is then
586 T_Is; -- past IS and we are done
588 -- Allow OF or => or = in place of IS (with error message)
590 elsif Token = Tok_Of
591 or else Token = Tok_Arrow
592 or else Token = Tok_Equal
593 then
594 T_Is; -- give missing IS message and skip bad token
596 else
597 T_Is; -- give missing IS message
598 Save_Scan_State (Scan_State); -- at start of junk tokens
600 loop
601 if Prev_Token_Ptr < Current_Line_Start
602 or else Token = Tok_Semicolon
603 or else Token = Tok_EOF
604 then
605 Restore_Scan_State (Scan_State); -- to where we were!
606 return;
607 end if;
609 Scan; -- continue search!
611 if Token = Tok_Is
612 or else Token = Tok_Of
613 or else Token = Tok_Arrow
614 then
615 Scan; -- past IS or OF or =>
616 return;
617 end if;
618 end loop;
619 end if;
620 end TF_Is;
622 -------------
623 -- TF_Loop --
624 -------------
626 procedure TF_Loop is
627 Scan_State : Saved_Scan_State;
629 begin
630 if Token = Tok_Loop then
631 Scan; -- past LOOP and we are done
633 -- Allow DO or THEN in place of LOOP
635 elsif Token = Tok_Then or else Token = Tok_Do then
636 T_Loop; -- give missing LOOP message
638 else
639 T_Loop; -- give missing LOOP message
640 Save_Scan_State (Scan_State); -- at start of junk tokens
642 loop
643 if Prev_Token_Ptr < Current_Line_Start
644 or else Token = Tok_Semicolon
645 or else Token = Tok_EOF
646 then
647 Restore_Scan_State (Scan_State); -- to where we were!
648 return;
649 end if;
651 Scan; -- continue search!
653 if Token = Tok_Loop or else Token = Tok_Then then
654 Scan; -- past loop or then (message already generated)
655 return;
656 end if;
657 end loop;
658 end if;
659 end TF_Loop;
661 --------------
662 -- TF_Return--
663 --------------
665 procedure TF_Return is
666 Scan_State : Saved_Scan_State;
668 begin
669 if Token = Tok_Return then
670 Scan; -- skip RETURN and we are done
672 else
673 Error_Msg_SC -- CODEFIX
674 ("missing RETURN");
675 Save_Scan_State (Scan_State); -- at start of junk tokens
677 loop
678 if Prev_Token_Ptr < Current_Line_Start
679 or else Token = Tok_Semicolon
680 or else Token = Tok_EOF
681 then
682 Restore_Scan_State (Scan_State); -- to where we were!
683 return;
684 end if;
686 Scan; -- continue search!
688 if Token = Tok_Return then
689 Scan; -- past RETURN
690 return;
691 end if;
692 end loop;
693 end if;
694 end TF_Return;
696 ------------------
697 -- TF_Semicolon --
698 ------------------
700 procedure TF_Semicolon is
701 Scan_State : Saved_Scan_State;
703 begin
704 if Token = Tok_Semicolon then
705 T_Semicolon;
706 return;
708 -- An interesting little kludge here. If the previous token is a
709 -- semicolon, then there is no way that we can legitimately need
710 -- another semicolon. This could only arise in an error situation
711 -- where an error has already been signalled. By simply ignoring
712 -- the request for a semicolon in this case, we avoid some spurious
713 -- missing semicolon messages.
715 elsif Prev_Token = Tok_Semicolon then
716 return;
718 else
719 -- Deal with pragma. If pragma is not at start of line, it is
720 -- considered misplaced otherwise we treat it as a normal
721 -- missing semicolon case.
723 if Token = Tok_Pragma
724 and then not Token_Is_At_Start_Of_Line
725 then
726 P_Pragmas_Misplaced;
728 if Token = Tok_Semicolon then
729 T_Semicolon;
730 return;
731 end if;
732 end if;
734 -- Here we definitely have a missing semicolon, so give message
736 T_Semicolon;
738 -- Scan out junk on rest of line. Scan stops on END keyword, since
739 -- that seems to help avoid cascaded errors.
741 Save_Scan_State (Scan_State); -- at start of junk tokens
743 loop
744 if Prev_Token_Ptr < Current_Line_Start
745 or else Token = Tok_EOF
746 or else Token = Tok_End
747 then
748 Restore_Scan_State (Scan_State); -- to where we were
749 return;
750 end if;
752 Scan; -- continue search
754 if Token = Tok_Semicolon then
755 T_Semicolon;
756 return;
758 elsif Token in Token_Class_After_SM then
759 return;
760 end if;
761 end loop;
762 end if;
763 end TF_Semicolon;
765 -------------
766 -- TF_Then --
767 -------------
769 procedure TF_Then is
770 Scan_State : Saved_Scan_State;
772 begin
773 if Token = Tok_Then then
774 Scan; -- past THEN and we are done
776 else
777 T_Then; -- give missing THEN message
778 Save_Scan_State (Scan_State); -- at start of junk tokens
780 loop
781 if Prev_Token_Ptr < Current_Line_Start
782 or else Token = Tok_Semicolon
783 or else Token = Tok_EOF
784 then
785 Restore_Scan_State (Scan_State); -- to where we were
786 return;
787 end if;
789 Scan; -- continue search!
791 if Token = Tok_Then then
792 Scan; -- past THEN
793 return;
794 end if;
795 end loop;
796 end if;
797 end TF_Then;
799 ------------
800 -- TF_Use --
801 ------------
803 procedure TF_Use is
804 Scan_State : Saved_Scan_State;
806 begin
807 if Token = Tok_Use then
808 Scan; -- past USE and we are done
810 else
811 T_Use; -- give USE expected message
812 Save_Scan_State (Scan_State); -- at start of junk tokens
814 loop
815 if Prev_Token_Ptr < Current_Line_Start
816 or else Token = Tok_Semicolon
817 or else Token = Tok_EOF
818 then
819 Restore_Scan_State (Scan_State); -- to where we were
820 return;
821 end if;
823 Scan; -- continue search!
825 if Token = Tok_Use then
826 Scan; -- past use
827 return;
828 end if;
829 end loop;
830 end if;
831 end TF_Use;
833 ------------------
834 -- U_Left_Paren --
835 ------------------
837 procedure U_Left_Paren is
838 begin
839 if Token = Tok_Left_Paren then
840 Scan;
841 else
842 Error_Msg_AP -- CODEFIX
843 ("missing ""(""!");
844 end if;
845 end U_Left_Paren;
847 -------------------
848 -- U_Right_Paren --
849 -------------------
851 procedure U_Right_Paren is
852 begin
853 if Token = Tok_Right_Paren then
854 Scan;
855 else
856 Error_Msg_AP -- CODEFIX
857 ("|missing "")""!");
858 end if;
859 end U_Right_Paren;
861 -----------------
862 -- Wrong_Token --
863 -----------------
865 procedure Wrong_Token (T : Token_Type; P : Position) is
866 Missing : constant String := "missing ";
867 Image : constant String := Token_Type'Image (T);
868 Tok_Name : constant String := Image (5 .. Image'Length);
869 M : constant String := Missing & Tok_Name;
871 begin
872 if Token = Tok_Semicolon then
873 Scan;
875 if Token = T then
876 Error_Msg_SP -- CODEFIX
877 ("|extra "";"" ignored");
878 Scan;
879 else
880 Error_Msg_SP (M);
881 end if;
883 elsif Token = Tok_Comma then
884 Scan;
886 if Token = T then
887 Error_Msg_SP -- CODEFIX
888 ("|extra "","" ignored");
889 Scan;
891 else
892 Error_Msg_SP (M);
893 end if;
895 else
896 case P is
897 when SC => Error_Msg_SC (M);
898 when BC => Error_Msg_BC (M);
899 when AP => Error_Msg_AP (M);
900 end case;
901 end if;
902 end Wrong_Token;
904 end Tchk;