source: branches/vendor/trolltech/qt/current/tools/linguist/shared/qscript.g @ 2

Last change on this file since 2 was 2, checked in by Dmitry A. Kuminov, 13 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 (qt-info@nokia.com)
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 qt-sales@nokia.com.
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.