src/declarative/qml/parser/qdeclarativejslexer.cpp
branchGCC_SURGE
changeset 31 5daf16870df6
parent 30 5dc02b23752f
child 33 3e2da88830cd
equal deleted inserted replaced
27:93b982ccede2 31:5daf16870df6
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 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 QtDeclarative module 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 #ifdef HAVE_CONFIG_H
       
    43 #include <config.h>
       
    44 #endif
       
    45 
       
    46 #include "private/qdeclarativejslexer_p.h"
       
    47 
       
    48 #include "private/qdeclarativejsglobal_p.h"
       
    49 #include "private/qdeclarativejsengine_p.h"
       
    50 #include "private/qdeclarativejsgrammar_p.h"
       
    51 
       
    52 #include <QtCore/qcoreapplication.h>
       
    53 
       
    54 #include <ctype.h>
       
    55 #include <stdlib.h>
       
    56 #include <stdio.h>
       
    57 #include <string.h>
       
    58 
       
    59 QT_BEGIN_NAMESPACE
       
    60 Q_DECL_IMPORT extern double qstrtod(const char *s00, char const **se, bool *ok);
       
    61 QT_END_NAMESPACE
       
    62 
       
    63 QT_QML_BEGIN_NAMESPACE
       
    64 
       
    65 #define shiftWindowsLineBreak() \
       
    66     do { \
       
    67         if (((current == '\r') && (next1 == '\n')) \
       
    68             || ((current == '\n') && (next1 == '\r'))) { \
       
    69             shift(1); \
       
    70         } \
       
    71     } \
       
    72     while (0)
       
    73 
       
    74 namespace QDeclarativeJS {
       
    75 extern double integerFromString(const char *buf, int size, int radix);
       
    76 }
       
    77 
       
    78 using namespace QDeclarativeJS;
       
    79 
       
    80 Lexer::Lexer(Engine *eng, bool tokenizeComments)
       
    81     : driver(eng),
       
    82       yylineno(0),
       
    83       done(false),
       
    84       size8(128), size16(128),
       
    85       pos8(0), pos16(0),
       
    86       terminator(false),
       
    87       restrKeyword(false),
       
    88       delimited(false),
       
    89       stackToken(-1),
       
    90       state(Start),
       
    91       pos(0),
       
    92       code(0), length(0),
       
    93       yycolumn(0),
       
    94       startpos(0),
       
    95       startlineno(0), startcolumn(0),
       
    96       bol(true),
       
    97       current(0), next1(0), next2(0), next3(0),
       
    98       err(NoError),
       
    99       wantRx(false),
       
   100       check_reserved(true),
       
   101       parenthesesState(IgnoreParentheses),
       
   102       parenthesesCount(0),
       
   103       prohibitAutomaticSemicolon(false),
       
   104       tokenizeComments(tokenizeComments)
       
   105 {
       
   106     driver->setLexer(this);
       
   107     // allocate space for read buffers
       
   108     buffer8 = new char[size8];
       
   109     buffer16 = new QChar[size16];
       
   110     pattern = 0;
       
   111     flags = 0;
       
   112 
       
   113 }
       
   114 
       
   115 Lexer::~Lexer()
       
   116 {
       
   117     delete [] buffer8;
       
   118     delete [] buffer16;
       
   119 }
       
   120 
       
   121 void Lexer::setCode(const QString &c, int lineno)
       
   122 {
       
   123     errmsg = QString();
       
   124     yylineno = lineno;
       
   125     yycolumn = 1;
       
   126     restrKeyword = false;
       
   127     delimited = false;
       
   128     stackToken = -1;
       
   129     pos = 0;
       
   130     code = c.unicode();
       
   131     length = c.length();
       
   132     bol = true;
       
   133 
       
   134     // read first characters
       
   135     current = (length > 0) ? code[0].unicode() : 0;
       
   136     next1 = (length > 1) ? code[1].unicode() : 0;
       
   137     next2 = (length > 2) ? code[2].unicode() : 0;
       
   138     next3 = (length > 3) ? code[3].unicode() : 0;
       
   139 }
       
   140 
       
   141 void Lexer::shift(uint p)
       
   142 {
       
   143     while (p--) {
       
   144         ++pos;
       
   145         ++yycolumn;
       
   146         current = next1;
       
   147         next1 = next2;
       
   148         next2 = next3;
       
   149         next3 = (pos + 3 < length) ? code[pos+3].unicode() : 0;
       
   150     }
       
   151 }
       
   152 
       
   153 void Lexer::setDone(State s)
       
   154 {
       
   155     state = s;
       
   156     done = true;
       
   157 }
       
   158 
       
   159 int Lexer::findReservedWord(const QChar *c, int size) const
       
   160 {
       
   161     switch (size) {
       
   162     case 2: {
       
   163         if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('o'))
       
   164             return QDeclarativeJSGrammar::T_DO;
       
   165         else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('f'))
       
   166             return QDeclarativeJSGrammar::T_IF;
       
   167         else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n'))
       
   168             return QDeclarativeJSGrammar::T_IN;
       
   169         else if (c[0] == QLatin1Char('a') && c[1] == QLatin1Char('s'))
       
   170             return QDeclarativeJSGrammar::T_AS;
       
   171         else if (c[0] == QLatin1Char('o') && c[1] == QLatin1Char('n'))
       
   172             return QDeclarativeJSGrammar::T_ON;
       
   173     }   break;
       
   174 
       
   175     case 3: {
       
   176         if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('o') && c[2] == QLatin1Char('r'))
       
   177             return QDeclarativeJSGrammar::T_FOR;
       
   178         else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('e') && c[2] == QLatin1Char('w'))
       
   179             return QDeclarativeJSGrammar::T_NEW;
       
   180         else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r') && c[2] == QLatin1Char('y'))
       
   181             return QDeclarativeJSGrammar::T_TRY;
       
   182         else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('a') && c[2] == QLatin1Char('r'))
       
   183             return QDeclarativeJSGrammar::T_VAR;
       
   184         else if (check_reserved) {
       
   185             if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n') && c[2] == QLatin1Char('t'))
       
   186                 return QDeclarativeJSGrammar::T_RESERVED_WORD;
       
   187         }
       
   188     }   break;
       
   189 
       
   190     case 4: {
       
   191         if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('a')
       
   192                 && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('e'))
       
   193             return QDeclarativeJSGrammar::T_CASE;
       
   194         else if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('l')
       
   195                 && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('e'))
       
   196             return QDeclarativeJSGrammar::T_ELSE;
       
   197         else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h')
       
   198                 && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('s'))
       
   199             return QDeclarativeJSGrammar::T_THIS;
       
   200         else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('o')
       
   201                 && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('d'))
       
   202             return QDeclarativeJSGrammar::T_VOID;
       
   203         else if (c[0] == QLatin1Char('w') && c[1] == QLatin1Char('i')
       
   204                 && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('h'))
       
   205             return QDeclarativeJSGrammar::T_WITH;
       
   206         else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r')
       
   207                 && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('e'))
       
   208             return QDeclarativeJSGrammar::T_TRUE;
       
   209         else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('u')
       
   210                 && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('l'))
       
   211             return QDeclarativeJSGrammar::T_NULL;
       
   212         else if (check_reserved) {
       
   213             if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('n')
       
   214                     && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('m'))
       
   215                 return QDeclarativeJSGrammar::T_RESERVED_WORD;
       
   216             else if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('y')
       
   217                     && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e'))
       
   218                 return QDeclarativeJSGrammar::T_RESERVED_WORD;
       
   219             else if (c[0] == QLatin1Char('l') && c[1] == QLatin1Char('o')
       
   220                     && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('g'))
       
   221                 return QDeclarativeJSGrammar::T_RESERVED_WORD;
       
   222             else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('h')
       
   223                     && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('r'))
       
   224                 return QDeclarativeJSGrammar::T_RESERVED_WORD;
       
   225             else if (c[0] == QLatin1Char('g') && c[1] == QLatin1Char('o')
       
   226                     && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('o'))
       
   227                 return QDeclarativeJSGrammar::T_RESERVED_WORD;
       
   228         }
       
   229     }   break;
       
   230 
       
   231     case 5: {
       
   232         if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('r')
       
   233                 && c[2] == QLatin1Char('e') && c[3] == QLatin1Char('a')
       
   234                 && c[4] == QLatin1Char('k'))
       
   235             return QDeclarativeJSGrammar::T_BREAK;
       
   236         else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('a')
       
   237                 && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('c')
       
   238                 && c[4] == QLatin1Char('h'))
       
   239             return QDeclarativeJSGrammar::T_CATCH;
       
   240         else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h')
       
   241                 && c[2] == QLatin1Char('r') && c[3] == QLatin1Char('o')
       
   242                 && c[4] == QLatin1Char('w'))
       
   243             return QDeclarativeJSGrammar::T_THROW;
       
   244         else if (c[0] == QLatin1Char('w') && c[1] == QLatin1Char('h')
       
   245                 && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('l')
       
   246                 && c[4] == QLatin1Char('e'))
       
   247             return QDeclarativeJSGrammar::T_WHILE;
       
   248         else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('o')
       
   249                 && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('s')
       
   250                 && c[4] == QLatin1Char('t'))
       
   251             return QDeclarativeJSGrammar::T_CONST;
       
   252         else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('a')
       
   253                 && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('s')
       
   254                 && c[4] == QLatin1Char('e'))
       
   255             return QDeclarativeJSGrammar::T_FALSE;
       
   256         else if (check_reserved) {
       
   257             if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('h')
       
   258                     && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('r')
       
   259                     && c[4] == QLatin1Char('t'))
       
   260                 return QDeclarativeJSGrammar::T_RESERVED_WORD;
       
   261             else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('u')
       
   262                     && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('e')
       
   263                     && c[4] == QLatin1Char('r'))
       
   264                 return QDeclarativeJSGrammar::T_RESERVED_WORD;
       
   265             else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('i')
       
   266                     && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('a')
       
   267                     && c[4] == QLatin1Char('l'))
       
   268                 return QDeclarativeJSGrammar::T_RESERVED_WORD;
       
   269             else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('l')
       
   270                     && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('s')
       
   271                     && c[4] == QLatin1Char('s'))
       
   272                 return QDeclarativeJSGrammar::T_RESERVED_WORD;
       
   273             else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('l')
       
   274                     && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('a')
       
   275                     && c[4] == QLatin1Char('t'))
       
   276                 return QDeclarativeJSGrammar::T_RESERVED_WORD;
       
   277         }
       
   278     }   break;
       
   279 
       
   280     case 6: {
       
   281         if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('e')
       
   282                 && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('e')
       
   283                 && c[4] == QLatin1Char('t') && c[5] == QLatin1Char('e'))
       
   284             return QDeclarativeJSGrammar::T_DELETE;
       
   285         else if (c[0] == QLatin1Char('r') && c[1] == QLatin1Char('e')
       
   286                 && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('u')
       
   287                 && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('n'))
       
   288             return QDeclarativeJSGrammar::T_RETURN;
       
   289         else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('w')
       
   290                 && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('t')
       
   291                 && c[4] == QLatin1Char('c') && c[5] == QLatin1Char('h'))
       
   292             return QDeclarativeJSGrammar::T_SWITCH;
       
   293         else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('y')
       
   294                 && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('e')
       
   295                 && c[4] == QLatin1Char('o') && c[5] == QLatin1Char('f'))
       
   296             return QDeclarativeJSGrammar::T_TYPEOF;
       
   297         else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('m')
       
   298             && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('o')
       
   299             && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('t'))
       
   300             return QDeclarativeJSGrammar::T_IMPORT;
       
   301         else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('i')
       
   302             && c[2] == QLatin1Char('g') && c[3] == QLatin1Char('n')
       
   303             && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('l'))
       
   304             return QDeclarativeJSGrammar::T_SIGNAL;
       
   305         else if (check_reserved) {
       
   306             if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('x')
       
   307                     && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('o')
       
   308                     && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('t'))
       
   309                 return QDeclarativeJSGrammar::T_RESERVED_WORD;
       
   310             else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('t')
       
   311                     && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('t')
       
   312                     && c[4] == QLatin1Char('i') && c[5] == QLatin1Char('c'))
       
   313                 return QDeclarativeJSGrammar::T_RESERVED_WORD;
       
   314             else if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('o')
       
   315                     && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('b')
       
   316                     && c[4] == QLatin1Char('l') && c[5] == QLatin1Char('e'))
       
   317                 return QDeclarativeJSGrammar::T_RESERVED_WORD;
       
   318             else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('m')
       
   319                     && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('o')
       
   320                     && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('t'))
       
   321                 return QDeclarativeJSGrammar::T_RESERVED_WORD;
       
   322             else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('u')
       
   323                     && c[2] == QLatin1Char('b') && c[3] == QLatin1Char('l')
       
   324                     && c[4] == QLatin1Char('i') && c[5] == QLatin1Char('c'))
       
   325                 return QDeclarativeJSGrammar::T_PUBLIC;
       
   326             else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('a')
       
   327                     && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('i')
       
   328                     && c[4] == QLatin1Char('v') && c[5] == QLatin1Char('e'))
       
   329                 return QDeclarativeJSGrammar::T_RESERVED_WORD;
       
   330             else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h')
       
   331                     && c[2] == QLatin1Char('r') && c[3] == QLatin1Char('o')
       
   332                     && c[4] == QLatin1Char('w') && c[5] == QLatin1Char('s'))
       
   333                 return QDeclarativeJSGrammar::T_RESERVED_WORD;
       
   334         }
       
   335     }   break;
       
   336 
       
   337     case 7: {
       
   338         if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('e')
       
   339                 && c[2] == QLatin1Char('f') && c[3] == QLatin1Char('a')
       
   340                 && c[4] == QLatin1Char('u') && c[5] == QLatin1Char('l')
       
   341                 && c[6] == QLatin1Char('t'))
       
   342             return QDeclarativeJSGrammar::T_DEFAULT;
       
   343         else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('i')
       
   344                 && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('a')
       
   345                 && c[4] == QLatin1Char('l') && c[5] == QLatin1Char('l')
       
   346                 && c[6] == QLatin1Char('y'))
       
   347             return QDeclarativeJSGrammar::T_FINALLY;
       
   348         else if (check_reserved) {
       
   349             if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('o')
       
   350                     && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('l')
       
   351                     && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('a')
       
   352                     && c[6] == QLatin1Char('n'))
       
   353                 return QDeclarativeJSGrammar::T_RESERVED_WORD;
       
   354             else if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('x')
       
   355                     && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e')
       
   356                     && c[4] == QLatin1Char('n') && c[5] == QLatin1Char('d')
       
   357                     && c[6] == QLatin1Char('s'))
       
   358                 return QDeclarativeJSGrammar::T_RESERVED_WORD;
       
   359             else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('a')
       
   360                     && c[2] == QLatin1Char('c') && c[3] == QLatin1Char('k')
       
   361                     && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('g')
       
   362                     && c[6] == QLatin1Char('e'))
       
   363                 return QDeclarativeJSGrammar::T_RESERVED_WORD;
       
   364             else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('r')
       
   365                     && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('v')
       
   366                     && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('t')
       
   367                     && c[6] == QLatin1Char('e'))
       
   368                 return QDeclarativeJSGrammar::T_RESERVED_WORD;
       
   369         }
       
   370     }   break;
       
   371 
       
   372     case 8: {
       
   373         if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('o')
       
   374                 && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('t')
       
   375                 && c[4] == QLatin1Char('i') && c[5] == QLatin1Char('n')
       
   376                 && c[6] == QLatin1Char('u') && c[7] == QLatin1Char('e'))
       
   377             return QDeclarativeJSGrammar::T_CONTINUE;
       
   378         else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('u')
       
   379                 && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('c')
       
   380                 && c[4] == QLatin1Char('t') && c[5] == QLatin1Char('i')
       
   381                 && c[6] == QLatin1Char('o') && c[7] == QLatin1Char('n'))
       
   382             return QDeclarativeJSGrammar::T_FUNCTION;
       
   383         else if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('e')
       
   384                 && c[2] == QLatin1Char('b') && c[3] == QLatin1Char('u')
       
   385                 && c[4] == QLatin1Char('g') && c[5] == QLatin1Char('g')
       
   386                 && c[6] == QLatin1Char('e') && c[7] == QLatin1Char('r'))
       
   387             return QDeclarativeJSGrammar::T_DEBUGGER;
       
   388         else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('r')
       
   389                 && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('p')
       
   390                 && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('r')
       
   391                 && c[6] == QLatin1Char('t') && c[7] == QLatin1Char('y'))
       
   392             return QDeclarativeJSGrammar::T_PROPERTY;
       
   393         else if (c[0] == QLatin1Char('r') && c[1] == QLatin1Char('e')
       
   394                 && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('d')
       
   395                 && c[4] == QLatin1Char('o') && c[5] == QLatin1Char('n')
       
   396                 && c[6] == QLatin1Char('l') && c[7] == QLatin1Char('y'))
       
   397             return QDeclarativeJSGrammar::T_READONLY;
       
   398         else if (check_reserved) {
       
   399             if (c[0] == QLatin1Char('a') && c[1] == QLatin1Char('b')
       
   400                     && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('t')
       
   401                     && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('a')
       
   402                     && c[6] == QLatin1Char('c') && c[7] == QLatin1Char('t'))
       
   403                 return QDeclarativeJSGrammar::T_RESERVED_WORD;
       
   404             else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('o')
       
   405                     && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('a')
       
   406                     && c[4] == QLatin1Char('t') && c[5] == QLatin1Char('i')
       
   407                     && c[6] == QLatin1Char('l') && c[7] == QLatin1Char('e'))
       
   408                 return QDeclarativeJSGrammar::T_RESERVED_WORD;
       
   409         }
       
   410     }   break;
       
   411 
       
   412     case 9: {
       
   413         if (check_reserved) {
       
   414             if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n')
       
   415                     && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e')
       
   416                     && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('f')
       
   417                     && c[6] == QLatin1Char('a') && c[7] == QLatin1Char('c')
       
   418                     && c[8] == QLatin1Char('e'))
       
   419                 return QDeclarativeJSGrammar::T_RESERVED_WORD;
       
   420             else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r')
       
   421                     && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('n')
       
   422                     && c[4] == QLatin1Char('s') && c[5] == QLatin1Char('i')
       
   423                     && c[6] == QLatin1Char('e') && c[7] == QLatin1Char('n')
       
   424                     && c[8] == QLatin1Char('t'))
       
   425                 return QDeclarativeJSGrammar::T_RESERVED_WORD;
       
   426             else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('r')
       
   427                     && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('t')
       
   428                     && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('c')
       
   429                     && c[6] == QLatin1Char('t') && c[7] == QLatin1Char('e')
       
   430                     && c[8] == QLatin1Char('d'))
       
   431                 return QDeclarativeJSGrammar::T_RESERVED_WORD;
       
   432         }
       
   433     }   break;
       
   434 
       
   435     case 10: {
       
   436         if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n')
       
   437                 && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('t')
       
   438                 && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('n')
       
   439                 && c[6] == QLatin1Char('c') && c[7] == QLatin1Char('e')
       
   440                 && c[8] == QLatin1Char('o') && c[9] == QLatin1Char('f'))
       
   441             return QDeclarativeJSGrammar::T_INSTANCEOF;
       
   442         else if (check_reserved) {
       
   443             if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('m')
       
   444                     && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('l')
       
   445                     && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('m')
       
   446                     && c[6] == QLatin1Char('e') && c[7] == QLatin1Char('n')
       
   447                     && c[8] == QLatin1Char('t') && c[9] == QLatin1Char('s'))
       
   448                 return QDeclarativeJSGrammar::T_RESERVED_WORD;
       
   449         }
       
   450     }   break;
       
   451 
       
   452     case 12: {
       
   453         if (check_reserved) {
       
   454             if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('y')
       
   455                     && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('c')
       
   456                     && c[4] == QLatin1Char('h') && c[5] == QLatin1Char('r')
       
   457                     && c[6] == QLatin1Char('o') && c[7] == QLatin1Char('n')
       
   458                     && c[8] == QLatin1Char('i') && c[9] == QLatin1Char('z')
       
   459                     && c[10] == QLatin1Char('e') && c[11] == QLatin1Char('d'))
       
   460                 return QDeclarativeJSGrammar::T_RESERVED_WORD;
       
   461         }
       
   462     }   break;
       
   463 
       
   464     } // switch
       
   465 
       
   466     return -1;
       
   467 }
       
   468 
       
   469 int Lexer::lex()
       
   470 {
       
   471     int token = 0;
       
   472     state = Start;
       
   473     ushort stringType = 0; // either single or double quotes
       
   474     bool multiLineString = false;
       
   475     pos8 = pos16 = 0;
       
   476     done = false;
       
   477     terminator = false;
       
   478 
       
   479     // did we push a token on the stack previously ?
       
   480     // (after an automatic semicolon insertion)
       
   481     if (stackToken >= 0) {
       
   482         setDone(Other);
       
   483         token = stackToken;
       
   484         stackToken = -1;
       
   485     }
       
   486 
       
   487     bool identifierWithEscapedUnicode = false;
       
   488 
       
   489     while (!done) {
       
   490         switch (state) {
       
   491         case Start:
       
   492             if (isWhiteSpace()) {
       
   493                 // do nothing
       
   494             } else if (current == '/' && next1 == '/') {
       
   495                 recordStartPos();
       
   496                 shift(1);
       
   497                 state = InSingleLineComment;
       
   498             } else if (current == '/' && next1 == '*') {
       
   499                 recordStartPos();
       
   500                 shift(1);
       
   501                 state = InMultiLineComment;
       
   502             } else if (current == 0) {
       
   503                 syncProhibitAutomaticSemicolon();
       
   504                 if (!terminator && !delimited && !prohibitAutomaticSemicolon) {
       
   505                     // automatic semicolon insertion if program incomplete
       
   506                     token = QDeclarativeJSGrammar::T_SEMICOLON;
       
   507                     stackToken = 0;
       
   508                     setDone(Other);
       
   509                 } else {
       
   510                     setDone(Eof);
       
   511                 }
       
   512             } else if (isLineTerminator()) {
       
   513                 shiftWindowsLineBreak();
       
   514                 yylineno++;
       
   515                 yycolumn = 0;
       
   516                 bol = true;
       
   517                 terminator = true;
       
   518                 syncProhibitAutomaticSemicolon();
       
   519                 if (restrKeyword) {
       
   520                     token = QDeclarativeJSGrammar::T_SEMICOLON;
       
   521                     setDone(Other);
       
   522                 }
       
   523             } else if (current == '"' || current == '\'') {
       
   524                 recordStartPos();
       
   525                 state = InString;
       
   526                 multiLineString = false;
       
   527                 stringType = current;
       
   528             } else if (current == '\\' && next1 == 'u') {
       
   529                 identifierWithEscapedUnicode = true;
       
   530                 recordStartPos();
       
   531 
       
   532                 shift(2); // skip the unicode escape prefix `\u'
       
   533 
       
   534                 if (isHexDigit(current) && isHexDigit(next1) &&
       
   535                      isHexDigit(next2) && isHexDigit(next3)) {
       
   536                     record16(convertUnicode(current, next1, next2, next3));
       
   537                     shift(3);
       
   538                     state = InIdentifier;
       
   539                 } else {
       
   540                     setDone(Bad);
       
   541                     err = IllegalUnicodeEscapeSequence;
       
   542                     errmsg = QCoreApplication::translate("QDeclarativeParser", "Illegal unicode escape sequence");
       
   543                     break;
       
   544                 }
       
   545 
       
   546             } else if (isIdentLetter(current)) {
       
   547                 identifierWithEscapedUnicode = false;
       
   548                 recordStartPos();
       
   549                 record16(current);
       
   550                 state = InIdentifier;
       
   551             } else if (current == '0') {
       
   552                 recordStartPos();
       
   553                 record8(current);
       
   554                 state = InNum0;
       
   555             } else if (isDecimalDigit(current)) {
       
   556                 recordStartPos();
       
   557                 record8(current);
       
   558                 state = InNum;
       
   559             } else if (current == '.' && isDecimalDigit(next1)) {
       
   560                 recordStartPos();
       
   561                 record8(current);
       
   562                 state = InDecimal;
       
   563             } else {
       
   564                 recordStartPos();
       
   565                 token = matchPunctuator(current, next1, next2, next3);
       
   566                 if (token != -1) {
       
   567                     if (terminator && !delimited && !prohibitAutomaticSemicolon
       
   568                         && (token == QDeclarativeJSGrammar::T_PLUS_PLUS
       
   569                             || token == QDeclarativeJSGrammar::T_MINUS_MINUS)) {
       
   570                         // automatic semicolon insertion
       
   571                         stackToken = token;
       
   572                         token = QDeclarativeJSGrammar::T_SEMICOLON;
       
   573                     }
       
   574                     setDone(Other);
       
   575                 }
       
   576                 else {
       
   577                     setDone(Bad);
       
   578                     err = IllegalCharacter;
       
   579                     errmsg = QCoreApplication::translate("QDeclarativeParser", "Illegal character");
       
   580                 }
       
   581             }
       
   582             break;
       
   583         case InString:
       
   584             if (current == stringType) {
       
   585                 shift(1);
       
   586                 setDone(String);
       
   587             } else if (isLineTerminator()) {
       
   588                 multiLineString = true;
       
   589                 record16(current);
       
   590             } else if (current == 0 || isLineTerminator()) {
       
   591                 setDone(Bad);
       
   592                 err = UnclosedStringLiteral;
       
   593                 errmsg = QCoreApplication::translate("QDeclarativeParser", "Unclosed string at end of line");
       
   594             } else if (current == '\\') {
       
   595                 state = InEscapeSequence;
       
   596             } else {
       
   597                 record16(current);
       
   598             }
       
   599             break;
       
   600             // Escape Sequences inside of strings
       
   601         case InEscapeSequence:
       
   602             if (isOctalDigit(current)) {
       
   603                 if (current >= '0' && current <= '3' &&
       
   604                      isOctalDigit(next1) && isOctalDigit(next2)) {
       
   605                     record16(convertOctal(current, next1, next2));
       
   606                     shift(2);
       
   607                     state = InString;
       
   608                 } else if (isOctalDigit(current) &&
       
   609                             isOctalDigit(next1)) {
       
   610                     record16(convertOctal('0', current, next1));
       
   611                     shift(1);
       
   612                     state = InString;
       
   613                 } else if (isOctalDigit(current)) {
       
   614                     record16(convertOctal('0', '0', current));
       
   615                     state = InString;
       
   616                 } else {
       
   617                     setDone(Bad);
       
   618                     err = IllegalEscapeSequence;
       
   619                     errmsg = QCoreApplication::translate("QDeclarativeParser", "Illegal escape squence");
       
   620                 }
       
   621             } else if (current == 'x')
       
   622                 state = InHexEscape;
       
   623             else if (current == 'u')
       
   624                 state = InUnicodeEscape;
       
   625             else {
       
   626                 if (isLineTerminator()) {
       
   627                     shiftWindowsLineBreak();
       
   628                     yylineno++;
       
   629                     yycolumn = 0;
       
   630                     bol = true;
       
   631                 } else {
       
   632                     record16(singleEscape(current));
       
   633                 }
       
   634                 state = InString;
       
   635             }
       
   636             break;
       
   637         case InHexEscape:
       
   638             if (isHexDigit(current) && isHexDigit(next1)) {
       
   639                 state = InString;
       
   640                 record16(QLatin1Char(convertHex(current, next1)));
       
   641                 shift(1);
       
   642             } else if (current == stringType) {
       
   643                 record16(QLatin1Char('x'));
       
   644                 shift(1);
       
   645                 setDone(String);
       
   646             } else {
       
   647                 record16(QLatin1Char('x'));
       
   648                 record16(current);
       
   649                 state = InString;
       
   650             }
       
   651             break;
       
   652         case InUnicodeEscape:
       
   653             if (isHexDigit(current) && isHexDigit(next1) &&
       
   654                  isHexDigit(next2) && isHexDigit(next3)) {
       
   655                 record16(convertUnicode(current, next1, next2, next3));
       
   656                 shift(3);
       
   657                 state = InString;
       
   658             } else if (current == stringType) {
       
   659                 record16(QLatin1Char('u'));
       
   660                 shift(1);
       
   661                 setDone(String);
       
   662             } else {
       
   663                 setDone(Bad);
       
   664                 err = IllegalUnicodeEscapeSequence;
       
   665                 errmsg = QCoreApplication::translate("QDeclarativeParser", "Illegal unicode escape sequence");
       
   666             }
       
   667             break;
       
   668         case InSingleLineComment:
       
   669             if (isLineTerminator()) {
       
   670                 shiftWindowsLineBreak();
       
   671                 yylineno++;
       
   672                 yycolumn = 0;
       
   673                 terminator = true;
       
   674                 bol = true;
       
   675                 if (restrKeyword) {
       
   676                     token = QDeclarativeJSGrammar::T_SEMICOLON;
       
   677                     setDone(Other);
       
   678                 } else
       
   679                     state = Start;
       
   680                 driver->addComment(startpos, tokenLength(), startlineno, startcolumn);
       
   681             } else if (current == 0) {
       
   682                 driver->addComment(startpos, tokenLength(), startlineno, startcolumn);
       
   683                 setDone(Eof);
       
   684             }
       
   685 
       
   686             break;
       
   687         case InMultiLineComment:
       
   688             if (current == 0) {
       
   689                 setDone(Bad);
       
   690                 err = UnclosedComment;
       
   691                 errmsg = QCoreApplication::translate("QDeclarativeParser", "Unclosed comment at end of file");
       
   692                 driver->addComment(startpos, tokenLength(), startlineno, startcolumn);
       
   693             } else if (isLineTerminator()) {
       
   694                 shiftWindowsLineBreak();
       
   695                 yylineno++;
       
   696             } else if (current == '*' && next1 == '/') {
       
   697                 state = Start;
       
   698                 shift(1);
       
   699                 driver->addComment(startpos, tokenLength(), startlineno, startcolumn);
       
   700             }
       
   701 
       
   702             break;
       
   703         case InIdentifier:
       
   704             if (isIdentLetter(current) || isDecimalDigit(current)) {
       
   705                 record16(current);
       
   706                 break;
       
   707             } else if (current == '\\' && next1 == 'u') {
       
   708                 identifierWithEscapedUnicode = true;
       
   709                 shift(2); // skip the unicode escape prefix `\u'
       
   710 
       
   711                 if (isHexDigit(current) && isHexDigit(next1) &&
       
   712                      isHexDigit(next2) && isHexDigit(next3)) {
       
   713                     record16(convertUnicode(current, next1, next2, next3));
       
   714                     shift(3);
       
   715                     break;
       
   716                 } else {
       
   717                     setDone(Bad);
       
   718                     err = IllegalUnicodeEscapeSequence;
       
   719                     errmsg = QCoreApplication::translate("QDeclarativeParser", "Illegal unicode escape sequence");
       
   720                     break;
       
   721                 }
       
   722             }
       
   723             setDone(Identifier);
       
   724             break;
       
   725         case InNum0:
       
   726             if (current == 'x' || current == 'X') {
       
   727                 record8(current);
       
   728                 state = InHex;
       
   729             } else if (current == '.') {
       
   730                 record8(current);
       
   731                 state = InDecimal;
       
   732             } else if (current == 'e' || current == 'E') {
       
   733                 record8(current);
       
   734                 state = InExponentIndicator;
       
   735             } else if (isOctalDigit(current)) {
       
   736                 record8(current);
       
   737                 state = InOctal;
       
   738             } else if (isDecimalDigit(current)) {
       
   739                 record8(current);
       
   740                 state = InDecimal;
       
   741             } else {
       
   742                 setDone(Number);
       
   743             }
       
   744             break;
       
   745         case InHex:
       
   746             if (isHexDigit(current))
       
   747                 record8(current);
       
   748             else
       
   749                 setDone(Hex);
       
   750             break;
       
   751         case InOctal:
       
   752             if (isOctalDigit(current)) {
       
   753                 record8(current);
       
   754             } else if (isDecimalDigit(current)) {
       
   755                 record8(current);
       
   756                 state = InDecimal;
       
   757             } else {
       
   758                 setDone(Octal);
       
   759             }
       
   760             break;
       
   761         case InNum:
       
   762             if (isDecimalDigit(current)) {
       
   763                 record8(current);
       
   764             } else if (current == '.') {
       
   765                 record8(current);
       
   766                 state = InDecimal;
       
   767             } else if (current == 'e' || current == 'E') {
       
   768                 record8(current);
       
   769                 state = InExponentIndicator;
       
   770             } else {
       
   771                 setDone(Number);
       
   772             }
       
   773             break;
       
   774         case InDecimal:
       
   775             if (isDecimalDigit(current)) {
       
   776                 record8(current);
       
   777             } else if (current == 'e' || current == 'E') {
       
   778                 record8(current);
       
   779                 state = InExponentIndicator;
       
   780             } else {
       
   781                 setDone(Number);
       
   782             }
       
   783             break;
       
   784         case InExponentIndicator:
       
   785             if (current == '+' || current == '-') {
       
   786                 record8(current);
       
   787             } else if (isDecimalDigit(current)) {
       
   788                 record8(current);
       
   789                 state = InExponent;
       
   790             } else {
       
   791                 setDone(Bad);
       
   792                 err = IllegalExponentIndicator;
       
   793                 errmsg = QCoreApplication::translate("QDeclarativeParser", "Illegal syntax for exponential number");
       
   794             }
       
   795             break;
       
   796         case InExponent:
       
   797             if (isDecimalDigit(current)) {
       
   798                 record8(current);
       
   799             } else {
       
   800                 setDone(Number);
       
   801             }
       
   802             break;
       
   803         default:
       
   804             Q_ASSERT_X(0, "Lexer::lex", "Unhandled state in switch statement");
       
   805         }
       
   806 
       
   807         // move on to the next character
       
   808         if (!done)
       
   809             shift(1);
       
   810         if (state != Start && state != InSingleLineComment)
       
   811             bol = false;
       
   812     }
       
   813 
       
   814     // no identifiers allowed directly after numeric literal, e.g. "3in" is bad
       
   815     if ((state == Number || state == Octal || state == Hex)
       
   816          && isIdentLetter(current)) {
       
   817         state = Bad;
       
   818         err = IllegalIdentifier;
       
   819         errmsg = QCoreApplication::translate("QDeclarativeParser", "Identifier cannot start with numeric literal");
       
   820     }
       
   821 
       
   822     // terminate string
       
   823     buffer8[pos8] = '\0';
       
   824 
       
   825     double dval = 0;
       
   826     if (state == Number) {
       
   827         dval = qstrtod(buffer8, 0, 0);
       
   828     } else if (state == Hex) { // scan hex numbers
       
   829         dval = integerFromString(buffer8, pos8, 16);
       
   830         state = Number;
       
   831     } else if (state == Octal) {   // scan octal number
       
   832         dval = integerFromString(buffer8, pos8, 8);
       
   833         state = Number;
       
   834     }
       
   835 
       
   836     restrKeyword = false;
       
   837     delimited = false;
       
   838 
       
   839     switch (parenthesesState) {
       
   840     case IgnoreParentheses:
       
   841         break;
       
   842     case CountParentheses:
       
   843         if (token == QDeclarativeJSGrammar::T_RPAREN) {
       
   844             --parenthesesCount;
       
   845             if (parenthesesCount == 0)
       
   846                 parenthesesState = BalancedParentheses;
       
   847         } else if (token == QDeclarativeJSGrammar::T_LPAREN) {
       
   848             ++parenthesesCount;
       
   849         }
       
   850         break;
       
   851     case BalancedParentheses:
       
   852         parenthesesState = IgnoreParentheses;
       
   853         break;
       
   854     }
       
   855 
       
   856     switch (state) {
       
   857     case Eof:
       
   858         return 0;
       
   859     case Other:
       
   860         if (token == QDeclarativeJSGrammar::T_RBRACE || token == QDeclarativeJSGrammar::T_SEMICOLON)
       
   861             delimited = true;
       
   862         return token;
       
   863     case Identifier:
       
   864         token = -1;
       
   865         if (! identifierWithEscapedUnicode)
       
   866             token = findReservedWord(buffer16, pos16);
       
   867 
       
   868         if (token < 0) {
       
   869             /* TODO: close leak on parse error. same holds true for String */
       
   870             if (driver)
       
   871                 qsyylval.ustr = driver->intern(buffer16, pos16);
       
   872             else
       
   873                 qsyylval.ustr = 0;
       
   874             return QDeclarativeJSGrammar::T_IDENTIFIER;
       
   875         }
       
   876         if (token == QDeclarativeJSGrammar::T_CONTINUE || token == QDeclarativeJSGrammar::T_BREAK
       
   877             || token == QDeclarativeJSGrammar::T_RETURN || token == QDeclarativeJSGrammar::T_THROW) {
       
   878             restrKeyword = true;
       
   879         } else if (token == QDeclarativeJSGrammar::T_IF || token == QDeclarativeJSGrammar::T_FOR
       
   880                    || token == QDeclarativeJSGrammar::T_WHILE || token == QDeclarativeJSGrammar::T_WITH) {
       
   881             parenthesesState = CountParentheses;
       
   882             parenthesesCount = 0;
       
   883         } else if (token == QDeclarativeJSGrammar::T_DO) {
       
   884             parenthesesState = BalancedParentheses;
       
   885         }
       
   886         return token;
       
   887     case String:
       
   888         if (driver)
       
   889             qsyylval.ustr = driver->intern(buffer16, pos16);
       
   890         else
       
   891             qsyylval.ustr = 0;
       
   892         return multiLineString?QDeclarativeJSGrammar::T_MULTILINE_STRING_LITERAL:QDeclarativeJSGrammar::T_STRING_LITERAL;
       
   893     case Number:
       
   894         qsyylval.dval = dval;
       
   895         return QDeclarativeJSGrammar::T_NUMERIC_LITERAL;
       
   896     case Bad:
       
   897         return -1;
       
   898     default:
       
   899         Q_ASSERT(!"unhandled numeration value in switch");
       
   900         return -1;
       
   901     }
       
   902 }
       
   903 
       
   904 bool Lexer::isWhiteSpace() const
       
   905 {
       
   906     return (current == ' ' || current == '\t' ||
       
   907              current == 0x0b || current == 0x0c);
       
   908 }
       
   909 
       
   910 bool Lexer::isLineTerminator() const
       
   911 {
       
   912     return (current == '\n' || current == '\r');
       
   913 }
       
   914 
       
   915 bool Lexer::isIdentLetter(ushort c)
       
   916 {
       
   917     // ASCII-biased, since all reserved words are ASCII, aand hence the
       
   918     // bulk of content to be parsed.
       
   919     if ((c >= 'a' && c <= 'z')
       
   920             || (c >= 'A' && c <= 'Z')
       
   921             || c == '$'
       
   922             || c == '_')
       
   923         return true;
       
   924     if (c < 128)
       
   925         return false;
       
   926     return QChar(c).isLetterOrNumber();
       
   927 }
       
   928 
       
   929 bool Lexer::isDecimalDigit(ushort c)
       
   930 {
       
   931     return (c >= '0' && c <= '9');
       
   932 }
       
   933 
       
   934 bool Lexer::isHexDigit(ushort c) const
       
   935 {
       
   936     return ((c >= '0' && c <= '9')
       
   937             || (c >= 'a' && c <= 'f')
       
   938             || (c >= 'A' && c <= 'F'));
       
   939 }
       
   940 
       
   941 bool Lexer::isOctalDigit(ushort c) const
       
   942 {
       
   943     return (c >= '0' && c <= '7');
       
   944 }
       
   945 
       
   946 int Lexer::matchPunctuator(ushort c1, ushort c2,
       
   947                             ushort c3, ushort c4)
       
   948 {
       
   949     if (c1 == '>' && c2 == '>' && c3 == '>' && c4 == '=') {
       
   950         shift(4);
       
   951         return QDeclarativeJSGrammar::T_GT_GT_GT_EQ;
       
   952     } else if (c1 == '=' && c2 == '=' && c3 == '=') {
       
   953         shift(3);
       
   954         return QDeclarativeJSGrammar::T_EQ_EQ_EQ;
       
   955     } else if (c1 == '!' && c2 == '=' && c3 == '=') {
       
   956         shift(3);
       
   957         return QDeclarativeJSGrammar::T_NOT_EQ_EQ;
       
   958     } else if (c1 == '>' && c2 == '>' && c3 == '>') {
       
   959         shift(3);
       
   960         return QDeclarativeJSGrammar::T_GT_GT_GT;
       
   961     } else if (c1 == '<' && c2 == '<' && c3 == '=') {
       
   962         shift(3);
       
   963         return QDeclarativeJSGrammar::T_LT_LT_EQ;
       
   964     } else if (c1 == '>' && c2 == '>' && c3 == '=') {
       
   965         shift(3);
       
   966         return QDeclarativeJSGrammar::T_GT_GT_EQ;
       
   967     } else if (c1 == '<' && c2 == '=') {
       
   968         shift(2);
       
   969         return QDeclarativeJSGrammar::T_LE;
       
   970     } else if (c1 == '>' && c2 == '=') {
       
   971         shift(2);
       
   972         return QDeclarativeJSGrammar::T_GE;
       
   973     } else if (c1 == '!' && c2 == '=') {
       
   974         shift(2);
       
   975         return QDeclarativeJSGrammar::T_NOT_EQ;
       
   976     } else if (c1 == '+' && c2 == '+') {
       
   977         shift(2);
       
   978         return QDeclarativeJSGrammar::T_PLUS_PLUS;
       
   979     } else if (c1 == '-' && c2 == '-') {
       
   980         shift(2);
       
   981         return QDeclarativeJSGrammar::T_MINUS_MINUS;
       
   982     } else if (c1 == '=' && c2 == '=') {
       
   983         shift(2);
       
   984         return QDeclarativeJSGrammar::T_EQ_EQ;
       
   985     } else if (c1 == '+' && c2 == '=') {
       
   986         shift(2);
       
   987         return QDeclarativeJSGrammar::T_PLUS_EQ;
       
   988     } else if (c1 == '-' && c2 == '=') {
       
   989         shift(2);
       
   990         return QDeclarativeJSGrammar::T_MINUS_EQ;
       
   991     } else if (c1 == '*' && c2 == '=') {
       
   992         shift(2);
       
   993         return QDeclarativeJSGrammar::T_STAR_EQ;
       
   994     } else if (c1 == '/' && c2 == '=') {
       
   995         shift(2);
       
   996         return QDeclarativeJSGrammar::T_DIVIDE_EQ;
       
   997     } else if (c1 == '&' && c2 == '=') {
       
   998         shift(2);
       
   999         return QDeclarativeJSGrammar::T_AND_EQ;
       
  1000     } else if (c1 == '^' && c2 == '=') {
       
  1001         shift(2);
       
  1002         return QDeclarativeJSGrammar::T_XOR_EQ;
       
  1003     } else if (c1 == '%' && c2 == '=') {
       
  1004         shift(2);
       
  1005         return QDeclarativeJSGrammar::T_REMAINDER_EQ;
       
  1006     } else if (c1 == '|' && c2 == '=') {
       
  1007         shift(2);
       
  1008         return QDeclarativeJSGrammar::T_OR_EQ;
       
  1009     } else if (c1 == '<' && c2 == '<') {
       
  1010         shift(2);
       
  1011         return QDeclarativeJSGrammar::T_LT_LT;
       
  1012     } else if (c1 == '>' && c2 == '>') {
       
  1013         shift(2);
       
  1014         return QDeclarativeJSGrammar::T_GT_GT;
       
  1015     } else if (c1 == '&' && c2 == '&') {
       
  1016         shift(2);
       
  1017         return QDeclarativeJSGrammar::T_AND_AND;
       
  1018     } else if (c1 == '|' && c2 == '|') {
       
  1019         shift(2);
       
  1020         return QDeclarativeJSGrammar::T_OR_OR;
       
  1021     }
       
  1022 
       
  1023     switch(c1) {
       
  1024         case '=': shift(1); return QDeclarativeJSGrammar::T_EQ;
       
  1025         case '>': shift(1); return QDeclarativeJSGrammar::T_GT;
       
  1026         case '<': shift(1); return QDeclarativeJSGrammar::T_LT;
       
  1027         case ',': shift(1); return QDeclarativeJSGrammar::T_COMMA;
       
  1028         case '!': shift(1); return QDeclarativeJSGrammar::T_NOT;
       
  1029         case '~': shift(1); return QDeclarativeJSGrammar::T_TILDE;
       
  1030         case '?': shift(1); return QDeclarativeJSGrammar::T_QUESTION;
       
  1031         case ':': shift(1); return QDeclarativeJSGrammar::T_COLON;
       
  1032         case '.': shift(1); return QDeclarativeJSGrammar::T_DOT;
       
  1033         case '+': shift(1); return QDeclarativeJSGrammar::T_PLUS;
       
  1034         case '-': shift(1); return QDeclarativeJSGrammar::T_MINUS;
       
  1035         case '*': shift(1); return QDeclarativeJSGrammar::T_STAR;
       
  1036         case '/': shift(1); return QDeclarativeJSGrammar::T_DIVIDE_;
       
  1037         case '&': shift(1); return QDeclarativeJSGrammar::T_AND;
       
  1038         case '|': shift(1); return QDeclarativeJSGrammar::T_OR;
       
  1039         case '^': shift(1); return QDeclarativeJSGrammar::T_XOR;
       
  1040         case '%': shift(1); return QDeclarativeJSGrammar::T_REMAINDER;
       
  1041         case '(': shift(1); return QDeclarativeJSGrammar::T_LPAREN;
       
  1042         case ')': shift(1); return QDeclarativeJSGrammar::T_RPAREN;
       
  1043         case '{': shift(1); return QDeclarativeJSGrammar::T_LBRACE;
       
  1044         case '}': shift(1); return QDeclarativeJSGrammar::T_RBRACE;
       
  1045         case '[': shift(1); return QDeclarativeJSGrammar::T_LBRACKET;
       
  1046         case ']': shift(1); return QDeclarativeJSGrammar::T_RBRACKET;
       
  1047         case ';': shift(1); return QDeclarativeJSGrammar::T_SEMICOLON;
       
  1048 
       
  1049         default: return -1;
       
  1050     }
       
  1051 }
       
  1052 
       
  1053 ushort Lexer::singleEscape(ushort c) const
       
  1054 {
       
  1055     switch(c) {
       
  1056     case 'b':
       
  1057         return 0x08;
       
  1058     case 't':
       
  1059         return 0x09;
       
  1060     case 'n':
       
  1061         return 0x0A;
       
  1062     case 'v':
       
  1063         return 0x0B;
       
  1064     case 'f':
       
  1065         return 0x0C;
       
  1066     case 'r':
       
  1067         return 0x0D;
       
  1068     case '"':
       
  1069         return 0x22;
       
  1070     case '\'':
       
  1071         return 0x27;
       
  1072     case '\\':
       
  1073         return 0x5C;
       
  1074     default:
       
  1075         return c;
       
  1076     }
       
  1077 }
       
  1078 
       
  1079 ushort Lexer::convertOctal(ushort c1, ushort c2,
       
  1080                             ushort c3) const
       
  1081 {
       
  1082     return ((c1 - '0') * 64 + (c2 - '0') * 8 + c3 - '0');
       
  1083 }
       
  1084 
       
  1085 unsigned char Lexer::convertHex(ushort c)
       
  1086 {
       
  1087     if (c >= '0' && c <= '9')
       
  1088         return (c - '0');
       
  1089     else if (c >= 'a' && c <= 'f')
       
  1090         return (c - 'a' + 10);
       
  1091     else
       
  1092         return (c - 'A' + 10);
       
  1093 }
       
  1094 
       
  1095 unsigned char Lexer::convertHex(ushort c1, ushort c2)
       
  1096 {
       
  1097     return ((convertHex(c1) << 4) + convertHex(c2));
       
  1098 }
       
  1099 
       
  1100 QChar Lexer::convertUnicode(ushort c1, ushort c2,
       
  1101                              ushort c3, ushort c4)
       
  1102 {
       
  1103     return QChar((convertHex(c3) << 4) + convertHex(c4),
       
  1104                   (convertHex(c1) << 4) + convertHex(c2));
       
  1105 }
       
  1106 
       
  1107 void Lexer::record8(ushort c)
       
  1108 {
       
  1109     Q_ASSERT(c <= 0xff);
       
  1110 
       
  1111     // enlarge buffer if full
       
  1112     if (pos8 >= size8 - 1) {
       
  1113         char *tmp = new char[2 * size8];
       
  1114         memcpy(tmp, buffer8, size8 * sizeof(char));
       
  1115         delete [] buffer8;
       
  1116         buffer8 = tmp;
       
  1117         size8 *= 2;
       
  1118     }
       
  1119 
       
  1120     buffer8[pos8++] = (char) c;
       
  1121 }
       
  1122 
       
  1123 void Lexer::record16(QChar c)
       
  1124 {
       
  1125     // enlarge buffer if full
       
  1126     if (pos16 >= size16 - 1) {
       
  1127         QChar *tmp = new QChar[2 * size16];
       
  1128         memcpy(tmp, buffer16, size16 * sizeof(QChar));
       
  1129         delete [] buffer16;
       
  1130         buffer16 = tmp;
       
  1131         size16 *= 2;
       
  1132     }
       
  1133 
       
  1134     buffer16[pos16++] = c;
       
  1135 }
       
  1136 
       
  1137 void Lexer::recordStartPos()
       
  1138 {
       
  1139     startpos = pos;
       
  1140     startlineno = yylineno;
       
  1141     startcolumn = yycolumn;
       
  1142 }
       
  1143 
       
  1144 bool Lexer::scanRegExp(RegExpBodyPrefix prefix)
       
  1145 {
       
  1146     pos16 = 0;
       
  1147     pattern = 0;
       
  1148 
       
  1149     if (prefix == EqualPrefix)
       
  1150         record16(QLatin1Char('='));
       
  1151 
       
  1152     while (true) {
       
  1153         switch (current) {
       
  1154 
       
  1155         case 0: // eof
       
  1156         case '\n': case '\r': // line terminator
       
  1157             errmsg = QCoreApplication::translate("QDeclarativeParser", "Unterminated regular expression literal");
       
  1158             return false;
       
  1159 
       
  1160         case '/':
       
  1161             shift(1);
       
  1162 
       
  1163             if (driver) // create the pattern
       
  1164                 pattern = driver->intern(buffer16, pos16);
       
  1165 
       
  1166             // scan the flags
       
  1167             pos16 = 0;
       
  1168             flags = 0;
       
  1169             while (isIdentLetter(current)) {
       
  1170                 int flag = Ecma::RegExp::flagFromChar(current);
       
  1171                 if (flag == 0) {
       
  1172                     errmsg = QCoreApplication::translate("QDeclarativeParser", "Invalid regular expression flag '%0'")
       
  1173                              .arg(QChar(current));
       
  1174                     return false;
       
  1175                 }
       
  1176                 flags |= flag;
       
  1177                 record16(current);
       
  1178                 shift(1);
       
  1179             }
       
  1180             return true;
       
  1181 
       
  1182         case '\\':
       
  1183             // regular expression backslash sequence
       
  1184             record16(current);
       
  1185             shift(1);
       
  1186 
       
  1187             if (! current || isLineTerminator()) {
       
  1188                 errmsg = QCoreApplication::translate("QDeclarativeParser", "Unterminated regular expression backslash sequence");
       
  1189                 return false;
       
  1190             }
       
  1191 
       
  1192             record16(current);
       
  1193             shift(1);
       
  1194             break;
       
  1195 
       
  1196         case '[':
       
  1197             // regular expression class
       
  1198             record16(current);
       
  1199             shift(1);
       
  1200 
       
  1201             while (current && ! isLineTerminator()) {
       
  1202                 if (current == ']')
       
  1203                     break;
       
  1204                 else if (current == '\\') {
       
  1205                     // regular expression backslash sequence
       
  1206                     record16(current);
       
  1207                     shift(1);
       
  1208 
       
  1209                     if (! current || isLineTerminator()) {
       
  1210                         errmsg = QCoreApplication::translate("QDeclarativeParser", "Unterminated regular expression backslash sequence");
       
  1211                         return false;
       
  1212                     }
       
  1213 
       
  1214                     record16(current);
       
  1215                     shift(1);
       
  1216                 } else {
       
  1217                     record16(current);
       
  1218                     shift(1);
       
  1219                 }
       
  1220             }
       
  1221 
       
  1222             if (current != ']') {
       
  1223                 errmsg = QCoreApplication::translate("QDeclarativeParser", "Unterminated regular expression class");
       
  1224                 return false;
       
  1225             }
       
  1226 
       
  1227             record16(current);
       
  1228             shift(1); // skip ]
       
  1229             break;
       
  1230 
       
  1231         default:
       
  1232             record16(current);
       
  1233             shift(1);
       
  1234         } // switch
       
  1235     } // while
       
  1236 
       
  1237     return false;
       
  1238 }
       
  1239 
       
  1240 void Lexer::syncProhibitAutomaticSemicolon()
       
  1241 {
       
  1242     if (parenthesesState == BalancedParentheses) {
       
  1243         // we have seen something like "if (foo)", which means we should
       
  1244         // never insert an automatic semicolon at this point, since it would
       
  1245         // then be expanded into an empty statement (ECMA-262 7.9.1)
       
  1246         prohibitAutomaticSemicolon = true;
       
  1247         parenthesesState = IgnoreParentheses;
       
  1248     } else {
       
  1249         prohibitAutomaticSemicolon = false;
       
  1250     }
       
  1251 }
       
  1252 
       
  1253 QT_QML_END_NAMESPACE
       
  1254 
       
  1255