1 /****************************************************************************
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 ** This file is part of the QtScript module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
10 ** This file contains pre-release code and may not be distributed.
11 ** You may use this file in accordance with the terms and conditions
12 ** contained in the either Technology Preview License Agreement or the
13 ** Beta Release License Agreement.
15 ** GNU Lesser General Public License Usage
16 ** Alternatively, this file may be used under the terms of the GNU Lesser
17 ** General Public License version 2.1 as published by the Free Software
18 ** Foundation and appearing in the file LICENSE.LGPL included in the
19 ** packaging of this file. Please review the following information to
20 ** ensure the GNU Lesser General Public License version 2.1 requirements
21 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 ** In addition, as a special exception, Nokia gives you certain
24 ** additional rights. These rights are described in the Nokia Qt LGPL
25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
28 ** GNU General Public License Usage
29 ** Alternatively, this file may be used under the terms of the GNU
30 ** General Public License version 3.0 as published by the Free Software
31 ** Foundation and appearing in the file LICENSE.GPL included in the
32 ** packaging of this file. Please review the following information to
33 ** ensure the GNU General Public License version 3.0 requirements will be
34 ** met: http://www.gnu.org/copyleft/gpl.html.
36 ** If you are unsure which license is appropriate for your use, please
37 ** contact the sales department at http://www.qtsoftware.com/contact.
40 ****************************************************************************/
46 #include "qscriptengine_p.h"
50 #include "qscriptvalueimpl_p.h"
51 #include "qscriptcontext_p.h"
52 #include "qscriptmember_p.h"
53 #include "qscriptobject_p.h"
54 #include "qscriptlexer_p.h"
55 #include "qscriptgrammar_p.h"
64 extern double qstrtod(const char *s00
, char const **se
, bool *ok
);
66 #define shiftWindowsLineBreak() \
68 if (((current == '\r') && (next1 == '\n')) \
69 || ((current == '\n') && (next1 == '\r'))) { \
76 extern qsreal
integerFromString(const char *buf
, int size
, int radix
);
79 QScript::Lexer::Lexer(QScriptEnginePrivate
*eng
)
83 size8(128), size16(128),
93 startlineno(0), startcolumn(0),
95 current(0), next1(0), next2(0), next3(0),
99 parenthesesState(IgnoreParentheses
),
101 prohibitAutomaticSemicolon(false)
103 // allocate space for read buffers
104 buffer8
= new char[size8
];
105 buffer16
= new QChar
[size16
];
111 QScript::Lexer::~Lexer()
117 void QScript::Lexer::setCode(const QString
&c
, int lineno
)
122 restrKeyword
= false;
130 // read first characters
131 current
= (length
> 0) ? code
[0].unicode() : 0;
132 next1
= (length
> 1) ? code
[1].unicode() : 0;
133 next2
= (length
> 2) ? code
[2].unicode() : 0;
134 next3
= (length
> 3) ? code
[3].unicode() : 0;
137 void QScript::Lexer::shift(uint p
)
145 next3
= (pos
+ 3 < length
) ? code
[pos
+3].unicode() : 0;
149 void QScript::Lexer::setDone(State s
)
155 int QScript::Lexer::findReservedWord(const QChar
*c
, int size
) const
159 if (c
[0] == QLatin1Char('d') && c
[1] == QLatin1Char('o'))
160 return QScriptGrammar::T_DO
;
161 else if (c
[0] == QLatin1Char('i') && c
[1] == QLatin1Char('f'))
162 return QScriptGrammar::T_IF
;
163 else if (c
[0] == QLatin1Char('i') && c
[1] == QLatin1Char('n'))
164 return QScriptGrammar::T_IN
;
168 if (c
[0] == QLatin1Char('f') && c
[1] == QLatin1Char('o') && c
[2] == QLatin1Char('r'))
169 return QScriptGrammar::T_FOR
;
170 else if (c
[0] == QLatin1Char('n') && c
[1] == QLatin1Char('e') && c
[2] == QLatin1Char('w'))
171 return QScriptGrammar::T_NEW
;
172 else if (c
[0] == QLatin1Char('t') && c
[1] == QLatin1Char('r') && c
[2] == QLatin1Char('y'))
173 return QScriptGrammar::T_TRY
;
174 else if (c
[0] == QLatin1Char('v') && c
[1] == QLatin1Char('a') && c
[2] == QLatin1Char('r'))
175 return QScriptGrammar::T_VAR
;
176 else if (check_reserved
) {
177 if (c
[0] == QLatin1Char('i') && c
[1] == QLatin1Char('n') && c
[2] == QLatin1Char('t'))
178 return QScriptGrammar::T_RESERVED_WORD
;
183 if (c
[0] == QLatin1Char('c') && c
[1] == QLatin1Char('a')
184 && c
[2] == QLatin1Char('s') && c
[3] == QLatin1Char('e'))
185 return QScriptGrammar::T_CASE
;
186 else if (c
[0] == QLatin1Char('e') && c
[1] == QLatin1Char('l')
187 && c
[2] == QLatin1Char('s') && c
[3] == QLatin1Char('e'))
188 return QScriptGrammar::T_ELSE
;
189 else if (c
[0] == QLatin1Char('t') && c
[1] == QLatin1Char('h')
190 && c
[2] == QLatin1Char('i') && c
[3] == QLatin1Char('s'))
191 return QScriptGrammar::T_THIS
;
192 else if (c
[0] == QLatin1Char('v') && c
[1] == QLatin1Char('o')
193 && c
[2] == QLatin1Char('i') && c
[3] == QLatin1Char('d'))
194 return QScriptGrammar::T_VOID
;
195 else if (c
[0] == QLatin1Char('w') && c
[1] == QLatin1Char('i')
196 && c
[2] == QLatin1Char('t') && c
[3] == QLatin1Char('h'))
197 return QScriptGrammar::T_WITH
;
198 else if (c
[0] == QLatin1Char('t') && c
[1] == QLatin1Char('r')
199 && c
[2] == QLatin1Char('u') && c
[3] == QLatin1Char('e'))
200 return QScriptGrammar::T_TRUE
;
201 else if (c
[0] == QLatin1Char('n') && c
[1] == QLatin1Char('u')
202 && c
[2] == QLatin1Char('l') && c
[3] == QLatin1Char('l'))
203 return QScriptGrammar::T_NULL
;
204 else if (check_reserved
) {
205 if (c
[0] == QLatin1Char('e') && c
[1] == QLatin1Char('n')
206 && c
[2] == QLatin1Char('u') && c
[3] == QLatin1Char('m'))
207 return QScriptGrammar::T_RESERVED_WORD
;
208 else if (c
[0] == QLatin1Char('b') && c
[1] == QLatin1Char('y')
209 && c
[2] == QLatin1Char('t') && c
[3] == QLatin1Char('e'))
210 return QScriptGrammar::T_RESERVED_WORD
;
211 else if (c
[0] == QLatin1Char('l') && c
[1] == QLatin1Char('o')
212 && c
[2] == QLatin1Char('n') && c
[3] == QLatin1Char('g'))
213 return QScriptGrammar::T_RESERVED_WORD
;
214 else if (c
[0] == QLatin1Char('c') && c
[1] == QLatin1Char('h')
215 && c
[2] == QLatin1Char('a') && c
[3] == QLatin1Char('r'))
216 return QScriptGrammar::T_RESERVED_WORD
;
217 else if (c
[0] == QLatin1Char('g') && c
[1] == QLatin1Char('o')
218 && c
[2] == QLatin1Char('t') && c
[3] == QLatin1Char('o'))
219 return QScriptGrammar::T_RESERVED_WORD
;
224 if (c
[0] == QLatin1Char('b') && c
[1] == QLatin1Char('r')
225 && c
[2] == QLatin1Char('e') && c
[3] == QLatin1Char('a')
226 && c
[4] == QLatin1Char('k'))
227 return QScriptGrammar::T_BREAK
;
228 else if (c
[0] == QLatin1Char('c') && c
[1] == QLatin1Char('a')
229 && c
[2] == QLatin1Char('t') && c
[3] == QLatin1Char('c')
230 && c
[4] == QLatin1Char('h'))
231 return QScriptGrammar::T_CATCH
;
232 else if (c
[0] == QLatin1Char('t') && c
[1] == QLatin1Char('h')
233 && c
[2] == QLatin1Char('r') && c
[3] == QLatin1Char('o')
234 && c
[4] == QLatin1Char('w'))
235 return QScriptGrammar::T_THROW
;
236 else if (c
[0] == QLatin1Char('w') && c
[1] == QLatin1Char('h')
237 && c
[2] == QLatin1Char('i') && c
[3] == QLatin1Char('l')
238 && c
[4] == QLatin1Char('e'))
239 return QScriptGrammar::T_WHILE
;
240 else if (c
[0] == QLatin1Char('c') && c
[1] == QLatin1Char('o')
241 && c
[2] == QLatin1Char('n') && c
[3] == QLatin1Char('s')
242 && c
[4] == QLatin1Char('t'))
243 return QScriptGrammar::T_CONST
;
244 else if (c
[0] == QLatin1Char('f') && c
[1] == QLatin1Char('a')
245 && c
[2] == QLatin1Char('l') && c
[3] == QLatin1Char('s')
246 && c
[4] == QLatin1Char('e'))
247 return QScriptGrammar::T_FALSE
;
248 else if (check_reserved
) {
249 if (c
[0] == QLatin1Char('s') && c
[1] == QLatin1Char('h')
250 && c
[2] == QLatin1Char('o') && c
[3] == QLatin1Char('r')
251 && c
[4] == QLatin1Char('t'))
252 return QScriptGrammar::T_RESERVED_WORD
;
253 else if (c
[0] == QLatin1Char('s') && c
[1] == QLatin1Char('u')
254 && c
[2] == QLatin1Char('p') && c
[3] == QLatin1Char('e')
255 && c
[4] == QLatin1Char('r'))
256 return QScriptGrammar::T_RESERVED_WORD
;
257 else if (c
[0] == QLatin1Char('f') && c
[1] == QLatin1Char('i')
258 && c
[2] == QLatin1Char('n') && c
[3] == QLatin1Char('a')
259 && c
[4] == QLatin1Char('l'))
260 return QScriptGrammar::T_RESERVED_WORD
;
261 else if (c
[0] == QLatin1Char('c') && c
[1] == QLatin1Char('l')
262 && c
[2] == QLatin1Char('a') && c
[3] == QLatin1Char('s')
263 && c
[4] == QLatin1Char('s'))
264 return QScriptGrammar::T_RESERVED_WORD
;
265 else if (c
[0] == QLatin1Char('f') && c
[1] == QLatin1Char('l')
266 && c
[2] == QLatin1Char('o') && c
[3] == QLatin1Char('a')
267 && c
[4] == QLatin1Char('t'))
268 return QScriptGrammar::T_RESERVED_WORD
;
273 if (c
[0] == QLatin1Char('d') && c
[1] == QLatin1Char('e')
274 && c
[2] == QLatin1Char('l') && c
[3] == QLatin1Char('e')
275 && c
[4] == QLatin1Char('t') && c
[5] == QLatin1Char('e'))
276 return QScriptGrammar::T_DELETE
;
277 else if (c
[0] == QLatin1Char('r') && c
[1] == QLatin1Char('e')
278 && c
[2] == QLatin1Char('t') && c
[3] == QLatin1Char('u')
279 && c
[4] == QLatin1Char('r') && c
[5] == QLatin1Char('n'))
280 return QScriptGrammar::T_RETURN
;
281 else if (c
[0] == QLatin1Char('s') && c
[1] == QLatin1Char('w')
282 && c
[2] == QLatin1Char('i') && c
[3] == QLatin1Char('t')
283 && c
[4] == QLatin1Char('c') && c
[5] == QLatin1Char('h'))
284 return QScriptGrammar::T_SWITCH
;
285 else if (c
[0] == QLatin1Char('t') && c
[1] == QLatin1Char('y')
286 && c
[2] == QLatin1Char('p') && c
[3] == QLatin1Char('e')
287 && c
[4] == QLatin1Char('o') && c
[5] == QLatin1Char('f'))
288 return QScriptGrammar::T_TYPEOF
;
289 else if (check_reserved
) {
290 if (c
[0] == QLatin1Char('e') && c
[1] == QLatin1Char('x')
291 && c
[2] == QLatin1Char('p') && c
[3] == QLatin1Char('o')
292 && c
[4] == QLatin1Char('r') && c
[5] == QLatin1Char('t'))
293 return QScriptGrammar::T_RESERVED_WORD
;
294 else if (c
[0] == QLatin1Char('s') && c
[1] == QLatin1Char('t')
295 && c
[2] == QLatin1Char('a') && c
[3] == QLatin1Char('t')
296 && c
[4] == QLatin1Char('i') && c
[5] == QLatin1Char('c'))
297 return QScriptGrammar::T_RESERVED_WORD
;
298 else if (c
[0] == QLatin1Char('d') && c
[1] == QLatin1Char('o')
299 && c
[2] == QLatin1Char('u') && c
[3] == QLatin1Char('b')
300 && c
[4] == QLatin1Char('l') && c
[5] == QLatin1Char('e'))
301 return QScriptGrammar::T_RESERVED_WORD
;
302 else if (c
[0] == QLatin1Char('i') && c
[1] == QLatin1Char('m')
303 && c
[2] == QLatin1Char('p') && c
[3] == QLatin1Char('o')
304 && c
[4] == QLatin1Char('r') && c
[5] == QLatin1Char('t'))
305 return QScriptGrammar::T_RESERVED_WORD
;
306 else if (c
[0] == QLatin1Char('p') && c
[1] == QLatin1Char('u')
307 && c
[2] == QLatin1Char('b') && c
[3] == QLatin1Char('l')
308 && c
[4] == QLatin1Char('i') && c
[5] == QLatin1Char('c'))
309 return QScriptGrammar::T_RESERVED_WORD
;
310 else if (c
[0] == QLatin1Char('n') && c
[1] == QLatin1Char('a')
311 && c
[2] == QLatin1Char('t') && c
[3] == QLatin1Char('i')
312 && c
[4] == QLatin1Char('v') && c
[5] == QLatin1Char('e'))
313 return QScriptGrammar::T_RESERVED_WORD
;
314 else if (c
[0] == QLatin1Char('t') && c
[1] == QLatin1Char('h')
315 && c
[2] == QLatin1Char('r') && c
[3] == QLatin1Char('o')
316 && c
[4] == QLatin1Char('w') && c
[5] == QLatin1Char('s'))
317 return QScriptGrammar::T_RESERVED_WORD
;
322 if (c
[0] == QLatin1Char('d') && c
[1] == QLatin1Char('e')
323 && c
[2] == QLatin1Char('f') && c
[3] == QLatin1Char('a')
324 && c
[4] == QLatin1Char('u') && c
[5] == QLatin1Char('l')
325 && c
[6] == QLatin1Char('t'))
326 return QScriptGrammar::T_DEFAULT
;
327 else if (c
[0] == QLatin1Char('f') && c
[1] == QLatin1Char('i')
328 && c
[2] == QLatin1Char('n') && c
[3] == QLatin1Char('a')
329 && c
[4] == QLatin1Char('l') && c
[5] == QLatin1Char('l')
330 && c
[6] == QLatin1Char('y'))
331 return QScriptGrammar::T_FINALLY
;
332 else if (check_reserved
) {
333 if (c
[0] == QLatin1Char('b') && c
[1] == QLatin1Char('o')
334 && c
[2] == QLatin1Char('o') && c
[3] == QLatin1Char('l')
335 && c
[4] == QLatin1Char('e') && c
[5] == QLatin1Char('a')
336 && c
[6] == QLatin1Char('n'))
337 return QScriptGrammar::T_RESERVED_WORD
;
338 else if (c
[0] == QLatin1Char('e') && c
[1] == QLatin1Char('x')
339 && c
[2] == QLatin1Char('t') && c
[3] == QLatin1Char('e')
340 && c
[4] == QLatin1Char('n') && c
[5] == QLatin1Char('d')
341 && c
[6] == QLatin1Char('s'))
342 return QScriptGrammar::T_RESERVED_WORD
;
343 else if (c
[0] == QLatin1Char('p') && c
[1] == QLatin1Char('a')
344 && c
[2] == QLatin1Char('c') && c
[3] == QLatin1Char('k')
345 && c
[4] == QLatin1Char('a') && c
[5] == QLatin1Char('g')
346 && c
[6] == QLatin1Char('e'))
347 return QScriptGrammar::T_RESERVED_WORD
;
348 else if (c
[0] == QLatin1Char('p') && c
[1] == QLatin1Char('r')
349 && c
[2] == QLatin1Char('i') && c
[3] == QLatin1Char('v')
350 && c
[4] == QLatin1Char('a') && c
[5] == QLatin1Char('t')
351 && c
[6] == QLatin1Char('e'))
352 return QScriptGrammar::T_RESERVED_WORD
;
357 if (c
[0] == QLatin1Char('c') && c
[1] == QLatin1Char('o')
358 && c
[2] == QLatin1Char('n') && c
[3] == QLatin1Char('t')
359 && c
[4] == QLatin1Char('i') && c
[5] == QLatin1Char('n')
360 && c
[6] == QLatin1Char('u') && c
[7] == QLatin1Char('e'))
361 return QScriptGrammar::T_CONTINUE
;
362 else if (c
[0] == QLatin1Char('f') && c
[1] == QLatin1Char('u')
363 && c
[2] == QLatin1Char('n') && c
[3] == QLatin1Char('c')
364 && c
[4] == QLatin1Char('t') && c
[5] == QLatin1Char('i')
365 && c
[6] == QLatin1Char('o') && c
[7] == QLatin1Char('n'))
366 return QScriptGrammar::T_FUNCTION
;
367 else if (c
[0] == QLatin1Char('d') && c
[1] == QLatin1Char('e')
368 && c
[2] == QLatin1Char('b') && c
[3] == QLatin1Char('u')
369 && c
[4] == QLatin1Char('g') && c
[5] == QLatin1Char('g')
370 && c
[6] == QLatin1Char('e') && c
[7] == QLatin1Char('r'))
371 return QScriptGrammar::T_DEBUGGER
;
372 else if (check_reserved
) {
373 if (c
[0] == QLatin1Char('a') && c
[1] == QLatin1Char('b')
374 && c
[2] == QLatin1Char('s') && c
[3] == QLatin1Char('t')
375 && c
[4] == QLatin1Char('r') && c
[5] == QLatin1Char('a')
376 && c
[6] == QLatin1Char('c') && c
[7] == QLatin1Char('t'))
377 return QScriptGrammar::T_RESERVED_WORD
;
378 else if (c
[0] == QLatin1Char('v') && c
[1] == QLatin1Char('o')
379 && c
[2] == QLatin1Char('l') && c
[3] == QLatin1Char('a')
380 && c
[4] == QLatin1Char('t') && c
[5] == QLatin1Char('i')
381 && c
[6] == QLatin1Char('l') && c
[7] == QLatin1Char('e'))
382 return QScriptGrammar::T_RESERVED_WORD
;
387 if (check_reserved
) {
388 if (c
[0] == QLatin1Char('i') && c
[1] == QLatin1Char('n')
389 && c
[2] == QLatin1Char('t') && c
[3] == QLatin1Char('e')
390 && c
[4] == QLatin1Char('r') && c
[5] == QLatin1Char('f')
391 && c
[6] == QLatin1Char('a') && c
[7] == QLatin1Char('c')
392 && c
[8] == QLatin1Char('e'))
393 return QScriptGrammar::T_RESERVED_WORD
;
394 else if (c
[0] == QLatin1Char('t') && c
[1] == QLatin1Char('r')
395 && c
[2] == QLatin1Char('a') && c
[3] == QLatin1Char('n')
396 && c
[4] == QLatin1Char('s') && c
[5] == QLatin1Char('i')
397 && c
[6] == QLatin1Char('e') && c
[7] == QLatin1Char('n')
398 && c
[8] == QLatin1Char('t'))
399 return QScriptGrammar::T_RESERVED_WORD
;
400 else if (c
[0] == QLatin1Char('p') && c
[1] == QLatin1Char('r')
401 && c
[2] == QLatin1Char('o') && c
[3] == QLatin1Char('t')
402 && c
[4] == QLatin1Char('e') && c
[5] == QLatin1Char('c')
403 && c
[6] == QLatin1Char('t') && c
[7] == QLatin1Char('e')
404 && c
[8] == QLatin1Char('d'))
405 return QScriptGrammar::T_RESERVED_WORD
;
410 if (c
[0] == QLatin1Char('i') && c
[1] == QLatin1Char('n')
411 && c
[2] == QLatin1Char('s') && c
[3] == QLatin1Char('t')
412 && c
[4] == QLatin1Char('a') && c
[5] == QLatin1Char('n')
413 && c
[6] == QLatin1Char('c') && c
[7] == QLatin1Char('e')
414 && c
[8] == QLatin1Char('o') && c
[9] == QLatin1Char('f'))
415 return QScriptGrammar::T_INSTANCEOF
;
416 else if (check_reserved
) {
417 if (c
[0] == QLatin1Char('i') && c
[1] == QLatin1Char('m')
418 && c
[2] == QLatin1Char('p') && c
[3] == QLatin1Char('l')
419 && c
[4] == QLatin1Char('e') && c
[5] == QLatin1Char('m')
420 && c
[6] == QLatin1Char('e') && c
[7] == QLatin1Char('n')
421 && c
[8] == QLatin1Char('t') && c
[9] == QLatin1Char('s'))
422 return QScriptGrammar::T_RESERVED_WORD
;
427 if (check_reserved
) {
428 if (c
[0] == QLatin1Char('s') && c
[1] == QLatin1Char('y')
429 && c
[2] == QLatin1Char('n') && c
[3] == QLatin1Char('c')
430 && c
[4] == QLatin1Char('h') && c
[5] == QLatin1Char('r')
431 && c
[6] == QLatin1Char('o') && c
[7] == QLatin1Char('n')
432 && c
[8] == QLatin1Char('i') && c
[9] == QLatin1Char('z')
433 && c
[10] == QLatin1Char('e') && c
[11] == QLatin1Char('d'))
434 return QScriptGrammar::T_RESERVED_WORD
;
443 int QScript::Lexer::lex()
447 ushort stringType
= 0; // either single or double quotes
452 // did we push a token on the stack previously ?
453 // (after an automatic semicolon insertion)
454 if (stackToken
>= 0) {
463 if (isWhiteSpace()) {
465 } else if (current
== '/' && next1
== '/') {
468 state
= InSingleLineComment
;
469 } else if (current
== '/' && next1
== '*') {
472 state
= InMultiLineComment
;
473 } else if (current
== 0) {
474 syncProhibitAutomaticSemicolon();
475 if (!terminator
&& !delimited
&& !prohibitAutomaticSemicolon
) {
476 // automatic semicolon insertion if program incomplete
477 token
= QScriptGrammar::T_SEMICOLON
;
483 } else if (isLineTerminator()) {
484 shiftWindowsLineBreak();
489 syncProhibitAutomaticSemicolon();
491 token
= QScriptGrammar::T_SEMICOLON
;
494 } else if (current
== '"' || current
== '\'') {
497 stringType
= current
;
498 } else if (isIdentLetter(current
)) {
501 state
= InIdentifier
;
502 } else if (current
== '0') {
506 } else if (isDecimalDigit(current
)) {
510 } else if (current
== '.' && isDecimalDigit(next1
)) {
516 token
= matchPunctuator(current
, next1
, next2
, next3
);
518 if (terminator
&& !delimited
&& !prohibitAutomaticSemicolon
519 && (token
== QScriptGrammar::T_PLUS_PLUS
520 || token
== QScriptGrammar::T_MINUS_MINUS
)) {
521 // automatic semicolon insertion
523 token
= QScriptGrammar::T_SEMICOLON
;
529 err
= IllegalCharacter
;
530 errmsg
= QLatin1String("Illegal character");
535 if (current
== stringType
) {
538 } else if (current
== 0 || isLineTerminator()) {
540 err
= UnclosedStringLiteral
;
541 errmsg
= QLatin1String("Unclosed string at end of line");
542 } else if (current
== '\\') {
543 state
= InEscapeSequence
;
548 // Escape Sequences inside of strings
549 case InEscapeSequence
:
550 if (isOctalDigit(current
)) {
551 if (current
>= '0' && current
<= '3' &&
552 isOctalDigit(next1
) && isOctalDigit(next2
)) {
553 record16(convertOctal(current
, next1
, next2
));
556 } else if (isOctalDigit(current
) &&
557 isOctalDigit(next1
)) {
558 record16(convertOctal('0', current
, next1
));
561 } else if (isOctalDigit(current
)) {
562 record16(convertOctal('0', '0', current
));
566 err
= IllegalEscapeSequence
;
567 errmsg
= QLatin1String("Illegal escape squence");
569 } else if (current
== 'x')
571 else if (current
== 'u')
572 state
= InUnicodeEscape
;
574 if (isLineTerminator()) {
575 shiftWindowsLineBreak();
580 record16(singleEscape(current
));
586 if (isHexDigit(current
) && isHexDigit(next1
)) {
588 record16(QLatin1Char(convertHex(current
, next1
)));
590 } else if (current
== stringType
) {
591 record16(QLatin1Char('x'));
595 record16(QLatin1Char('x'));
600 case InUnicodeEscape
:
601 if (isHexDigit(current
) && isHexDigit(next1
) &&
602 isHexDigit(next2
) && isHexDigit(next3
)) {
603 record16(convertUnicode(current
, next1
, next2
, next3
));
606 } else if (current
== stringType
) {
607 record16(QLatin1Char('u'));
612 err
= IllegalUnicodeEscapeSequence
;
613 errmsg
= QLatin1String("Illegal unicode escape sequence");
616 case InSingleLineComment
:
617 if (isLineTerminator()) {
618 shiftWindowsLineBreak();
624 token
= QScriptGrammar::T_SEMICOLON
;
628 } else if (current
== 0) {
632 case InMultiLineComment
:
635 err
= UnclosedComment
;
636 errmsg
= QLatin1String("Unclosed comment at end of file");
637 } else if (isLineTerminator()) {
638 shiftWindowsLineBreak();
640 } else if (current
== '*' && next1
== '/') {
646 if (isIdentLetter(current
) || isDecimalDigit(current
)) {
653 if (current
== 'x' || current
== 'X') {
656 } else if (current
== '.') {
659 } else if (current
== 'e' || current
== 'E') {
661 state
= InExponentIndicator
;
662 } else if (isOctalDigit(current
)) {
665 } else if (isDecimalDigit(current
)) {
673 if (isHexDigit(current
))
679 if (isOctalDigit(current
)) {
681 } else if (isDecimalDigit(current
)) {
689 if (isDecimalDigit(current
)) {
691 } else if (current
== '.') {
694 } else if (current
== 'e' || current
== 'E') {
696 state
= InExponentIndicator
;
702 if (isDecimalDigit(current
)) {
704 } else if (current
== 'e' || current
== 'E') {
706 state
= InExponentIndicator
;
711 case InExponentIndicator
:
712 if (current
== '+' || current
== '-') {
714 } else if (isDecimalDigit(current
)) {
719 err
= IllegalExponentIndicator
;
720 errmsg
= QLatin1String("Illegal syntax for exponential number");
724 if (isDecimalDigit(current
)) {
731 Q_ASSERT_X(0, "Lexer::lex", "Unhandled state in switch statement");
734 // move on to the next character
737 if (state
!= Start
&& state
!= InSingleLineComment
)
741 // no identifiers allowed directly after numeric literal, e.g. "3in" is bad
742 if ((state
== Number
|| state
== Octal
|| state
== Hex
)
743 && isIdentLetter(current
)) {
745 err
= IllegalIdentifier
;
746 errmsg
= QLatin1String("Identifier cannot start with numeric literal");
750 buffer8
[pos8
] = '\0';
753 if (state
== Number
) {
754 dval
= qstrtod(buffer8
, 0, 0);
755 } else if (state
== Hex
) { // scan hex numbers
756 dval
= QScript::integerFromString(buffer8
, pos8
, 16);
758 } else if (state
== Octal
) { // scan octal number
759 dval
= QScript::integerFromString(buffer8
, pos8
, 8);
763 restrKeyword
= false;
766 switch (parenthesesState
) {
767 case IgnoreParentheses
:
769 case CountParentheses
:
770 if (token
== QScriptGrammar::T_RPAREN
) {
772 if (parenthesesCount
== 0)
773 parenthesesState
= BalancedParentheses
;
774 } else if (token
== QScriptGrammar::T_LPAREN
) {
778 case BalancedParentheses
:
779 parenthesesState
= IgnoreParentheses
;
787 if(token
== QScriptGrammar::T_RBRACE
|| token
== QScriptGrammar::T_SEMICOLON
)
791 if ((token
= findReservedWord(buffer16
, pos16
)) < 0) {
792 /* TODO: close leak on parse error. same holds true for String */
794 qsyylval
.ustr
= driver
->intern(buffer16
, pos16
);
797 return QScriptGrammar::T_IDENTIFIER
;
799 if (token
== QScriptGrammar::T_CONTINUE
|| token
== QScriptGrammar::T_BREAK
800 || token
== QScriptGrammar::T_RETURN
|| token
== QScriptGrammar::T_THROW
) {
802 } else if (token
== QScriptGrammar::T_IF
|| token
== QScriptGrammar::T_FOR
803 || token
== QScriptGrammar::T_WHILE
|| token
== QScriptGrammar::T_WITH
) {
804 parenthesesState
= CountParentheses
;
805 parenthesesCount
= 0;
806 } else if (token
== QScriptGrammar::T_DO
) {
807 parenthesesState
= BalancedParentheses
;
812 qsyylval
.ustr
= driver
->intern(buffer16
, pos16
);
815 return QScriptGrammar::T_STRING_LITERAL
;
817 qsyylval
.dval
= dval
;
818 return QScriptGrammar::T_NUMERIC_LITERAL
;
822 Q_ASSERT(!"unhandled numeration value in switch");
827 bool QScript::Lexer::isWhiteSpace() const
829 return (current
== ' ' || current
== '\t' ||
830 current
== 0x0b || current
== 0x0c);
833 bool QScript::Lexer::isLineTerminator() const
835 return (current
== '\n' || current
== '\r');
838 bool QScript::Lexer::isIdentLetter(ushort c
)
840 /* TODO: allow other legitimate unicode chars */
841 return ((c
>= 'a' && c
<= 'z')
842 || (c
>= 'A' && c
<= 'Z')
847 bool QScript::Lexer::isDecimalDigit(ushort c
)
849 return (c
>= '0' && c
<= '9');
852 bool QScript::Lexer::isHexDigit(ushort c
) const
854 return ((c
>= '0' && c
<= '9')
855 || (c
>= 'a' && c
<= 'f')
856 || (c
>= 'A' && c
<= 'F'));
859 bool QScript::Lexer::isOctalDigit(ushort c
) const
861 return (c
>= '0' && c
<= '7');
864 int QScript::Lexer::matchPunctuator(ushort c1
, ushort c2
,
865 ushort c3
, ushort c4
)
867 if (c1
== '>' && c2
== '>' && c3
== '>' && c4
== '=') {
869 return QScriptGrammar::T_GT_GT_GT_EQ
;
870 } else if (c1
== '=' && c2
== '=' && c3
== '=') {
872 return QScriptGrammar::T_EQ_EQ_EQ
;
873 } else if (c1
== '!' && c2
== '=' && c3
== '=') {
875 return QScriptGrammar::T_NOT_EQ_EQ
;
876 } else if (c1
== '>' && c2
== '>' && c3
== '>') {
878 return QScriptGrammar::T_GT_GT_GT
;
879 } else if (c1
== '<' && c2
== '<' && c3
== '=') {
881 return QScriptGrammar::T_LT_LT_EQ
;
882 } else if (c1
== '>' && c2
== '>' && c3
== '=') {
884 return QScriptGrammar::T_GT_GT_EQ
;
885 } else if (c1
== '<' && c2
== '=') {
887 return QScriptGrammar::T_LE
;
888 } else if (c1
== '>' && c2
== '=') {
890 return QScriptGrammar::T_GE
;
891 } else if (c1
== '!' && c2
== '=') {
893 return QScriptGrammar::T_NOT_EQ
;
894 } else if (c1
== '+' && c2
== '+') {
896 return QScriptGrammar::T_PLUS_PLUS
;
897 } else if (c1
== '-' && c2
== '-') {
899 return QScriptGrammar::T_MINUS_MINUS
;
900 } else if (c1
== '=' && c2
== '=') {
902 return QScriptGrammar::T_EQ_EQ
;
903 } else if (c1
== '+' && c2
== '=') {
905 return QScriptGrammar::T_PLUS_EQ
;
906 } else if (c1
== '-' && c2
== '=') {
908 return QScriptGrammar::T_MINUS_EQ
;
909 } else if (c1
== '*' && c2
== '=') {
911 return QScriptGrammar::T_STAR_EQ
;
912 } else if (c1
== '/' && c2
== '=') {
914 return QScriptGrammar::T_DIVIDE_EQ
;
915 } else if (c1
== '&' && c2
== '=') {
917 return QScriptGrammar::T_AND_EQ
;
918 } else if (c1
== '^' && c2
== '=') {
920 return QScriptGrammar::T_XOR_EQ
;
921 } else if (c1
== '%' && c2
== '=') {
923 return QScriptGrammar::T_REMAINDER_EQ
;
924 } else if (c1
== '|' && c2
== '=') {
926 return QScriptGrammar::T_OR_EQ
;
927 } else if (c1
== '<' && c2
== '<') {
929 return QScriptGrammar::T_LT_LT
;
930 } else if (c1
== '>' && c2
== '>') {
932 return QScriptGrammar::T_GT_GT
;
933 } else if (c1
== '&' && c2
== '&') {
935 return QScriptGrammar::T_AND_AND
;
936 } else if (c1
== '|' && c2
== '|') {
938 return QScriptGrammar::T_OR_OR
;
942 case '=': shift(1); return QScriptGrammar::T_EQ
;
943 case '>': shift(1); return QScriptGrammar::T_GT
;
944 case '<': shift(1); return QScriptGrammar::T_LT
;
945 case ',': shift(1); return QScriptGrammar::T_COMMA
;
946 case '!': shift(1); return QScriptGrammar::T_NOT
;
947 case '~': shift(1); return QScriptGrammar::T_TILDE
;
948 case '?': shift(1); return QScriptGrammar::T_QUESTION
;
949 case ':': shift(1); return QScriptGrammar::T_COLON
;
950 case '.': shift(1); return QScriptGrammar::T_DOT
;
951 case '+': shift(1); return QScriptGrammar::T_PLUS
;
952 case '-': shift(1); return QScriptGrammar::T_MINUS
;
953 case '*': shift(1); return QScriptGrammar::T_STAR
;
954 case '/': shift(1); return QScriptGrammar::T_DIVIDE_
;
955 case '&': shift(1); return QScriptGrammar::T_AND
;
956 case '|': shift(1); return QScriptGrammar::T_OR
;
957 case '^': shift(1); return QScriptGrammar::T_XOR
;
958 case '%': shift(1); return QScriptGrammar::T_REMAINDER
;
959 case '(': shift(1); return QScriptGrammar::T_LPAREN
;
960 case ')': shift(1); return QScriptGrammar::T_RPAREN
;
961 case '{': shift(1); return QScriptGrammar::T_LBRACE
;
962 case '}': shift(1); return QScriptGrammar::T_RBRACE
;
963 case '[': shift(1); return QScriptGrammar::T_LBRACKET
;
964 case ']': shift(1); return QScriptGrammar::T_RBRACKET
;
965 case ';': shift(1); return QScriptGrammar::T_SEMICOLON
;
971 ushort
QScript::Lexer::singleEscape(ushort c
) const
997 ushort
QScript::Lexer::convertOctal(ushort c1
, ushort c2
,
1000 return ((c1
- '0') * 64 + (c2
- '0') * 8 + c3
- '0');
1003 unsigned char QScript::Lexer::convertHex(ushort c
)
1005 if (c
>= '0' && c
<= '9')
1007 else if (c
>= 'a' && c
<= 'f')
1008 return (c
- 'a' + 10);
1010 return (c
- 'A' + 10);
1013 unsigned char QScript::Lexer::convertHex(ushort c1
, ushort c2
)
1015 return ((convertHex(c1
) << 4) + convertHex(c2
));
1018 QChar
QScript::Lexer::convertUnicode(ushort c1
, ushort c2
,
1019 ushort c3
, ushort c4
)
1021 return QChar((convertHex(c3
) << 4) + convertHex(c4
),
1022 (convertHex(c1
) << 4) + convertHex(c2
));
1025 void QScript::Lexer::record8(ushort c
)
1027 Q_ASSERT(c
<= 0xff);
1029 // enlarge buffer if full
1030 if (pos8
>= size8
- 1) {
1031 char *tmp
= new char[2 * size8
];
1032 memcpy(tmp
, buffer8
, size8
* sizeof(char));
1038 buffer8
[pos8
++] = (char) c
;
1041 void QScript::Lexer::record16(QChar c
)
1043 // enlarge buffer if full
1044 if (pos16
>= size16
- 1) {
1045 QChar
*tmp
= new QChar
[2 * size16
];
1046 memcpy(tmp
, buffer16
, size16
* sizeof(QChar
));
1052 buffer16
[pos16
++] = c
;
1055 void QScript::Lexer::recordStartPos()
1057 startlineno
= yylineno
;
1058 startcolumn
= yycolumn
;
1061 bool QScript::Lexer::scanRegExp(RegExpBodyPrefix prefix
)
1064 bool lastWasEscape
= false;
1066 if (prefix
== EqualPrefix
)
1067 record16(QLatin1Char('='));
1070 if (isLineTerminator() || current
== 0) {
1071 errmsg
= QLatin1String("Unterminated regular expression literal");
1074 else if (current
!= '/' || lastWasEscape
== true)
1077 lastWasEscape
= !lastWasEscape
&& (current
== '\\');
1081 pattern
= driver
->intern(buffer16
, pos16
);
1092 while (isIdentLetter(current
)) {
1093 int flag
= QScript::Ecma::RegExp::flagFromChar(current
);
1095 errmsg
= QString::fromLatin1("Invalid regular expression flag '%0'")
1096 .arg(QChar(current
));
1107 void QScript::Lexer::syncProhibitAutomaticSemicolon()
1109 if (parenthesesState
== BalancedParentheses
) {
1110 // we have seen something like "if (foo)", which means we should
1111 // never insert an automatic semicolon at this point, since it would
1112 // then be expanded into an empty statement (ECMA-262 7.9.1)
1113 prohibitAutomaticSemicolon
= true;
1114 parenthesesState
= IgnoreParentheses
;
1116 prohibitAutomaticSemicolon
= false;
1122 #endif // QT_NO_SCRIPT