2016-10-26 François Dumont <fdumont@gcc.gnu.org>
[official-gcc.git] / gcc / ada / par-tchk.adb
blobf9f2ec50ecc1755aa986131a351b2c96fd8d9c30
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-2014, 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 case. If the previous token is a semicolon,
456 -- then there is no way that we can legitimately need another semicolon.
457 -- This could only arise in an situation where an error has already been
458 -- signalled. By simply ignoring the request for a semicolon in this
459 -- case, we avoid some spurious missing semicolon messages.
461 elsif Prev_Token = Tok_Semicolon then
462 return;
464 -- If the current token is | then this is a reasonable place to suggest
465 -- the possibility of a "C" confusion.
467 elsif Token = Tok_Vertical_Bar then
468 Error_Msg_SC -- CODEFIX
469 ("unexpected occurrence of ""'|"", did you mean OR'?");
470 Resync_Past_Semicolon;
471 return;
473 -- Deal with pragma. If pragma is not at start of line, it is considered
474 -- misplaced otherwise we treat it as a normal missing semicolon case.
476 elsif Token = Tok_Pragma and then not Token_Is_At_Start_Of_Line then
477 P_Pragmas_Misplaced;
479 if Token = Tok_Semicolon then
480 Scan;
481 return;
482 end if;
483 end if;
485 -- If none of those tests return, we really have a missing semicolon
487 Error_Msg_AP -- CODEFIX
488 ("|missing "";""");
489 return;
490 end T_Semicolon;
492 ------------
493 -- T_Then --
494 ------------
496 procedure T_Then is
497 begin
498 Check_Token (Tok_Then, AP);
499 end T_Then;
501 ------------
502 -- T_Type --
503 ------------
505 procedure T_Type is
506 begin
507 Check_Token (Tok_Type, BC);
508 end T_Type;
510 -----------
511 -- T_Use --
512 -----------
514 procedure T_Use is
515 begin
516 Check_Token (Tok_Use, SC);
517 end T_Use;
519 ------------
520 -- T_When --
521 ------------
523 procedure T_When is
524 begin
525 Check_Token (Tok_When, SC);
526 end T_When;
528 ------------
529 -- T_With --
530 ------------
532 procedure T_With is
533 begin
534 Check_Token (Tok_With, BC);
535 end T_With;
537 --------------
538 -- TF_Arrow --
539 --------------
541 procedure TF_Arrow is
542 Scan_State : Saved_Scan_State;
544 begin
545 if Token = Tok_Arrow then
546 Scan; -- skip arrow and we are done
548 elsif Token = Tok_Colon_Equal then
549 T_Arrow; -- Let T_Arrow give the message
551 else
552 T_Arrow; -- give missing arrow message
553 Save_Scan_State (Scan_State); -- at start of junk tokens
555 loop
556 if Prev_Token_Ptr < Current_Line_Start
557 or else Token = Tok_Semicolon
558 or else Token = Tok_EOF
559 then
560 Restore_Scan_State (Scan_State); -- to where we were
561 return;
562 end if;
564 Scan; -- continue search
566 if Token = Tok_Arrow then
567 Scan; -- past arrow
568 return;
569 end if;
570 end loop;
571 end if;
572 end TF_Arrow;
574 -----------
575 -- TF_Is --
576 -----------
578 procedure TF_Is is
579 Scan_State : Saved_Scan_State;
581 begin
582 if Token = Tok_Is then
583 T_Is; -- past IS and we are done
585 -- Allow OF or => or = in place of IS (with error message)
587 elsif Token = Tok_Of
588 or else Token = Tok_Arrow
589 or else Token = Tok_Equal
590 then
591 T_Is; -- give missing IS message and skip bad token
593 else
594 T_Is; -- give missing IS message
595 Save_Scan_State (Scan_State); -- at start of junk tokens
597 loop
598 if Prev_Token_Ptr < Current_Line_Start
599 or else Token = Tok_Semicolon
600 or else Token = Tok_EOF
601 then
602 Restore_Scan_State (Scan_State); -- to where we were
603 return;
604 end if;
606 Scan; -- continue search
608 if Token = Tok_Is
609 or else Token = Tok_Of
610 or else Token = Tok_Arrow
611 then
612 Scan; -- past IS or OF or =>
613 return;
614 end if;
615 end loop;
616 end if;
617 end TF_Is;
619 -------------
620 -- TF_Loop --
621 -------------
623 procedure TF_Loop is
624 Scan_State : Saved_Scan_State;
626 begin
627 if Token = Tok_Loop then
628 Scan; -- past LOOP and we are done
630 -- Allow DO or THEN in place of LOOP
632 elsif Token = Tok_Then or else Token = Tok_Do then
633 T_Loop; -- give missing LOOP message
635 else
636 T_Loop; -- give missing LOOP message
637 Save_Scan_State (Scan_State); -- at start of junk tokens
639 loop
640 if Prev_Token_Ptr < Current_Line_Start
641 or else Token = Tok_Semicolon
642 or else Token = Tok_EOF
643 then
644 Restore_Scan_State (Scan_State); -- to where we were
645 return;
646 end if;
648 Scan; -- continue search
650 if Token = Tok_Loop or else Token = Tok_Then then
651 Scan; -- past loop or then (message already generated)
652 return;
653 end if;
654 end loop;
655 end if;
656 end TF_Loop;
658 --------------
659 -- TF_Return--
660 --------------
662 procedure TF_Return is
663 Scan_State : Saved_Scan_State;
665 begin
666 if Token = Tok_Return then
667 Scan; -- skip RETURN and we are done
669 else
670 Error_Msg_SC -- CODEFIX
671 ("missing RETURN");
672 Save_Scan_State (Scan_State); -- at start of junk tokens
674 loop
675 if Prev_Token_Ptr < Current_Line_Start
676 or else Token = Tok_Semicolon
677 or else Token = Tok_EOF
678 then
679 Restore_Scan_State (Scan_State); -- to where we were
680 return;
681 end if;
683 Scan; -- continue search
685 if Token = Tok_Return then
686 Scan; -- past RETURN
687 return;
688 end if;
689 end loop;
690 end if;
691 end TF_Return;
693 ------------------
694 -- TF_Semicolon --
695 ------------------
697 procedure TF_Semicolon is
698 Scan_State : Saved_Scan_State;
700 begin
701 if Token = Tok_Semicolon then
702 T_Semicolon;
703 return;
705 -- An interesting little test here. If the previous token is a
706 -- semicolon, then there is no way that we can legitimately need
707 -- another semicolon. This could only arise in an error situation
708 -- where an error has already been signalled. By simply ignoring
709 -- the request for a semicolon in this case, we avoid some spurious
710 -- missing semicolon messages.
712 elsif Prev_Token = Tok_Semicolon then
713 return;
715 else
716 -- Deal with pragma. If pragma is not at start of line, it is
717 -- considered misplaced otherwise we treat it as a normal
718 -- missing semicolon case.
720 if Token = Tok_Pragma
721 and then not Token_Is_At_Start_Of_Line
722 then
723 P_Pragmas_Misplaced;
725 if Token = Tok_Semicolon then
726 T_Semicolon;
727 return;
728 end if;
729 end if;
731 -- Here we definitely have a missing semicolon, so give message
733 T_Semicolon;
735 -- Scan out junk on rest of line. Scan stops on END keyword, since
736 -- that seems to help avoid cascaded errors.
738 Save_Scan_State (Scan_State); -- at start of junk tokens
740 loop
741 if Prev_Token_Ptr < Current_Line_Start
742 or else Token = Tok_EOF
743 or else Token = Tok_End
744 then
745 Restore_Scan_State (Scan_State); -- to where we were
746 return;
747 end if;
749 Scan; -- continue search
751 if Token = Tok_Semicolon then
752 T_Semicolon;
753 return;
755 elsif Token in Token_Class_After_SM then
756 return;
757 end if;
758 end loop;
759 end if;
760 end TF_Semicolon;
762 -------------
763 -- TF_Then --
764 -------------
766 procedure TF_Then is
767 Scan_State : Saved_Scan_State;
769 begin
770 if Token = Tok_Then then
771 Scan; -- past THEN and we are done
773 else
774 T_Then; -- give missing THEN message
775 Save_Scan_State (Scan_State); -- at start of junk tokens
777 loop
778 if Prev_Token_Ptr < Current_Line_Start
779 or else Token = Tok_Semicolon
780 or else Token = Tok_EOF
781 then
782 Restore_Scan_State (Scan_State); -- to where we were
783 return;
784 end if;
786 Scan; -- continue search
788 if Token = Tok_Then then
789 Scan; -- past THEN
790 return;
791 end if;
792 end loop;
793 end if;
794 end TF_Then;
796 ------------
797 -- TF_Use --
798 ------------
800 procedure TF_Use is
801 Scan_State : Saved_Scan_State;
803 begin
804 if Token = Tok_Use then
805 Scan; -- past USE and we are done
807 else
808 T_Use; -- give USE expected message
809 Save_Scan_State (Scan_State); -- at start of junk tokens
811 loop
812 if Prev_Token_Ptr < Current_Line_Start
813 or else Token = Tok_Semicolon
814 or else Token = Tok_EOF
815 then
816 Restore_Scan_State (Scan_State); -- to where we were
817 return;
818 end if;
820 Scan; -- continue search
822 if Token = Tok_Use then
823 Scan; -- past use
824 return;
825 end if;
826 end loop;
827 end if;
828 end TF_Use;
830 ------------------
831 -- U_Left_Paren --
832 ------------------
834 procedure U_Left_Paren is
835 begin
836 if Token = Tok_Left_Paren then
837 Scan;
838 else
839 Error_Msg_AP -- CODEFIX
840 ("missing ""(""!");
841 end if;
842 end U_Left_Paren;
844 -------------------
845 -- U_Right_Paren --
846 -------------------
848 procedure U_Right_Paren is
849 begin
850 if Token = Tok_Right_Paren then
851 Scan;
852 else
853 Error_Msg_AP -- CODEFIX
854 ("|missing "")""!");
855 end if;
856 end U_Right_Paren;
858 -----------------
859 -- Wrong_Token --
860 -----------------
862 procedure Wrong_Token (T : Token_Type; P : Position) is
863 Missing : constant String := "missing ";
864 Image : constant String := Token_Type'Image (T);
865 Tok_Name : constant String := Image (5 .. Image'Length);
866 M : constant String := Missing & Tok_Name;
868 begin
869 if Token = Tok_Semicolon then
870 Scan;
872 if Token = T then
873 Error_Msg_SP -- CODEFIX
874 ("|extra "";"" ignored");
875 Scan;
876 else
877 Error_Msg_SP (M);
878 end if;
880 elsif Token = Tok_Comma then
881 Scan;
883 if Token = T then
884 Error_Msg_SP -- CODEFIX
885 ("|extra "","" ignored");
886 Scan;
888 else
889 Error_Msg_SP (M);
890 end if;
892 else
893 case P is
894 when SC => Error_Msg_SC (M);
895 when BC => Error_Msg_BC (M);
896 when AP => Error_Msg_AP (M);
897 end case;
898 end if;
899 end Wrong_Token;
901 end Tchk;