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