source: trunk/src/declarative/qml/parser/qdeclarativejslexer.cpp

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 48.0 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the QtDeclarative module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
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.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#ifdef HAVE_CONFIG_H
43#include <config.h>
44#endif
45
46#include "private/qdeclarativejslexer_p.h"
47
48#include "private/qdeclarativejsglobal_p.h"
49#include "private/qdeclarativejsengine_p.h"
50#include "private/qdeclarativejsgrammar_p.h"
51
52#include <QtCore/qcoreapplication.h>
53
54#include <ctype.h>
55#include <stdlib.h>
56#include <stdio.h>
57#include <string.h>
58
59QT_BEGIN_NAMESPACE
60Q_CORE_EXPORT double qstrtod(const char *s00, char const **se, bool *ok);
61QT_END_NAMESPACE
62
63QT_QML_BEGIN_NAMESPACE
64
65#define shiftWindowsLineBreak() \
66 do { \
67 if (((current == '\r') && (next1 == '\n')) \
68 || ((current == '\n') && (next1 == '\r'))) { \
69 shift(1); \
70 } \
71 } \
72 while (0)
73
74namespace QDeclarativeJS {
75extern double integerFromString(const char *buf, int size, int radix);
76}
77
78using namespace QDeclarativeJS;
79
80Lexer::Lexer(Engine *eng, bool tokenizeComments)
81 : driver(eng),
82 yylineno(0),
83 done(false),
84 size8(128), size16(128),
85 pos8(0), pos16(0),
86 terminator(false),
87 restrKeyword(false),
88 delimited(false),
89 stackToken(-1),
90 state(Start),
91 pos(0),
92 code(0), length(0),
93 yycolumn(0),
94 startpos(0),
95 startlineno(0), startcolumn(0),
96 bol(true),
97 current(0), next1(0), next2(0), next3(0),
98 err(NoError),
99 wantRx(false),
100 check_reserved(true),
101 parenthesesState(IgnoreParentheses),
102 parenthesesCount(0),
103 prohibitAutomaticSemicolon(false),
104 tokenizeComments(tokenizeComments)
105{
106 if (driver) driver->setLexer(this);
107 // allocate space for read buffers
108 buffer8 = new char[size8];
109 buffer16 = new QChar[size16];
110 pattern = 0;
111 flags = 0;
112
113}
114
115Lexer::~Lexer()
116{
117 delete [] buffer8;
118 delete [] buffer16;
119}
120
121void Lexer::setCode(const QString &c, int lineno)
122{
123 errmsg.clear();
124 yylineno = lineno;
125 yycolumn = 1;
126 restrKeyword = false;
127 delimited = false;
128 stackToken = -1;
129 pos = 0;
130 code = c.unicode();
131 length = c.length();
132 bol = true;
133
134 // read first characters
135 current = (length > 0) ? code[0].unicode() : 0;
136 next1 = (length > 1) ? code[1].unicode() : 0;
137 next2 = (length > 2) ? code[2].unicode() : 0;
138 next3 = (length > 3) ? code[3].unicode() : 0;
139}
140
141void Lexer::shift(uint p)
142{
143 while (p--) {
144 ++pos;
145 ++yycolumn;
146 current = next1;
147 next1 = next2;
148 next2 = next3;
149 next3 = (pos + 3 < length) ? code[pos+3].unicode() : 0;
150 }
151}
152
153void Lexer::setDone(State s)
154{
155 state = s;
156 done = true;
157}
158
159int Lexer::findReservedWord(const QChar *c, int size) const
160{
161 switch (size) {
162 case 2: {
163 if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('o'))
164 return QDeclarativeJSGrammar::T_DO;
165 else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('f'))
166 return QDeclarativeJSGrammar::T_IF;
167 else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n'))
168 return QDeclarativeJSGrammar::T_IN;
169 else if (c[0] == QLatin1Char('a') && c[1] == QLatin1Char('s'))
170 return QDeclarativeJSGrammar::T_AS;
171 else if (c[0] == QLatin1Char('o') && c[1] == QLatin1Char('n'))
172 return QDeclarativeJSGrammar::T_ON;
173 } break;
174
175 case 3: {
176 if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('o') && c[2] == QLatin1Char('r'))
177 return QDeclarativeJSGrammar::T_FOR;
178 else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('e') && c[2] == QLatin1Char('w'))
179 return QDeclarativeJSGrammar::T_NEW;
180 else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r') && c[2] == QLatin1Char('y'))
181 return QDeclarativeJSGrammar::T_TRY;
182 else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('a') && c[2] == QLatin1Char('r'))
183 return QDeclarativeJSGrammar::T_VAR;
184 else if (check_reserved) {
185 if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n') && c[2] == QLatin1Char('t'))
186 return QDeclarativeJSGrammar::T_RESERVED_WORD;
187 }
188 } break;
189
190 case 4: {
191 if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('a')
192 && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('e'))
193 return QDeclarativeJSGrammar::T_CASE;
194 else if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('l')
195 && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('e'))
196 return QDeclarativeJSGrammar::T_ELSE;
197 else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h')
198 && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('s'))
199 return QDeclarativeJSGrammar::T_THIS;
200 else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('o')
201 && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('d'))
202 return QDeclarativeJSGrammar::T_VOID;
203 else if (c[0] == QLatin1Char('w') && c[1] == QLatin1Char('i')
204 && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('h'))
205 return QDeclarativeJSGrammar::T_WITH;
206 else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r')
207 && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('e'))
208 return QDeclarativeJSGrammar::T_TRUE;
209 else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('u')
210 && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('l'))
211 return QDeclarativeJSGrammar::T_NULL;
212 else if (check_reserved) {
213 if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('n')
214 && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('m'))
215 return QDeclarativeJSGrammar::T_RESERVED_WORD;
216 else if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('y')
217 && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e'))
218 return QDeclarativeJSGrammar::T_RESERVED_WORD;
219 else if (c[0] == QLatin1Char('l') && c[1] == QLatin1Char('o')
220 && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('g'))
221 return QDeclarativeJSGrammar::T_RESERVED_WORD;
222 else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('h')
223 && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('r'))
224 return QDeclarativeJSGrammar::T_RESERVED_WORD;
225 else if (c[0] == QLatin1Char('g') && c[1] == QLatin1Char('o')
226 && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('o'))
227 return QDeclarativeJSGrammar::T_RESERVED_WORD;
228 }
229 } break;
230
231 case 5: {
232 if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('r')
233 && c[2] == QLatin1Char('e') && c[3] == QLatin1Char('a')
234 && c[4] == QLatin1Char('k'))
235 return QDeclarativeJSGrammar::T_BREAK;
236 else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('a')
237 && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('c')
238 && c[4] == QLatin1Char('h'))
239 return QDeclarativeJSGrammar::T_CATCH;
240 else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h')
241 && c[2] == QLatin1Char('r') && c[3] == QLatin1Char('o')
242 && c[4] == QLatin1Char('w'))
243 return QDeclarativeJSGrammar::T_THROW;
244 else if (c[0] == QLatin1Char('w') && c[1] == QLatin1Char('h')
245 && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('l')
246 && c[4] == QLatin1Char('e'))
247 return QDeclarativeJSGrammar::T_WHILE;
248 else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('o')
249 && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('s')
250 && c[4] == QLatin1Char('t'))
251 return QDeclarativeJSGrammar::T_CONST;
252 else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('a')
253 && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('s')
254 && c[4] == QLatin1Char('e'))
255 return QDeclarativeJSGrammar::T_FALSE;
256 else if (check_reserved) {
257 if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('h')
258 && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('r')
259 && c[4] == QLatin1Char('t'))
260 return QDeclarativeJSGrammar::T_RESERVED_WORD;
261 else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('u')
262 && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('e')
263 && c[4] == QLatin1Char('r'))
264 return QDeclarativeJSGrammar::T_RESERVED_WORD;
265 else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('i')
266 && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('a')
267 && c[4] == QLatin1Char('l'))
268 return QDeclarativeJSGrammar::T_RESERVED_WORD;
269 else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('l')
270 && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('s')
271 && c[4] == QLatin1Char('s'))
272 return QDeclarativeJSGrammar::T_RESERVED_WORD;
273 else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('l')
274 && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('a')
275 && c[4] == QLatin1Char('t'))
276 return QDeclarativeJSGrammar::T_RESERVED_WORD;
277 }
278 } break;
279
280 case 6: {
281 if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('e')
282 && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('e')
283 && c[4] == QLatin1Char('t') && c[5] == QLatin1Char('e'))
284 return QDeclarativeJSGrammar::T_DELETE;
285 else if (c[0] == QLatin1Char('r') && c[1] == QLatin1Char('e')
286 && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('u')
287 && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('n'))
288 return QDeclarativeJSGrammar::T_RETURN;
289 else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('w')
290 && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('t')
291 && c[4] == QLatin1Char('c') && c[5] == QLatin1Char('h'))
292 return QDeclarativeJSGrammar::T_SWITCH;
293 else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('y')
294 && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('e')
295 && c[4] == QLatin1Char('o') && c[5] == QLatin1Char('f'))
296 return QDeclarativeJSGrammar::T_TYPEOF;
297 else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('m')
298 && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('o')
299 && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('t'))
300 return QDeclarativeJSGrammar::T_IMPORT;
301 else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('i')
302 && c[2] == QLatin1Char('g') && c[3] == QLatin1Char('n')
303 && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('l'))
304 return QDeclarativeJSGrammar::T_SIGNAL;
305 else if (check_reserved) {
306 if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('x')
307 && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('o')
308 && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('t'))
309 return QDeclarativeJSGrammar::T_RESERVED_WORD;
310 else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('t')
311 && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('t')
312 && c[4] == QLatin1Char('i') && c[5] == QLatin1Char('c'))
313 return QDeclarativeJSGrammar::T_RESERVED_WORD;
314 else if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('o')
315 && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('b')
316 && c[4] == QLatin1Char('l') && c[5] == QLatin1Char('e'))
317 return QDeclarativeJSGrammar::T_RESERVED_WORD;
318 else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('m')
319 && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('o')
320 && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('t'))
321 return QDeclarativeJSGrammar::T_RESERVED_WORD;
322 else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('u')
323 && c[2] == QLatin1Char('b') && c[3] == QLatin1Char('l')
324 && c[4] == QLatin1Char('i') && c[5] == QLatin1Char('c'))
325 return QDeclarativeJSGrammar::T_PUBLIC;
326 else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('a')
327 && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('i')
328 && c[4] == QLatin1Char('v') && c[5] == QLatin1Char('e'))
329 return QDeclarativeJSGrammar::T_RESERVED_WORD;
330 else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h')
331 && c[2] == QLatin1Char('r') && c[3] == QLatin1Char('o')
332 && c[4] == QLatin1Char('w') && c[5] == QLatin1Char('s'))
333 return QDeclarativeJSGrammar::T_RESERVED_WORD;
334 }
335 } break;
336
337 case 7: {
338 if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('e')
339 && c[2] == QLatin1Char('f') && c[3] == QLatin1Char('a')
340 && c[4] == QLatin1Char('u') && c[5] == QLatin1Char('l')
341 && c[6] == QLatin1Char('t'))
342 return QDeclarativeJSGrammar::T_DEFAULT;
343 else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('i')
344 && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('a')
345 && c[4] == QLatin1Char('l') && c[5] == QLatin1Char('l')
346 && c[6] == QLatin1Char('y'))
347 return QDeclarativeJSGrammar::T_FINALLY;
348 else if (check_reserved) {
349 if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('o')
350 && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('l')
351 && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('a')
352 && c[6] == QLatin1Char('n'))
353 return QDeclarativeJSGrammar::T_RESERVED_WORD;
354 else if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('x')
355 && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e')
356 && c[4] == QLatin1Char('n') && c[5] == QLatin1Char('d')
357 && c[6] == QLatin1Char('s'))
358 return QDeclarativeJSGrammar::T_RESERVED_WORD;
359 else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('a')
360 && c[2] == QLatin1Char('c') && c[3] == QLatin1Char('k')
361 && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('g')
362 && c[6] == QLatin1Char('e'))
363 return QDeclarativeJSGrammar::T_RESERVED_WORD;
364 else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('r')
365 && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('v')
366 && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('t')
367 && c[6] == QLatin1Char('e'))
368 return QDeclarativeJSGrammar::T_RESERVED_WORD;
369 }
370 } break;
371
372 case 8: {
373 if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('o')
374 && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('t')
375 && c[4] == QLatin1Char('i') && c[5] == QLatin1Char('n')
376 && c[6] == QLatin1Char('u') && c[7] == QLatin1Char('e'))
377 return QDeclarativeJSGrammar::T_CONTINUE;
378 else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('u')
379 && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('c')
380 && c[4] == QLatin1Char('t') && c[5] == QLatin1Char('i')
381 && c[6] == QLatin1Char('o') && c[7] == QLatin1Char('n'))
382 return QDeclarativeJSGrammar::T_FUNCTION;
383 else if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('e')
384 && c[2] == QLatin1Char('b') && c[3] == QLatin1Char('u')
385 && c[4] == QLatin1Char('g') && c[5] == QLatin1Char('g')
386 && c[6] == QLatin1Char('e') && c[7] == QLatin1Char('r'))
387 return QDeclarativeJSGrammar::T_DEBUGGER;
388 else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('r')
389 && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('p')
390 && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('r')
391 && c[6] == QLatin1Char('t') && c[7] == QLatin1Char('y'))
392 return QDeclarativeJSGrammar::T_PROPERTY;
393 else if (c[0] == QLatin1Char('r') && c[1] == QLatin1Char('e')
394 && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('d')
395 && c[4] == QLatin1Char('o') && c[5] == QLatin1Char('n')
396 && c[6] == QLatin1Char('l') && c[7] == QLatin1Char('y'))
397 return QDeclarativeJSGrammar::T_READONLY;
398 else if (check_reserved) {
399 if (c[0] == QLatin1Char('a') && c[1] == QLatin1Char('b')
400 && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('t')
401 && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('a')
402 && c[6] == QLatin1Char('c') && c[7] == QLatin1Char('t'))
403 return QDeclarativeJSGrammar::T_RESERVED_WORD;
404 else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('o')
405 && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('a')
406 && c[4] == QLatin1Char('t') && c[5] == QLatin1Char('i')
407 && c[6] == QLatin1Char('l') && c[7] == QLatin1Char('e'))
408 return QDeclarativeJSGrammar::T_RESERVED_WORD;
409 }
410 } break;
411
412 case 9: {
413 if (check_reserved) {
414 if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n')
415 && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e')
416 && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('f')
417 && c[6] == QLatin1Char('a') && c[7] == QLatin1Char('c')
418 && c[8] == QLatin1Char('e'))
419 return QDeclarativeJSGrammar::T_RESERVED_WORD;
420 else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r')
421 && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('n')
422 && c[4] == QLatin1Char('s') && c[5] == QLatin1Char('i')
423 && c[6] == QLatin1Char('e') && c[7] == QLatin1Char('n')
424 && c[8] == QLatin1Char('t'))
425 return QDeclarativeJSGrammar::T_RESERVED_WORD;
426 else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('r')
427 && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('t')
428 && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('c')
429 && c[6] == QLatin1Char('t') && c[7] == QLatin1Char('e')
430 && c[8] == QLatin1Char('d'))
431 return QDeclarativeJSGrammar::T_RESERVED_WORD;
432 }
433 } break;
434
435 case 10: {
436 if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n')
437 && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('t')
438 && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('n')
439 && c[6] == QLatin1Char('c') && c[7] == QLatin1Char('e')
440 && c[8] == QLatin1Char('o') && c[9] == QLatin1Char('f'))
441 return QDeclarativeJSGrammar::T_INSTANCEOF;
442 else if (check_reserved) {
443 if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('m')
444 && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('l')
445 && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('m')
446 && c[6] == QLatin1Char('e') && c[7] == QLatin1Char('n')
447 && c[8] == QLatin1Char('t') && c[9] == QLatin1Char('s'))
448 return QDeclarativeJSGrammar::T_RESERVED_WORD;
449 }
450 } break;
451
452 case 12: {
453 if (check_reserved) {
454 if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('y')
455 && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('c')
456 && c[4] == QLatin1Char('h') && c[5] == QLatin1Char('r')
457 && c[6] == QLatin1Char('o') && c[7] == QLatin1Char('n')
458 && c[8] == QLatin1Char('i') && c[9] == QLatin1Char('z')
459 && c[10] == QLatin1Char('e') && c[11] == QLatin1Char('d'))
460 return QDeclarativeJSGrammar::T_RESERVED_WORD;
461 }
462 } break;
463
464 } // switch
465
466 return -1;
467}
468
469int Lexer::lex()
470{
471 int token = 0;
472 state = Start;
473 ushort stringType = 0; // either single or double quotes
474 bool multiLineString = false;
475 pos8 = pos16 = 0;
476 done = false;
477 terminator = false;
478
479 // did we push a token on the stack previously ?
480 // (after an automatic semicolon insertion)
481 if (stackToken >= 0) {
482 setDone(Other);
483 token = stackToken;
484 stackToken = -1;
485 }
486
487 bool identifierWithEscapedUnicode = false;
488
489 while (!done) {
490 switch (state) {
491 case Start:
492 if (isWhiteSpace()) {
493 // do nothing
494 } else if (current == '/' && next1 == '/') {
495 recordStartPos();
496 shift(1);
497 state = InSingleLineComment;
498 } else if (current == '/' && next1 == '*') {
499 recordStartPos();
500 shift(1);
501 state = InMultiLineComment;
502 } else if (current == 0) {
503 syncProhibitAutomaticSemicolon();
504 if (!terminator && !delimited && !prohibitAutomaticSemicolon) {
505 // automatic semicolon insertion if program incomplete
506 token = QDeclarativeJSGrammar::T_SEMICOLON;
507 stackToken = 0;
508 setDone(Other);
509 } else {
510 setDone(Eof);
511 }
512 } else if (isLineTerminator()) {
513 if (restrKeyword) {
514 // automatic semicolon insertion
515 recordStartPos();
516 token = QDeclarativeJSGrammar::T_SEMICOLON;
517 setDone(Other);
518 } else {
519 shiftWindowsLineBreak();
520 yylineno++;
521 yycolumn = 0;
522 bol = true;
523 terminator = true;
524 syncProhibitAutomaticSemicolon();
525 }
526 } else if (current == '"' || current == '\'') {
527 recordStartPos();
528 state = InString;
529 multiLineString = false;
530 stringType = current;
531 } else if (current == '\\' && next1 == 'u') {
532 identifierWithEscapedUnicode = true;
533 recordStartPos();
534
535 shift(2); // skip the unicode escape prefix `\u'
536
537 if (isHexDigit(current) && isHexDigit(next1) &&
538 isHexDigit(next2) && isHexDigit(next3)) {
539 record16(convertUnicode(current, next1, next2, next3));
540 shift(3);
541 state = InIdentifier;
542 } else {
543 setDone(Bad);
544 err = IllegalUnicodeEscapeSequence;
545 errmsg = QCoreApplication::translate("QDeclarativeParser", "Illegal unicode escape sequence");
546 break;
547 }
548
549 } else if (isIdentLetter(current)) {
550 identifierWithEscapedUnicode = false;
551 recordStartPos();
552 record16(current);
553 state = InIdentifier;
554 } else if (current == '0') {
555 recordStartPos();
556 record8(current);
557 state = InNum0;
558 } else if (isDecimalDigit(current)) {
559 recordStartPos();
560 record8(current);
561 state = InNum;
562 } else if (current == '.' && isDecimalDigit(next1)) {
563 recordStartPos();
564 record8(current);
565 state = InDecimal;
566 } else {
567 recordStartPos();
568 token = matchPunctuator(current, next1, next2, next3);
569 if (token != -1) {
570 if (terminator && !delimited && !prohibitAutomaticSemicolon
571 && (token == QDeclarativeJSGrammar::T_PLUS_PLUS
572 || token == QDeclarativeJSGrammar::T_MINUS_MINUS)) {
573 // automatic semicolon insertion
574 stackToken = token;
575 token = QDeclarativeJSGrammar::T_SEMICOLON;
576 }
577 setDone(Other);
578 }
579 else {
580 setDone(Bad);
581 err = IllegalCharacter;
582 errmsg = QCoreApplication::translate("QDeclarativeParser", "Illegal character");
583 }
584 }
585 break;
586 case InString:
587 if (current == stringType) {
588 shift(1);
589 setDone(String);
590 } else if (isLineTerminator()) {
591 multiLineString = true;
592 record16(current);
593 } else if (current == 0 || isLineTerminator()) {
594 setDone(Bad);
595 err = UnclosedStringLiteral;
596 errmsg = QCoreApplication::translate("QDeclarativeParser", "Unclosed string at end of line");
597 } else if (current == '\\') {
598 state = InEscapeSequence;
599 } else {
600 record16(current);
601 }
602 break;
603 // Escape Sequences inside of strings
604 case InEscapeSequence:
605 if (isOctalDigit(current)) {
606 if (current >= '0' && current <= '3' &&
607 isOctalDigit(next1) && isOctalDigit(next2)) {
608 record16(convertOctal(current, next1, next2));
609 shift(2);
610 state = InString;
611 } else if (isOctalDigit(current) &&
612 isOctalDigit(next1)) {
613 record16(convertOctal('0', current, next1));
614 shift(1);
615 state = InString;
616 } else if (isOctalDigit(current)) {
617 record16(convertOctal('0', '0', current));
618 state = InString;
619 } else {
620 setDone(Bad);
621 err = IllegalEscapeSequence;
622 errmsg = QCoreApplication::translate("QDeclarativeParser", "Illegal escape squence");
623 }
624 } else if (current == 'x')
625 state = InHexEscape;
626 else if (current == 'u')
627 state = InUnicodeEscape;
628 else {
629 if (isLineTerminator()) {
630 shiftWindowsLineBreak();
631 yylineno++;
632 yycolumn = 0;
633 bol = true;
634 } else {
635 record16(singleEscape(current));
636 }
637 state = InString;
638 }
639 break;
640 case InHexEscape:
641 if (isHexDigit(current) && isHexDigit(next1)) {
642 state = InString;
643 record16(QLatin1Char(convertHex(current, next1)));
644 shift(1);
645 } else if (current == stringType) {
646 record16(QLatin1Char('x'));
647 shift(1);
648 setDone(String);
649 } else {
650 record16(QLatin1Char('x'));
651 record16(current);
652 state = InString;
653 }
654 break;
655 case InUnicodeEscape:
656 if (isHexDigit(current) && isHexDigit(next1) &&
657 isHexDigit(next2) && isHexDigit(next3)) {
658 record16(convertUnicode(current, next1, next2, next3));
659 shift(3);
660 state = InString;
661 } else if (current == stringType) {
662 record16(QLatin1Char('u'));
663 shift(1);
664 setDone(String);
665 } else {
666 setDone(Bad);
667 err = IllegalUnicodeEscapeSequence;
668 errmsg = QCoreApplication::translate("QDeclarativeParser", "Illegal unicode escape sequence");
669 }
670 break;
671 case InSingleLineComment:
672 if (isLineTerminator()) {
673 shiftWindowsLineBreak();
674 yylineno++;
675 yycolumn = 0;
676 terminator = true;
677 bol = true;
678 if (restrKeyword) {
679 token = QDeclarativeJSGrammar::T_SEMICOLON;
680 setDone(Other);
681 } else
682 state = Start;
683 if (driver) driver->addComment(startpos+2, tokenLength()-2, startlineno, startcolumn+2);
684 } else if (current == 0) {
685 if (driver) driver->addComment(startpos+2, tokenLength()-2, startlineno, startcolumn+2);
686 setDone(Eof);
687 }
688
689 break;
690 case InMultiLineComment:
691 if (current == 0) {
692 setDone(Bad);
693 err = UnclosedComment;
694 errmsg = QCoreApplication::translate("QDeclarativeParser", "Unclosed comment at end of file");
695 if (driver) driver->addComment(startpos+2, tokenLength()-2, startlineno, startcolumn+2);
696 } else if (isLineTerminator()) {
697 shiftWindowsLineBreak();
698 yylineno++;
699 } else if (current == '*' && next1 == '/') {
700 state = Start;
701 shift(1);
702 if (driver) driver->addComment(startpos+2, tokenLength()-3, startlineno, startcolumn+2);
703 }
704
705 break;
706 case InIdentifier:
707 if (isIdentLetter(current) || isDecimalDigit(current)) {
708 record16(current);
709 break;
710 } else if (current == '\\' && next1 == 'u') {
711 identifierWithEscapedUnicode = true;
712 shift(2); // skip the unicode escape prefix `\u'
713
714 if (isHexDigit(current) && isHexDigit(next1) &&
715 isHexDigit(next2) && isHexDigit(next3)) {
716 record16(convertUnicode(current, next1, next2, next3));
717 shift(3);
718 break;
719 } else {
720 setDone(Bad);
721 err = IllegalUnicodeEscapeSequence;
722 errmsg = QCoreApplication::translate("QDeclarativeParser", "Illegal unicode escape sequence");
723 break;
724 }
725 }
726 setDone(Identifier);
727 break;
728 case InNum0:
729 if (current == 'x' || current == 'X') {
730 record8(current);
731 state = InHex;
732 } else if (current == '.') {
733 record8(current);
734 state = InDecimal;
735 } else if (current == 'e' || current == 'E') {
736 record8(current);
737 state = InExponentIndicator;
738 } else if (isOctalDigit(current)) {
739 record8(current);
740 state = InOctal;
741 } else if (isDecimalDigit(current)) {
742 record8(current);
743 state = InDecimal;
744 } else {
745 setDone(Number);
746 }
747 break;
748 case InHex:
749 if (isHexDigit(current))
750 record8(current);
751 else
752 setDone(Hex);
753 break;
754 case InOctal:
755 if (isOctalDigit(current)) {
756 record8(current);
757 } else if (isDecimalDigit(current)) {
758 record8(current);
759 state = InDecimal;
760 } else {
761 setDone(Octal);
762 }
763 break;
764 case InNum:
765 if (isDecimalDigit(current)) {
766 record8(current);
767 } else if (current == '.') {
768 record8(current);
769 state = InDecimal;
770 } else if (current == 'e' || current == 'E') {
771 record8(current);
772 state = InExponentIndicator;
773 } else {
774 setDone(Number);
775 }
776 break;
777 case InDecimal:
778 if (isDecimalDigit(current)) {
779 record8(current);
780 } else if (current == 'e' || current == 'E') {
781 record8(current);
782 state = InExponentIndicator;
783 } else {
784 setDone(Number);
785 }
786 break;
787 case InExponentIndicator:
788 if (current == '+' || current == '-') {
789 record8(current);
790 } else if (isDecimalDigit(current)) {
791 record8(current);
792 state = InExponent;
793 } else {
794 setDone(Bad);
795 err = IllegalExponentIndicator;
796 errmsg = QCoreApplication::translate("QDeclarativeParser", "Illegal syntax for exponential number");
797 }
798 break;
799 case InExponent:
800 if (isDecimalDigit(current)) {
801 record8(current);
802 } else {
803 setDone(Number);
804 }
805 break;
806 default:
807 Q_ASSERT_X(0, "Lexer::lex", "Unhandled state in switch statement");
808 }
809
810 // move on to the next character
811 if (!done)
812 shift(1);
813 if (state != Start && state != InSingleLineComment)
814 bol = false;
815 }
816
817 // no identifiers allowed directly after numeric literal, e.g. "3in" is bad
818 if ((state == Number || state == Octal || state == Hex)
819 && isIdentLetter(current)) {
820 state = Bad;
821 err = IllegalIdentifier;
822 errmsg = QCoreApplication::translate("QDeclarativeParser", "Identifier cannot start with numeric literal");
823 }
824
825 // terminate string
826 buffer8[pos8] = '\0';
827
828 double dval = 0;
829 if (state == Number) {
830 dval = qstrtod(buffer8, 0, 0);
831 } else if (state == Hex) { // scan hex numbers
832 dval = integerFromString(buffer8, pos8, 16);
833 state = Number;
834 } else if (state == Octal) { // scan octal number
835 dval = integerFromString(buffer8, pos8, 8);
836 state = Number;
837 }
838
839 restrKeyword = false;
840 delimited = false;
841
842 switch (parenthesesState) {
843 case IgnoreParentheses:
844 break;
845 case CountParentheses:
846 if (token == QDeclarativeJSGrammar::T_RPAREN) {
847 --parenthesesCount;
848 if (parenthesesCount == 0)
849 parenthesesState = BalancedParentheses;
850 } else if (token == QDeclarativeJSGrammar::T_LPAREN) {
851 ++parenthesesCount;
852 }
853 break;
854 case BalancedParentheses:
855 parenthesesState = IgnoreParentheses;
856 break;
857 }
858
859 switch (state) {
860 case Eof:
861 return 0;
862 case Other:
863 if (token == QDeclarativeJSGrammar::T_RBRACE || token == QDeclarativeJSGrammar::T_SEMICOLON)
864 delimited = true;
865 return token;
866 case Identifier:
867 token = -1;
868 if (! identifierWithEscapedUnicode)
869 token = findReservedWord(buffer16, pos16);
870
871 if (token < 0) {
872 /* TODO: close leak on parse error. same holds true for String */
873 if (driver)
874 qsyylval.ustr = driver->intern(buffer16, pos16);
875 else
876 qsyylval.ustr = 0;
877 return QDeclarativeJSGrammar::T_IDENTIFIER;
878 }
879 if (token == QDeclarativeJSGrammar::T_CONTINUE || token == QDeclarativeJSGrammar::T_BREAK
880 || token == QDeclarativeJSGrammar::T_RETURN || token == QDeclarativeJSGrammar::T_THROW) {
881 restrKeyword = true;
882 } else if (token == QDeclarativeJSGrammar::T_IF || token == QDeclarativeJSGrammar::T_FOR
883 || token == QDeclarativeJSGrammar::T_WHILE || token == QDeclarativeJSGrammar::T_WITH) {
884 parenthesesState = CountParentheses;
885 parenthesesCount = 0;
886 } else if (token == QDeclarativeJSGrammar::T_DO) {
887 parenthesesState = BalancedParentheses;
888 }
889 return token;
890 case String:
891 if (driver)
892 qsyylval.ustr = driver->intern(buffer16, pos16);
893 else
894 qsyylval.ustr = 0;
895 return multiLineString?QDeclarativeJSGrammar::T_MULTILINE_STRING_LITERAL:QDeclarativeJSGrammar::T_STRING_LITERAL;
896 case Number:
897 qsyylval.dval = dval;
898 return QDeclarativeJSGrammar::T_NUMERIC_LITERAL;
899 case Bad:
900 return -1;
901 default:
902 Q_ASSERT(!"unhandled numeration value in switch");
903 return -1;
904 }
905}
906
907bool Lexer::isWhiteSpace() const
908{
909 return (current == ' ' || current == '\t' ||
910 current == 0x0b || current == 0x0c);
911}
912
913bool Lexer::isLineTerminator() const
914{
915 return (current == '\n' || current == '\r');
916}
917
918bool Lexer::isIdentLetter(ushort c)
919{
920 // ASCII-biased, since all reserved words are ASCII, aand hence the
921 // bulk of content to be parsed.
922 if ((c >= 'a' && c <= 'z')
923 || (c >= 'A' && c <= 'Z')
924 || c == '$'
925 || c == '_')
926 return true;
927 if (c < 128)
928 return false;
929 return QChar(c).isLetterOrNumber();
930}
931
932bool Lexer::isDecimalDigit(ushort c)
933{
934 return (c >= '0' && c <= '9');
935}
936
937bool Lexer::isHexDigit(ushort c) const
938{
939 return ((c >= '0' && c <= '9')
940 || (c >= 'a' && c <= 'f')
941 || (c >= 'A' && c <= 'F'));
942}
943
944bool Lexer::isOctalDigit(ushort c) const
945{
946 return (c >= '0' && c <= '7');
947}
948
949int Lexer::matchPunctuator(ushort c1, ushort c2,
950 ushort c3, ushort c4)
951{
952 if (c1 == '>' && c2 == '>' && c3 == '>' && c4 == '=') {
953 shift(4);
954 return QDeclarativeJSGrammar::T_GT_GT_GT_EQ;
955 } else if (c1 == '=' && c2 == '=' && c3 == '=') {
956 shift(3);
957 return QDeclarativeJSGrammar::T_EQ_EQ_EQ;
958 } else if (c1 == '!' && c2 == '=' && c3 == '=') {
959 shift(3);
960 return QDeclarativeJSGrammar::T_NOT_EQ_EQ;
961 } else if (c1 == '>' && c2 == '>' && c3 == '>') {
962 shift(3);
963 return QDeclarativeJSGrammar::T_GT_GT_GT;
964 } else if (c1 == '<' && c2 == '<' && c3 == '=') {
965 shift(3);
966 return QDeclarativeJSGrammar::T_LT_LT_EQ;
967 } else if (c1 == '>' && c2 == '>' && c3 == '=') {
968 shift(3);
969 return QDeclarativeJSGrammar::T_GT_GT_EQ;
970 } else if (c1 == '<' && c2 == '=') {
971 shift(2);
972 return QDeclarativeJSGrammar::T_LE;
973 } else if (c1 == '>' && c2 == '=') {
974 shift(2);
975 return QDeclarativeJSGrammar::T_GE;
976 } else if (c1 == '!' && c2 == '=') {
977 shift(2);
978 return QDeclarativeJSGrammar::T_NOT_EQ;
979 } else if (c1 == '+' && c2 == '+') {
980 shift(2);
981 return QDeclarativeJSGrammar::T_PLUS_PLUS;
982 } else if (c1 == '-' && c2 == '-') {
983 shift(2);
984 return QDeclarativeJSGrammar::T_MINUS_MINUS;
985 } else if (c1 == '=' && c2 == '=') {
986 shift(2);
987 return QDeclarativeJSGrammar::T_EQ_EQ;
988 } else if (c1 == '+' && c2 == '=') {
989 shift(2);
990 return QDeclarativeJSGrammar::T_PLUS_EQ;
991 } else if (c1 == '-' && c2 == '=') {
992 shift(2);
993 return QDeclarativeJSGrammar::T_MINUS_EQ;
994 } else if (c1 == '*' && c2 == '=') {
995 shift(2);
996 return QDeclarativeJSGrammar::T_STAR_EQ;
997 } else if (c1 == '/' && c2 == '=') {
998 shift(2);
999 return QDeclarativeJSGrammar::T_DIVIDE_EQ;
1000 } else if (c1 == '&' && c2 == '=') {
1001 shift(2);
1002 return QDeclarativeJSGrammar::T_AND_EQ;
1003 } else if (c1 == '^' && c2 == '=') {
1004 shift(2);
1005 return QDeclarativeJSGrammar::T_XOR_EQ;
1006 } else if (c1 == '%' && c2 == '=') {
1007 shift(2);
1008 return QDeclarativeJSGrammar::T_REMAINDER_EQ;
1009 } else if (c1 == '|' && c2 == '=') {
1010 shift(2);
1011 return QDeclarativeJSGrammar::T_OR_EQ;
1012 } else if (c1 == '<' && c2 == '<') {
1013 shift(2);
1014 return QDeclarativeJSGrammar::T_LT_LT;
1015 } else if (c1 == '>' && c2 == '>') {
1016 shift(2);
1017 return QDeclarativeJSGrammar::T_GT_GT;
1018 } else if (c1 == '&' && c2 == '&') {
1019 shift(2);
1020 return QDeclarativeJSGrammar::T_AND_AND;
1021 } else if (c1 == '|' && c2 == '|') {
1022 shift(2);
1023 return QDeclarativeJSGrammar::T_OR_OR;
1024 }
1025
1026 switch(c1) {
1027 case '=': shift(1); return QDeclarativeJSGrammar::T_EQ;
1028 case '>': shift(1); return QDeclarativeJSGrammar::T_GT;
1029 case '<': shift(1); return QDeclarativeJSGrammar::T_LT;
1030 case ',': shift(1); return QDeclarativeJSGrammar::T_COMMA;
1031 case '!': shift(1); return QDeclarativeJSGrammar::T_NOT;
1032 case '~': shift(1); return QDeclarativeJSGrammar::T_TILDE;
1033 case '?': shift(1); return QDeclarativeJSGrammar::T_QUESTION;
1034 case ':': shift(1); return QDeclarativeJSGrammar::T_COLON;
1035 case '.': shift(1); return QDeclarativeJSGrammar::T_DOT;
1036 case '+': shift(1); return QDeclarativeJSGrammar::T_PLUS;
1037 case '-': shift(1); return QDeclarativeJSGrammar::T_MINUS;
1038 case '*': shift(1); return QDeclarativeJSGrammar::T_STAR;
1039 case '/': shift(1); return QDeclarativeJSGrammar::T_DIVIDE_;
1040 case '&': shift(1); return QDeclarativeJSGrammar::T_AND;
1041 case '|': shift(1); return QDeclarativeJSGrammar::T_OR;
1042 case '^': shift(1); return QDeclarativeJSGrammar::T_XOR;
1043 case '%': shift(1); return QDeclarativeJSGrammar::T_REMAINDER;
1044 case '(': shift(1); return QDeclarativeJSGrammar::T_LPAREN;
1045 case ')': shift(1); return QDeclarativeJSGrammar::T_RPAREN;
1046 case '{': shift(1); return QDeclarativeJSGrammar::T_LBRACE;
1047 case '}': shift(1); return QDeclarativeJSGrammar::T_RBRACE;
1048 case '[': shift(1); return QDeclarativeJSGrammar::T_LBRACKET;
1049 case ']': shift(1); return QDeclarativeJSGrammar::T_RBRACKET;
1050 case ';': shift(1); return QDeclarativeJSGrammar::T_SEMICOLON;
1051
1052 default: return -1;
1053 }
1054}
1055
1056ushort Lexer::singleEscape(ushort c) const
1057{
1058 switch(c) {
1059 case 'b':
1060 return 0x08;
1061 case 't':
1062 return 0x09;
1063 case 'n':
1064 return 0x0A;
1065 case 'v':
1066 return 0x0B;
1067 case 'f':
1068 return 0x0C;
1069 case 'r':
1070 return 0x0D;
1071 case '"':
1072 return 0x22;
1073 case '\'':
1074 return 0x27;
1075 case '\\':
1076 return 0x5C;
1077 default:
1078 return c;
1079 }
1080}
1081
1082ushort Lexer::convertOctal(ushort c1, ushort c2,
1083 ushort c3) const
1084{
1085 return ((c1 - '0') * 64 + (c2 - '0') * 8 + c3 - '0');
1086}
1087
1088unsigned char Lexer::convertHex(ushort c)
1089{
1090 if (c >= '0' && c <= '9')
1091 return (c - '0');
1092 else if (c >= 'a' && c <= 'f')
1093 return (c - 'a' + 10);
1094 else
1095 return (c - 'A' + 10);
1096}
1097
1098unsigned char Lexer::convertHex(ushort c1, ushort c2)
1099{
1100 return ((convertHex(c1) << 4) + convertHex(c2));
1101}
1102
1103QChar Lexer::convertUnicode(ushort c1, ushort c2,
1104 ushort c3, ushort c4)
1105{
1106 return QChar((convertHex(c3) << 4) + convertHex(c4),
1107 (convertHex(c1) << 4) + convertHex(c2));
1108}
1109
1110void Lexer::record8(ushort c)
1111{
1112 Q_ASSERT(c <= 0xff);
1113
1114 // enlarge buffer if full
1115 if (pos8 >= size8 - 1) {
1116 char *tmp = new char[2 * size8];
1117 memcpy(tmp, buffer8, size8 * sizeof(char));
1118 delete [] buffer8;
1119 buffer8 = tmp;
1120 size8 *= 2;
1121 }
1122
1123 buffer8[pos8++] = (char) c;
1124}
1125
1126void Lexer::record16(QChar c)
1127{
1128 // enlarge buffer if full
1129 if (pos16 >= size16 - 1) {
1130 QChar *tmp = new QChar[2 * size16];
1131 memcpy(tmp, buffer16, size16 * sizeof(QChar));
1132 delete [] buffer16;
1133 buffer16 = tmp;
1134 size16 *= 2;
1135 }
1136
1137 buffer16[pos16++] = c;
1138}
1139
1140void Lexer::recordStartPos()
1141{
1142 startpos = pos;
1143 startlineno = yylineno;
1144 startcolumn = yycolumn;
1145}
1146
1147bool Lexer::scanRegExp(RegExpBodyPrefix prefix)
1148{
1149 pos16 = 0;
1150 pattern = 0;
1151
1152 if (prefix == EqualPrefix)
1153 record16(QLatin1Char('='));
1154
1155 while (true) {
1156 switch (current) {
1157
1158 case 0: // eof
1159 case '\n': case '\r': // line terminator
1160 errmsg = QCoreApplication::translate("QDeclarativeParser", "Unterminated regular expression literal");
1161 return false;
1162
1163 case '/':
1164 shift(1);
1165
1166 if (driver) // create the pattern
1167 pattern = driver->intern(buffer16, pos16);
1168
1169 // scan the flags
1170 pos16 = 0;
1171 flags = 0;
1172 while (isIdentLetter(current)) {
1173 int flag = Ecma::RegExp::flagFromChar(current);
1174 if (flag == 0) {
1175 errmsg = QCoreApplication::translate("QDeclarativeParser", "Invalid regular expression flag '%0'")
1176 .arg(QChar(current));
1177 return false;
1178 }
1179 flags |= flag;
1180 record16(current);
1181 shift(1);
1182 }
1183 return true;
1184
1185 case '\\':
1186 // regular expression backslash sequence
1187 record16(current);
1188 shift(1);
1189
1190 if (! current || isLineTerminator()) {
1191 errmsg = QCoreApplication::translate("QDeclarativeParser", "Unterminated regular expression backslash sequence");
1192 return false;
1193 }
1194
1195 record16(current);
1196 shift(1);
1197 break;
1198
1199 case '[':
1200 // regular expression class
1201 record16(current);
1202 shift(1);
1203
1204 while (current && ! isLineTerminator()) {
1205 if (current == ']')
1206 break;
1207 else if (current == '\\') {
1208 // regular expression backslash sequence
1209 record16(current);
1210 shift(1);
1211
1212 if (! current || isLineTerminator()) {
1213 errmsg = QCoreApplication::translate("QDeclarativeParser", "Unterminated regular expression backslash sequence");
1214 return false;
1215 }
1216
1217 record16(current);
1218 shift(1);
1219 } else {
1220 record16(current);
1221 shift(1);
1222 }
1223 }
1224
1225 if (current != ']') {
1226 errmsg = QCoreApplication::translate("QDeclarativeParser", "Unterminated regular expression class");
1227 return false;
1228 }
1229
1230 record16(current);
1231 shift(1); // skip ]
1232 break;
1233
1234 default:
1235 record16(current);
1236 shift(1);
1237 } // switch
1238 } // while
1239
1240 return false;
1241}
1242
1243void Lexer::syncProhibitAutomaticSemicolon()
1244{
1245 if (parenthesesState == BalancedParentheses) {
1246 // we have seen something like "if (foo)", which means we should
1247 // never insert an automatic semicolon at this point, since it would
1248 // then be expanded into an empty statement (ECMA-262 7.9.1)
1249 prohibitAutomaticSemicolon = true;
1250 parenthesesState = IgnoreParentheses;
1251 } else {
1252 prohibitAutomaticSemicolon = false;
1253 }
1254}
1255
1256QT_QML_END_NAMESPACE
1257
1258
Note: See TracBrowser for help on using the repository browser.