OSDN Git Service

2007-09-26 Thomas Quinot <quinot@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / ada / par-util.adb
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                         GNAT COMPILER COMPONENTS                         --
4 --                                                                          --
5 --                             P A R . U T I L                              --
6 --                                                                          --
7 --                                 B o d y                                  --
8 --                                                                          --
9 --          Copyright (C) 1992-2007, 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 ------------------------------------------------------------------------------
25
26 with Csets;   use Csets;
27 with Stylesw; use Stylesw;
28 with Uintp;   use Uintp;
29
30 with GNAT.Spelling_Checker; use GNAT.Spelling_Checker;
31
32 separate (Par)
33 package body Util is
34
35    ---------------------
36    -- Bad_Spelling_Of --
37    ---------------------
38
39    function Bad_Spelling_Of (T : Token_Type) return Boolean is
40       Tname : constant String := Token_Type'Image (T);
41       --  Characters of token name
42
43       S : String (1 .. Tname'Last - 4);
44       --  Characters of token name folded to lower case, omitting TOK_ at start
45
46       M1 : String (1 .. 42) := "incorrect spelling of keyword ************";
47       M2 : String (1 .. 44) := "illegal abbreviation of keyword ************";
48       --  Buffers used to construct error message
49
50       P1 : constant := 30;
51       P2 : constant := 32;
52       --  Starting subscripts in M1, M2 for keyword name
53
54       SL : constant Natural := S'Length;
55       --  Length of expected token name excluding TOK_ at start
56
57    begin
58       if Token /= Tok_Identifier then
59          return False;
60       end if;
61
62       for J in S'Range loop
63          S (J) := Fold_Lower (Tname (J + 4));
64       end loop;
65
66       Get_Name_String (Token_Name);
67
68       --  A special check for case of PROGRAM used for PROCEDURE
69
70       if T = Tok_Procedure
71         and then Name_Len = 7
72         and then Name_Buffer (1 .. 7) = "program"
73       then
74          Error_Msg_SC ("PROCEDURE expected");
75          Token := T;
76          return True;
77
78       --  A special check for an illegal abbrevation
79
80       elsif Name_Len < S'Length
81         and then Name_Len >= 4
82         and then Name_Buffer (1 .. Name_Len) = S (1 .. Name_Len)
83       then
84          for J in 1 .. S'Last loop
85             M2 (P2 + J - 1) := Fold_Upper (S (J));
86          end loop;
87
88          Error_Msg_SC (M2 (1 .. P2 - 1 + S'Last));
89          Token := T;
90          return True;
91       end if;
92
93       --  Now we go into the full circuit to check for a misspelling
94
95       --  Never consider something a misspelling if either the actual or
96       --  expected string is less than 3 characters (before this check we
97       --  used to consider i to be a misspelled if in some cases!)
98
99       if SL < 3 or else Name_Len < 3 then
100          return False;
101
102       --  Special case: prefix matches, i.e. the leading characters of the
103       --  token that we have exactly match the required keyword. If there
104       --  are at least two characters left over, assume that we have a case
105       --  of two keywords joined together which should not be joined.
106
107       elsif Name_Len > SL + 1
108         and then S = Name_Buffer (1 .. SL)
109       then
110          Scan_Ptr := Token_Ptr + S'Length;
111          Error_Msg_S ("missing space");
112          Token := T;
113          return True;
114       end if;
115
116       if Is_Bad_Spelling_Of (Name_Buffer (1 .. Name_Len), S) then
117          for J in 1 .. S'Last loop
118             M1 (P1 + J - 1) := Fold_Upper (S (J));
119          end loop;
120
121          Error_Msg_SC (M1 (1 .. P1 - 1 + S'Last));
122          Token := T;
123          return True;
124
125       else
126          return False;
127       end if;
128    end Bad_Spelling_Of;
129
130    ----------------------
131    -- Check_95_Keyword --
132    ----------------------
133
134    --  On entry, the caller has checked that current token is an identifier
135    --  whose name matches the name of the 95 keyword New_Tok.
136
137    procedure Check_95_Keyword (Token_95, Next : Token_Type) is
138       Scan_State : Saved_Scan_State;
139
140    begin
141       Save_Scan_State (Scan_State); -- at identifier/keyword
142       Scan; -- past identifier/keyword
143
144       if Token = Next then
145          Restore_Scan_State (Scan_State); -- to identifier
146          Error_Msg_Name_1 := Token_Name;
147          Error_Msg_SC ("(Ada 83) keyword* cannot be used!");
148          Token := Token_95;
149       else
150          Restore_Scan_State (Scan_State); -- to identifier
151       end if;
152    end Check_95_Keyword;
153
154    ----------------------
155    -- Check_Bad_Layout --
156    ----------------------
157
158    procedure Check_Bad_Layout is
159    begin
160       if Style.RM_Column_Check and then Token_Is_At_Start_Of_Line
161         and then Start_Column <= Scope.Table (Scope.Last).Ecol
162       then
163          Error_Msg_BC ("(style) incorrect layout");
164       end if;
165    end Check_Bad_Layout;
166
167    --------------------------
168    -- Check_Misspelling_Of --
169    --------------------------
170
171    procedure Check_Misspelling_Of (T : Token_Type) is
172    begin
173       if Bad_Spelling_Of (T) then
174          null;
175       end if;
176    end Check_Misspelling_Of;
177
178    --------------------------
179    -- Check_No_Right_Paren --
180    --------------------------
181
182    procedure Check_No_Right_Paren is
183    begin
184       if Token = Tok_Right_Paren then
185          Error_Msg_SC ("unexpected right parenthesis");
186          Scan; -- past unexpected right paren
187       end if;
188    end Check_No_Right_Paren;
189
190    -----------------------------
191    -- Check_Simple_Expression --
192    -----------------------------
193
194    procedure Check_Simple_Expression (E : Node_Id) is
195    begin
196       if Expr_Form = EF_Non_Simple then
197          Error_Msg_N ("this expression must be parenthesized", E);
198       end if;
199    end Check_Simple_Expression;
200
201    ---------------------------------------
202    -- Check_Simple_Expression_In_Ada_83 --
203    ---------------------------------------
204
205    procedure Check_Simple_Expression_In_Ada_83 (E : Node_Id) is
206    begin
207       if Expr_Form = EF_Non_Simple then
208          if Ada_Version = Ada_83 then
209             Error_Msg_N ("(Ada 83) this expression must be parenthesized!", E);
210          end if;
211       end if;
212    end Check_Simple_Expression_In_Ada_83;
213
214    ------------------------
215    -- Check_Subtype_Mark --
216    ------------------------
217
218    function Check_Subtype_Mark (Mark : Node_Id) return Node_Id is
219    begin
220       if Nkind (Mark) = N_Identifier
221         or else Nkind (Mark) = N_Selected_Component
222         or else (Nkind (Mark) = N_Attribute_Reference
223                   and then Is_Type_Attribute_Name (Attribute_Name (Mark)))
224         or else Mark = Error
225       then
226          return Mark;
227       else
228          Error_Msg ("subtype mark expected", Sloc (Mark));
229          return Error;
230       end if;
231    end Check_Subtype_Mark;
232
233    -------------------
234    -- Comma_Present --
235    -------------------
236
237    function Comma_Present return Boolean is
238       Scan_State  : Saved_Scan_State;
239       Paren_Count : Nat;
240
241    begin
242       --  First check, if a comma is present, then a comma is present!
243
244       if Token = Tok_Comma then
245          T_Comma;
246          return True;
247
248       --  If we have a right paren, then that is taken as ending the list
249       --  i.e. no comma is present.
250
251       elsif Token = Tok_Right_Paren then
252          return False;
253
254       --  If pragmas, then get rid of them and make a recursive call
255       --  to process what follows these pragmas.
256
257       elsif Token = Tok_Pragma then
258          P_Pragmas_Misplaced;
259          return Comma_Present;
260
261       --  At this stage we have an error, and the goal is to decide on whether
262       --  or not we should diagnose an error and report a (non-existent)
263       --  comma as being present, or simply to report no comma is present
264
265       --  If we are a semicolon, then the question is whether we have a missing
266       --  right paren, or whether the semicolon should have been a comma. To
267       --  guess the right answer, we scan ahead keeping track of the paren
268       --  level, looking for a clue that helps us make the right decision.
269
270       --  This approach is highly accurate in the single error case, and does
271       --  not make bad mistakes in the multiple error case (indeed we can't
272       --  really make a very bad decision at this point in any case).
273
274       elsif Token = Tok_Semicolon then
275          Save_Scan_State (Scan_State);
276          Scan; -- past semicolon
277
278          --  Check for being followed by identifier => which almost certainly
279          --  means we are still in a parameter list and the comma should have
280          --  been a semicolon (such a sequence could not follow a semicolon)
281
282          if Token = Tok_Identifier then
283             Scan;
284
285             if Token = Tok_Arrow then
286                goto Assume_Comma;
287             end if;
288          end if;
289
290          --  If that test didn't work, loop ahead looking for a comma or
291          --  semicolon at the same parenthesis level. Always remember that
292          --  we can't go badly wrong in an error situation like this!
293
294          Paren_Count := 0;
295
296          --  Here is the look ahead loop, Paren_Count tells us whether the
297          --  token we are looking at is at the same paren level as the
298          --  suspicious semicolon that we are trying to figure out.
299
300          loop
301
302             --  If we hit another semicolon or an end of file, and we have
303             --  not seen a right paren or another comma on the way, then
304             --  probably the semicolon did end the list. Indeed that is
305             --  certainly the only single error correction possible here.
306
307             if Token = Tok_Semicolon or else Token = Tok_EOF then
308                Restore_Scan_State (Scan_State);
309                return False;
310
311             --  A comma at the same paren level as the semicolon is a strong
312             --  indicator that the semicolon should have been a comma, indeed
313             --  again this is the only possible single error correction.
314
315             elsif Token = Tok_Comma then
316                exit when Paren_Count = 0;
317
318             --  A left paren just bumps the paren count
319
320             elsif Token = Tok_Left_Paren then
321                Paren_Count := Paren_Count + 1;
322
323             --  A right paren that is at the same paren level as the semicolon
324             --  also means that the only possible single error correction is
325             --  to assume that the semicolon should have been a comma. If we
326             --  are not at the same paren level, then adjust the paren level.
327
328             elsif Token = Tok_Right_Paren then
329                exit when Paren_Count = 0;
330                Paren_Count := Paren_Count - 1;
331             end if;
332
333             --  Keep going, we haven't made a decision yet
334
335             Scan;
336          end loop;
337
338          --  If we fall through the loop, it means that we found a terminating
339          --  right paren or another comma. In either case it is reasonable to
340          --  assume that the semicolon was really intended to be a comma. Also
341          --  come here for the identifier arrow case.
342
343          <<Assume_Comma>>
344             Restore_Scan_State (Scan_State);
345             Error_Msg_SC (""";"" illegal here, replaced by "",""");
346             Scan; -- past the semicolon
347             return True;
348
349       --  If we are not at semicolon or a right paren, then we base the
350       --  decision on whether or not the next token can be part of an
351       --  expression. If not, then decide that no comma is present (the
352       --  caller will eventually generate a missing right parent message)
353
354       elsif Token in Token_Class_Eterm then
355          return False;
356
357       --  Otherwise we assume a comma is present, even if none is present,
358       --  since the next token must be part of an expression, so if we were
359       --  at the end of the list, then there is more than one error present.
360
361       else
362          T_Comma; -- to give error
363          return True;
364       end if;
365    end Comma_Present;
366
367    -----------------------
368    -- Discard_Junk_List --
369    -----------------------
370
371    procedure Discard_Junk_List (L : List_Id) is
372       pragma Warnings (Off, L);
373    begin
374       null;
375    end Discard_Junk_List;
376
377    -----------------------
378    -- Discard_Junk_Node --
379    -----------------------
380
381    procedure Discard_Junk_Node (N : Node_Id) is
382       pragma Warnings (Off, N);
383    begin
384       null;
385    end Discard_Junk_Node;
386
387    ------------
388    -- Ignore --
389    ------------
390
391    procedure Ignore (T : Token_Type) is
392    begin
393       if Token = T then
394          if T = Tok_Comma then
395             Error_Msg_SC ("unexpected "","" ignored");
396
397          elsif T = Tok_Left_Paren then
398             Error_Msg_SC ("unexpected ""("" ignored");
399
400          elsif T = Tok_Right_Paren then
401             Error_Msg_SC ("unexpected "")"" ignored");
402
403          elsif T = Tok_Semicolon then
404             Error_Msg_SC ("unexpected "";"" ignored");
405
406          else
407             declare
408                Tname : constant String := Token_Type'Image (Token);
409                Msg   : String := "unexpected keyword ????????????????????????";
410
411             begin
412                --  Loop to copy characters of keyword name (ignoring Tok_)
413
414                for J in 5 .. Tname'Last loop
415                   Msg (J + 14) := Fold_Upper (Tname (J));
416                end loop;
417
418                Msg (Tname'Last + 15 .. Tname'Last + 22) := " ignored";
419                Error_Msg_SC (Msg (1 .. Tname'Last + 22));
420             end;
421          end if;
422
423          Scan; -- Scan past ignored token
424       end if;
425    end Ignore;
426
427    ----------------------------
428    -- Is_Reserved_Identifier --
429    ----------------------------
430
431    function Is_Reserved_Identifier (C : Id_Check := None) return Boolean is
432    begin
433       if not Is_Reserved_Keyword (Token) then
434          return False;
435
436       else
437          declare
438             Ident_Casing : constant Casing_Type :=
439                              Identifier_Casing (Current_Source_File);
440
441             Key_Casing   : constant Casing_Type :=
442                              Keyword_Casing (Current_Source_File);
443
444          begin
445             --  If the casing of identifiers and keywords is different in
446             --  this source file, and the casing of this token matches the
447             --  keyword casing, then we return False, since it is pretty
448             --  clearly intended to be a keyword.
449
450             if Ident_Casing = Unknown
451               or else Key_Casing = Unknown
452               or else Ident_Casing = Key_Casing
453               or else Determine_Token_Casing /= Key_Casing
454             then
455                return True;
456
457             --  Here we have a keyword written clearly with keyword casing.
458             --  In default mode, we would not be willing to consider this as
459             --  a reserved identifier, but if C is set, we may still accept it
460
461             elsif C /= None then
462                declare
463                   Scan_State  : Saved_Scan_State;
464                   OK_Next_Tok : Boolean;
465
466                begin
467                   Save_Scan_State (Scan_State);
468                   Scan;
469
470                   if Token_Is_At_Start_Of_Line then
471                      return False;
472                   end if;
473
474                   case C is
475                      when None =>
476                         raise Program_Error;
477
478                      when C_Comma_Right_Paren =>
479                         OK_Next_Tok :=
480                           Token = Tok_Comma or else Token = Tok_Right_Paren;
481
482                      when C_Comma_Colon =>
483                         OK_Next_Tok :=
484                           Token = Tok_Comma or else Token = Tok_Colon;
485
486                      when C_Do =>
487                         OK_Next_Tok :=
488                           Token = Tok_Do;
489
490                      when C_Dot =>
491                         OK_Next_Tok :=
492                           Token = Tok_Dot;
493
494                      when C_Greater_Greater =>
495                         OK_Next_Tok :=
496                           Token = Tok_Greater_Greater;
497
498                      when C_In =>
499                         OK_Next_Tok :=
500                           Token = Tok_In;
501
502                      when C_Is =>
503                         OK_Next_Tok :=
504                           Token = Tok_Is;
505
506                      when C_Left_Paren_Semicolon =>
507                         OK_Next_Tok :=
508                           Token = Tok_Left_Paren or else Token = Tok_Semicolon;
509
510                      when C_Use =>
511                         OK_Next_Tok :=
512                           Token = Tok_Use;
513
514                      when C_Vertical_Bar_Arrow =>
515                         OK_Next_Tok :=
516                           Token = Tok_Vertical_Bar or else Token = Tok_Arrow;
517                   end case;
518
519                   Restore_Scan_State (Scan_State);
520
521                   if OK_Next_Tok then
522                      return True;
523                   end if;
524                end;
525             end if;
526          end;
527       end if;
528
529       --  If we fall through it is not a reserved identifier
530
531       return False;
532    end Is_Reserved_Identifier;
533
534    ----------------------
535    -- Merge_Identifier --
536    ----------------------
537
538    procedure Merge_Identifier (Prev : Node_Id; Nxt : Token_Type) is
539    begin
540       if Token /= Tok_Identifier then
541          return;
542       end if;
543
544       declare
545          S : Saved_Scan_State;
546          T : Token_Type;
547
548       begin
549          Save_Scan_State (S);
550          Scan;
551          T := Token;
552          Restore_Scan_State (S);
553
554          if T /= Nxt then
555             return;
556          end if;
557       end;
558
559       --  Check exactly one space between identifiers
560
561       if Source (Token_Ptr - 1) /= ' '
562         or else Int (Token_Ptr) /=
563                   Int (Prev_Token_Ptr) + Length_Of_Name (Chars (Prev)) + 1
564       then
565          return;
566       end if;
567
568       --  Do the merge
569
570       Get_Name_String (Chars (Token_Node));
571
572       declare
573          Buf : constant String (1 .. Name_Len) :=
574                  Name_Buffer (1 .. Name_Len);
575
576       begin
577          Get_Name_String (Chars (Prev));
578          Add_Char_To_Name_Buffer ('_');
579          Add_Str_To_Name_Buffer (Buf);
580          Set_Chars (Prev, Name_Find);
581       end;
582
583       Error_Msg_Node_1 := Prev;
584       Error_Msg_SC
585         ("unexpected identifier, possibly & was meant here");
586       Scan;
587    end Merge_Identifier;
588
589    -------------------
590    -- No_Constraint --
591    -------------------
592
593    procedure No_Constraint is
594    begin
595       if Token in Token_Class_Consk then
596          Error_Msg_SC ("constraint not allowed here");
597          Discard_Junk_Node (P_Constraint_Opt);
598       end if;
599    end No_Constraint;
600
601    ---------------------
602    -- Pop_Scope_Stack --
603    ---------------------
604
605    procedure Pop_Scope_Stack is
606    begin
607       pragma Assert (Scope.Last > 0);
608       Scope.Decrement_Last;
609
610       if Debug_Flag_P then
611          Error_Msg_Uint_1 := UI_From_Int (Scope.Last);
612          Error_Msg_SC ("decrement scope stack ptr, new value = ^!");
613       end if;
614    end Pop_Scope_Stack;
615
616    ----------------------
617    -- Push_Scope_Stack --
618    ----------------------
619
620    procedure Push_Scope_Stack is
621    begin
622       Scope.Increment_Last;
623
624       if Style_Check_Max_Nesting_Level
625         and then Scope.Last = Style_Max_Nesting_Level + 1
626       then
627          Error_Msg
628            ("(style) maximum nesting level exceeded",
629             First_Non_Blank_Location);
630       end if;
631
632       Scope.Table (Scope.Last).Junk := False;
633       Scope.Table (Scope.Last).Node := Empty;
634
635       if Debug_Flag_P then
636          Error_Msg_Uint_1 := UI_From_Int (Scope.Last);
637          Error_Msg_SC ("increment scope stack ptr, new value = ^!");
638       end if;
639    end Push_Scope_Stack;
640
641    ----------------------
642    -- Separate_Present --
643    ----------------------
644
645    function Separate_Present return Boolean is
646       Scan_State : Saved_Scan_State;
647
648    begin
649       if Token = Tok_Separate then
650          return True;
651
652       elsif Token /= Tok_Identifier then
653          return False;
654
655       else
656          Save_Scan_State (Scan_State);
657          Scan; -- past identifier
658
659          if Token = Tok_Semicolon then
660             Restore_Scan_State (Scan_State);
661             return Bad_Spelling_Of (Tok_Separate);
662
663          else
664             Restore_Scan_State (Scan_State);
665             return False;
666          end if;
667       end if;
668    end Separate_Present;
669
670    --------------------------
671    -- Signal_Bad_Attribute --
672    --------------------------
673
674    procedure Signal_Bad_Attribute is
675    begin
676       Error_Msg_N ("unrecognized attribute&", Token_Node);
677
678       --  Check for possible misspelling
679
680       Get_Name_String (Token_Name);
681
682       declare
683          AN : constant String := Name_Buffer (1 .. Name_Len);
684
685       begin
686          Error_Msg_Name_1 := First_Attribute_Name;
687          while Error_Msg_Name_1 <= Last_Attribute_Name loop
688             Get_Name_String (Error_Msg_Name_1);
689
690             if Is_Bad_Spelling_Of
691                  (AN, Name_Buffer (1 .. Name_Len))
692             then
693                Error_Msg_N
694                  ("\possible misspelling of %", Token_Node);
695                exit;
696             end if;
697
698             Error_Msg_Name_1 := Error_Msg_Name_1 + 1;
699          end loop;
700       end;
701    end Signal_Bad_Attribute;
702
703    -----------------------------
704    -- Token_Is_At_End_Of_Line --
705    -----------------------------
706
707    function Token_Is_At_End_Of_Line return Boolean is
708       S : Source_Ptr;
709
710    begin
711       --  Skip past blanks and horizontal tabs
712
713       S := Scan_Ptr;
714       while Source (S) = ' ' or else Source (S) = ASCII.HT loop
715          S := S + 1;
716       end loop;
717
718       --  We are at end of line if at a control character (CR/LF/VT/FF/EOF)
719       --  or if we are at the start of an end of line comment sequence.
720
721       return Source (S) < ' '
722         or else (Source (S) = '-' and then Source (S + 1) = '-');
723    end Token_Is_At_End_Of_Line;
724
725    -------------------------------
726    -- Token_Is_At_Start_Of_Line --
727    -------------------------------
728
729    function Token_Is_At_Start_Of_Line return Boolean is
730    begin
731       return (Token_Ptr = First_Non_Blank_Location or else Token = Tok_EOF);
732    end Token_Is_At_Start_Of_Line;
733
734 end Util;