source: trunk/tools/linguist/lupdate/qscript.g@ 1147

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

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

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