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