1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901
|
------------------------------------------------------------------------------
-- --
-- GNAT COMPILER COMPONENTS --
-- --
-- P A R . T C H K --
-- --
-- B o d y --
-- --
-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
-- ware Foundation; either version 3, or (at your option) any later ver- --
-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
-- for more details. You should have received a copy of the GNU General --
-- Public License distributed with GNAT; see file COPYING3. If not, go to --
-- http://www.gnu.org/licenses for a complete copy of the license. --
-- --
-- GNAT was originally developed by the GNAT team at New York University. --
-- Extensive contributions were provided by Ada Core Technologies Inc. --
-- --
------------------------------------------------------------------------------
-- Token scan routines
-- Error recovery: none of the T_xxx or TF_xxx routines raise Error_Resync
separate (Par)
package body Tchk is
type Position is (SC, BC, AP);
-- Specify position of error message (see Error_Msg_SC/BC/AP)
-----------------------
-- Local Subprograms --
-----------------------
procedure Check_Token (T : Token_Type; P : Position);
pragma Inline (Check_Token);
-- Called by T_xx routines to check for reserved keyword token. P is the
-- position of the error message if the token is missing (see Wrong_Token)
procedure Wrong_Token (T : Token_Type; P : Position);
-- Called when scanning a reserved keyword when the keyword is not present.
-- T is the token type for the keyword, and P indicates the position to be
-- used to place a message relative to the current token if the keyword is
-- not located nearby.
-----------------
-- Check_Token --
-----------------
procedure Check_Token (T : Token_Type; P : Position) is
begin
if Token = T then
Scan;
return;
else
Wrong_Token (T, P);
end if;
end Check_Token;
-------------
-- T_Abort --
-------------
procedure T_Abort is
begin
Check_Token (Tok_Abort, SC);
end T_Abort;
-------------
-- T_Arrow --
-------------
procedure T_Arrow is
begin
if Token = Tok_Arrow then
Scan;
-- A little recovery helper, accept then in place of =>
elsif Token = Tok_Then then
Error_Msg_BC -- CODEFIX
("|THEN should be ""='>""");
Scan; -- past THEN used in place of =>
elsif Token = Tok_Colon_Equal then
Error_Msg_SC -- CODEFIX
("|"":="" should be ""='>""");
Scan; -- past := used in place of =>
else
Error_Msg_AP -- CODEFIX
("missing ""='>""");
end if;
end T_Arrow;
----------
-- T_At --
----------
procedure T_At is
begin
Check_Token (Tok_At, SC);
end T_At;
------------
-- T_Body --
------------
procedure T_Body is
begin
Check_Token (Tok_Body, BC);
end T_Body;
-----------
-- T_Box --
-----------
procedure T_Box is
begin
if Token = Tok_Box then
Scan;
else
Error_Msg_AP -- CODEFIX
("missing ""'<'>""");
end if;
end T_Box;
-------------
-- T_Colon --
-------------
procedure T_Colon is
begin
if Token = Tok_Colon then
Scan;
else
Error_Msg_AP -- CODEFIX
("missing "":""");
end if;
end T_Colon;
-------------------
-- T_Colon_Equal --
-------------------
procedure T_Colon_Equal is
begin
if Token = Tok_Colon_Equal then
Scan;
elsif Token = Tok_Equal then
Error_Msg_SC -- CODEFIX
("|""="" should be "":=""");
Scan;
elsif Token = Tok_Colon then
Error_Msg_SC -- CODEFIX
("|"":"" should be "":=""");
Scan;
elsif Token = Tok_Is then
Error_Msg_SC -- CODEFIX
("|IS should be "":=""");
Scan;
else
Error_Msg_AP -- CODEFIX
("missing "":=""");
end if;
end T_Colon_Equal;
-------------
-- T_Comma --
-------------
procedure T_Comma is
begin
if Token = Tok_Comma then
Scan;
else
if Token = Tok_Pragma then
P_Pragmas_Misplaced;
end if;
if Token = Tok_Comma then
Scan;
else
Error_Msg_AP -- CODEFIX
("missing "",""");
end if;
end if;
if Token = Tok_Pragma then
P_Pragmas_Misplaced;
end if;
end T_Comma;
---------------
-- T_Dot_Dot --
---------------
procedure T_Dot_Dot is
begin
if Token = Tok_Dot_Dot then
Scan;
else
Error_Msg_AP -- CODEFIX
("missing ""..""");
end if;
end T_Dot_Dot;
-----------
-- T_For --
-----------
procedure T_For is
begin
Check_Token (Tok_For, AP);
end T_For;
-----------------------
-- T_Greater_Greater --
-----------------------
procedure T_Greater_Greater is
begin
if Token = Tok_Greater_Greater then
Scan;
else
Error_Msg_AP -- CODEFIX
("missing ""'>'>""");
end if;
end T_Greater_Greater;
------------------
-- T_Identifier --
------------------
procedure T_Identifier is
begin
if Token = Tok_Identifier then
Scan;
elsif Token in Token_Class_Literal then
Error_Msg_SC ("identifier expected");
Scan;
else
Error_Msg_AP ("identifier expected");
end if;
end T_Identifier;
----------
-- T_In --
----------
procedure T_In is
begin
Check_Token (Tok_In, AP);
end T_In;
----------
-- T_Is --
----------
procedure T_Is is
begin
Ignore (Tok_Semicolon);
-- If we have IS scan past it
if Token = Tok_Is then
Scan;
-- And ignore any following semicolons
Ignore (Tok_Semicolon);
-- Allow OF, => or = to substitute for IS with complaint
elsif Token = Tok_Arrow then
Error_Msg_SC -- CODEFIX
("|""=>"" should be IS");
Scan; -- past =>
elsif Token = Tok_Of then
Error_Msg_SC -- CODEFIX
("|OF should be IS");
Scan; -- past OF
elsif Token = Tok_Equal then
Error_Msg_SC -- CODEFIX
("|""="" should be IS");
Scan; -- past =
else
Wrong_Token (Tok_Is, AP);
end if;
-- Ignore extra IS keywords
while Token = Tok_Is loop
Error_Msg_SC -- CODEFIX
("|extra IS ignored");
Scan;
end loop;
end T_Is;
------------------
-- T_Left_Paren --
------------------
procedure T_Left_Paren is
begin
if Token = Tok_Left_Paren then
Scan;
else
Error_Msg_AP -- CODEFIX
("missing ""(""");
end if;
end T_Left_Paren;
------------
-- T_Loop --
------------
procedure T_Loop is
begin
if Token = Tok_Do then
Error_Msg_SC -- CODEFIX
("LOOP expected");
Scan;
else
Check_Token (Tok_Loop, AP);
end if;
end T_Loop;
-----------
-- T_Mod --
-----------
procedure T_Mod is
begin
Check_Token (Tok_Mod, AP);
end T_Mod;
-----------
-- T_New --
-----------
procedure T_New is
begin
Check_Token (Tok_New, AP);
end T_New;
----------
-- T_Of --
----------
procedure T_Of is
begin
Check_Token (Tok_Of, AP);
end T_Of;
----------
-- T_Or --
----------
procedure T_Or is
begin
Check_Token (Tok_Or, AP);
end T_Or;
---------------
-- T_Private --
---------------
procedure T_Private is
begin
Check_Token (Tok_Private, SC);
end T_Private;
-------------
-- T_Range --
-------------
procedure T_Range is
begin
Check_Token (Tok_Range, AP);
end T_Range;
--------------
-- T_Record --
--------------
procedure T_Record is
begin
Check_Token (Tok_Record, AP);
end T_Record;
-------------------
-- T_Right_Paren --
-------------------
procedure T_Right_Paren is
begin
if Token = Tok_Right_Paren then
Scan;
else
Error_Msg_AP -- CODEFIX
("|missing "")""");
end if;
end T_Right_Paren;
-----------------
-- T_Semicolon --
-----------------
procedure T_Semicolon is
begin
if Token = Tok_Semicolon then
Scan;
if Token = Tok_Semicolon then
Error_Msg_SC -- CODEFIX
("|extra "";"" ignored");
Scan;
end if;
return;
elsif Token = Tok_Colon then
Error_Msg_SC -- CODEFIX
("|"":"" should be "";""");
Scan;
return;
elsif Token = Tok_Comma then
Error_Msg_SC -- CODEFIX
("|"","" should be "";""");
Scan;
return;
elsif Token = Tok_Dot then
Error_Msg_SC -- CODEFIX
("|""."" should be "";""");
Scan;
return;
-- An interesting little case. If the previous token is a semicolon,
-- then there is no way that we can legitimately need another semicolon.
-- This could only arise in an situation where an error has already been
-- signalled. By simply ignoring the request for a semicolon in this
-- case, we avoid some spurious missing semicolon messages.
elsif Prev_Token = Tok_Semicolon then
return;
-- If the current token is | then this is a reasonable place to suggest
-- the possibility of a "C" confusion.
elsif Token = Tok_Vertical_Bar then
Error_Msg_SC -- CODEFIX
("unexpected occurrence of ""'|"", did you mean OR'?");
Resync_Past_Semicolon;
return;
-- Deal with pragma. If pragma is not at start of line, it is considered
-- misplaced otherwise we treat it as a normal missing semicolon case.
elsif Token = Tok_Pragma and then not Token_Is_At_Start_Of_Line then
P_Pragmas_Misplaced;
if Token = Tok_Semicolon then
Scan;
return;
end if;
end if;
-- If none of those tests return, we really have a missing semicolon
Error_Msg_AP -- CODEFIX
("|missing "";""");
return;
end T_Semicolon;
------------
-- T_Then --
------------
procedure T_Then is
begin
Check_Token (Tok_Then, AP);
end T_Then;
------------
-- T_Type --
------------
procedure T_Type is
begin
Check_Token (Tok_Type, BC);
end T_Type;
-----------
-- T_Use --
-----------
procedure T_Use is
begin
Check_Token (Tok_Use, SC);
end T_Use;
------------
-- T_When --
------------
procedure T_When is
begin
Check_Token (Tok_When, SC);
end T_When;
------------
-- T_With --
------------
procedure T_With is
begin
Check_Token (Tok_With, BC);
end T_With;
--------------
-- TF_Arrow --
--------------
procedure TF_Arrow is
Scan_State : Saved_Scan_State;
begin
if Token = Tok_Arrow then
Scan; -- skip arrow and we are done
elsif Token = Tok_Colon_Equal then
T_Arrow; -- Let T_Arrow give the message
else
T_Arrow; -- give missing arrow message
Save_Scan_State (Scan_State); -- at start of junk tokens
loop
if Prev_Token_Ptr < Current_Line_Start
or else Token = Tok_Semicolon
or else Token = Tok_EOF
then
Restore_Scan_State (Scan_State); -- to where we were
return;
end if;
Scan; -- continue search
if Token = Tok_Arrow then
Scan; -- past arrow
return;
end if;
end loop;
end if;
end TF_Arrow;
-----------
-- TF_Is --
-----------
procedure TF_Is is
Scan_State : Saved_Scan_State;
begin
if Token = Tok_Is then
T_Is; -- past IS and we are done
-- Allow OF or => or = in place of IS (with error message)
elsif Token = Tok_Of
or else Token = Tok_Arrow
or else Token = Tok_Equal
then
T_Is; -- give missing IS message and skip bad token
else
T_Is; -- give missing IS message
Save_Scan_State (Scan_State); -- at start of junk tokens
loop
if Prev_Token_Ptr < Current_Line_Start
or else Token = Tok_Semicolon
or else Token = Tok_EOF
then
Restore_Scan_State (Scan_State); -- to where we were
return;
end if;
Scan; -- continue search
if Token = Tok_Is
or else Token = Tok_Of
or else Token = Tok_Arrow
then
Scan; -- past IS or OF or =>
return;
end if;
end loop;
end if;
end TF_Is;
-------------
-- TF_Loop --
-------------
procedure TF_Loop is
Scan_State : Saved_Scan_State;
begin
if Token = Tok_Loop then
Scan; -- past LOOP and we are done
-- Allow DO or THEN in place of LOOP
elsif Token = Tok_Then or else Token = Tok_Do then
T_Loop; -- give missing LOOP message
else
T_Loop; -- give missing LOOP message
Save_Scan_State (Scan_State); -- at start of junk tokens
loop
if Prev_Token_Ptr < Current_Line_Start
or else Token = Tok_Semicolon
or else Token = Tok_EOF
then
Restore_Scan_State (Scan_State); -- to where we were
return;
end if;
Scan; -- continue search
if Token = Tok_Loop or else Token = Tok_Then then
Scan; -- past loop or then (message already generated)
return;
end if;
end loop;
end if;
end TF_Loop;
--------------
-- TF_Return--
--------------
procedure TF_Return is
Scan_State : Saved_Scan_State;
begin
if Token = Tok_Return then
Scan; -- skip RETURN and we are done
else
Error_Msg_SC -- CODEFIX
("missing RETURN");
Save_Scan_State (Scan_State); -- at start of junk tokens
loop
if Prev_Token_Ptr < Current_Line_Start
or else Token = Tok_Semicolon
or else Token = Tok_EOF
then
Restore_Scan_State (Scan_State); -- to where we were
return;
end if;
Scan; -- continue search
if Token = Tok_Return then
Scan; -- past RETURN
return;
end if;
end loop;
end if;
end TF_Return;
------------------
-- TF_Semicolon --
------------------
procedure TF_Semicolon is
Scan_State : Saved_Scan_State;
begin
if Token = Tok_Semicolon then
T_Semicolon;
return;
-- An interesting little test here. If the previous token is a
-- semicolon, then there is no way that we can legitimately need
-- another semicolon. This could only arise in an error situation
-- where an error has already been signalled. By simply ignoring
-- the request for a semicolon in this case, we avoid some spurious
-- missing semicolon messages.
elsif Prev_Token = Tok_Semicolon then
return;
else
-- Deal with pragma. If pragma is not at start of line, it is
-- considered misplaced otherwise we treat it as a normal
-- missing semicolon case.
if Token = Tok_Pragma
and then not Token_Is_At_Start_Of_Line
then
P_Pragmas_Misplaced;
if Token = Tok_Semicolon then
T_Semicolon;
return;
end if;
end if;
-- Here we definitely have a missing semicolon, so give message
T_Semicolon;
-- Scan out junk on rest of line. Scan stops on END keyword, since
-- that seems to help avoid cascaded errors.
Save_Scan_State (Scan_State); -- at start of junk tokens
loop
if Prev_Token_Ptr < Current_Line_Start
or else Token = Tok_EOF
or else Token = Tok_End
then
Restore_Scan_State (Scan_State); -- to where we were
return;
end if;
Scan; -- continue search
if Token = Tok_Semicolon then
T_Semicolon;
return;
elsif Token in Token_Class_After_SM then
return;
end if;
end loop;
end if;
end TF_Semicolon;
-------------
-- TF_Then --
-------------
procedure TF_Then is
Scan_State : Saved_Scan_State;
begin
if Token = Tok_Then then
Scan; -- past THEN and we are done
else
T_Then; -- give missing THEN message
Save_Scan_State (Scan_State); -- at start of junk tokens
loop
if Prev_Token_Ptr < Current_Line_Start
or else Token = Tok_Semicolon
or else Token = Tok_EOF
then
Restore_Scan_State (Scan_State); -- to where we were
return;
end if;
Scan; -- continue search
if Token = Tok_Then then
Scan; -- past THEN
return;
end if;
end loop;
end if;
end TF_Then;
------------
-- TF_Use --
------------
procedure TF_Use is
Scan_State : Saved_Scan_State;
begin
if Token = Tok_Use then
Scan; -- past USE and we are done
else
T_Use; -- give USE expected message
Save_Scan_State (Scan_State); -- at start of junk tokens
loop
if Prev_Token_Ptr < Current_Line_Start
or else Token = Tok_Semicolon
or else Token = Tok_EOF
then
Restore_Scan_State (Scan_State); -- to where we were
return;
end if;
Scan; -- continue search
if Token = Tok_Use then
Scan; -- past use
return;
end if;
end loop;
end if;
end TF_Use;
------------------
-- U_Left_Paren --
------------------
procedure U_Left_Paren is
begin
if Token = Tok_Left_Paren then
Scan;
else
Error_Msg_AP -- CODEFIX
("missing ""(""!");
end if;
end U_Left_Paren;
-------------------
-- U_Right_Paren --
-------------------
procedure U_Right_Paren is
begin
if Token = Tok_Right_Paren then
Scan;
else
Error_Msg_AP -- CODEFIX
("|missing "")""!");
end if;
end U_Right_Paren;
-----------------
-- Wrong_Token --
-----------------
procedure Wrong_Token (T : Token_Type; P : Position) is
Missing : constant String := "missing ";
Image : constant String := Token_Type'Image (T);
Tok_Name : constant String := Image (5 .. Image'Length);
M : constant String := Missing & Tok_Name;
begin
if Token = Tok_Semicolon then
Scan;
if Token = T then
Error_Msg_SP -- CODEFIX
("|extra "";"" ignored");
Scan;
else
Error_Msg_SP (M);
end if;
elsif Token = Tok_Comma then
Scan;
if Token = T then
Error_Msg_SP -- CODEFIX
("|extra "","" ignored");
Scan;
else
Error_Msg_SP (M);
end if;
else
case P is
when SC => Error_Msg_SC (M);
when BC => Error_Msg_BC (M);
when AP => Error_Msg_AP (M);
end case;
end if;
end Wrong_Token;
end Tchk;
|