Qt 4.8
qscriptlexer.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtScript module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL-ONLY$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser
11 ** General Public License version 2.1 as published by the Free Software
12 ** Foundation and appearing in the file LICENSE.LGPL included in the
13 ** packaging of this file. Please review the following information to
14 ** ensure the GNU Lesser General Public License version 2.1 requirements
15 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** If you have questions regarding the use of this file, please contact
18 ** us via http://www.qt-project.org/.
19 **
20 ** $QT_END_LICENSE$
21 **
22 ****************************************************************************/
23 
24 #include "qscriptlexer_p.h"
25 
26 #include "qscriptgrammar_p.h"
27 #include <ctype.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31 
33 
34 Q_CORE_EXPORT double qstrtod(const char *s00, char const **se, bool *ok);
35 
36 #define shiftWindowsLineBreak() \
37  do { \
38  if (((current == '\r') && (next1 == '\n')) \
39  || ((current == '\n') && (next1 == '\r'))) { \
40  shift(1); \
41  } \
42  } \
43  while (0)
44 
45 typedef double qsreal; // ###
46 
47 namespace QScript {
48 extern qsreal integerFromString(const char *buf, int size, int radix);
49 }
50 
52  : driver(eng),
53  yylineno(0),
54  size8(128), size16(128), restrKeyword(false),
55  stackToken(-1), pos(0),
56  code(0), length(0),
57  bol(true),
58  current(0), next1(0), next2(0), next3(0),
59  err(NoError),
60  check_reserved(true),
61  parenthesesState(IgnoreParentheses),
62  prohibitAutomaticSemicolon(false)
63 {
64  // allocate space for read buffers
65  buffer8 = new char[size8];
66  buffer16 = new QChar[size16];
67  pattern = 0;
68  flags = 0;
69 
70 }
71 
73 {
74  delete [] buffer8;
75  delete [] buffer16;
76 }
77 
78 void QScript::Lexer::setCode(const QString &c, int lineno)
79 {
80  errmsg = QString();
81  yylineno = lineno;
82  yycolumn = 1;
83  restrKeyword = false;
84  delimited = false;
85  stackToken = -1;
86  pos = 0;
87  code = c.unicode();
88  length = c.length();
89  bol = true;
90 
91  // read first characters
92  current = (length > 0) ? code[0].unicode() : 0;
93  next1 = (length > 1) ? code[1].unicode() : 0;
94  next2 = (length > 2) ? code[2].unicode() : 0;
95  next3 = (length > 3) ? code[3].unicode() : 0;
96 }
97 
99 {
100  while (p--) {
101  ++pos;
102  ++yycolumn;
103  current = next1;
104  next1 = next2;
105  next2 = next3;
106  next3 = (pos + 3 < length) ? code[pos+3].unicode() : 0;
107  }
108 }
109 
111 {
112  state = s;
113  done = true;
114 }
115 
116 int QScript::Lexer::findReservedWord(const QChar *c, int size) const
117 {
118  switch (size) {
119  case 2: {
120  if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('o'))
121  return QScriptGrammar::T_DO;
122  else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('f'))
123  return QScriptGrammar::T_IF;
124  else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n'))
125  return QScriptGrammar::T_IN;
126  } break;
127 
128  case 3: {
129  if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('o') && c[2] == QLatin1Char('r'))
130  return QScriptGrammar::T_FOR;
131  else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('e') && c[2] == QLatin1Char('w'))
132  return QScriptGrammar::T_NEW;
133  else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r') && c[2] == QLatin1Char('y'))
134  return QScriptGrammar::T_TRY;
135  else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('a') && c[2] == QLatin1Char('r'))
136  return QScriptGrammar::T_VAR;
137  else if (check_reserved) {
138  if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n') && c[2] == QLatin1Char('t'))
140  }
141  } break;
142 
143  case 4: {
144  if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('a')
145  && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('e'))
146  return QScriptGrammar::T_CASE;
147  else if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('l')
148  && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('e'))
149  return QScriptGrammar::T_ELSE;
150  else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h')
151  && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('s'))
152  return QScriptGrammar::T_THIS;
153  else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('o')
154  && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('d'))
155  return QScriptGrammar::T_VOID;
156  else if (c[0] == QLatin1Char('w') && c[1] == QLatin1Char('i')
157  && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('h'))
158  return QScriptGrammar::T_WITH;
159  else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r')
160  && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('e'))
161  return QScriptGrammar::T_TRUE;
162  else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('u')
163  && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('l'))
164  return QScriptGrammar::T_NULL;
165  else if (check_reserved) {
166  if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('n')
167  && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('m'))
169  else if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('y')
170  && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e'))
172  else if (c[0] == QLatin1Char('l') && c[1] == QLatin1Char('o')
173  && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('g'))
175  else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('h')
176  && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('r'))
178  else if (c[0] == QLatin1Char('g') && c[1] == QLatin1Char('o')
179  && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('o'))
181  }
182  } break;
183 
184  case 5: {
185  if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('r')
186  && c[2] == QLatin1Char('e') && c[3] == QLatin1Char('a')
187  && c[4] == QLatin1Char('k'))
189  else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('a')
190  && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('c')
191  && c[4] == QLatin1Char('h'))
193  else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h')
194  && c[2] == QLatin1Char('r') && c[3] == QLatin1Char('o')
195  && c[4] == QLatin1Char('w'))
197  else if (c[0] == QLatin1Char('w') && c[1] == QLatin1Char('h')
198  && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('l')
199  && c[4] == QLatin1Char('e'))
201  else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('o')
202  && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('s')
203  && c[4] == QLatin1Char('t'))
205  else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('a')
206  && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('s')
207  && c[4] == QLatin1Char('e'))
209  else if (check_reserved) {
210  if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('h')
211  && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('r')
212  && c[4] == QLatin1Char('t'))
214  else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('u')
215  && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('e')
216  && c[4] == QLatin1Char('r'))
218  else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('i')
219  && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('a')
220  && c[4] == QLatin1Char('l'))
222  else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('l')
223  && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('s')
224  && c[4] == QLatin1Char('s'))
226  else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('l')
227  && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('a')
228  && c[4] == QLatin1Char('t'))
230  }
231  } break;
232 
233  case 6: {
234  if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('e')
235  && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('e')
236  && c[4] == QLatin1Char('t') && c[5] == QLatin1Char('e'))
238  else if (c[0] == QLatin1Char('r') && c[1] == QLatin1Char('e')
239  && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('u')
240  && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('n'))
242  else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('w')
243  && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('t')
244  && c[4] == QLatin1Char('c') && c[5] == QLatin1Char('h'))
246  else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('y')
247  && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('e')
248  && c[4] == QLatin1Char('o') && c[5] == QLatin1Char('f'))
250  else if (check_reserved) {
251  if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('x')
252  && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('o')
253  && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('t'))
255  else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('t')
256  && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('t')
257  && c[4] == QLatin1Char('i') && c[5] == QLatin1Char('c'))
259  else if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('o')
260  && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('b')
261  && c[4] == QLatin1Char('l') && c[5] == QLatin1Char('e'))
263  else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('m')
264  && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('o')
265  && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('t'))
267  else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('u')
268  && c[2] == QLatin1Char('b') && c[3] == QLatin1Char('l')
269  && c[4] == QLatin1Char('i') && c[5] == QLatin1Char('c'))
271  else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('a')
272  && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('i')
273  && c[4] == QLatin1Char('v') && c[5] == QLatin1Char('e'))
275  else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h')
276  && c[2] == QLatin1Char('r') && c[3] == QLatin1Char('o')
277  && c[4] == QLatin1Char('w') && c[5] == QLatin1Char('s'))
279  }
280  } break;
281 
282  case 7: {
283  if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('e')
284  && c[2] == QLatin1Char('f') && c[3] == QLatin1Char('a')
285  && c[4] == QLatin1Char('u') && c[5] == QLatin1Char('l')
286  && c[6] == QLatin1Char('t'))
288  else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('i')
289  && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('a')
290  && c[4] == QLatin1Char('l') && c[5] == QLatin1Char('l')
291  && c[6] == QLatin1Char('y'))
293  else if (check_reserved) {
294  if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('o')
295  && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('l')
296  && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('a')
297  && c[6] == QLatin1Char('n'))
299  else if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('x')
300  && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e')
301  && c[4] == QLatin1Char('n') && c[5] == QLatin1Char('d')
302  && c[6] == QLatin1Char('s'))
304  else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('a')
305  && c[2] == QLatin1Char('c') && c[3] == QLatin1Char('k')
306  && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('g')
307  && c[6] == QLatin1Char('e'))
309  else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('r')
310  && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('v')
311  && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('t')
312  && c[6] == QLatin1Char('e'))
314  }
315  } break;
316 
317  case 8: {
318  if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('o')
319  && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('t')
320  && c[4] == QLatin1Char('i') && c[5] == QLatin1Char('n')
321  && c[6] == QLatin1Char('u') && c[7] == QLatin1Char('e'))
323  else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('u')
324  && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('c')
325  && c[4] == QLatin1Char('t') && c[5] == QLatin1Char('i')
326  && c[6] == QLatin1Char('o') && c[7] == QLatin1Char('n'))
328  else if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('e')
329  && c[2] == QLatin1Char('b') && c[3] == QLatin1Char('u')
330  && c[4] == QLatin1Char('g') && c[5] == QLatin1Char('g')
331  && c[6] == QLatin1Char('e') && c[7] == QLatin1Char('r'))
333  else if (check_reserved) {
334  if (c[0] == QLatin1Char('a') && c[1] == QLatin1Char('b')
335  && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('t')
336  && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('a')
337  && c[6] == QLatin1Char('c') && c[7] == QLatin1Char('t'))
339  else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('o')
340  && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('a')
341  && c[4] == QLatin1Char('t') && c[5] == QLatin1Char('i')
342  && c[6] == QLatin1Char('l') && c[7] == QLatin1Char('e'))
344  }
345  } break;
346 
347  case 9: {
348  if (check_reserved) {
349  if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n')
350  && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e')
351  && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('f')
352  && c[6] == QLatin1Char('a') && c[7] == QLatin1Char('c')
353  && c[8] == QLatin1Char('e'))
355  else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r')
356  && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('n')
357  && c[4] == QLatin1Char('s') && c[5] == QLatin1Char('i')
358  && c[6] == QLatin1Char('e') && c[7] == QLatin1Char('n')
359  && c[8] == QLatin1Char('t'))
361  else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('r')
362  && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('t')
363  && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('c')
364  && c[6] == QLatin1Char('t') && c[7] == QLatin1Char('e')
365  && c[8] == QLatin1Char('d'))
367  }
368  } break;
369 
370  case 10: {
371  if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n')
372  && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('t')
373  && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('n')
374  && c[6] == QLatin1Char('c') && c[7] == QLatin1Char('e')
375  && c[8] == QLatin1Char('o') && c[9] == QLatin1Char('f'))
377  else if (check_reserved) {
378  if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('m')
379  && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('l')
380  && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('m')
381  && c[6] == QLatin1Char('e') && c[7] == QLatin1Char('n')
382  && c[8] == QLatin1Char('t') && c[9] == QLatin1Char('s'))
384  }
385  } break;
386 
387  case 12: {
388  if (check_reserved) {
389  if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('y')
390  && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('c')
391  && c[4] == QLatin1Char('h') && c[5] == QLatin1Char('r')
392  && c[6] == QLatin1Char('o') && c[7] == QLatin1Char('n')
393  && c[8] == QLatin1Char('i') && c[9] == QLatin1Char('z')
394  && c[10] == QLatin1Char('e') && c[11] == QLatin1Char('d'))
396  }
397  } break;
398 
399  } // switch
400 
401  return -1;
402 }
403 
405 {
406  int token = 0;
407  state = Start;
408  ushort stringType = 0; // either single or double quotes
409  pos8 = pos16 = 0;
410  done = false;
411  terminator = false;
412 
413  // did we push a token on the stack previously ?
414  // (after an automatic semicolon insertion)
415  if (stackToken >= 0) {
416  setDone(Other);
417  token = stackToken;
418  stackToken = -1;
419  }
420 
421  while (!done) {
422  switch (state) {
423  case Start:
424  if (isWhiteSpace()) {
425  // do nothing
426  } else if (current == '/' && next1 == '/') {
427  recordStartPos();
428  shift(1);
430  } else if (current == '/' && next1 == '*') {
431  recordStartPos();
432  shift(1);
434  } else if (current == 0) {
437  // automatic semicolon insertion if program incomplete
439  stackToken = 0;
440  setDone(Other);
441  } else {
442  setDone(Eof);
443  }
444  } else if (isLineTerminator()) {
446  yylineno++;
447  yycolumn = 0;
448  bol = true;
449  terminator = true;
451  if (restrKeyword) {
453  setDone(Other);
454  }
455  } else if (current == '"' || current == '\'') {
456  recordStartPos();
457  state = InString;
458  stringType = current;
459  } else if (isIdentLetter(current)) {
460  recordStartPos();
461  record16(current);
463  } else if (current == '0') {
464  recordStartPos();
465  record8(current);
466  state = InNum0;
467  } else if (isDecimalDigit(current)) {
468  recordStartPos();
469  record8(current);
470  state = InNum;
471  } else if (current == '.' && isDecimalDigit(next1)) {
472  recordStartPos();
473  record8(current);
474  state = InDecimal;
475  } else {
476  recordStartPos();
478  if (token != -1) {
480  && (token == QScriptGrammar::T_PLUS_PLUS
481  || token == QScriptGrammar::T_MINUS_MINUS)) {
482  // automatic semicolon insertion
483  stackToken = token;
485  }
486  setDone(Other);
487  }
488  else {
489  setDone(Bad);
491  errmsg = QLatin1String("Illegal character");
492  }
493  }
494  break;
495  case InString:
496  if (current == stringType) {
497  shift(1);
498  setDone(String);
499  } else if (current == 0 || isLineTerminator()) {
500  setDone(Bad);
502  errmsg = QLatin1String("Unclosed string at end of line");
503  } else if (current == '\\') {
505  } else {
506  record16(current);
507  }
508  break;
509  // Escape Sequences inside of strings
510  case InEscapeSequence:
511  if (isOctalDigit(current)) {
512  if (current >= '0' && current <= '3' &&
515  shift(2);
516  state = InString;
517  } else if (isOctalDigit(current) &&
518  isOctalDigit(next1)) {
520  shift(1);
521  state = InString;
522  } else if (isOctalDigit(current)) {
523  record16(convertOctal('0', '0', current));
524  state = InString;
525  } else {
526  setDone(Bad);
528  errmsg = QLatin1String("Illegal escape squence");
529  }
530  } else if (current == 'x')
531  state = InHexEscape;
532  else if (current == 'u')
534  else {
535  if (isLineTerminator()) {
537  yylineno++;
538  yycolumn = 0;
539  bol = true;
540  } else {
542  }
543  state = InString;
544  }
545  break;
546  case InHexEscape:
547  if (isHexDigit(current) && isHexDigit(next1)) {
548  state = InString;
550  shift(1);
551  } else if (current == stringType) {
552  record16(QLatin1Char('x'));
553  shift(1);
554  setDone(String);
555  } else {
556  record16(QLatin1Char('x'));
557  record16(current);
558  state = InString;
559  }
560  break;
561  case InUnicodeEscape:
562  if (isHexDigit(current) && isHexDigit(next1) &&
565  shift(3);
566  state = InString;
567  } else if (current == stringType) {
568  record16(QLatin1Char('u'));
569  shift(1);
570  setDone(String);
571  } else {
572  setDone(Bad);
574  errmsg = QLatin1String("Illegal unicode escape sequence");
575  }
576  break;
577  case InSingleLineComment:
578  if (isLineTerminator()) {
580  yylineno++;
581  yycolumn = 0;
582  terminator = true;
583  bol = true;
584  if (restrKeyword) {
586  setDone(Other);
587  } else
588  state = Start;
589  } else if (current == 0) {
590  setDone(Eof);
591  }
592  break;
593  case InMultiLineComment:
594  if (current == 0) {
595  setDone(Bad);
597  errmsg = QLatin1String("Unclosed comment at end of file");
598  } else if (isLineTerminator()) {
600  yylineno++;
601  } else if (current == '*' && next1 == '/') {
602  state = Start;
603  shift(1);
604  }
605  break;
606  case InIdentifier:
608  record16(current);
609  break;
610  }
612  break;
613  case InNum0:
614  if (current == 'x' || current == 'X') {
615  record8(current);
616  state = InHex;
617  } else if (current == '.') {
618  record8(current);
619  state = InDecimal;
620  } else if (current == 'e' || current == 'E') {
621  record8(current);
623  } else if (isOctalDigit(current)) {
624  record8(current);
625  state = InOctal;
626  } else if (isDecimalDigit(current)) {
627  record8(current);
628  state = InDecimal;
629  } else {
630  setDone(Number);
631  }
632  break;
633  case InHex:
634  if (isHexDigit(current))
635  record8(current);
636  else
637  setDone(Hex);
638  break;
639  case InOctal:
640  if (isOctalDigit(current)) {
641  record8(current);
642  } else if (isDecimalDigit(current)) {
643  record8(current);
644  state = InDecimal;
645  } else {
646  setDone(Octal);
647  }
648  break;
649  case InNum:
650  if (isDecimalDigit(current)) {
651  record8(current);
652  } else if (current == '.') {
653  record8(current);
654  state = InDecimal;
655  } else if (current == 'e' || current == 'E') {
656  record8(current);
658  } else {
659  setDone(Number);
660  }
661  break;
662  case InDecimal:
663  if (isDecimalDigit(current)) {
664  record8(current);
665  } else if (current == 'e' || current == 'E') {
666  record8(current);
668  } else {
669  setDone(Number);
670  }
671  break;
672  case InExponentIndicator:
673  if (current == '+' || current == '-') {
674  record8(current);
675  } else if (isDecimalDigit(current)) {
676  record8(current);
677  state = InExponent;
678  } else {
679  setDone(Bad);
681  errmsg = QLatin1String("Illegal syntax for exponential number");
682  }
683  break;
684  case InExponent:
685  if (isDecimalDigit(current)) {
686  record8(current);
687  } else {
688  setDone(Number);
689  }
690  break;
691  default:
692  Q_ASSERT_X(0, "Lexer::lex", "Unhandled state in switch statement");
693  }
694 
695  // move on to the next character
696  if (!done)
697  shift(1);
698  if (state != Start && state != InSingleLineComment)
699  bol = false;
700  }
701 
702  // no identifiers allowed directly after numeric literal, e.g. "3in" is bad
703  if ((state == Number || state == Octal || state == Hex)
704  && isIdentLetter(current)) {
705  state = Bad;
707  errmsg = QLatin1String("Identifier cannot start with numeric literal");
708  }
709 
710  // terminate string
711  buffer8[pos8] = '\0';
712 
713  double dval = 0;
714  if (state == Number) {
715  dval = qstrtod(buffer8, 0, 0);
716  } else if (state == Hex) { // scan hex numbers
718  state = Number;
719  } else if (state == Octal) { // scan octal number
721  state = Number;
722  }
723 
724  restrKeyword = false;
725  delimited = false;
726 
727  switch (parenthesesState) {
728  case IgnoreParentheses:
729  break;
730  case CountParentheses:
731  if (token == QScriptGrammar::T_RPAREN) {
733  if (parenthesesCount == 0)
735  } else if (token == QScriptGrammar::T_LPAREN) {
737  }
738  break;
739  case BalancedParentheses:
741  break;
742  }
743 
744  switch (state) {
745  case Eof:
746  return 0;
747  case Other:
749  delimited = true;
750  return token;
751  case Identifier:
752  if ((token = findReservedWord(buffer16, pos16)) < 0) {
753  /* TODO: close leak on parse error. same holds true for String */
754  if (driver) {
755  Q_ASSERT_X(false, Q_FUNC_INFO, "not implemented");
756  qsyylval.ustr = 0; // driver->intern(buffer16, pos16);
757  } else
758  qsyylval.ustr = 0;
760  }
761  if (token == QScriptGrammar::T_CONTINUE || token == QScriptGrammar::T_BREAK
762  || token == QScriptGrammar::T_RETURN || token == QScriptGrammar::T_THROW) {
763  restrKeyword = true;
764  } else if (token == QScriptGrammar::T_IF || token == QScriptGrammar::T_FOR
765  || token == QScriptGrammar::T_WHILE || token == QScriptGrammar::T_WITH) {
767  parenthesesCount = 0;
768  } else if (token == QScriptGrammar::T_DO) {
770  }
771  return token;
772  case String:
773  if (driver) {
774  Q_ASSERT_X(false, Q_FUNC_INFO, "not implemented");
775  qsyylval.ustr = 0; // driver->intern(buffer16, pos16);
776  } else
777  qsyylval.ustr = 0;
779  case Number:
780  qsyylval.dval = dval;
782  case Bad:
783  return -1;
784  default:
785  Q_ASSERT(!"unhandled numeration value in switch");
786  return -1;
787  }
788 }
789 
791 {
792  return (current == ' ' || current == '\t' ||
793  current == 0x0b || current == 0x0c);
794 }
795 
797 {
798  return (current == '\n' || current == '\r');
799 }
800 
802 {
803  /* TODO: allow other legitimate unicode chars */
804  return ((c >= 'a' && c <= 'z')
805  || (c >= 'A' && c <= 'Z')
806  || c == '$'
807  || c == '_');
808 }
809 
811 {
812  return (c >= '0' && c <= '9');
813 }
814 
816 {
817  return ((c >= '0' && c <= '9')
818  || (c >= 'a' && c <= 'f')
819  || (c >= 'A' && c <= 'F'));
820 }
821 
823 {
824  return (c >= '0' && c <= '7');
825 }
826 
828  ushort c3, ushort c4)
829 {
830  if (c1 == '>' && c2 == '>' && c3 == '>' && c4 == '=') {
831  shift(4);
833  } else if (c1 == '=' && c2 == '=' && c3 == '=') {
834  shift(3);
836  } else if (c1 == '!' && c2 == '=' && c3 == '=') {
837  shift(3);
839  } else if (c1 == '>' && c2 == '>' && c3 == '>') {
840  shift(3);
842  } else if (c1 == '<' && c2 == '<' && c3 == '=') {
843  shift(3);
845  } else if (c1 == '>' && c2 == '>' && c3 == '=') {
846  shift(3);
848  } else if (c1 == '<' && c2 == '=') {
849  shift(2);
850  return QScriptGrammar::T_LE;
851  } else if (c1 == '>' && c2 == '=') {
852  shift(2);
853  return QScriptGrammar::T_GE;
854  } else if (c1 == '!' && c2 == '=') {
855  shift(2);
857  } else if (c1 == '+' && c2 == '+') {
858  shift(2);
860  } else if (c1 == '-' && c2 == '-') {
861  shift(2);
863  } else if (c1 == '=' && c2 == '=') {
864  shift(2);
866  } else if (c1 == '+' && c2 == '=') {
867  shift(2);
869  } else if (c1 == '-' && c2 == '=') {
870  shift(2);
872  } else if (c1 == '*' && c2 == '=') {
873  shift(2);
875  } else if (c1 == '/' && c2 == '=') {
876  shift(2);
878  } else if (c1 == '&' && c2 == '=') {
879  shift(2);
881  } else if (c1 == '^' && c2 == '=') {
882  shift(2);
884  } else if (c1 == '%' && c2 == '=') {
885  shift(2);
887  } else if (c1 == '|' && c2 == '=') {
888  shift(2);
890  } else if (c1 == '<' && c2 == '<') {
891  shift(2);
893  } else if (c1 == '>' && c2 == '>') {
894  shift(2);
896  } else if (c1 == '&' && c2 == '&') {
897  shift(2);
899  } else if (c1 == '|' && c2 == '|') {
900  shift(2);
902  }
903 
904  switch(c1) {
905  case '=': shift(1); return QScriptGrammar::T_EQ;
906  case '>': shift(1); return QScriptGrammar::T_GT;
907  case '<': shift(1); return QScriptGrammar::T_LT;
908  case ',': shift(1); return QScriptGrammar::T_COMMA;
909  case '!': shift(1); return QScriptGrammar::T_NOT;
910  case '~': shift(1); return QScriptGrammar::T_TILDE;
911  case '?': shift(1); return QScriptGrammar::T_QUESTION;
912  case ':': shift(1); return QScriptGrammar::T_COLON;
913  case '.': shift(1); return QScriptGrammar::T_DOT;
914  case '+': shift(1); return QScriptGrammar::T_PLUS;
915  case '-': shift(1); return QScriptGrammar::T_MINUS;
916  case '*': shift(1); return QScriptGrammar::T_STAR;
917  case '/': shift(1); return QScriptGrammar::T_DIVIDE_;
918  case '&': shift(1); return QScriptGrammar::T_AND;
919  case '|': shift(1); return QScriptGrammar::T_OR;
920  case '^': shift(1); return QScriptGrammar::T_XOR;
921  case '%': shift(1); return QScriptGrammar::T_REMAINDER;
922  case '(': shift(1); return QScriptGrammar::T_LPAREN;
923  case ')': shift(1); return QScriptGrammar::T_RPAREN;
924  case '{': shift(1); return QScriptGrammar::T_LBRACE;
925  case '}': shift(1); return QScriptGrammar::T_RBRACE;
926  case '[': shift(1); return QScriptGrammar::T_LBRACKET;
927  case ']': shift(1); return QScriptGrammar::T_RBRACKET;
928  case ';': shift(1); return QScriptGrammar::T_SEMICOLON;
929 
930  default: return -1;
931  }
932 }
933 
935 {
936  switch(c) {
937  case 'b':
938  return 0x08;
939  case 't':
940  return 0x09;
941  case 'n':
942  return 0x0A;
943  case 'v':
944  return 0x0B;
945  case 'f':
946  return 0x0C;
947  case 'r':
948  return 0x0D;
949  case '"':
950  return 0x22;
951  case '\'':
952  return 0x27;
953  case '\\':
954  return 0x5C;
955  default:
956  return c;
957  }
958 }
959 
961  ushort c3) const
962 {
963  return ((c1 - '0') * 64 + (c2 - '0') * 8 + c3 - '0');
964 }
965 
967 {
968  if (c >= '0' && c <= '9')
969  return (c - '0');
970  else if (c >= 'a' && c <= 'f')
971  return (c - 'a' + 10);
972  else
973  return (c - 'A' + 10);
974 }
975 
977 {
978  return ((convertHex(c1) << 4) + convertHex(c2));
979 }
980 
982  ushort c3, ushort c4)
983 {
984  return QChar((convertHex(c3) << 4) + convertHex(c4),
985  (convertHex(c1) << 4) + convertHex(c2));
986 }
987 
989 {
990  Q_ASSERT(c <= 0xff);
991 
992  // enlarge buffer if full
993  if (pos8 >= size8 - 1) {
994  char *tmp = new char[2 * size8];
995  memcpy(tmp, buffer8, size8 * sizeof(char));
996  delete [] buffer8;
997  buffer8 = tmp;
998  size8 *= 2;
999  }
1000 
1001  buffer8[pos8++] = (char) c;
1002 }
1003 
1005 {
1006  // enlarge buffer if full
1007  if (pos16 >= size16 - 1) {
1008  QChar *tmp = new QChar[2 * size16];
1009  memcpy(tmp, buffer16, size16 * sizeof(QChar));
1010  delete [] buffer16;
1011  buffer16 = tmp;
1012  size16 *= 2;
1013  }
1014 
1015  buffer16[pos16++] = c;
1016 }
1017 
1019 {
1022 }
1023 
1025 {
1026  pos16 = 0;
1027  bool lastWasEscape = false;
1028 
1029  if (prefix == EqualPrefix)
1030  record16(QLatin1Char('='));
1031 
1032  while (1) {
1033  if (isLineTerminator() || current == 0) {
1034  errmsg = QLatin1String("Unterminated regular expression literal");
1035  return false;
1036  }
1037  else if (current != '/' || lastWasEscape == true)
1038  {
1039  record16(current);
1040  lastWasEscape = !lastWasEscape && (current == '\\');
1041  }
1042  else {
1043  if (driver) {
1044  Q_ASSERT_X(false, Q_FUNC_INFO, "not implemented");
1045  pattern = 0; // driver->intern(buffer16, pos16);
1046  } else
1047  pattern = 0;
1048  pos16 = 0;
1049  shift(1);
1050  break;
1051  }
1052  shift(1);
1053  }
1054 
1055  flags = 0;
1056  while (isIdentLetter(current)) {
1057  // current version was remade from this line:
1058  //int flag = QScript::Ecma::RegExp::flagFromChar(current);
1059  //code was "inlined" because it was only one call to this function
1060  int flag;
1061  switch (current) {
1062  case 'g': flag = 0x01; break;
1063  case 'm': flag = 0x02; break;
1064  case 'i': flag = 0x04; break;
1065  default: flag = 0;
1066  }
1067  if (flag == 0) {
1068  errmsg = QString::fromLatin1("Invalid regular expression flag '%0'")
1069  .arg(QChar(current));
1070  return false;
1071  }
1072  flags |= flag;
1073  record16(current);
1074  shift(1);
1075  }
1076 
1077  return true;
1078 }
1079 
1081 {
1083  // we have seen something like "if (foo)", which means we should
1084  // never insert an automatic semicolon at this point, since it would
1085  // then be expanded into an empty statement (ECMA-262 7.9.1)
1088  } else {
1090  }
1091 }
1092 
void shift(uint p)
void syncProhibitAutomaticSemicolon()
unsigned char c[8]
Definition: qnumeric_p.h:62
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
bool isLineTerminator() const
void record16(QChar c)
#define shiftWindowsLineBreak()
QScriptEnginePrivate * driver
Q_CORE_EXPORT double qstrtod(const char *s00, char const **se, bool *ok)
int length() const
Returns the number of characters in this string.
Definition: qstring.h:696
bool isWhiteSpace() const
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
void setDone(State s)
bool isHexDigit(ushort c) const
The QString class provides a Unicode character string.
Definition: qstring.h:83
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
The QChar class provides a 16-bit Unicode character.
Definition: qchar.h:72
static bool isIdentLetter(ushort c)
bool isOctalDigit(ushort c) const
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
int matchPunctuator(ushort c1, ushort c2, ushort c3, ushort c4)
const QChar * unicode() const
Returns a &#39;\0&#39;-terminated Unicode representation of the string.
Definition: qstring.h:706
Lexer(QScriptEnginePrivate *eng)
QScriptNameIdImpl * pattern
double qsreal
union QScript::Lexer::@359 qsyylval
bool scanRegExp(RegExpBodyPrefix prefix=NoPrefix)
unsigned int uint
Definition: qglobal.h:996
The State element defines configurations of objects and properties.
const QChar * code
static unsigned char convertHex(ushort c1)
#define Q_ASSERT_X(cond, where, what)
Definition: qglobal.h:1837
QString arg(qlonglong a, int fieldwidth=0, int base=10, const QChar &fillChar=QLatin1Char(' ')) const Q_REQUIRED_RESULT
Definition: qstring.cpp:7186
#define Q_CORE_EXPORT
Definition: qglobal.h:1449
unsigned short ushort
Definition: qglobal.h:995
static QString fromLatin1(const char *, int size=-1)
Returns a QString initialized with the first size characters of the Latin-1 string str...
Definition: qstring.cpp:4188
int findReservedWord(const QChar *buffer, int size) const
static bool isDecimalDigit(ushort c)
double qsreal
Definition: qscriptvalue.h:52
void record8(ushort c)
ushort convertOctal(ushort c1, ushort c2, ushort c3) const
ParenthesesState parenthesesState
bool prohibitAutomaticSemicolon
double dval() const
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
void setCode(const QString &c, int lineno)
static QChar convertUnicode(ushort c1, ushort c2, ushort c3, ushort c4)
ushort singleEscape(ushort c) const
qsreal integerFromString(const char *buf, int size, int radix)
#define Q_FUNC_INFO
Definition: qglobal.h:1871