summaryrefslogtreecommitdiff
authorzecke <zecke>2003-08-31 19:06:45 (UTC)
committer zecke <zecke>2003-08-31 19:06:45 (UTC)
commit2696413e75a401899764f244c8c24026999fdb9d (patch) (unidiff)
tree630522a33052ea7d337bc76f624be0d7e142ff04
parentce4a99860d28e003871994cca88a82133c1921a7 (diff)
downloadopie-2696413e75a401899764f244c8c24026999fdb9d.zip
opie-2696413e75a401899764f244c8c24026999fdb9d.tar.gz
opie-2696413e75a401899764f244c8c24026999fdb9d.tar.bz2
recognize i18n as well
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--development/translation/opie-lupdate/fetchtr.cpp3
1 files changed, 3 insertions, 0 deletions
diff --git a/development/translation/opie-lupdate/fetchtr.cpp b/development/translation/opie-lupdate/fetchtr.cpp
index eb25555..d1f5881 100644
--- a/development/translation/opie-lupdate/fetchtr.cpp
+++ b/development/translation/opie-lupdate/fetchtr.cpp
@@ -1,370 +1,373 @@
1/********************************************************************** 1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved. 2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3** 3**
4** This file is part of Qt Linguist. 4** This file is part of Qt Linguist.
5** 5**
6** This file may be distributed and/or modified under the terms of the 6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software 7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the 8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file. 9** packaging of this file.
10** 10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13** 13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information. 14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15** 15**
16** Contact info@trolltech.com if any conditions of this licensing are 16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you. 17** not clear to you.
18** 18**
19**********************************************************************/ 19**********************************************************************/
20 20
21#include <metatranslator.h> 21#include <metatranslator.h>
22 22
23#include <qfile.h> 23#include <qfile.h>
24#include <qregexp.h> 24#include <qregexp.h>
25#include <qstring.h> 25#include <qstring.h>
26#include <qtextstream.h> 26#include <qtextstream.h>
27#include <qvaluestack.h> 27#include <qvaluestack.h>
28#include <qxml.h> 28#include <qxml.h>
29 29
30#include <ctype.h> 30#include <ctype.h>
31#include <errno.h> 31#include <errno.h>
32#include <stdio.h> 32#include <stdio.h>
33#include <string.h> 33#include <string.h>
34 34
35/* qmake ignore Q_OBJECT */ 35/* qmake ignore Q_OBJECT */
36 36
37static const char MagicComment[] = "TRANSLATOR "; 37static const char MagicComment[] = "TRANSLATOR ";
38 38
39static QMap<QCString, int> needs_Q_OBJECT; 39static QMap<QCString, int> needs_Q_OBJECT;
40static QMap<QCString, int> lacks_Q_OBJECT; 40static QMap<QCString, int> lacks_Q_OBJECT;
41 41
42/* 42/*
43 The first part of this source file is the C++ tokenizer. We skip 43 The first part of this source file is the C++ tokenizer. We skip
44 most of C++; the only tokens that interest us are defined here. 44 most of C++; the only tokens that interest us are defined here.
45 Thus, the code fragment 45 Thus, the code fragment
46 46
47 int main() 47 int main()
48 { 48 {
49 printf( "Hello, world!\n" ); 49 printf( "Hello, world!\n" );
50 return 0; 50 return 0;
51 } 51 }
52 52
53 is broken down into the following tokens (Tok_ omitted): 53 is broken down into the following tokens (Tok_ omitted):
54 54
55 Ident Ident LeftParen RightParen 55 Ident Ident LeftParen RightParen
56 LeftBrace 56 LeftBrace
57 Ident LeftParen String RightParen Semicolon 57 Ident LeftParen String RightParen Semicolon
58 return Semicolon 58 return Semicolon
59 RightBrace. 59 RightBrace.
60 60
61 The 0 doesn't produce any token. 61 The 0 doesn't produce any token.
62*/ 62*/
63 63
64enum { Tok_Eof, Tok_class, Tok_namespace, Tok_return, Tok_tr, 64enum { Tok_Eof, Tok_class, Tok_namespace, Tok_return, Tok_tr,
65 Tok_trUtf8, Tok_translate, Tok_Q_OBJECT, Tok_Ident, 65 Tok_trUtf8, Tok_translate, Tok_Q_OBJECT, Tok_Ident,
66 Tok_Comment, Tok_String, Tok_Arrow, Tok_Colon, 66 Tok_Comment, Tok_String, Tok_Arrow, Tok_Colon,
67 Tok_Gulbrandsen, Tok_LeftBrace, Tok_RightBrace, Tok_LeftParen, 67 Tok_Gulbrandsen, Tok_LeftBrace, Tok_RightBrace, Tok_LeftParen,
68 Tok_RightParen, Tok_Comma, Tok_Semicolon }; 68 Tok_RightParen, Tok_Comma, Tok_Semicolon };
69 69
70/* 70/*
71 The tokenizer maintains the following global variables. The names 71 The tokenizer maintains the following global variables. The names
72 should be self-explanatory. 72 should be self-explanatory.
73*/ 73*/
74static QCString yyFileName; 74static QCString yyFileName;
75static int yyCh; 75static int yyCh;
76static char yyIdent[128]; 76static char yyIdent[128];
77static size_t yyIdentLen; 77static size_t yyIdentLen;
78static char yyComment[65536]; 78static char yyComment[65536];
79static size_t yyCommentLen; 79static size_t yyCommentLen;
80static char yyString[16384]; 80static char yyString[16384];
81static size_t yyStringLen; 81static size_t yyStringLen;
82static QValueStack<int> yySavedBraceDepth; 82static QValueStack<int> yySavedBraceDepth;
83static int yyBraceDepth; 83static int yyBraceDepth;
84static int yyParenDepth; 84static int yyParenDepth;
85static int yyLineNo; 85static int yyLineNo;
86static int yyCurLineNo; 86static int yyCurLineNo;
87 87
88// the file to read from (if reading from a file) 88// the file to read from (if reading from a file)
89static FILE *yyInFile; 89static FILE *yyInFile;
90 90
91// the string to read from and current position in the string (otherwise) 91// the string to read from and current position in the string (otherwise)
92static QString yyInStr; 92static QString yyInStr;
93static int yyInPos; 93static int yyInPos;
94 94
95static int (*getChar)(); 95static int (*getChar)();
96 96
97static int getCharFromFile() 97static int getCharFromFile()
98{ 98{
99 int c = getc( yyInFile ); 99 int c = getc( yyInFile );
100 if ( c == '\n' ) 100 if ( c == '\n' )
101 yyCurLineNo++; 101 yyCurLineNo++;
102 return c; 102 return c;
103} 103}
104 104
105static int getCharFromString() 105static int getCharFromString()
106{ 106{
107 if ( yyInPos == (int) yyInStr.length() ) { 107 if ( yyInPos == (int) yyInStr.length() ) {
108 return EOF; 108 return EOF;
109 } else { 109 } else {
110 return yyInStr[yyInPos++].latin1(); 110 return yyInStr[yyInPos++].latin1();
111 } 111 }
112} 112}
113 113
114static void startTokenizer( const char *fileName, int (*getCharFunc)() ) 114static void startTokenizer( const char *fileName, int (*getCharFunc)() )
115{ 115{
116 yyInPos = 0; 116 yyInPos = 0;
117 getChar = getCharFunc; 117 getChar = getCharFunc;
118 118
119 yyFileName = fileName; 119 yyFileName = fileName;
120 yyCh = getChar(); 120 yyCh = getChar();
121 yySavedBraceDepth.clear(); 121 yySavedBraceDepth.clear();
122 yyBraceDepth = 0; 122 yyBraceDepth = 0;
123 yyParenDepth = 0; 123 yyParenDepth = 0;
124 yyCurLineNo = 1; 124 yyCurLineNo = 1;
125} 125}
126 126
127static int getToken() 127static int getToken()
128{ 128{
129 const char tab[] = "abfnrtv"; 129 const char tab[] = "abfnrtv";
130 const char backTab[] = "\a\b\f\n\r\t\v"; 130 const char backTab[] = "\a\b\f\n\r\t\v";
131 uint n; 131 uint n;
132 132
133 yyIdentLen = 0; 133 yyIdentLen = 0;
134 yyCommentLen = 0; 134 yyCommentLen = 0;
135 yyStringLen = 0; 135 yyStringLen = 0;
136 136
137 while ( yyCh != EOF ) { 137 while ( yyCh != EOF ) {
138 yyLineNo = yyCurLineNo; 138 yyLineNo = yyCurLineNo;
139 139
140 if ( isalpha(yyCh) || yyCh == '_' ) { 140 if ( isalpha(yyCh) || yyCh == '_' ) {
141 do { 141 do {
142 if ( yyIdentLen < sizeof(yyIdent) - 1 ) 142 if ( yyIdentLen < sizeof(yyIdent) - 1 )
143 yyIdent[yyIdentLen++] = (char) yyCh; 143 yyIdent[yyIdentLen++] = (char) yyCh;
144 yyCh = getChar(); 144 yyCh = getChar();
145 } while ( isalnum(yyCh) || yyCh == '_' ); 145 } while ( isalnum(yyCh) || yyCh == '_' );
146 yyIdent[yyIdentLen] = '\0'; 146 yyIdent[yyIdentLen] = '\0';
147 147
148 switch ( yyIdent[0] ) { 148 switch ( yyIdent[0] ) {
149 case 'Q': 149 case 'Q':
150 if ( strcmp(yyIdent + 1, "_OBJECT") == 0 ) { 150 if ( strcmp(yyIdent + 1, "_OBJECT") == 0 ) {
151 return Tok_Q_OBJECT; 151 return Tok_Q_OBJECT;
152 } else if ( strcmp(yyIdent + 1, "T_TR_NOOP") == 0 ) { 152 } else if ( strcmp(yyIdent + 1, "T_TR_NOOP") == 0 ) {
153 return Tok_tr; 153 return Tok_tr;
154 } else if ( strcmp(yyIdent + 1, "T_TRANSLATE_NOOP") == 0 ) { 154 } else if ( strcmp(yyIdent + 1, "T_TRANSLATE_NOOP") == 0 ) {
155 return Tok_translate; 155 return Tok_translate;
156 } 156 }
157 break; 157 break;
158 case 'T': 158 case 'T':
159 // TR() for when all else fails 159 // TR() for when all else fails
160 if ( qstricmp(yyIdent + 1, "R") == 0 ) 160 if ( qstricmp(yyIdent + 1, "R") == 0 )
161 return Tok_tr; 161 return Tok_tr;
162 break; 162 break;
163 case 'c': 163 case 'c':
164 if ( strcmp(yyIdent + 1, "lass") == 0 ) 164 if ( strcmp(yyIdent + 1, "lass") == 0 )
165 return Tok_class; 165 return Tok_class;
166 break; 166 break;
167 case 'n': 167 case 'n':
168 if ( strcmp(yyIdent + 1, "amespace") == 0 ) 168 if ( strcmp(yyIdent + 1, "amespace") == 0 )
169 return Tok_namespace; 169 return Tok_namespace;
170 break; 170 break;
171 case 'r': 171 case 'r':
172 if ( strcmp(yyIdent + 1, "eturn") == 0 ) 172 if ( strcmp(yyIdent + 1, "eturn") == 0 )
173 return Tok_return; 173 return Tok_return;
174 break; 174 break;
175 case 's': 175 case 's':
176 if ( strcmp(yyIdent + 1, "truct") == 0 ) 176 if ( strcmp(yyIdent + 1, "truct") == 0 )
177 return Tok_class; 177 return Tok_class;
178 break; 178 break;
179 case 'i':
180 if( strcmp(yyIdent + 1, "18n") == 0 )
181 return Tok_tr;
179 case 't': 182 case 't':
180 if ( strcmp(yyIdent + 1, "r") == 0 ) { 183 if ( strcmp(yyIdent + 1, "r") == 0 ) {
181 return Tok_tr; 184 return Tok_tr;
182 } else if ( qstrcmp(yyIdent + 1, "rUtf8") == 0 ) { 185 } else if ( qstrcmp(yyIdent + 1, "rUtf8") == 0 ) {
183 return Tok_trUtf8; 186 return Tok_trUtf8;
184 } else if ( qstrcmp(yyIdent + 1, "ranslate") == 0 ) { 187 } else if ( qstrcmp(yyIdent + 1, "ranslate") == 0 ) {
185 return Tok_translate; 188 return Tok_translate;
186 } 189 }
187 } 190 }
188 return Tok_Ident; 191 return Tok_Ident;
189 } else { 192 } else {
190 switch ( yyCh ) { 193 switch ( yyCh ) {
191 case '#': 194 case '#':
192 /* 195 /*
193 Early versions of lupdate complained about 196 Early versions of lupdate complained about
194 unbalanced braces in the following code: 197 unbalanced braces in the following code:
195 198
196 #ifdef ALPHA 199 #ifdef ALPHA
197 while ( beta ) { 200 while ( beta ) {
198 #else 201 #else
199 while ( gamma ) { 202 while ( gamma ) {
200 #endif 203 #endif
201 delta; 204 delta;
202 } 205 }
203 206
204 The code contains, indeed, two opening braces for 207 The code contains, indeed, two opening braces for
205 one closing brace; yet there's no reason to panic. 208 one closing brace; yet there's no reason to panic.
206 209
207 The solution is to remember yyBraceDepth as it was 210 The solution is to remember yyBraceDepth as it was
208 when #if, #ifdef or #ifndef was met, and to set 211 when #if, #ifdef or #ifndef was met, and to set
209 yyBraceDepth to that value when meeting #elif or 212 yyBraceDepth to that value when meeting #elif or
210 #else. 213 #else.
211 */ 214 */
212 do { 215 do {
213 yyCh = getChar(); 216 yyCh = getChar();
214 } while ( isspace(yyCh) && yyCh != '\n' ); 217 } while ( isspace(yyCh) && yyCh != '\n' );
215 218
216 switch ( yyCh ) { 219 switch ( yyCh ) {
217 case 'i': 220 case 'i':
218 yyCh = getChar(); 221 yyCh = getChar();
219 if ( yyCh == 'f' ) { 222 if ( yyCh == 'f' ) {
220 // if, ifdef, ifndef 223 // if, ifdef, ifndef
221 yySavedBraceDepth.push( yyBraceDepth ); 224 yySavedBraceDepth.push( yyBraceDepth );
222 } 225 }
223 break; 226 break;
224 case 'e': 227 case 'e':
225 yyCh = getChar(); 228 yyCh = getChar();
226 if ( yyCh == 'l' ) { 229 if ( yyCh == 'l' ) {
227 // elif, else 230 // elif, else
228 if ( !yySavedBraceDepth.isEmpty() ) 231 if ( !yySavedBraceDepth.isEmpty() )
229 yyBraceDepth = yySavedBraceDepth.top(); 232 yyBraceDepth = yySavedBraceDepth.top();
230 } else if ( yyCh == 'n' ) { 233 } else if ( yyCh == 'n' ) {
231 // endif 234 // endif
232 if ( !yySavedBraceDepth.isEmpty() ) 235 if ( !yySavedBraceDepth.isEmpty() )
233 yySavedBraceDepth.pop(); 236 yySavedBraceDepth.pop();
234 } 237 }
235 } 238 }
236 while ( isalnum(yyCh) || yyCh == '_' ) 239 while ( isalnum(yyCh) || yyCh == '_' )
237 yyCh = getChar(); 240 yyCh = getChar();
238 break; 241 break;
239 case '/': 242 case '/':
240 yyCh = getChar(); 243 yyCh = getChar();
241 if ( yyCh == '/' ) { 244 if ( yyCh == '/' ) {
242 do { 245 do {
243 yyCh = getChar(); 246 yyCh = getChar();
244 } while ( yyCh != EOF && yyCh != '\n' ); 247 } while ( yyCh != EOF && yyCh != '\n' );
245 } else if ( yyCh == '*' ) { 248 } else if ( yyCh == '*' ) {
246 bool metAster = FALSE; 249 bool metAster = FALSE;
247 bool metAsterSlash = FALSE; 250 bool metAsterSlash = FALSE;
248 251
249 while ( !metAsterSlash ) { 252 while ( !metAsterSlash ) {
250 yyCh = getChar(); 253 yyCh = getChar();
251 if ( yyCh == EOF ) { 254 if ( yyCh == EOF ) {
252 fprintf( stderr, 255 fprintf( stderr,
253 "%s: Unterminated C++ comment starting at" 256 "%s: Unterminated C++ comment starting at"
254 " line %d\n", 257 " line %d\n",
255 (const char *) yyFileName, yyLineNo ); 258 (const char *) yyFileName, yyLineNo );
256 yyComment[yyCommentLen] = '\0'; 259 yyComment[yyCommentLen] = '\0';
257 return Tok_Comment; 260 return Tok_Comment;
258 } 261 }
259 if ( yyCommentLen < sizeof(yyComment) - 1 ) 262 if ( yyCommentLen < sizeof(yyComment) - 1 )
260 yyComment[yyCommentLen++] = (char) yyCh; 263 yyComment[yyCommentLen++] = (char) yyCh;
261 264
262 if ( yyCh == '*' ) 265 if ( yyCh == '*' )
263 metAster = TRUE; 266 metAster = TRUE;
264 else if ( metAster && yyCh == '/' ) 267 else if ( metAster && yyCh == '/' )
265 metAsterSlash = TRUE; 268 metAsterSlash = TRUE;
266 else 269 else
267 metAster = FALSE; 270 metAster = FALSE;
268 } 271 }
269 yyCh = getChar(); 272 yyCh = getChar();
270 yyCommentLen -= 2; 273 yyCommentLen -= 2;
271 yyComment[yyCommentLen] = '\0'; 274 yyComment[yyCommentLen] = '\0';
272 return Tok_Comment; 275 return Tok_Comment;
273 } 276 }
274 break; 277 break;
275 case '"': 278 case '"':
276 yyCh = getChar(); 279 yyCh = getChar();
277 280
278 while ( yyCh != EOF && yyCh != '\n' && yyCh != '"' ) { 281 while ( yyCh != EOF && yyCh != '\n' && yyCh != '"' ) {
279 if ( yyCh == '\\' ) { 282 if ( yyCh == '\\' ) {
280 yyCh = getChar(); 283 yyCh = getChar();
281 284
282 if ( yyCh == '\n' ) { 285 if ( yyCh == '\n' ) {
283 yyCh = getChar(); 286 yyCh = getChar();
284 } else if ( yyCh == 'x' ) { 287 } else if ( yyCh == 'x' ) {
285 QCString hex = "0"; 288 QCString hex = "0";
286 289
287 yyCh = getChar(); 290 yyCh = getChar();
288 while ( isxdigit(yyCh) ) { 291 while ( isxdigit(yyCh) ) {
289 hex += (char) yyCh; 292 hex += (char) yyCh;
290 yyCh = getChar(); 293 yyCh = getChar();
291 } 294 }
292 sscanf( hex, "%x", &n ); 295 sscanf( hex, "%x", &n );
293 if ( yyStringLen < sizeof(yyString) - 1 ) 296 if ( yyStringLen < sizeof(yyString) - 1 )
294 yyString[yyStringLen++] = (char) n; 297 yyString[yyStringLen++] = (char) n;
295 } else if ( yyCh >= '0' && yyCh < '8' ) { 298 } else if ( yyCh >= '0' && yyCh < '8' ) {
296 QCString oct = ""; 299 QCString oct = "";
297 300
298 do { 301 do {
299 oct += (char) yyCh; 302 oct += (char) yyCh;
300 yyCh = getChar(); 303 yyCh = getChar();
301 } while ( yyCh >= '0' && yyCh < '8' ); 304 } while ( yyCh >= '0' && yyCh < '8' );
302 sscanf( oct, "%o", &n ); 305 sscanf( oct, "%o", &n );
303 if ( yyStringLen < sizeof(yyString) - 1 ) 306 if ( yyStringLen < sizeof(yyString) - 1 )
304 yyString[yyStringLen++] = (char) n; 307 yyString[yyStringLen++] = (char) n;
305 } else { 308 } else {
306 const char *p = strchr( tab, yyCh ); 309 const char *p = strchr( tab, yyCh );
307 if ( yyStringLen < sizeof(yyString) - 1 ) 310 if ( yyStringLen < sizeof(yyString) - 1 )
308 yyString[yyStringLen++] = ( p == 0 ) ? 311 yyString[yyStringLen++] = ( p == 0 ) ?
309 (char) yyCh : backTab[p - tab]; 312 (char) yyCh : backTab[p - tab];
310 yyCh = getChar(); 313 yyCh = getChar();
311 } 314 }
312 } else { 315 } else {
313 if ( yyStringLen < sizeof(yyString) - 1 ) 316 if ( yyStringLen < sizeof(yyString) - 1 )
314 yyString[yyStringLen++] = (char) yyCh; 317 yyString[yyStringLen++] = (char) yyCh;
315 yyCh = getChar(); 318 yyCh = getChar();
316 } 319 }
317 } 320 }
318 yyString[yyStringLen] = '\0'; 321 yyString[yyStringLen] = '\0';
319 322
320 if ( yyCh != '"' ) 323 if ( yyCh != '"' )
321 qWarning( "%s:%d: Unterminated C++ string", 324 qWarning( "%s:%d: Unterminated C++ string",
322 (const char *) yyFileName, yyLineNo ); 325 (const char *) yyFileName, yyLineNo );
323 326
324 if ( yyCh == EOF ) { 327 if ( yyCh == EOF ) {
325 return Tok_Eof; 328 return Tok_Eof;
326 } else { 329 } else {
327 yyCh = getChar(); 330 yyCh = getChar();
328 return Tok_String; 331 return Tok_String;
329 } 332 }
330 break; 333 break;
331 case '-': 334 case '-':
332 yyCh = getChar(); 335 yyCh = getChar();
333 if ( yyCh == '>' ) { 336 if ( yyCh == '>' ) {
334 yyCh = getChar(); 337 yyCh = getChar();
335 return Tok_Arrow; 338 return Tok_Arrow;
336 } 339 }
337 break; 340 break;
338 case ':': 341 case ':':
339 yyCh = getChar(); 342 yyCh = getChar();
340 if ( yyCh == ':' ) { 343 if ( yyCh == ':' ) {
341 yyCh = getChar(); 344 yyCh = getChar();
342 return Tok_Gulbrandsen; 345 return Tok_Gulbrandsen;
343 } 346 }
344 return Tok_Colon; 347 return Tok_Colon;
345 case '\'': 348 case '\'':
346 yyCh = getChar(); 349 yyCh = getChar();
347 if ( yyCh == '\\' ) 350 if ( yyCh == '\\' )
348 yyCh = getChar(); 351 yyCh = getChar();
349 352
350 do { 353 do {
351 yyCh = getChar(); 354 yyCh = getChar();
352 } while ( yyCh != EOF && yyCh != '\'' ); 355 } while ( yyCh != EOF && yyCh != '\'' );
353 yyCh = getChar(); 356 yyCh = getChar();
354 break; 357 break;
355 case '{': 358 case '{':
356 yyBraceDepth++; 359 yyBraceDepth++;
357 yyCh = getChar(); 360 yyCh = getChar();
358 return Tok_LeftBrace; 361 return Tok_LeftBrace;
359 case '}': 362 case '}':
360 yyBraceDepth--; 363 yyBraceDepth--;
361 yyCh = getChar(); 364 yyCh = getChar();
362 return Tok_RightBrace; 365 return Tok_RightBrace;
363 case '(': 366 case '(':
364 yyParenDepth++; 367 yyParenDepth++;
365 yyCh = getChar(); 368 yyCh = getChar();
366 return Tok_LeftParen; 369 return Tok_LeftParen;
367 case ')': 370 case ')':
368 yyParenDepth--; 371 yyParenDepth--;
369 yyCh = getChar(); 372 yyCh = getChar();
370 return Tok_RightParen; 373 return Tok_RightParen;