source: trunk/tools/linguist/shared/qscript.g@ 275

Last change on this file since 275 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 71.5 KB
Line 
1----------------------------------------------------------------------------
2--
3-- Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4-- Contact: Qt Software Information ([email protected])
5--
6-- This file is part of the Qt Linguist of the Qt Toolkit.
7--
8-- $QT_BEGIN_LICENSE:LGPL$
9-- Commercial Usage
10-- Licensees holding valid Qt Commercial licenses may use this file in
11-- accordance with the Qt Commercial License Agreement provided with the
12-- Software or, alternatively, in accordance with the terms contained in
13-- a written agreement between you and Nokia.
14--
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.
22--
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
26-- 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 are unsure which license is appropriate for your use, please
37-- contact the sales department at [email protected].
38-- $QT_END_LICENSE$
39--
40-- This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
41-- WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
42--
43----------------------------------------------------------------------------
44
45%parser QScriptGrammar
46%merged_output qscript.cpp
47%expect 3
48%expect-rr 1
49
50%token T_AND "&" T_AND_AND "&&" T_AND_EQ "&="
51%token T_BREAK "break" T_CASE "case" T_CATCH "catch"
52%token T_COLON ":" T_COMMA ";" T_CONTINUE "continue"
53%token T_DEFAULT "default" T_DELETE "delete" T_DIVIDE_ "/"
54%token T_DIVIDE_EQ "/=" T_DO "do" T_DOT "."
55%token T_ELSE "else" T_EQ "=" T_EQ_EQ "=="
56%token T_EQ_EQ_EQ "===" T_FINALLY "finally" T_FOR "for"
57%token T_FUNCTION "function" T_GE ">=" T_GT ">"
58%token T_GT_GT ">>" T_GT_GT_EQ ">>=" T_GT_GT_GT ">>>"
59%token T_GT_GT_GT_EQ ">>>=" T_IDENTIFIER "identifier" T_IF "if"
60%token T_IN "in" T_INSTANCEOF "instanceof" T_LBRACE "{"
61%token T_LBRACKET "[" T_LE "<=" T_LPAREN "("
62%token T_LT "<" T_LT_LT "<<" T_LT_LT_EQ "<<="
63%token T_MINUS "-" T_MINUS_EQ "-=" T_MINUS_MINUS "--"
64%token T_NEW "new" T_NOT "!" T_NOT_EQ "!="
65%token T_NOT_EQ_EQ "!==" T_NUMERIC_LITERAL "numeric literal" T_OR "|"
66%token T_OR_EQ "|=" T_OR_OR "||" T_PLUS "+"
67%token T_PLUS_EQ "+=" T_PLUS_PLUS "++" T_QUESTION "?"
68%token T_RBRACE "}" T_RBRACKET "]" T_REMAINDER "%"
69%token T_REMAINDER_EQ "%=" T_RETURN "return" T_RPAREN ")"
70%token T_SEMICOLON ";" T_AUTOMATIC_SEMICOLON T_STAR "*"
71%token T_STAR_EQ "*=" T_STRING_LITERAL "string literal"
72%token T_SWITCH "switch" T_THIS "this" T_THROW "throw"
73%token T_TILDE "~" T_TRY "try" T_TYPEOF "typeof"
74%token T_VAR "var" T_VOID "void" T_WHILE "while"
75%token T_WITH "with" T_XOR "^" T_XOR_EQ "^="
76%token T_NULL "null" T_TRUE "true" T_FALSE "false"
77%token T_CONST "const"
78%token T_DEBUGGER "debugger"
79%token T_RESERVED_WORD "reserved word"
80
81%start Program
82
83/.
84#include "translator.h"
85
86#include <QtCore/qdebug.h>
87#include <QtCore/qnumeric.h>
88#include <QtCore/qstring.h>
89#include <QtCore/qtextcodec.h>
90#include <QtCore/qvariant.h>
91
92#include <ctype.h>
93#include <stdlib.h>
94#include <stdio.h>
95#include <string.h>
96
97QT_BEGIN_NAMESPACE
98
99static void recordMessage(
100 Translator *tor, const QString &context, const QString &text, const QString &comment,
101 const QString &extracomment, bool plural, const QString &fileName, int lineNo)
102{
103 TranslatorMessage msg(
104 context, text, comment, QString(),
105 fileName, lineNo, QStringList(),
106 TranslatorMessage::Unfinished, plural);
107 msg.setExtraComment(extracomment.simplified());
108 tor->replace(msg);
109}
110
111
112namespace QScript
113{
114
115class Lexer
116{
117public:
118 Lexer();
119 ~Lexer();
120
121 void setCode(const QString &c, int lineno);
122 int lex();
123
124 int currentLineNo() const { return yylineno; }
125 int currentColumnNo() const { return yycolumn; }
126
127 int startLineNo() const { return startlineno; }
128 int startColumnNo() const { return startcolumn; }
129
130 int endLineNo() const { return currentLineNo(); }
131 int endColumnNo() const
132 { int col = currentColumnNo(); return (col > 0) ? col - 1 : col; }
133
134 bool prevTerminator() const { return terminator; }
135
136 enum State { Start,
137 Identifier,
138 InIdentifier,
139 InSingleLineComment,
140 InMultiLineComment,
141 InNum,
142 InNum0,
143 InHex,
144 InOctal,
145 InDecimal,
146 InExponentIndicator,
147 InExponent,
148 Hex,
149 Octal,
150 Number,
151 String,
152 Eof,
153 InString,
154 InEscapeSequence,
155 InHexEscape,
156 InUnicodeEscape,
157 Other,
158 Bad };
159
160 enum Error {
161 NoError,
162 IllegalCharacter,
163 UnclosedStringLiteral,
164 IllegalEscapeSequence,
165 IllegalUnicodeEscapeSequence,
166 UnclosedComment,
167 IllegalExponentIndicator,
168 IllegalIdentifier
169 };
170
171 enum ParenthesesState {
172 IgnoreParentheses,
173 CountParentheses,
174 BalancedParentheses
175 };
176
177 enum RegExpBodyPrefix {
178 NoPrefix,
179 EqualPrefix
180 };
181
182 bool scanRegExp(RegExpBodyPrefix prefix = NoPrefix);
183
184 QString pattern;
185 int flags;
186
187 State lexerState() const
188 { return state; }
189
190 QString errorMessage() const
191 { return errmsg; }
192 void setErrorMessage(const QString &err)
193 { errmsg = err; }
194 void setErrorMessage(const char *err)
195 { setErrorMessage(QString::fromLatin1(err)); }
196
197 Error error() const
198 { return err; }
199 void clearError()
200 { err = NoError; }
201
202private:
203 int yylineno;
204 bool done;
205 char *buffer8;
206 QChar *buffer16;
207 uint size8, size16;
208 uint pos8, pos16;
209 bool terminator;
210 bool restrKeyword;
211 // encountered delimiter like "'" and "}" on last run
212 bool delimited;
213 int stackToken;
214
215 State state;
216 void setDone(State s);
217 uint pos;
218 void shift(uint p);
219 int lookupKeyword(const char *);
220
221 bool isWhiteSpace() const;
222 bool isLineTerminator() const;
223 bool isHexDigit(ushort c) const;
224 bool isOctalDigit(ushort c) const;
225
226 int matchPunctuator(ushort c1, ushort c2,
227 ushort c3, ushort c4);
228 ushort singleEscape(ushort c) const;
229 ushort convertOctal(ushort c1, ushort c2,
230 ushort c3) const;
231public:
232 static unsigned char convertHex(ushort c1);
233 static unsigned char convertHex(ushort c1, ushort c2);
234 static QChar convertUnicode(ushort c1, ushort c2,
235 ushort c3, ushort c4);
236 static bool isIdentLetter(ushort c);
237 static bool isDecimalDigit(ushort c);
238
239 inline int ival() const { return qsyylval.toInt(); }
240 inline double dval() const { return qsyylval.toDouble(); }
241 inline QString ustr() const { return qsyylval.toString(); }
242 inline QVariant val() const { return qsyylval; }
243
244 const QChar *characterBuffer() const { return buffer16; }
245 int characterCount() const { return pos16; }
246
247private:
248 void record8(ushort c);
249 void record16(QChar c);
250 void recordStartPos();
251
252 int findReservedWord(const QChar *buffer, int size) const;
253
254 void syncProhibitAutomaticSemicolon();
255
256 const QChar *code;
257 uint length;
258 int yycolumn;
259 int startlineno;
260 int startcolumn;
261 int bol; // begin of line
262
263 QVariant qsyylval;
264
265 // current and following unicode characters
266 ushort current, next1, next2, next3;
267
268 struct keyword {
269 const char *name;
270 int token;
271 };
272
273 QString errmsg;
274 Error err;
275
276 bool wantRx;
277 bool check_reserved;
278
279 ParenthesesState parenthesesState;
280 int parenthesesCount;
281 bool prohibitAutomaticSemicolon;
282};
283
284} // namespace QScript
285
286extern double qstrtod(const char *s00, char const **se, bool *ok);
287
288#define shiftWindowsLineBreak() if(current == '\r' && next1 == '\n') shift(1);
289
290namespace QScript {
291
292static int toDigit(char c)
293{
294 if ((c >= '0') && (c <= '9'))
295 return c - '0';
296 else if ((c >= 'a') && (c <= 'z'))
297 return 10 + c - 'a';
298 else if ((c >= 'A') && (c <= 'Z'))
299 return 10 + c - 'A';
300 return -1;
301}
302
303double integerFromString(const char *buf, int size, int radix)
304{
305 if (size == 0)
306 return qSNaN();
307
308 double sign = 1.0;
309 int i = 0;
310 if (buf[0] == '+') {
311 ++i;
312 } else if (buf[0] == '-') {
313 sign = -1.0;
314 ++i;
315 }
316
317 if (((size-i) >= 2) && (buf[i] == '0')) {
318 if (((buf[i+1] == 'x') || (buf[i+1] == 'X'))
319 && (radix < 34)) {
320 if ((radix != 0) && (radix != 16))
321 return 0;
322 radix = 16;
323 i += 2;
324 } else {
325 if (radix == 0) {
326 radix = 8;
327 ++i;
328 }
329 }
330 } else if (radix == 0) {
331 radix = 10;
332 }
333
334 int j = i;
335 for ( ; i < size; ++i) {
336 int d = toDigit(buf[i]);
337 if ((d == -1) || (d >= radix))
338 break;
339 }
340 double result;
341 if (j == i) {
342 if (!qstrcmp(buf, "Infinity"))
343 result = qInf();
344 else
345 result = qSNaN();
346 } else {
347 result = 0;
348 double multiplier = 1;
349 for (--i ; i >= j; --i, multiplier *= radix)
350 result += toDigit(buf[i]) * multiplier;
351 }
352 result *= sign;
353 return result;
354}
355
356} // namespace QScript
357
358QScript::Lexer::Lexer()
359 :
360 yylineno(0),
361 size8(128), size16(128), restrKeyword(false),
362 stackToken(-1), pos(0),
363 code(0), length(0),
364 bol(true),
365 current(0), next1(0), next2(0), next3(0),
366 err(NoError),
367 check_reserved(true),
368 parenthesesState(IgnoreParentheses),
369 prohibitAutomaticSemicolon(false)
370{
371 // allocate space for read buffers
372 buffer8 = new char[size8];
373 buffer16 = new QChar[size16];
374 flags = 0;
375
376}
377
378QScript::Lexer::~Lexer()
379{
380 delete [] buffer8;
381 delete [] buffer16;
382}
383
384void QScript::Lexer::setCode(const QString &c, int lineno)
385{
386 errmsg = QString();
387 yylineno = lineno;
388 yycolumn = 1;
389 restrKeyword = false;
390 delimited = false;
391 stackToken = -1;
392 pos = 0;
393 code = c.unicode();
394 length = c.length();
395 bol = true;
396
397 // read first characters
398 current = (length > 0) ? code[0].unicode() : 0;
399 next1 = (length > 1) ? code[1].unicode() : 0;
400 next2 = (length > 2) ? code[2].unicode() : 0;
401 next3 = (length > 3) ? code[3].unicode() : 0;
402}
403
404void QScript::Lexer::shift(uint p)
405{
406 while (p--) {
407 ++pos;
408 ++yycolumn;
409 current = next1;
410 next1 = next2;
411 next2 = next3;
412 next3 = (pos + 3 < length) ? code[pos+3].unicode() : 0;
413 }
414}
415
416void QScript::Lexer::setDone(State s)
417{
418 state = s;
419 done = true;
420}
421
422int QScript::Lexer::findReservedWord(const QChar *c, int size) const
423{
424 switch (size) {
425 case 2: {
426 if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('o'))
427 return QScriptGrammar::T_DO;
428 else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('f'))
429 return QScriptGrammar::T_IF;
430 else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n'))
431 return QScriptGrammar::T_IN;
432 } break;
433
434 case 3: {
435 if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('o') && c[2] == QLatin1Char('r'))
436 return QScriptGrammar::T_FOR;
437 else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('e') && c[2] == QLatin1Char('w'))
438 return QScriptGrammar::T_NEW;
439 else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r') && c[2] == QLatin1Char('y'))
440 return QScriptGrammar::T_TRY;
441 else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('a') && c[2] == QLatin1Char('r'))
442 return QScriptGrammar::T_VAR;
443 else if (check_reserved) {
444 if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n') && c[2] == QLatin1Char('t'))
445 return QScriptGrammar::T_RESERVED_WORD;
446 }
447 } break;
448
449 case 4: {
450 if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('a')
451 && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('e'))
452 return QScriptGrammar::T_CASE;
453 else if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('l')
454 && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('e'))
455 return QScriptGrammar::T_ELSE;
456 else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h')
457 && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('s'))
458 return QScriptGrammar::T_THIS;
459 else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('o')
460 && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('d'))
461 return QScriptGrammar::T_VOID;
462 else if (c[0] == QLatin1Char('w') && c[1] == QLatin1Char('i')
463 && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('h'))
464 return QScriptGrammar::T_WITH;
465 else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r')
466 && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('e'))
467 return QScriptGrammar::T_TRUE;
468 else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('u')
469 && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('l'))
470 return QScriptGrammar::T_NULL;
471 else if (check_reserved) {
472 if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('n')
473 && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('m'))
474 return QScriptGrammar::T_RESERVED_WORD;
475 else if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('y')
476 && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e'))
477 return QScriptGrammar::T_RESERVED_WORD;
478 else if (c[0] == QLatin1Char('l') && c[1] == QLatin1Char('o')
479 && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('g'))
480 return QScriptGrammar::T_RESERVED_WORD;
481 else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('h')
482 && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('r'))
483 return QScriptGrammar::T_RESERVED_WORD;
484 else if (c[0] == QLatin1Char('g') && c[1] == QLatin1Char('o')
485 && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('o'))
486 return QScriptGrammar::T_RESERVED_WORD;
487 }
488 } break;
489
490 case 5: {
491 if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('r')
492 && c[2] == QLatin1Char('e') && c[3] == QLatin1Char('a')
493 && c[4] == QLatin1Char('k'))
494 return QScriptGrammar::T_BREAK;
495 else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('a')
496 && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('c')
497 && c[4] == QLatin1Char('h'))
498 return QScriptGrammar::T_CATCH;
499 else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h')
500 && c[2] == QLatin1Char('r') && c[3] == QLatin1Char('o')
501 && c[4] == QLatin1Char('w'))
502 return QScriptGrammar::T_THROW;
503 else if (c[0] == QLatin1Char('w') && c[1] == QLatin1Char('h')
504 && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('l')
505 && c[4] == QLatin1Char('e'))
506 return QScriptGrammar::T_WHILE;
507 else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('o')
508 && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('s')
509 && c[4] == QLatin1Char('t'))
510 return QScriptGrammar::T_CONST;
511 else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('a')
512 && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('s')
513 && c[4] == QLatin1Char('e'))
514 return QScriptGrammar::T_FALSE;
515 else if (check_reserved) {
516 if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('h')
517 && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('r')
518 && c[4] == QLatin1Char('t'))
519 return QScriptGrammar::T_RESERVED_WORD;
520 else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('u')
521 && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('e')
522 && c[4] == QLatin1Char('r'))
523 return QScriptGrammar::T_RESERVED_WORD;
524 else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('i')
525 && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('a')
526 && c[4] == QLatin1Char('l'))
527 return QScriptGrammar::T_RESERVED_WORD;
528 else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('l')
529 && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('s')
530 && c[4] == QLatin1Char('s'))
531 return QScriptGrammar::T_RESERVED_WORD;
532 else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('l')
533 && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('a')
534 && c[4] == QLatin1Char('t'))
535 return QScriptGrammar::T_RESERVED_WORD;
536 }
537 } break;
538
539 case 6: {
540 if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('e')
541 && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('e')
542 && c[4] == QLatin1Char('t') && c[5] == QLatin1Char('e'))
543 return QScriptGrammar::T_DELETE;
544 else if (c[0] == QLatin1Char('r') && c[1] == QLatin1Char('e')
545 && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('u')
546 && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('n'))
547 return QScriptGrammar::T_RETURN;
548 else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('w')
549 && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('t')
550 && c[4] == QLatin1Char('c') && c[5] == QLatin1Char('h'))
551 return QScriptGrammar::T_SWITCH;
552 else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('y')
553 && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('e')
554 && c[4] == QLatin1Char('o') && c[5] == QLatin1Char('f'))
555 return QScriptGrammar::T_TYPEOF;
556 else if (check_reserved) {
557 if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('x')
558 && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('o')
559 && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('t'))
560 return QScriptGrammar::T_RESERVED_WORD;
561 else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('t')
562 && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('t')
563 && c[4] == QLatin1Char('i') && c[5] == QLatin1Char('c'))
564 return QScriptGrammar::T_RESERVED_WORD;
565 else if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('o')
566 && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('b')
567 && c[4] == QLatin1Char('l') && c[5] == QLatin1Char('e'))
568 return QScriptGrammar::T_RESERVED_WORD;
569 else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('m')
570 && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('o')
571 && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('t'))
572 return QScriptGrammar::T_RESERVED_WORD;
573 else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('u')
574 && c[2] == QLatin1Char('b') && c[3] == QLatin1Char('l')
575 && c[4] == QLatin1Char('i') && c[5] == QLatin1Char('c'))
576 return QScriptGrammar::T_RESERVED_WORD;
577 else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('a')
578 && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('i')
579 && c[4] == QLatin1Char('v') && c[5] == QLatin1Char('e'))
580 return QScriptGrammar::T_RESERVED_WORD;
581 else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h')
582 && c[2] == QLatin1Char('r') && c[3] == QLatin1Char('o')
583 && c[4] == QLatin1Char('w') && c[5] == QLatin1Char('s'))
584 return QScriptGrammar::T_RESERVED_WORD;
585 }
586 } break;
587
588 case 7: {
589 if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('e')
590 && c[2] == QLatin1Char('f') && c[3] == QLatin1Char('a')
591 && c[4] == QLatin1Char('u') && c[5] == QLatin1Char('l')
592 && c[6] == QLatin1Char('t'))
593 return QScriptGrammar::T_DEFAULT;
594 else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('i')
595 && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('a')
596 && c[4] == QLatin1Char('l') && c[5] == QLatin1Char('l')
597 && c[6] == QLatin1Char('y'))
598 return QScriptGrammar::T_FINALLY;
599 else if (check_reserved) {
600 if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('o')
601 && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('l')
602 && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('a')
603 && c[6] == QLatin1Char('n'))
604 return QScriptGrammar::T_RESERVED_WORD;
605 else if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('x')
606 && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e')
607 && c[4] == QLatin1Char('n') && c[5] == QLatin1Char('d')
608 && c[6] == QLatin1Char('s'))
609 return QScriptGrammar::T_RESERVED_WORD;
610 else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('a')
611 && c[2] == QLatin1Char('c') && c[3] == QLatin1Char('k')
612 && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('g')
613 && c[6] == QLatin1Char('e'))
614 return QScriptGrammar::T_RESERVED_WORD;
615 else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('r')
616 && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('v')
617 && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('t')
618 && c[6] == QLatin1Char('e'))
619 return QScriptGrammar::T_RESERVED_WORD;
620 }
621 } break;
622
623 case 8: {
624 if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('o')
625 && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('t')
626 && c[4] == QLatin1Char('i') && c[5] == QLatin1Char('n')
627 && c[6] == QLatin1Char('u') && c[7] == QLatin1Char('e'))
628 return QScriptGrammar::T_CONTINUE;
629 else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('u')
630 && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('c')
631 && c[4] == QLatin1Char('t') && c[5] == QLatin1Char('i')
632 && c[6] == QLatin1Char('o') && c[7] == QLatin1Char('n'))
633 return QScriptGrammar::T_FUNCTION;
634 else if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('e')
635 && c[2] == QLatin1Char('b') && c[3] == QLatin1Char('u')
636 && c[4] == QLatin1Char('g') && c[5] == QLatin1Char('g')
637 && c[6] == QLatin1Char('e') && c[7] == QLatin1Char('r'))
638 return QScriptGrammar::T_DEBUGGER;
639 else if (check_reserved) {
640 if (c[0] == QLatin1Char('a') && c[1] == QLatin1Char('b')
641 && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('t')
642 && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('a')
643 && c[6] == QLatin1Char('c') && c[7] == QLatin1Char('t'))
644 return QScriptGrammar::T_RESERVED_WORD;
645 else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('o')
646 && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('a')
647 && c[4] == QLatin1Char('t') && c[5] == QLatin1Char('i')
648 && c[6] == QLatin1Char('l') && c[7] == QLatin1Char('e'))
649 return QScriptGrammar::T_RESERVED_WORD;
650 }
651 } break;
652
653 case 9: {
654 if (check_reserved) {
655 if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n')
656 && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e')
657 && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('f')
658 && c[6] == QLatin1Char('a') && c[7] == QLatin1Char('c')
659 && c[8] == QLatin1Char('e'))
660 return QScriptGrammar::T_RESERVED_WORD;
661 else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r')
662 && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('n')
663 && c[4] == QLatin1Char('s') && c[5] == QLatin1Char('i')
664 && c[6] == QLatin1Char('e') && c[7] == QLatin1Char('n')
665 && c[8] == QLatin1Char('t'))
666 return QScriptGrammar::T_RESERVED_WORD;
667 else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('r')
668 && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('t')
669 && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('c')
670 && c[6] == QLatin1Char('t') && c[7] == QLatin1Char('e')
671 && c[8] == QLatin1Char('d'))
672 return QScriptGrammar::T_RESERVED_WORD;
673 }
674 } break;
675
676 case 10: {
677 if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n')
678 && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('t')
679 && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('n')
680 && c[6] == QLatin1Char('c') && c[7] == QLatin1Char('e')
681 && c[8] == QLatin1Char('o') && c[9] == QLatin1Char('f'))
682 return QScriptGrammar::T_INSTANCEOF;
683 else if (check_reserved) {
684 if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('m')
685 && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('l')
686 && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('m')
687 && c[6] == QLatin1Char('e') && c[7] == QLatin1Char('n')
688 && c[8] == QLatin1Char('t') && c[9] == QLatin1Char('s'))
689 return QScriptGrammar::T_RESERVED_WORD;
690 }
691 } break;
692
693 case 12: {
694 if (check_reserved) {
695 if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('y')
696 && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('c')
697 && c[4] == QLatin1Char('h') && c[5] == QLatin1Char('r')
698 && c[6] == QLatin1Char('o') && c[7] == QLatin1Char('n')
699 && c[8] == QLatin1Char('i') && c[9] == QLatin1Char('z')
700 && c[10] == QLatin1Char('e') && c[11] == QLatin1Char('d'))
701 return QScriptGrammar::T_RESERVED_WORD;
702 }
703 } break;
704
705 } // switch
706
707 return -1;
708}
709
710int QScript::Lexer::lex()
711{
712 int token = 0;
713 state = Start;
714 ushort stringType = 0; // either single or double quotes
715 pos8 = pos16 = 0;
716 done = false;
717 terminator = false;
718
719 // did we push a token on the stack previously ?
720 // (after an automatic semicolon insertion)
721 if (stackToken >= 0) {
722 setDone(Other);
723 token = stackToken;
724 stackToken = -1;
725 }
726
727 while (!done) {
728 switch (state) {
729 case Start:
730 if (isWhiteSpace()) {
731 // do nothing
732 } else if (current == '/' && next1 == '/') {
733 recordStartPos();
734 shift(1);
735 state = InSingleLineComment;
736 } else if (current == '/' && next1 == '*') {
737 recordStartPos();
738 shift(1);
739 state = InMultiLineComment;
740 } else if (current == 0) {
741 syncProhibitAutomaticSemicolon();
742 if (!terminator && !delimited && !prohibitAutomaticSemicolon) {
743 // automatic semicolon insertion if program incomplete
744 token = QScriptGrammar::T_SEMICOLON;
745 stackToken = 0;
746 setDone(Other);
747 } else {
748 setDone(Eof);
749 }
750 } else if (isLineTerminator()) {
751 shiftWindowsLineBreak();
752 yylineno++;
753 yycolumn = 0;
754 bol = true;
755 terminator = true;
756 syncProhibitAutomaticSemicolon();
757 if (restrKeyword) {
758 token = QScriptGrammar::T_SEMICOLON;
759 setDone(Other);
760 }
761 } else if (current == '"' || current == '\'') {
762 recordStartPos();
763 state = InString;
764 stringType = current;
765 } else if (isIdentLetter(current)) {
766 recordStartPos();
767 record16(current);
768 state = InIdentifier;
769 } else if (current == '0') {
770 recordStartPos();
771 record8(current);
772 state = InNum0;
773 } else if (isDecimalDigit(current)) {
774 recordStartPos();
775 record8(current);
776 state = InNum;
777 } else if (current == '.' && isDecimalDigit(next1)) {
778 recordStartPos();
779 record8(current);
780 state = InDecimal;
781 } else {
782 recordStartPos();
783 token = matchPunctuator(current, next1, next2, next3);
784 if (token != -1) {
785 if (terminator && !delimited && !prohibitAutomaticSemicolon
786 && (token == QScriptGrammar::T_PLUS_PLUS
787 || token == QScriptGrammar::T_MINUS_MINUS)) {
788 // automatic semicolon insertion
789 stackToken = token;
790 token = QScriptGrammar::T_SEMICOLON;
791 }
792 setDone(Other);
793 }
794 else {
795 setDone(Bad);
796 err = IllegalCharacter;
797 errmsg = QLatin1String("Illegal character");
798 }
799 }
800 break;
801 case InString:
802 if (current == stringType) {
803 shift(1);
804 setDone(String);
805 } else if (current == 0 || isLineTerminator()) {
806 setDone(Bad);
807 err = UnclosedStringLiteral;
808 errmsg = QLatin1String("Unclosed string at end of line");
809 } else if (current == '\\') {
810 state = InEscapeSequence;
811 } else {
812 record16(current);
813 }
814 break;
815 // Escape Sequences inside of strings
816 case InEscapeSequence:
817 if (isOctalDigit(current)) {
818 if (current >= '0' && current <= '3' &&
819 isOctalDigit(next1) && isOctalDigit(next2)) {
820 record16(convertOctal(current, next1, next2));
821 shift(2);
822 state = InString;
823 } else if (isOctalDigit(current) &&
824 isOctalDigit(next1)) {
825 record16(convertOctal('0', current, next1));
826 shift(1);
827 state = InString;
828 } else if (isOctalDigit(current)) {
829 record16(convertOctal('0', '0', current));
830 state = InString;
831 } else {
832 setDone(Bad);
833 err = IllegalEscapeSequence;
834 errmsg = QLatin1String("Illegal escape squence");
835 }
836 } else if (current == 'x')
837 state = InHexEscape;
838 else if (current == 'u')
839 state = InUnicodeEscape;
840 else {
841 record16(singleEscape(current));
842 state = InString;
843 }
844 break;
845 case InHexEscape:
846 if (isHexDigit(current) && isHexDigit(next1)) {
847 state = InString;
848 record16(QLatin1Char(convertHex(current, next1)));
849 shift(1);
850 } else if (current == stringType) {
851 record16(QLatin1Char('x'));
852 shift(1);
853 setDone(String);
854 } else {
855 record16(QLatin1Char('x'));
856 record16(current);
857 state = InString;
858 }
859 break;
860 case InUnicodeEscape:
861 if (isHexDigit(current) && isHexDigit(next1) &&
862 isHexDigit(next2) && isHexDigit(next3)) {
863 record16(convertUnicode(current, next1, next2, next3));
864 shift(3);
865 state = InString;
866 } else if (current == stringType) {
867 record16(QLatin1Char('u'));
868 shift(1);
869 setDone(String);
870 } else {
871 setDone(Bad);
872 err = IllegalUnicodeEscapeSequence;
873 errmsg = QLatin1String("Illegal unicode escape sequence");
874 }
875 break;
876 case InSingleLineComment:
877 if (isLineTerminator()) {
878 shiftWindowsLineBreak();
879 yylineno++;
880 yycolumn = 0;
881 terminator = true;
882 bol = true;
883 if (restrKeyword) {
884 token = QScriptGrammar::T_SEMICOLON;
885 setDone(Other);
886 } else
887 state = Start;
888 } else if (current == 0) {
889 setDone(Eof);
890 }
891 break;
892 case InMultiLineComment:
893 if (current == 0) {
894 setDone(Bad);
895 err = UnclosedComment;
896 errmsg = QLatin1String("Unclosed comment at end of file");
897 } else if (isLineTerminator()) {
898 shiftWindowsLineBreak();
899 yylineno++;
900 } else if (current == '*' && next1 == '/') {
901 state = Start;
902 shift(1);
903 }
904 break;
905 case InIdentifier:
906 if (isIdentLetter(current) || isDecimalDigit(current)) {
907 record16(current);
908 break;
909 }
910 setDone(Identifier);
911 break;
912 case InNum0:
913 if (current == 'x' || current == 'X') {
914 record8(current);
915 state = InHex;
916 } else if (current == '.') {
917 record8(current);
918 state = InDecimal;
919 } else if (current == 'e' || current == 'E') {
920 record8(current);
921 state = InExponentIndicator;
922 } else if (isOctalDigit(current)) {
923 record8(current);
924 state = InOctal;
925 } else if (isDecimalDigit(current)) {
926 record8(current);
927 state = InDecimal;
928 } else {
929 setDone(Number);
930 }
931 break;
932 case InHex:
933 if (isHexDigit(current))
934 record8(current);
935 else
936 setDone(Hex);
937 break;
938 case InOctal:
939 if (isOctalDigit(current)) {
940 record8(current);
941 } else if (isDecimalDigit(current)) {
942 record8(current);
943 state = InDecimal;
944 } else {
945 setDone(Octal);
946 }
947 break;
948 case InNum:
949 if (isDecimalDigit(current)) {
950 record8(current);
951 } else if (current == '.') {
952 record8(current);
953 state = InDecimal;
954 } else if (current == 'e' || current == 'E') {
955 record8(current);
956 state = InExponentIndicator;
957 } else {
958 setDone(Number);
959 }
960 break;
961 case InDecimal:
962 if (isDecimalDigit(current)) {
963 record8(current);
964 } else if (current == 'e' || current == 'E') {
965 record8(current);
966 state = InExponentIndicator;
967 } else {
968 setDone(Number);
969 }
970 break;
971 case InExponentIndicator:
972 if (current == '+' || current == '-') {
973 record8(current);
974 } else if (isDecimalDigit(current)) {
975 record8(current);
976 state = InExponent;
977 } else {
978 setDone(Bad);
979 err = IllegalExponentIndicator;
980 errmsg = QLatin1String("Illegal syntax for exponential number");
981 }
982 break;
983 case InExponent:
984 if (isDecimalDigit(current)) {
985 record8(current);
986 } else {
987 setDone(Number);
988 }
989 break;
990 default:
991 Q_ASSERT_X(0, "Lexer::lex", "Unhandled state in switch statement");
992 }
993
994 // move on to the next character
995 if (!done)
996 shift(1);
997 if (state != Start && state != InSingleLineComment)
998 bol = false;
999 }
1000
1001 // no identifiers allowed directly after numeric literal, e.g. "3in" is bad
1002 if ((state == Number || state == Octal || state == Hex)
1003 && isIdentLetter(current)) {
1004 state = Bad;
1005 err = IllegalIdentifier;
1006 errmsg = QLatin1String("Identifier cannot start with numeric literal");
1007 }
1008
1009 // terminate string
1010 buffer8[pos8] = '\0';
1011
1012 double dval = 0;
1013 if (state == Number) {
1014 dval = qstrtod(buffer8, 0, 0);
1015 } else if (state == Hex) { // scan hex numbers
1016 dval = QScript::integerFromString(buffer8, pos8, 16);
1017 state = Number;
1018 } else if (state == Octal) { // scan octal number
1019 dval = QScript::integerFromString(buffer8, pos8, 8);
1020 state = Number;
1021 }
1022
1023 restrKeyword = false;
1024 delimited = false;
1025
1026 switch (parenthesesState) {
1027 case IgnoreParentheses:
1028 break;
1029 case CountParentheses:
1030 if (token == QScriptGrammar::T_RPAREN) {
1031 --parenthesesCount;
1032 if (parenthesesCount == 0)
1033 parenthesesState = BalancedParentheses;
1034 } else if (token == QScriptGrammar::T_LPAREN) {
1035 ++parenthesesCount;
1036 }
1037 break;
1038 case BalancedParentheses:
1039 parenthesesState = IgnoreParentheses;
1040 break;
1041 }
1042
1043 switch (state) {
1044 case Eof:
1045 return 0;
1046 case Other:
1047 if(token == QScriptGrammar::T_RBRACE || token == QScriptGrammar::T_SEMICOLON)
1048 delimited = true;
1049 return token;
1050 case Identifier:
1051 if ((token = findReservedWord(buffer16, pos16)) < 0) {
1052 /* TODO: close leak on parse error. same holds true for String */
1053 qsyylval = QString(buffer16, pos16);
1054 return QScriptGrammar::T_IDENTIFIER;
1055 }
1056 if (token == QScriptGrammar::T_CONTINUE || token == QScriptGrammar::T_BREAK
1057 || token == QScriptGrammar::T_RETURN || token == QScriptGrammar::T_THROW) {
1058 restrKeyword = true;
1059 } else if (token == QScriptGrammar::T_IF || token == QScriptGrammar::T_FOR
1060 || token == QScriptGrammar::T_WHILE || token == QScriptGrammar::T_WITH) {
1061 parenthesesState = CountParentheses;
1062 parenthesesCount = 0;
1063 } else if (token == QScriptGrammar::T_DO) {
1064 parenthesesState = BalancedParentheses;
1065 }
1066 return token;
1067 case String:
1068 qsyylval = QString(buffer16, pos16);
1069 return QScriptGrammar::T_STRING_LITERAL;
1070 case Number:
1071 qsyylval = dval;
1072 return QScriptGrammar::T_NUMERIC_LITERAL;
1073 case Bad:
1074 return -1;
1075 default:
1076 Q_ASSERT(!"unhandled numeration value in switch");
1077 return -1;
1078 }
1079}
1080
1081bool QScript::Lexer::isWhiteSpace() const
1082{
1083 return (current == ' ' || current == '\t' ||
1084 current == 0x0b || current == 0x0c);
1085}
1086
1087bool QScript::Lexer::isLineTerminator() const
1088{
1089 return (current == '\n' || current == '\r');
1090}
1091
1092bool QScript::Lexer::isIdentLetter(ushort c)
1093{
1094 /* TODO: allow other legitimate unicode chars */
1095 return ((c >= 'a' && c <= 'z')
1096 || (c >= 'A' && c <= 'Z')
1097 || c == '$'
1098 || c == '_');
1099}
1100
1101bool QScript::Lexer::isDecimalDigit(ushort c)
1102{
1103 return (c >= '0' && c <= '9');
1104}
1105
1106bool QScript::Lexer::isHexDigit(ushort c) const
1107{
1108 return ((c >= '0' && c <= '9')
1109 || (c >= 'a' && c <= 'f')
1110 || (c >= 'A' && c <= 'F'));
1111}
1112
1113bool QScript::Lexer::isOctalDigit(ushort c) const
1114{
1115 return (c >= '0' && c <= '7');
1116}
1117
1118int QScript::Lexer::matchPunctuator(ushort c1, ushort c2,
1119 ushort c3, ushort c4)
1120{
1121 if (c1 == '>' && c2 == '>' && c3 == '>' && c4 == '=') {
1122 shift(4);
1123 return QScriptGrammar::T_GT_GT_GT_EQ;
1124 } else if (c1 == '=' && c2 == '=' && c3 == '=') {
1125 shift(3);
1126 return QScriptGrammar::T_EQ_EQ_EQ;
1127 } else if (c1 == '!' && c2 == '=' && c3 == '=') {
1128 shift(3);
1129 return QScriptGrammar::T_NOT_EQ_EQ;
1130 } else if (c1 == '>' && c2 == '>' && c3 == '>') {
1131 shift(3);
1132 return QScriptGrammar::T_GT_GT_GT;
1133 } else if (c1 == '<' && c2 == '<' && c3 == '=') {
1134 shift(3);
1135 return QScriptGrammar::T_LT_LT_EQ;
1136 } else if (c1 == '>' && c2 == '>' && c3 == '=') {
1137 shift(3);
1138 return QScriptGrammar::T_GT_GT_EQ;
1139 } else if (c1 == '<' && c2 == '=') {
1140 shift(2);
1141 return QScriptGrammar::T_LE;
1142 } else if (c1 == '>' && c2 == '=') {
1143 shift(2);
1144 return QScriptGrammar::T_GE;
1145 } else if (c1 == '!' && c2 == '=') {
1146 shift(2);
1147 return QScriptGrammar::T_NOT_EQ;
1148 } else if (c1 == '+' && c2 == '+') {
1149 shift(2);
1150 return QScriptGrammar::T_PLUS_PLUS;
1151 } else if (c1 == '-' && c2 == '-') {
1152 shift(2);
1153 return QScriptGrammar::T_MINUS_MINUS;
1154 } else if (c1 == '=' && c2 == '=') {
1155 shift(2);
1156 return QScriptGrammar::T_EQ_EQ;
1157 } else if (c1 == '+' && c2 == '=') {
1158 shift(2);
1159 return QScriptGrammar::T_PLUS_EQ;
1160 } else if (c1 == '-' && c2 == '=') {
1161 shift(2);
1162 return QScriptGrammar::T_MINUS_EQ;
1163 } else if (c1 == '*' && c2 == '=') {
1164 shift(2);
1165 return QScriptGrammar::T_STAR_EQ;
1166 } else if (c1 == '/' && c2 == '=') {
1167 shift(2);
1168 return QScriptGrammar::T_DIVIDE_EQ;
1169 } else if (c1 == '&' && c2 == '=') {
1170 shift(2);
1171 return QScriptGrammar::T_AND_EQ;
1172 } else if (c1 == '^' && c2 == '=') {
1173 shift(2);
1174 return QScriptGrammar::T_XOR_EQ;
1175 } else if (c1 == '%' && c2 == '=') {
1176 shift(2);
1177 return QScriptGrammar::T_REMAINDER_EQ;
1178 } else if (c1 == '|' && c2 == '=') {
1179 shift(2);
1180 return QScriptGrammar::T_OR_EQ;
1181 } else if (c1 == '<' && c2 == '<') {
1182 shift(2);
1183 return QScriptGrammar::T_LT_LT;
1184 } else if (c1 == '>' && c2 == '>') {
1185 shift(2);
1186 return QScriptGrammar::T_GT_GT;
1187 } else if (c1 == '&' && c2 == '&') {
1188 shift(2);
1189 return QScriptGrammar::T_AND_AND;
1190 } else if (c1 == '|' && c2 == '|') {
1191 shift(2);
1192 return QScriptGrammar::T_OR_OR;
1193 }
1194
1195 switch(c1) {
1196 case '=': shift(1); return QScriptGrammar::T_EQ;
1197 case '>': shift(1); return QScriptGrammar::T_GT;
1198 case '<': shift(1); return QScriptGrammar::T_LT;
1199 case ',': shift(1); return QScriptGrammar::T_COMMA;
1200 case '!': shift(1); return QScriptGrammar::T_NOT;
1201 case '~': shift(1); return QScriptGrammar::T_TILDE;
1202 case '?': shift(1); return QScriptGrammar::T_QUESTION;
1203 case ':': shift(1); return QScriptGrammar::T_COLON;
1204 case '.': shift(1); return QScriptGrammar::T_DOT;
1205 case '+': shift(1); return QScriptGrammar::T_PLUS;
1206 case '-': shift(1); return QScriptGrammar::T_MINUS;
1207 case '*': shift(1); return QScriptGrammar::T_STAR;
1208 case '/': shift(1); return QScriptGrammar::T_DIVIDE_;
1209 case '&': shift(1); return QScriptGrammar::T_AND;
1210 case '|': shift(1); return QScriptGrammar::T_OR;
1211 case '^': shift(1); return QScriptGrammar::T_XOR;
1212 case '%': shift(1); return QScriptGrammar::T_REMAINDER;
1213 case '(': shift(1); return QScriptGrammar::T_LPAREN;
1214 case ')': shift(1); return QScriptGrammar::T_RPAREN;
1215 case '{': shift(1); return QScriptGrammar::T_LBRACE;
1216 case '}': shift(1); return QScriptGrammar::T_RBRACE;
1217 case '[': shift(1); return QScriptGrammar::T_LBRACKET;
1218 case ']': shift(1); return QScriptGrammar::T_RBRACKET;
1219 case ';': shift(1); return QScriptGrammar::T_SEMICOLON;
1220
1221 default: return -1;
1222 }
1223}
1224
1225ushort QScript::Lexer::singleEscape(ushort c) const
1226{
1227 switch(c) {
1228 case 'b':
1229 return 0x08;
1230 case 't':
1231 return 0x09;
1232 case 'n':
1233 return 0x0A;
1234 case 'v':
1235 return 0x0B;
1236 case 'f':
1237 return 0x0C;
1238 case 'r':
1239 return 0x0D;
1240 case '"':
1241 return 0x22;
1242 case '\'':
1243 return 0x27;
1244 case '\\':
1245 return 0x5C;
1246 default:
1247 return c;
1248 }
1249}
1250
1251ushort QScript::Lexer::convertOctal(ushort c1, ushort c2,
1252 ushort c3) const
1253{
1254 return ((c1 - '0') * 64 + (c2 - '0') * 8 + c3 - '0');
1255}
1256
1257unsigned char QScript::Lexer::convertHex(ushort c)
1258{
1259 if (c >= '0' && c <= '9')
1260 return (c - '0');
1261 else if (c >= 'a' && c <= 'f')
1262 return (c - 'a' + 10);
1263 else
1264 return (c - 'A' + 10);
1265}
1266
1267unsigned char QScript::Lexer::convertHex(ushort c1, ushort c2)
1268{
1269 return ((convertHex(c1) << 4) + convertHex(c2));
1270}
1271
1272QChar QScript::Lexer::convertUnicode(ushort c1, ushort c2,
1273 ushort c3, ushort c4)
1274{
1275 return QChar((convertHex(c3) << 4) + convertHex(c4),
1276 (convertHex(c1) << 4) + convertHex(c2));
1277}
1278
1279void QScript::Lexer::record8(ushort c)
1280{
1281 Q_ASSERT(c <= 0xff);
1282
1283 // enlarge buffer if full
1284 if (pos8 >= size8 - 1) {
1285 char *tmp = new char[2 * size8];
1286 memcpy(tmp, buffer8, size8 * sizeof(char));
1287 delete [] buffer8;
1288 buffer8 = tmp;
1289 size8 *= 2;
1290 }
1291
1292 buffer8[pos8++] = (char) c;
1293}
1294
1295void QScript::Lexer::record16(QChar c)
1296{
1297 // enlarge buffer if full
1298 if (pos16 >= size16 - 1) {
1299 QChar *tmp = new QChar[2 * size16];
1300 memcpy(tmp, buffer16, size16 * sizeof(QChar));
1301 delete [] buffer16;
1302 buffer16 = tmp;
1303 size16 *= 2;
1304 }
1305
1306 buffer16[pos16++] = c;
1307}
1308
1309void QScript::Lexer::recordStartPos()
1310{
1311 startlineno = yylineno;
1312 startcolumn = yycolumn;
1313}
1314
1315bool QScript::Lexer::scanRegExp(RegExpBodyPrefix prefix)
1316{
1317 pos16 = 0;
1318 bool lastWasEscape = false;
1319
1320 if (prefix == EqualPrefix)
1321 record16(QLatin1Char('='));
1322
1323 while (1) {
1324 if (isLineTerminator() || current == 0) {
1325 errmsg = QLatin1String("Unterminated regular expression literal");
1326 return false;
1327 }
1328 else if (current != '/' || lastWasEscape == true)
1329 {
1330 record16(current);
1331 lastWasEscape = !lastWasEscape && (current == '\\');
1332 }
1333 else {
1334 pattern = QString(buffer16, pos16);
1335 pos16 = 0;
1336 shift(1);
1337 break;
1338 }
1339 shift(1);
1340 }
1341
1342 flags = 0;
1343 while (isIdentLetter(current)) {
1344 record16(current);
1345 shift(1);
1346 }
1347
1348 return true;
1349}
1350
1351void QScript::Lexer::syncProhibitAutomaticSemicolon()
1352{
1353 if (parenthesesState == BalancedParentheses) {
1354 // we have seen something like "if (foo)", which means we should
1355 // never insert an automatic semicolon at this point, since it would
1356 // then be expanded into an empty statement (ECMA-262 7.9.1)
1357 prohibitAutomaticSemicolon = true;
1358 parenthesesState = IgnoreParentheses;
1359 } else {
1360 prohibitAutomaticSemicolon = false;
1361 }
1362}
1363
1364
1365class Translator;
1366
1367class QScriptParser: protected $table
1368{
1369public:
1370 QVariant val;
1371
1372 struct Location {
1373 int startLine;
1374 int startColumn;
1375 int endLine;
1376 int endColumn;
1377 };
1378
1379public:
1380 QScriptParser();
1381 ~QScriptParser();
1382
1383 bool parse(QScript::Lexer *lexer,
1384 const QString &fileName,
1385 Translator *translator);
1386
1387 inline QString errorMessage() const
1388 { return error_message; }
1389 inline int errorLineNumber() const
1390 { return error_lineno; }
1391 inline int errorColumnNumber() const
1392 { return error_column; }
1393
1394protected:
1395 inline void reallocateStack();
1396
1397 inline QVariant &sym(int index)
1398 { return sym_stack [tos + index - 1]; }
1399
1400 inline Location &loc(int index)
1401 { return location_stack [tos + index - 2]; }
1402
1403protected:
1404 int tos;
1405 int stack_size;
1406 QVector<QVariant> sym_stack;
1407 int *state_stack;
1408 Location *location_stack;
1409 QString error_message;
1410 int error_lineno;
1411 int error_column;
1412};
1413
1414inline void QScriptParser::reallocateStack()
1415{
1416 if (! stack_size)
1417 stack_size = 128;
1418 else
1419 stack_size <<= 1;
1420
1421 sym_stack.resize(stack_size);
1422 state_stack = reinterpret_cast<int*> (qRealloc(state_stack, stack_size * sizeof(int)));
1423 location_stack = reinterpret_cast<Location*> (qRealloc(location_stack, stack_size * sizeof(Location)));
1424}
1425
1426inline static bool automatic(QScript::Lexer *lexer, int token)
1427{
1428 return (token == $table::T_RBRACE)
1429 || (token == 0)
1430 || lexer->prevTerminator();
1431}
1432
1433QScriptParser::QScriptParser():
1434 tos(0),
1435 stack_size(0),
1436 sym_stack(0),
1437 state_stack(0),
1438 location_stack(0)
1439{
1440}
1441
1442QScriptParser::~QScriptParser()
1443{
1444 if (stack_size) {
1445 qFree(state_stack);
1446 qFree(location_stack);
1447 }
1448}
1449
1450static inline QScriptParser::Location location(QScript::Lexer *lexer)
1451{
1452 QScriptParser::Location loc;
1453 loc.startLine = lexer->startLineNo();
1454 loc.startColumn = lexer->startColumnNo();
1455 loc.endLine = lexer->endLineNo();
1456 loc.endColumn = lexer->endColumnNo();
1457 return loc;
1458}
1459
1460bool QScriptParser::parse(QScript::Lexer *lexer,
1461 const QString &fileName,
1462 Translator *translator)
1463{
1464 const int INITIAL_STATE = 0;
1465
1466 int yytoken = -1;
1467 int saved_yytoken = -1;
1468 int identLineNo = -1;
1469
1470 reallocateStack();
1471
1472 tos = 0;
1473 state_stack[++tos] = INITIAL_STATE;
1474
1475 while (true)
1476 {
1477 const int state = state_stack [tos];
1478 if (yytoken == -1 && - TERMINAL_COUNT != action_index [state])
1479 {
1480 if (saved_yytoken == -1)
1481 {
1482 yytoken = lexer->lex();
1483 location_stack [tos] = location(lexer);
1484 }
1485 else
1486 {
1487 yytoken = saved_yytoken;
1488 saved_yytoken = -1;
1489 }
1490 }
1491
1492 int act = t_action (state, yytoken);
1493
1494 if (act == ACCEPT_STATE)
1495 return true;
1496
1497 else if (act > 0)
1498 {
1499 if (++tos == stack_size)
1500 reallocateStack();
1501
1502 sym_stack [tos] = lexer->val ();
1503 state_stack [tos] = act;
1504 location_stack [tos] = location(lexer);
1505 yytoken = -1;
1506 }
1507
1508 else if (act < 0)
1509 {
1510 int r = - act - 1;
1511
1512 tos -= rhs [r];
1513 act = state_stack [tos++];
1514
1515 switch (r) {
1516./
1517
1518PrimaryExpression: T_THIS ;
1519
1520PrimaryExpression: T_IDENTIFIER ;
1521/.
1522case $rule_number: {
1523 sym(1) = sym(1).toByteArray();
1524 identLineNo = lexer->startLineNo();
1525} break;
1526./
1527
1528PrimaryExpression: T_NULL ;
1529PrimaryExpression: T_TRUE ;
1530PrimaryExpression: T_FALSE ;
1531PrimaryExpression: T_NUMERIC_LITERAL ;
1532PrimaryExpression: T_STRING_LITERAL ;
1533
1534PrimaryExpression: T_DIVIDE_ ;
1535/:
1536#define Q_SCRIPT_REGEXPLITERAL_RULE1 $rule_number
1537:/
1538/.
1539case $rule_number: {
1540 bool rx = lexer->scanRegExp(QScript::Lexer::NoPrefix);
1541 if (!rx) {
1542 error_message = lexer->errorMessage();
1543 error_lineno = lexer->startLineNo();
1544 error_column = lexer->startColumnNo();
1545 return false;
1546 }
1547} break;
1548./
1549
1550PrimaryExpression: T_DIVIDE_EQ ;
1551/:
1552#define Q_SCRIPT_REGEXPLITERAL_RULE2 $rule_number
1553:/
1554/.
1555case $rule_number: {
1556 bool rx = lexer->scanRegExp(QScript::Lexer::EqualPrefix);
1557 if (!rx) {
1558 error_message = lexer->errorMessage();
1559 error_lineno = lexer->startLineNo();
1560 error_column = lexer->startColumnNo();
1561 return false;
1562 }
1563} break;
1564./
1565
1566PrimaryExpression: T_LBRACKET ElisionOpt T_RBRACKET ;
1567PrimaryExpression: T_LBRACKET ElementList T_RBRACKET ;
1568PrimaryExpression: T_LBRACKET ElementList T_COMMA ElisionOpt T_RBRACKET ;
1569PrimaryExpression: T_LBRACE PropertyNameAndValueListOpt T_RBRACE ;
1570PrimaryExpression: T_LPAREN Expression T_RPAREN ;
1571ElementList: ElisionOpt AssignmentExpression ;
1572ElementList: ElementList T_COMMA ElisionOpt AssignmentExpression ;
1573Elision: T_COMMA ;
1574Elision: Elision T_COMMA ;
1575ElisionOpt: ;
1576ElisionOpt: Elision ;
1577PropertyNameAndValueList: PropertyName T_COLON AssignmentExpression ;
1578PropertyNameAndValueList: PropertyNameAndValueList T_COMMA PropertyName T_COLON AssignmentExpression ;
1579PropertyName: T_IDENTIFIER ;
1580PropertyName: T_STRING_LITERAL ;
1581PropertyName: T_NUMERIC_LITERAL ;
1582PropertyName: ReservedIdentifier ;
1583ReservedIdentifier: T_BREAK ;
1584ReservedIdentifier: T_CASE ;
1585ReservedIdentifier: T_CATCH ;
1586ReservedIdentifier: T_CONST ;
1587ReservedIdentifier: T_CONTINUE ;
1588ReservedIdentifier: T_DEBUGGER ;
1589ReservedIdentifier: T_DEFAULT ;
1590ReservedIdentifier: T_DELETE ;
1591ReservedIdentifier: T_DO ;
1592ReservedIdentifier: T_ELSE ;
1593ReservedIdentifier: T_FALSE ;
1594ReservedIdentifier: T_FINALLY ;
1595ReservedIdentifier: T_FOR ;
1596ReservedIdentifier: T_FUNCTION ;
1597ReservedIdentifier: T_IF ;
1598ReservedIdentifier: T_IN ;
1599ReservedIdentifier: T_INSTANCEOF ;
1600ReservedIdentifier: T_NEW ;
1601ReservedIdentifier: T_NULL ;
1602ReservedIdentifier: T_RESERVED_WORD ;
1603ReservedIdentifier: T_RETURN ;
1604ReservedIdentifier: T_SWITCH ;
1605ReservedIdentifier: T_THIS ;
1606ReservedIdentifier: T_THROW ;
1607ReservedIdentifier: T_TRUE ;
1608ReservedIdentifier: T_TRY ;
1609ReservedIdentifier: T_TYPEOF ;
1610ReservedIdentifier: T_VAR ;
1611ReservedIdentifier: T_VOID ;
1612ReservedIdentifier: T_WHILE ;
1613ReservedIdentifier: T_WITH ;
1614PropertyIdentifier: T_IDENTIFIER ;
1615PropertyIdentifier: ReservedIdentifier ;
1616
1617MemberExpression: PrimaryExpression ;
1618MemberExpression: FunctionExpression ;
1619MemberExpression: MemberExpression T_LBRACKET Expression T_RBRACKET ;
1620MemberExpression: MemberExpression T_DOT PropertyIdentifier ;
1621MemberExpression: T_NEW MemberExpression Arguments ;
1622NewExpression: MemberExpression ;
1623NewExpression: T_NEW NewExpression ;
1624
1625CallExpression: MemberExpression Arguments ;
1626/.
1627case $rule_number: {
1628 QString name = sym(1).toString();
1629 if ((name == QLatin1String("qsTranslate")) || (name == QLatin1String("QT_TRANSLATE_NOOP"))) {
1630 QVariantList args = sym(2).toList();
1631 if (args.size() < 2) {
1632 qWarning("%s:%d: %s() requires at least two arguments",
1633 qPrintable(fileName), identLineNo, qPrintable(name));
1634 } else {
1635 if ((args.at(0).type() != QVariant::String)
1636 || (args.at(1).type() != QVariant::String)) {
1637 qWarning("%s:%d: %s(): both arguments must be literal strings",
1638 qPrintable(fileName), identLineNo, qPrintable(name));
1639 } else {
1640 QString context = args.at(0).toString();
1641 QString text = args.at(1).toString();
1642 QString comment = args.value(2).toString();
1643 QString extracomment;
1644 bool plural = (args.size() > 4);
1645 recordMessage(translator, context, text, comment, extracomment,
1646 plural, fileName, identLineNo);
1647 }
1648 }
1649 } else if ((name == QLatin1String("qsTr")) || (name == QLatin1String("QT_TR_NOOP"))) {
1650 QVariantList args = sym(2).toList();
1651 if (args.size() < 1) {
1652 qWarning("%s:%d: %s() requires at least one argument",
1653 qPrintable(fileName), identLineNo, qPrintable(name));
1654 } else {
1655 if (args.at(0).type() != QVariant::String) {
1656 qWarning("%s:%d: %s(): text to translate must be a literal string",
1657 qPrintable(fileName), identLineNo, qPrintable(name));
1658 } else {
1659 QString context = QFileInfo(fileName).baseName();
1660 QString text = args.at(0).toString();
1661 QString comment = args.value(1).toString();
1662 QString extracomment;
1663 bool plural = (args.size() > 2);
1664 recordMessage(translator, context, text, comment, extracomment,
1665 plural, fileName, identLineNo);
1666 }
1667 }
1668 }
1669} break;
1670./
1671
1672CallExpression: CallExpression Arguments ;
1673CallExpression: CallExpression T_LBRACKET Expression T_RBRACKET ;
1674CallExpression: CallExpression T_DOT PropertyIdentifier ;
1675
1676Arguments: T_LPAREN T_RPAREN ;
1677/.
1678case $rule_number: {
1679 sym(1) = QVariantList();
1680} break;
1681./
1682
1683Arguments: T_LPAREN ArgumentList T_RPAREN ;
1684/.
1685case $rule_number: {
1686 sym(1) = sym(2);
1687} break;
1688./
1689
1690ArgumentList: AssignmentExpression ;
1691/.
1692case $rule_number: {
1693 sym(1) = QVariantList() << sym(1);
1694} break;
1695./
1696
1697ArgumentList: ArgumentList T_COMMA AssignmentExpression ;
1698/.
1699case $rule_number: {
1700 sym(1) = sym(1).toList() << sym(3);
1701} break;
1702./
1703
1704LeftHandSideExpression: NewExpression ;
1705LeftHandSideExpression: CallExpression ;
1706PostfixExpression: LeftHandSideExpression ;
1707PostfixExpression: LeftHandSideExpression T_PLUS_PLUS ;
1708PostfixExpression: LeftHandSideExpression T_MINUS_MINUS ;
1709UnaryExpression: PostfixExpression ;
1710UnaryExpression: T_DELETE UnaryExpression ;
1711UnaryExpression: T_VOID UnaryExpression ;
1712UnaryExpression: T_TYPEOF UnaryExpression ;
1713UnaryExpression: T_PLUS_PLUS UnaryExpression ;
1714UnaryExpression: T_MINUS_MINUS UnaryExpression ;
1715UnaryExpression: T_PLUS UnaryExpression ;
1716UnaryExpression: T_MINUS UnaryExpression ;
1717UnaryExpression: T_TILDE UnaryExpression ;
1718UnaryExpression: T_NOT UnaryExpression ;
1719MultiplicativeExpression: UnaryExpression ;
1720MultiplicativeExpression: MultiplicativeExpression T_STAR UnaryExpression ;
1721MultiplicativeExpression: MultiplicativeExpression T_DIVIDE_ UnaryExpression ;
1722MultiplicativeExpression: MultiplicativeExpression T_REMAINDER UnaryExpression ;
1723AdditiveExpression: MultiplicativeExpression ;
1724
1725AdditiveExpression: AdditiveExpression T_PLUS MultiplicativeExpression ;
1726/.
1727case $rule_number: {
1728 if ((sym(1).type() == QVariant::String) || (sym(3).type() == QVariant::String))
1729 sym(1) = sym(1).toString() + sym(3).toString();
1730 else
1731 sym(1) = QVariant();
1732} break;
1733./
1734
1735AdditiveExpression: AdditiveExpression T_MINUS MultiplicativeExpression ;
1736ShiftExpression: AdditiveExpression ;
1737ShiftExpression: ShiftExpression T_LT_LT AdditiveExpression ;
1738ShiftExpression: ShiftExpression T_GT_GT AdditiveExpression ;
1739ShiftExpression: ShiftExpression T_GT_GT_GT AdditiveExpression ;
1740RelationalExpression: ShiftExpression ;
1741RelationalExpression: RelationalExpression T_LT ShiftExpression ;
1742RelationalExpression: RelationalExpression T_GT ShiftExpression ;
1743RelationalExpression: RelationalExpression T_LE ShiftExpression ;
1744RelationalExpression: RelationalExpression T_GE ShiftExpression ;
1745RelationalExpression: RelationalExpression T_INSTANCEOF ShiftExpression ;
1746RelationalExpression: RelationalExpression T_IN ShiftExpression ;
1747RelationalExpressionNotIn: ShiftExpression ;
1748RelationalExpressionNotIn: RelationalExpressionNotIn T_LT ShiftExpression ;
1749RelationalExpressionNotIn: RelationalExpressionNotIn T_GT ShiftExpression ;
1750RelationalExpressionNotIn: RelationalExpressionNotIn T_LE ShiftExpression ;
1751RelationalExpressionNotIn: RelationalExpressionNotIn T_GE ShiftExpression ;
1752RelationalExpressionNotIn: RelationalExpressionNotIn T_INSTANCEOF ShiftExpression ;
1753EqualityExpression: RelationalExpression ;
1754EqualityExpression: EqualityExpression T_EQ_EQ RelationalExpression ;
1755EqualityExpression: EqualityExpression T_NOT_EQ RelationalExpression ;
1756EqualityExpression: EqualityExpression T_EQ_EQ_EQ RelationalExpression ;
1757EqualityExpression: EqualityExpression T_NOT_EQ_EQ RelationalExpression ;
1758EqualityExpressionNotIn: RelationalExpressionNotIn ;
1759EqualityExpressionNotIn: EqualityExpressionNotIn T_EQ_EQ RelationalExpressionNotIn ;
1760EqualityExpressionNotIn: EqualityExpressionNotIn T_NOT_EQ RelationalExpressionNotIn;
1761EqualityExpressionNotIn: EqualityExpressionNotIn T_EQ_EQ_EQ RelationalExpressionNotIn ;
1762EqualityExpressionNotIn: EqualityExpressionNotIn T_NOT_EQ_EQ RelationalExpressionNotIn ;
1763BitwiseANDExpression: EqualityExpression ;
1764BitwiseANDExpression: BitwiseANDExpression T_AND EqualityExpression ;
1765BitwiseANDExpressionNotIn: EqualityExpressionNotIn ;
1766BitwiseANDExpressionNotIn: BitwiseANDExpressionNotIn T_AND EqualityExpressionNotIn ;
1767BitwiseXORExpression: BitwiseANDExpression ;
1768BitwiseXORExpression: BitwiseXORExpression T_XOR BitwiseANDExpression ;
1769BitwiseXORExpressionNotIn: BitwiseANDExpressionNotIn ;
1770BitwiseXORExpressionNotIn: BitwiseXORExpressionNotIn T_XOR BitwiseANDExpressionNotIn ;
1771BitwiseORExpression: BitwiseXORExpression ;
1772BitwiseORExpression: BitwiseORExpression T_OR BitwiseXORExpression ;
1773BitwiseORExpressionNotIn: BitwiseXORExpressionNotIn ;
1774BitwiseORExpressionNotIn: BitwiseORExpressionNotIn T_OR BitwiseXORExpressionNotIn ;
1775LogicalANDExpression: BitwiseORExpression ;
1776LogicalANDExpression: LogicalANDExpression T_AND_AND BitwiseORExpression ;
1777LogicalANDExpressionNotIn: BitwiseORExpressionNotIn ;
1778LogicalANDExpressionNotIn: LogicalANDExpressionNotIn T_AND_AND BitwiseORExpressionNotIn ;
1779LogicalORExpression: LogicalANDExpression ;
1780LogicalORExpression: LogicalORExpression T_OR_OR LogicalANDExpression ;
1781LogicalORExpressionNotIn: LogicalANDExpressionNotIn ;
1782LogicalORExpressionNotIn: LogicalORExpressionNotIn T_OR_OR LogicalANDExpressionNotIn ;
1783ConditionalExpression: LogicalORExpression ;
1784ConditionalExpression: LogicalORExpression T_QUESTION AssignmentExpression T_COLON AssignmentExpression ;
1785ConditionalExpressionNotIn: LogicalORExpressionNotIn ;
1786ConditionalExpressionNotIn: LogicalORExpressionNotIn T_QUESTION AssignmentExpressionNotIn T_COLON AssignmentExpressionNotIn ;
1787AssignmentExpression: ConditionalExpression ;
1788AssignmentExpression: LeftHandSideExpression AssignmentOperator AssignmentExpression ;
1789AssignmentExpressionNotIn: ConditionalExpressionNotIn ;
1790AssignmentExpressionNotIn: LeftHandSideExpression AssignmentOperator AssignmentExpressionNotIn ;
1791AssignmentOperator: T_EQ ;
1792AssignmentOperator: T_STAR_EQ ;
1793AssignmentOperator: T_DIVIDE_EQ ;
1794AssignmentOperator: T_REMAINDER_EQ ;
1795AssignmentOperator: T_PLUS_EQ ;
1796AssignmentOperator: T_MINUS_EQ ;
1797AssignmentOperator: T_LT_LT_EQ ;
1798AssignmentOperator: T_GT_GT_EQ ;
1799AssignmentOperator: T_GT_GT_GT_EQ ;
1800AssignmentOperator: T_AND_EQ ;
1801AssignmentOperator: T_XOR_EQ ;
1802AssignmentOperator: T_OR_EQ ;
1803Expression: AssignmentExpression ;
1804Expression: Expression T_COMMA AssignmentExpression ;
1805ExpressionOpt: ;
1806ExpressionOpt: Expression ;
1807ExpressionNotIn: AssignmentExpressionNotIn ;
1808ExpressionNotIn: ExpressionNotIn T_COMMA AssignmentExpressionNotIn ;
1809ExpressionNotInOpt: ;
1810ExpressionNotInOpt: ExpressionNotIn ;
1811
1812Statement: Block ;
1813Statement: VariableStatement ;
1814Statement: EmptyStatement ;
1815Statement: ExpressionStatement ;
1816Statement: IfStatement ;
1817Statement: IterationStatement ;
1818Statement: ContinueStatement ;
1819Statement: BreakStatement ;
1820Statement: ReturnStatement ;
1821Statement: WithStatement ;
1822Statement: LabelledStatement ;
1823Statement: SwitchStatement ;
1824Statement: ThrowStatement ;
1825Statement: TryStatement ;
1826Statement: DebuggerStatement ;
1827
1828Block: T_LBRACE StatementListOpt T_RBRACE ;
1829StatementList: Statement ;
1830StatementList: StatementList Statement ;
1831StatementListOpt: ;
1832StatementListOpt: StatementList ;
1833VariableStatement: VariableDeclarationKind VariableDeclarationList T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
1834VariableStatement: VariableDeclarationKind VariableDeclarationList T_SEMICOLON ;
1835VariableDeclarationKind: T_CONST ;
1836VariableDeclarationKind: T_VAR ;
1837VariableDeclarationList: VariableDeclaration ;
1838VariableDeclarationList: VariableDeclarationList T_COMMA VariableDeclaration ;
1839VariableDeclarationListNotIn: VariableDeclarationNotIn ;
1840VariableDeclarationListNotIn: VariableDeclarationListNotIn T_COMMA VariableDeclarationNotIn ;
1841VariableDeclaration: T_IDENTIFIER InitialiserOpt ;
1842VariableDeclarationNotIn: T_IDENTIFIER InitialiserNotInOpt ;
1843Initialiser: T_EQ AssignmentExpression ;
1844InitialiserOpt: ;
1845InitialiserOpt: Initialiser ;
1846InitialiserNotIn: T_EQ AssignmentExpressionNotIn ;
1847InitialiserNotInOpt: ;
1848InitialiserNotInOpt: InitialiserNotIn ;
1849EmptyStatement: T_SEMICOLON ;
1850ExpressionStatement: Expression T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
1851ExpressionStatement: Expression T_SEMICOLON ;
1852IfStatement: T_IF T_LPAREN Expression T_RPAREN Statement T_ELSE Statement ;
1853IfStatement: T_IF T_LPAREN Expression T_RPAREN Statement ;
1854IterationStatement: T_DO Statement T_WHILE T_LPAREN Expression T_RPAREN T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
1855IterationStatement: T_DO Statement T_WHILE T_LPAREN Expression T_RPAREN T_SEMICOLON ;
1856IterationStatement: T_WHILE T_LPAREN Expression T_RPAREN Statement ;
1857IterationStatement: T_FOR T_LPAREN ExpressionNotInOpt T_SEMICOLON ExpressionOpt T_SEMICOLON ExpressionOpt T_RPAREN Statement ;
1858IterationStatement: T_FOR T_LPAREN T_VAR VariableDeclarationListNotIn T_SEMICOLON ExpressionOpt T_SEMICOLON ExpressionOpt T_RPAREN Statement ;
1859IterationStatement: T_FOR T_LPAREN LeftHandSideExpression T_IN Expression T_RPAREN Statement ;
1860IterationStatement: T_FOR T_LPAREN T_VAR VariableDeclarationNotIn T_IN Expression T_RPAREN Statement ;
1861ContinueStatement: T_CONTINUE T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
1862ContinueStatement: T_CONTINUE T_SEMICOLON ;
1863ContinueStatement: T_CONTINUE T_IDENTIFIER T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
1864ContinueStatement: T_CONTINUE T_IDENTIFIER T_SEMICOLON ;
1865BreakStatement: T_BREAK T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
1866BreakStatement: T_BREAK T_SEMICOLON ;
1867BreakStatement: T_BREAK T_IDENTIFIER T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
1868BreakStatement: T_BREAK T_IDENTIFIER T_SEMICOLON ;
1869ReturnStatement: T_RETURN ExpressionOpt T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
1870ReturnStatement: T_RETURN ExpressionOpt T_SEMICOLON ;
1871WithStatement: T_WITH T_LPAREN Expression T_RPAREN Statement ;
1872SwitchStatement: T_SWITCH T_LPAREN Expression T_RPAREN CaseBlock ;
1873CaseBlock: T_LBRACE CaseClausesOpt T_RBRACE ;
1874CaseBlock: T_LBRACE CaseClausesOpt DefaultClause CaseClausesOpt T_RBRACE ;
1875CaseClauses: CaseClause ;
1876CaseClauses: CaseClauses CaseClause ;
1877CaseClausesOpt: ;
1878CaseClausesOpt: CaseClauses ;
1879CaseClause: T_CASE Expression T_COLON StatementListOpt ;
1880DefaultClause: T_DEFAULT T_COLON StatementListOpt ;
1881LabelledStatement: T_IDENTIFIER T_COLON Statement ;
1882ThrowStatement: T_THROW Expression T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
1883ThrowStatement: T_THROW Expression T_SEMICOLON ;
1884TryStatement: T_TRY Block Catch ;
1885TryStatement: T_TRY Block Finally ;
1886TryStatement: T_TRY Block Catch Finally ;
1887Catch: T_CATCH T_LPAREN T_IDENTIFIER T_RPAREN Block ;
1888Finally: T_FINALLY Block ;
1889DebuggerStatement: T_DEBUGGER ;
1890FunctionDeclaration: T_FUNCTION T_IDENTIFIER T_LPAREN FormalParameterListOpt T_RPAREN T_LBRACE FunctionBodyOpt T_RBRACE ;
1891FunctionExpression: T_FUNCTION IdentifierOpt T_LPAREN FormalParameterListOpt T_RPAREN T_LBRACE FunctionBodyOpt T_RBRACE ;
1892FormalParameterList: T_IDENTIFIER ;
1893FormalParameterList: FormalParameterList T_COMMA T_IDENTIFIER ;
1894FormalParameterListOpt: ;
1895FormalParameterListOpt: FormalParameterList ;
1896FunctionBodyOpt: ;
1897FunctionBodyOpt: FunctionBody ;
1898FunctionBody: SourceElements ;
1899Program: SourceElements ;
1900SourceElements: SourceElement ;
1901SourceElements: SourceElements SourceElement ;
1902SourceElement: Statement ;
1903SourceElement: FunctionDeclaration ;
1904IdentifierOpt: ;
1905IdentifierOpt: T_IDENTIFIER ;
1906PropertyNameAndValueListOpt: ;
1907PropertyNameAndValueListOpt: PropertyNameAndValueList ;
1908
1909/.
1910 } // switch
1911
1912 state_stack [tos] = nt_action (act, lhs [r] - TERMINAL_COUNT);
1913
1914 if (rhs[r] > 1) {
1915 location_stack[tos - 1].endLine = location_stack[tos + rhs[r] - 2].endLine;
1916 location_stack[tos - 1].endColumn = location_stack[tos + rhs[r] - 2].endColumn;
1917 location_stack[tos] = location_stack[tos + rhs[r] - 1];
1918 }
1919 }
1920
1921 else
1922 {
1923 if (saved_yytoken == -1 && automatic (lexer, yytoken) && t_action (state, T_AUTOMATIC_SEMICOLON) > 0)
1924 {
1925 saved_yytoken = yytoken;
1926 yytoken = T_SEMICOLON;
1927 continue;
1928 }
1929
1930 else if ((state == INITIAL_STATE) && (yytoken == 0)) {
1931 // accept empty input
1932 yytoken = T_SEMICOLON;
1933 continue;
1934 }
1935
1936 int ers = state;
1937 int shifts = 0;
1938 int reduces = 0;
1939 int expected_tokens [3];
1940 for (int tk = 0; tk < TERMINAL_COUNT; ++tk)
1941 {
1942 int k = t_action (ers, tk);
1943
1944 if (! k)
1945 continue;
1946 else if (k < 0)
1947 ++reduces;
1948 else if (spell [tk])
1949 {
1950 if (shifts < 3)
1951 expected_tokens [shifts] = tk;
1952 ++shifts;
1953 }
1954 }
1955
1956 error_message.clear ();
1957 if (shifts && shifts < 3)
1958 {
1959 bool first = true;
1960
1961 for (int s = 0; s < shifts; ++s)
1962 {
1963 if (first)
1964 error_message += QLatin1String ("Expected ");
1965 else
1966 error_message += QLatin1String (", ");
1967
1968 first = false;
1969 error_message += QLatin1String("`");
1970 error_message += QLatin1String (spell [expected_tokens [s]]);
1971 error_message += QLatin1String("'");
1972 }
1973 }
1974
1975 if (error_message.isEmpty())
1976 error_message = lexer->errorMessage();
1977
1978 error_lineno = lexer->startLineNo();
1979 error_column = lexer->startColumnNo();
1980
1981 return false;
1982 }
1983 }
1984
1985 return false;
1986}
1987
1988
1989bool loadQScript(Translator &translator, QIODevice &dev, ConversionData &cd)
1990{
1991 QTextStream ts(&dev);
1992 QByteArray codecName;
1993 if (!cd.m_codecForSource.isEmpty())
1994 codecName = cd.m_codecForSource;
1995 else
1996 codecName = translator.codecName(); // Just because it should be latin1 already
1997 ts.setCodec(QTextCodec::codecForName(codecName));
1998 ts.setAutoDetectUnicode(true);
1999
2000 QString code = ts.readAll();
2001 QScript::Lexer lexer;
2002 lexer.setCode(code, /*lineNumber=*/1);
2003 QScriptParser parser;
2004 if (!parser.parse(&lexer, cd.m_sourceFileName, &translator)) {
2005 qWarning("%s:%d: %s", qPrintable(cd.m_sourceFileName), parser.errorLineNumber(),
2006 qPrintable(parser.errorMessage()));
2007 return false;
2008 }
2009
2010 // Java uses UTF-16 internally and Jambi makes UTF-8 for tr() purposes of it.
2011 translator.setCodecName("UTF-8");
2012 return true;
2013}
2014
2015bool saveQScript(const Translator &translator, QIODevice &dev, ConversionData &cd)
2016{
2017 Q_UNUSED(dev);
2018 Q_UNUSED(translator);
2019 cd.appendError(QLatin1String("Cannot save .js files"));
2020 return false;
2021}
2022
2023int initQScript()
2024{
2025 Translator::FileFormat format;
2026 format.extension = QLatin1String("js");
2027 format.fileType = Translator::FileFormat::SourceCode;
2028 format.priority = 0;
2029 format.description = QObject::tr("Qt Script source files");
2030 format.loader = &loadQScript;
2031 format.saver = &saveQScript;
2032 Translator::registerFileFormat(format);
2033 return 1;
2034}
2035
2036Q_CONSTRUCTOR_FUNCTION(initQScript)
2037
2038QT_END_NAMESPACE
2039./
Note: See TracBrowser for help on using the repository browser.