1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- $Revision: 1.29 $ --
11 -- Copyright (C) 1992-1999 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 with Stringt; use Stringt;
34 Delimiter : Character;
35 -- Delimiter (first character of string)
38 -- Current source program character
41 -- Current character code value
44 -- Error flag for Scan_Wide call
46 String_Literal_Id : String_Id;
47 -- Id for currently scanned string value
49 Wide_Character_Found : Boolean := False;
50 -- Set True if wide character found
52 procedure Error_Bad_String_Char;
53 -- Signal bad character in string/character literal. On entry Scan_Ptr
54 -- points to the improper character encountered during the scan. Scan_Ptr
55 -- is not modified, so it still points to the bad character on return.
57 procedure Error_Unterminated_String;
58 -- Procedure called if a line terminator character is encountered during
59 -- scanning a string, meaning that the string is not properly terminated.
62 -- Procedure used to distinguish between string and operator symbol.
63 -- On entry the string has been scanned out, and its characters start
64 -- at Token_Ptr and end one character before Scan_Ptr. On exit Token
65 -- is set to Tok_String_Literal or Tok_Operator_Symbol as appropriate,
66 -- and Token_Node is appropriately initialized. In addition, in the
67 -- operator symbol case, Token_Name is appropriately set.
69 ---------------------------
70 -- Error_Bad_String_Char --
71 ---------------------------
73 procedure Error_Bad_String_Char is
74 C : constant Character := Source (Scan_Ptr);
78 Error_Msg_S ("horizontal tab not allowed in string");
80 elsif C = VT or else C = FF then
81 Error_Msg_S ("format effector not allowed in string");
83 elsif C in Upper_Half_Character then
84 Error_Msg_S ("(Ada 83) upper half character not allowed");
87 Error_Msg_S ("control character not allowed in string");
89 end Error_Bad_String_Char;
91 -------------------------------
92 -- Error_Unterminated_String --
93 -------------------------------
95 procedure Error_Unterminated_String is
97 -- An interesting little refinement. Consider the following examples:
99 -- A := "this is an unterminated string;
100 -- A := "this is an unterminated string &
101 -- P(A, "this is a parameter that didn't get terminated);
103 -- We fiddle a little to do slightly better placement in these cases
104 -- also if there is white space at the end of the line we place the
105 -- flag at the start of this white space, not at the end. Note that
106 -- we only have to test for blanks, since tabs aren't allowed in
107 -- strings in the first place and would have caused an error message.
109 -- Two more cases that we treat specially are:
111 -- A := "this string uses the wrong terminator'
112 -- A := "this string uses the wrong terminator' &
114 -- In these cases we give a different error message as well
116 -- We actually reposition the scan pointer to the point where we
117 -- place the flag in these cases, since it seems a better bet on
118 -- the original intention.
120 while Source (Scan_Ptr - 1) = ' '
121 or else Source (Scan_Ptr - 1) = '&'
123 Scan_Ptr := Scan_Ptr - 1;
127 -- Check for case of incorrect string terminator, but single quote is
128 -- not considered incorrect if the opening terminator misused a single
129 -- quote (error message already given).
132 and then Source (Scan_Ptr - 1) = '''
135 Error_Msg ("incorrect string terminator character", Scan_Ptr - 1);
139 if Source (Scan_Ptr - 1) = ';' then
140 Scan_Ptr := Scan_Ptr - 1;
143 if Source (Scan_Ptr - 1) = ')' then
144 Scan_Ptr := Scan_Ptr - 1;
149 Error_Msg_S ("missing string quote");
150 end Error_Unterminated_String;
156 procedure Set_String is
157 Slen : Int := Int (Scan_Ptr - Token_Ptr - 2);
163 -- Token_Name is currently set to Error_Name. The following section of
164 -- code resets Token_Name to the proper Name_Op_xx value if the string
165 -- is a valid operator symbol, otherwise it is left set to Error_Name.
168 C1 := Source (Token_Ptr + 1);
172 Token_Name := Name_Op_Eq;
175 Token_Name := Name_Op_Gt;
178 Token_Name := Name_Op_Lt;
181 Token_Name := Name_Op_Add;
184 Token_Name := Name_Op_Subtract;
187 Token_Name := Name_Op_Concat;
190 Token_Name := Name_Op_Multiply;
193 Token_Name := Name_Op_Divide;
200 C1 := Source (Token_Ptr + 1);
201 C2 := Source (Token_Ptr + 2);
203 if C1 = '*' and then C2 = '*' then
204 Token_Name := Name_Op_Expon;
209 Token_Name := Name_Op_Ne;
211 Token_Name := Name_Op_Le;
213 Token_Name := Name_Op_Ge;
216 elsif (C1 = 'O' or else C1 = 'o') and then -- OR
217 (C2 = 'R' or else C2 = 'r')
219 Token_Name := Name_Op_Or;
223 C1 := Source (Token_Ptr + 1);
224 C2 := Source (Token_Ptr + 2);
225 C3 := Source (Token_Ptr + 3);
227 if (C1 = 'A' or else C1 = 'a') and then -- AND
228 (C2 = 'N' or else C2 = 'n') and then
229 (C3 = 'D' or else C3 = 'd')
231 Token_Name := Name_Op_And;
233 elsif (C1 = 'A' or else C1 = 'a') and then -- ABS
234 (C2 = 'B' or else C2 = 'b') and then
235 (C3 = 'S' or else C3 = 's')
237 Token_Name := Name_Op_Abs;
239 elsif (C1 = 'M' or else C1 = 'm') and then -- MOD
240 (C2 = 'O' or else C2 = 'o') and then
241 (C3 = 'D' or else C3 = 'd')
243 Token_Name := Name_Op_Mod;
245 elsif (C1 = 'N' or else C1 = 'n') and then -- NOT
246 (C2 = 'O' or else C2 = 'o') and then
247 (C3 = 'T' or else C3 = 't')
249 Token_Name := Name_Op_Not;
251 elsif (C1 = 'R' or else C1 = 'r') and then -- REM
252 (C2 = 'E' or else C2 = 'e') and then
253 (C3 = 'M' or else C3 = 'm')
255 Token_Name := Name_Op_Rem;
257 elsif (C1 = 'X' or else C1 = 'x') and then -- XOR
258 (C2 = 'O' or else C2 = 'o') and then
259 (C3 = 'R' or else C3 = 'r')
261 Token_Name := Name_Op_Xor;
266 -- If it is an operator symbol, then Token_Name is set. If it is some
267 -- other string value, then Token_Name still contains Error_Name.
269 if Token_Name = Error_Name then
270 Token := Tok_String_Literal;
271 Token_Node := New_Node (N_String_Literal, Token_Ptr);
272 Set_Has_Wide_Character (Token_Node, Wide_Character_Found);
275 Token := Tok_Operator_Symbol;
276 Token_Node := New_Node (N_Operator_Symbol, Token_Ptr);
277 Set_Chars (Token_Node, Token_Name);
280 Set_Strval (Token_Node, String_Literal_Id);
289 -- On entry, Scan_Ptr points to the opening character of the string which
290 -- is either a percent, double quote, or apostrophe (single quote). The
291 -- latter case is an error detected by the character literal circuit.
293 Delimiter := Source (Scan_Ptr);
294 Accumulate_Checksum (Delimiter);
296 Scan_Ptr := Scan_Ptr + 1;
298 -- Loop to scan out characters of string literal
301 C := Source (Scan_Ptr);
303 if C = Delimiter then
304 Accumulate_Checksum (C);
305 Scan_Ptr := Scan_Ptr + 1;
306 exit when Source (Scan_Ptr) /= Delimiter;
307 Code := Get_Char_Code (C);
308 Accumulate_Checksum (C);
309 Scan_Ptr := Scan_Ptr + 1;
312 if C = '"' and then Delimiter = '%' then
313 Error_Msg_S ("quote not allowed in percent delimited string");
314 Code := Get_Char_Code (C);
315 Scan_Ptr := Scan_Ptr + 1;
319 Wide_Character_Encoding_Method in WC_ESC_Encoding_Method)
321 (C in Upper_Half_Character
327 Source (Scan_Ptr + 1) = '"'
329 Identifier_Char (Source (Scan_Ptr + 2)))
331 Scan_Wide (Source, Scan_Ptr, Code, Err);
332 Accumulate_Checksum (Code);
335 Error_Illegal_Wide_Character;
336 Code := Get_Char_Code (' ');
340 Accumulate_Checksum (C);
342 if C not in Graphic_Character then
343 if C in Line_Terminator then
344 Error_Unterminated_String;
347 elsif C in Upper_Half_Character then
349 Error_Bad_String_Char;
353 Error_Bad_String_Char;
357 Code := Get_Char_Code (C);
358 Scan_Ptr := Scan_Ptr + 1;
362 Store_String_Char (Code);
364 if not In_Character_Range (Code) then
365 Wide_Character_Found := True;
369 String_Literal_Id := End_String;