2011-05-24 Oliver Hunt <oliver@apple.com>
[WebKit-https.git] / Source / JavaScriptCore / parser / Lexer.cpp
1 /*
2  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3  *  Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All Rights Reserved.
4  *  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
5  *  Copyright (C) 2010 Zoltan Herczeg (zherczeg@inf.u-szeged.hu)
6  *
7  *  This library is free software; you can redistribute it and/or
8  *  modify it under the terms of the GNU Library General Public
9  *  License as published by the Free Software Foundation; either
10  *  version 2 of the License, or (at your option) any later version.
11  *
12  *  This library is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  *  Library General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Library General Public License
18  *  along with this library; see the file COPYING.LIB.  If not, write to
19  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  *  Boston, MA 02110-1301, USA.
21  *
22  */
23
24 #include "config.h"
25 #include "Lexer.h"
26
27 #include "JSFunction.h"
28
29 #include "JSGlobalObjectFunctions.h"
30 #include "Identifier.h"
31 #include "NodeInfo.h"
32 #include "Nodes.h"
33 #include "dtoa.h"
34 #include <ctype.h>
35 #include <limits.h>
36 #include <string.h>
37 #include <wtf/Assertions.h>
38
39 using namespace WTF;
40 using namespace Unicode;
41
42 #include "JSParser.h"
43 #include "Lookup.h"
44 #include "Lexer.lut.h"
45
46 namespace JSC {
47
48
49 enum CharacterType {
50     // Types for the main switch
51
52     // The first three types are fixed, and also used for identifying
53     // ASCII alpha and alphanumeric characters (see isIdentStart and isIdentPart).
54     CharacterIdentifierStart,
55     CharacterZero,
56     CharacterNumber,
57
58     CharacterInvalid,
59     CharacterLineTerminator,
60     CharacterExclamationMark,
61     CharacterOpenParen,
62     CharacterCloseParen,
63     CharacterOpenBracket,
64     CharacterCloseBracket,
65     CharacterComma,
66     CharacterColon,
67     CharacterQuestion,
68     CharacterTilde,
69     CharacterQuote,
70     CharacterDot,
71     CharacterSlash,
72     CharacterBackSlash,
73     CharacterSemicolon,
74     CharacterOpenBrace,
75     CharacterCloseBrace,
76
77     CharacterAdd,
78     CharacterSub,
79     CharacterMultiply,
80     CharacterModulo,
81     CharacterAnd,
82     CharacterXor,
83     CharacterOr,
84     CharacterLess,
85     CharacterGreater,
86     CharacterEqual,
87
88     // Other types (only one so far)
89     CharacterWhiteSpace,
90 };
91
92 // 128 ASCII codes
93 static const unsigned short typesOfASCIICharacters[128] = {
94 /*   0 - Null               */ CharacterInvalid,
95 /*   1 - Start of Heading   */ CharacterInvalid,
96 /*   2 - Start of Text      */ CharacterInvalid,
97 /*   3 - End of Text        */ CharacterInvalid,
98 /*   4 - End of Transm.     */ CharacterInvalid,
99 /*   5 - Enquiry            */ CharacterInvalid,
100 /*   6 - Acknowledgment     */ CharacterInvalid,
101 /*   7 - Bell               */ CharacterInvalid,
102 /*   8 - Back Space         */ CharacterInvalid,
103 /*   9 - Horizontal Tab     */ CharacterWhiteSpace,
104 /*  10 - Line Feed          */ CharacterLineTerminator,
105 /*  11 - Vertical Tab       */ CharacterWhiteSpace,
106 /*  12 - Form Feed          */ CharacterWhiteSpace,
107 /*  13 - Carriage Return    */ CharacterLineTerminator,
108 /*  14 - Shift Out          */ CharacterInvalid,
109 /*  15 - Shift In           */ CharacterInvalid,
110 /*  16 - Data Line Escape   */ CharacterInvalid,
111 /*  17 - Device Control 1   */ CharacterInvalid,
112 /*  18 - Device Control 2   */ CharacterInvalid,
113 /*  19 - Device Control 3   */ CharacterInvalid,
114 /*  20 - Device Control 4   */ CharacterInvalid,
115 /*  21 - Negative Ack.      */ CharacterInvalid,
116 /*  22 - Synchronous Idle   */ CharacterInvalid,
117 /*  23 - End of Transmit    */ CharacterInvalid,
118 /*  24 - Cancel             */ CharacterInvalid,
119 /*  25 - End of Medium      */ CharacterInvalid,
120 /*  26 - Substitute         */ CharacterInvalid,
121 /*  27 - Escape             */ CharacterInvalid,
122 /*  28 - File Separator     */ CharacterInvalid,
123 /*  29 - Group Separator    */ CharacterInvalid,
124 /*  30 - Record Separator   */ CharacterInvalid,
125 /*  31 - Unit Separator     */ CharacterInvalid,
126 /*  32 - Space              */ CharacterWhiteSpace,
127 /*  33 - !                  */ CharacterExclamationMark,
128 /*  34 - "                  */ CharacterQuote,
129 /*  35 - #                  */ CharacterInvalid,
130 /*  36 - $                  */ CharacterIdentifierStart,
131 /*  37 - %                  */ CharacterModulo,
132 /*  38 - &                  */ CharacterAnd,
133 /*  39 - '                  */ CharacterQuote,
134 /*  40 - (                  */ CharacterOpenParen,
135 /*  41 - )                  */ CharacterCloseParen,
136 /*  42 - *                  */ CharacterMultiply,
137 /*  43 - +                  */ CharacterAdd,
138 /*  44 - ,                  */ CharacterComma,
139 /*  45 - -                  */ CharacterSub,
140 /*  46 - .                  */ CharacterDot,
141 /*  47 - /                  */ CharacterSlash,
142 /*  48 - 0                  */ CharacterZero,
143 /*  49 - 1                  */ CharacterNumber,
144 /*  50 - 2                  */ CharacterNumber,
145 /*  51 - 3                  */ CharacterNumber,
146 /*  52 - 4                  */ CharacterNumber,
147 /*  53 - 5                  */ CharacterNumber,
148 /*  54 - 6                  */ CharacterNumber,
149 /*  55 - 7                  */ CharacterNumber,
150 /*  56 - 8                  */ CharacterNumber,
151 /*  57 - 9                  */ CharacterNumber,
152 /*  58 - :                  */ CharacterColon,
153 /*  59 - ;                  */ CharacterSemicolon,
154 /*  60 - <                  */ CharacterLess,
155 /*  61 - =                  */ CharacterEqual,
156 /*  62 - >                  */ CharacterGreater,
157 /*  63 - ?                  */ CharacterQuestion,
158 /*  64 - @                  */ CharacterInvalid,
159 /*  65 - A                  */ CharacterIdentifierStart,
160 /*  66 - B                  */ CharacterIdentifierStart,
161 /*  67 - C                  */ CharacterIdentifierStart,
162 /*  68 - D                  */ CharacterIdentifierStart,
163 /*  69 - E                  */ CharacterIdentifierStart,
164 /*  70 - F                  */ CharacterIdentifierStart,
165 /*  71 - G                  */ CharacterIdentifierStart,
166 /*  72 - H                  */ CharacterIdentifierStart,
167 /*  73 - I                  */ CharacterIdentifierStart,
168 /*  74 - J                  */ CharacterIdentifierStart,
169 /*  75 - K                  */ CharacterIdentifierStart,
170 /*  76 - L                  */ CharacterIdentifierStart,
171 /*  77 - M                  */ CharacterIdentifierStart,
172 /*  78 - N                  */ CharacterIdentifierStart,
173 /*  79 - O                  */ CharacterIdentifierStart,
174 /*  80 - P                  */ CharacterIdentifierStart,
175 /*  81 - Q                  */ CharacterIdentifierStart,
176 /*  82 - R                  */ CharacterIdentifierStart,
177 /*  83 - S                  */ CharacterIdentifierStart,
178 /*  84 - T                  */ CharacterIdentifierStart,
179 /*  85 - U                  */ CharacterIdentifierStart,
180 /*  86 - V                  */ CharacterIdentifierStart,
181 /*  87 - W                  */ CharacterIdentifierStart,
182 /*  88 - X                  */ CharacterIdentifierStart,
183 /*  89 - Y                  */ CharacterIdentifierStart,
184 /*  90 - Z                  */ CharacterIdentifierStart,
185 /*  91 - [                  */ CharacterOpenBracket,
186 /*  92 - \                  */ CharacterBackSlash,
187 /*  93 - ]                  */ CharacterCloseBracket,
188 /*  94 - ^                  */ CharacterXor,
189 /*  95 - _                  */ CharacterIdentifierStart,
190 /*  96 - `                  */ CharacterInvalid,
191 /*  97 - a                  */ CharacterIdentifierStart,
192 /*  98 - b                  */ CharacterIdentifierStart,
193 /*  99 - c                  */ CharacterIdentifierStart,
194 /* 100 - d                  */ CharacterIdentifierStart,
195 /* 101 - e                  */ CharacterIdentifierStart,
196 /* 102 - f                  */ CharacterIdentifierStart,
197 /* 103 - g                  */ CharacterIdentifierStart,
198 /* 104 - h                  */ CharacterIdentifierStart,
199 /* 105 - i                  */ CharacterIdentifierStart,
200 /* 106 - j                  */ CharacterIdentifierStart,
201 /* 107 - k                  */ CharacterIdentifierStart,
202 /* 108 - l                  */ CharacterIdentifierStart,
203 /* 109 - m                  */ CharacterIdentifierStart,
204 /* 110 - n                  */ CharacterIdentifierStart,
205 /* 111 - o                  */ CharacterIdentifierStart,
206 /* 112 - p                  */ CharacterIdentifierStart,
207 /* 113 - q                  */ CharacterIdentifierStart,
208 /* 114 - r                  */ CharacterIdentifierStart,
209 /* 115 - s                  */ CharacterIdentifierStart,
210 /* 116 - t                  */ CharacterIdentifierStart,
211 /* 117 - u                  */ CharacterIdentifierStart,
212 /* 118 - v                  */ CharacterIdentifierStart,
213 /* 119 - w                  */ CharacterIdentifierStart,
214 /* 120 - x                  */ CharacterIdentifierStart,
215 /* 121 - y                  */ CharacterIdentifierStart,
216 /* 122 - z                  */ CharacterIdentifierStart,
217 /* 123 - {                  */ CharacterOpenBrace,
218 /* 124 - |                  */ CharacterOr,
219 /* 125 - }                  */ CharacterCloseBrace,
220 /* 126 - ~                  */ CharacterTilde,
221 /* 127 - Delete             */ CharacterInvalid,
222 };
223
224 Lexer::Lexer(JSGlobalData* globalData)
225     : m_isReparsing(false)
226     , m_globalData(globalData)
227     , m_keywordTable(JSC::mainTable)
228 {
229 }
230
231 Lexer::~Lexer()
232 {
233     m_keywordTable.deleteTable();
234 }
235
236 ALWAYS_INLINE const UChar* Lexer::currentCharacter() const
237 {
238     ASSERT(m_code <= m_codeEnd);
239     return m_code;
240 }
241
242 ALWAYS_INLINE int Lexer::currentOffset() const
243 {
244     return currentCharacter() - m_codeStart;
245 }
246
247 void Lexer::setCode(const SourceCode& source, ParserArena& arena)
248 {
249     m_arena = &arena.identifierArena();
250
251     m_lineNumber = source.firstLine();
252     m_delimited = false;
253     m_lastToken = -1;
254
255     const UChar* data = source.provider()->data();
256
257     m_source = &source;
258     m_codeStart = data;
259     m_code = data + source.startOffset();
260     m_codeEnd = data + source.endOffset();
261     m_error = false;
262     m_atLineStart = true;
263
264     m_buffer8.reserveInitialCapacity(initialReadBufferCapacity);
265     m_buffer16.reserveInitialCapacity((m_codeEnd - m_code) / 2);
266
267     if (LIKELY(m_code < m_codeEnd))
268         m_current = *m_code;
269     else
270         m_current = -1;
271     ASSERT(currentOffset() == source.startOffset());
272 }
273
274 ALWAYS_INLINE void Lexer::shift()
275 {
276     // Faster than an if-else sequence
277     ASSERT(m_current != -1);
278     m_current = -1;
279     ++m_code;
280     if (LIKELY(m_code < m_codeEnd))
281         m_current = *m_code;
282 }
283
284 ALWAYS_INLINE int Lexer::peek(int offset)
285 {
286     // Only use if necessary
287     ASSERT(offset > 0 && offset < 5);
288     const UChar* code = m_code + offset;
289     return (code < m_codeEnd) ? *code : -1;
290 }
291
292 int Lexer::getUnicodeCharacter()
293 {
294     int char1 = peek(1);
295     int char2 = peek(2);
296     int char3 = peek(3);
297
298     if (UNLIKELY(!isASCIIHexDigit(m_current) || !isASCIIHexDigit(char1) || !isASCIIHexDigit(char2) || !isASCIIHexDigit(char3)))
299         return -1;
300
301     int result = convertUnicode(m_current, char1, char2, char3);
302     shift();
303     shift();
304     shift();
305     shift();
306     return result;
307 }
308
309 void Lexer::shiftLineTerminator()
310 {
311     ASSERT(isLineTerminator(m_current));
312
313     int m_prev = m_current;
314     shift();
315
316     // Allow both CRLF and LFCR.
317     if (m_prev + m_current == '\n' + '\r')
318         shift();
319
320     ++m_lineNumber;
321 }
322
323 ALWAYS_INLINE const Identifier* Lexer::makeIdentifier(const UChar* characters, size_t length)
324 {
325     return &m_arena->makeIdentifier(m_globalData, characters, length);
326 }
327
328 ALWAYS_INLINE bool Lexer::lastTokenWasRestrKeyword() const
329 {
330     return m_lastToken == CONTINUE || m_lastToken == BREAK || m_lastToken == RETURN || m_lastToken == THROW;
331 }
332
333 static NEVER_INLINE bool isNonASCIIIdentStart(int c)
334 {
335     return category(c) & (Letter_Uppercase | Letter_Lowercase | Letter_Titlecase | Letter_Modifier | Letter_Other);
336 }
337
338 static inline bool isIdentStart(int c)
339 {
340     return isASCII(c) ? typesOfASCIICharacters[c] == CharacterIdentifierStart : isNonASCIIIdentStart(c);
341 }
342
343 static NEVER_INLINE bool isNonASCIIIdentPart(int c)
344 {
345     return category(c) & (Letter_Uppercase | Letter_Lowercase | Letter_Titlecase | Letter_Modifier | Letter_Other
346         | Mark_NonSpacing | Mark_SpacingCombining | Number_DecimalDigit | Punctuation_Connector);
347 }
348
349 static inline bool isIdentPart(int c)
350 {
351     // Character types are divided into two groups depending on whether they can be part of an
352     // identifier or not. Those whose type value is less or equal than CharacterNumber can be
353     // part of an identifier. (See the CharacterType definition for more details.)
354     return isASCII(c) ? typesOfASCIICharacters[c] <= CharacterNumber : isNonASCIIIdentPart(c);
355 }
356
357 static inline int singleEscape(int c)
358 {
359     switch (c) {
360     case 'b':
361         return 0x08;
362     case 't':
363         return 0x09;
364     case 'n':
365         return 0x0A;
366     case 'v':
367         return 0x0B;
368     case 'f':
369         return 0x0C;
370     case 'r':
371         return 0x0D;
372     case '\\':
373         return '\\';
374     case '\'':
375         return '\'';
376     case '"':
377         return '"';
378     default:
379         return 0;
380     }
381 }
382
383 inline void Lexer::record8(int c)
384 {
385     ASSERT(c >= 0);
386     ASSERT(c <= 0xFF);
387     m_buffer8.append(static_cast<char>(c));
388 }
389
390 inline void Lexer::record16(UChar c)
391 {
392     m_buffer16.append(c);
393 }
394
395 inline void Lexer::record16(int c)
396 {
397     ASSERT(c >= 0);
398     ASSERT(c <= USHRT_MAX);
399     record16(UChar(static_cast<unsigned short>(c)));
400 }
401
402 template <bool shouldCreateIdentifier> ALWAYS_INLINE JSTokenType Lexer::parseIdentifier(JSTokenData* lvalp, unsigned lexType)
403 {
404     bool bufferRequired = false;
405     const UChar* identifierStart = currentCharacter();
406     int identifierLength;
407
408     while (true) {
409         if (LIKELY(isIdentPart(m_current))) {
410             shift();
411             continue;
412         }
413         if (LIKELY(m_current != '\\'))
414             break;
415
416         // \uXXXX unicode characters.
417         bufferRequired = true;
418         if (identifierStart != currentCharacter())
419             m_buffer16.append(identifierStart, currentCharacter() - identifierStart);
420         shift();
421         if (UNLIKELY(m_current != 'u'))
422             return ERRORTOK;
423         shift();
424         int character = getUnicodeCharacter();
425         if (UNLIKELY(character == -1))
426             return ERRORTOK;
427         if (UNLIKELY(m_buffer16.size() ? !isIdentPart(character) : !isIdentStart(character)))
428             return ERRORTOK;
429         if  (shouldCreateIdentifier)
430             record16(character);
431         identifierStart = currentCharacter();
432     }
433
434     const Identifier* ident = 0;
435     if (shouldCreateIdentifier) {
436         if (!bufferRequired)
437             identifierLength = currentCharacter() - identifierStart;
438         else {
439             if (identifierStart != currentCharacter())
440                 m_buffer16.append(identifierStart, currentCharacter() - identifierStart);
441             identifierStart = m_buffer16.data();
442             identifierLength = m_buffer16.size();
443         }
444
445         ident = makeIdentifier(identifierStart, identifierLength);
446         lvalp->ident = ident;
447     } else
448         lvalp->ident = 0;
449
450     m_delimited = false;
451
452     if (LIKELY(!bufferRequired && !(lexType & IgnoreReservedWords))) {
453         ASSERT(shouldCreateIdentifier);
454         // Keywords must not be recognized if there was an \uXXXX in the identifier.
455         const HashEntry* entry = m_keywordTable.entry(m_globalData, *ident);
456         return entry ? static_cast<JSTokenType>(entry->lexerValue()) : IDENT;
457     }
458
459     m_buffer16.resize(0);
460     return IDENT;
461 }
462
463 template <bool shouldBuildStrings> ALWAYS_INLINE bool Lexer::parseString(JSTokenData* lvalp, bool strictMode)
464 {
465     int stringQuoteCharacter = m_current;
466     shift();
467
468     const UChar* stringStart = currentCharacter();
469
470     while (m_current != stringQuoteCharacter) {
471         if (UNLIKELY(m_current == '\\')) {
472             if (stringStart != currentCharacter() && shouldBuildStrings)
473                 m_buffer16.append(stringStart, currentCharacter() - stringStart);
474             shift();
475
476             int escape = singleEscape(m_current);
477
478             // Most common escape sequences first
479             if (escape) {
480                  if (shouldBuildStrings)
481                      record16(escape);
482                 shift();
483             } else if (UNLIKELY(isLineTerminator(m_current)))
484                 shiftLineTerminator();
485             else if (m_current == 'x') {
486                 shift();
487                 if (isASCIIHexDigit(m_current) && isASCIIHexDigit(peek(1))) {
488                     int prev = m_current;
489                     shift();
490                     if (shouldBuildStrings)
491                         record16(convertHex(prev, m_current));
492                     shift();
493                 } else if (shouldBuildStrings)
494                     record16('x');
495             } else if (m_current == 'u') {
496                 shift();
497                 int character = getUnicodeCharacter();
498                 if (character != -1) {
499                     if (shouldBuildStrings)
500                         record16(character);
501                 } else if (m_current == stringQuoteCharacter) {
502                     if (shouldBuildStrings)
503                         record16('u');
504                 } else // Only stringQuoteCharacter allowed after \u
505                     return false;
506             } else if (strictMode && isASCIIDigit(m_current)) {
507                 // The only valid numeric escape in strict mode is '\0', and this must not be followed by a decimal digit.
508                 int character1 = m_current;
509                 shift();
510                 if (character1 != '0' || isASCIIDigit(m_current))
511                     return false;
512                 if (shouldBuildStrings)
513                     record16(0);
514             } else if (!strictMode && isASCIIOctalDigit(m_current)) {
515                 // Octal character sequences
516                 int character1 = m_current;
517                 shift();
518                 if (isASCIIOctalDigit(m_current)) {
519                     // Two octal characters
520                     int character2 = m_current;
521                     shift();
522                     if (character1 >= '0' && character1 <= '3' && isASCIIOctalDigit(m_current)) {
523                         if (shouldBuildStrings)
524                             record16((character1 - '0') * 64 + (character2 - '0') * 8 + m_current - '0');
525                         shift();
526                     } else {
527                         if (shouldBuildStrings)
528                             record16((character1 - '0') * 8 + character2 - '0');
529                     }
530                 } else {
531                     if (shouldBuildStrings)
532                         record16(character1 - '0');
533                 }
534             } else if (m_current != -1) {
535                 if (shouldBuildStrings)
536                     record16(m_current);
537                 shift();
538             } else
539                 return false;
540
541             stringStart = currentCharacter();
542             continue;
543         }
544         // Fast check for characters that require special handling.
545         // Catches -1, \n, \r, 0x2028, and 0x2029 as efficiently
546         // as possible, and lets through all common ASCII characters.
547         if (UNLIKELY(((static_cast<unsigned>(m_current) - 0xE) & 0x2000))) {
548             // New-line or end of input is not allowed
549             if (UNLIKELY(isLineTerminator(m_current)) || UNLIKELY(m_current == -1))
550                 return false;
551             // Anything else is just a normal character
552         }
553         shift();
554     }
555
556     if (currentCharacter() != stringStart && shouldBuildStrings)
557         m_buffer16.append(stringStart, currentCharacter() - stringStart);
558     if (shouldBuildStrings)
559         lvalp->ident = makeIdentifier(m_buffer16.data(), m_buffer16.size());
560     else
561         lvalp->ident = 0;
562
563     m_buffer16.resize(0);
564     return true;
565 }
566
567 ALWAYS_INLINE void Lexer::parseHex(double& returnValue)
568 {
569     // Optimization: most hexadecimal values fit into 4 bytes.
570     uint32_t hexValue = 0;
571     int maximumDigits = 7;
572
573     // Shift out the 'x' prefix.
574     shift();
575
576     do {
577         hexValue = (hexValue << 4) + toASCIIHexValue(m_current);
578         shift();
579         --maximumDigits;
580     } while (isASCIIHexDigit(m_current) && maximumDigits >= 0);
581
582     if (maximumDigits >= 0) {
583         returnValue = hexValue;
584         return;
585     }
586
587     // No more place in the hexValue buffer.
588     // The values are shifted out and placed into the m_buffer8 vector.
589     for (int i = 0; i < 8; ++i) {
590          int digit = hexValue >> 28;
591          if (digit < 10)
592              record8(digit + '0');
593          else
594              record8(digit - 10 + 'a');
595          hexValue <<= 4;
596     }
597
598     while (isASCIIHexDigit(m_current)) {
599         record8(m_current);
600         shift();
601     }
602
603     returnValue = parseIntOverflow(m_buffer8.data(), m_buffer8.size(), 16);
604 }
605
606 ALWAYS_INLINE bool Lexer::parseOctal(double& returnValue)
607 {
608     // Optimization: most octal values fit into 4 bytes.
609     uint32_t octalValue = 0;
610     int maximumDigits = 9;
611     // Temporary buffer for the digits. Makes easier
612     // to reconstruct the input characters when needed.
613     char digits[10];
614
615     do {
616         octalValue = octalValue * 8 + (m_current - '0');
617         digits[maximumDigits] = m_current;
618         shift();
619         --maximumDigits;
620     } while (isASCIIOctalDigit(m_current) && maximumDigits >= 0);
621
622     if (!isASCIIDigit(m_current) && maximumDigits >= 0) {
623         returnValue = octalValue;
624         return true;
625     }
626
627     for (int i = 9; i > maximumDigits; --i)
628          record8(digits[i]);
629
630     while (isASCIIOctalDigit(m_current)) {
631         record8(m_current);
632         shift();
633     }
634
635     if (isASCIIDigit(m_current))
636         return false;
637
638     returnValue = parseIntOverflow(m_buffer8.data(), m_buffer8.size(), 8);
639     return true;
640 }
641
642 ALWAYS_INLINE bool Lexer::parseDecimal(double& returnValue)
643 {
644     // Optimization: most decimal values fit into 4 bytes.
645     uint32_t decimalValue = 0;
646
647     // Since parseOctal may be executed before parseDecimal,
648     // the m_buffer8 may hold ascii digits.
649     if (!m_buffer8.size()) {
650         int maximumDigits = 9;
651         // Temporary buffer for the digits. Makes easier
652         // to reconstruct the input characters when needed.
653         char digits[10];
654
655         do {
656             decimalValue = decimalValue * 10 + (m_current - '0');
657             digits[maximumDigits] = m_current;
658             shift();
659             --maximumDigits;
660         } while (isASCIIDigit(m_current) && maximumDigits >= 0);
661
662         if (maximumDigits >= 0 && m_current != '.' && (m_current | 0x20) != 'e') {
663             returnValue = decimalValue;
664             return true;
665         }
666
667         for (int i = 9; i > maximumDigits; --i)
668             record8(digits[i]);
669     }
670
671     while (isASCIIDigit(m_current)) {
672         record8(m_current);
673         shift();
674     }
675
676     return false;
677 }
678
679 ALWAYS_INLINE void Lexer::parseNumberAfterDecimalPoint()
680 {
681     record8('.');
682     while (isASCIIDigit(m_current)) {
683         record8(m_current);
684         shift();
685     }
686 }
687
688 ALWAYS_INLINE bool Lexer::parseNumberAfterExponentIndicator()
689 {
690     record8('e');
691     shift();
692     if (m_current == '+' || m_current == '-') {
693         record8(m_current);
694         shift();
695     }
696
697     if (!isASCIIDigit(m_current))
698         return false;
699
700     do {
701         record8(m_current);
702         shift();
703     } while (isASCIIDigit(m_current));
704     return true;
705 }
706
707 ALWAYS_INLINE bool Lexer::parseMultilineComment()
708 {
709     while (true) {
710         while (UNLIKELY(m_current == '*')) {
711             shift();
712             if (m_current == '/') {
713                 shift();
714                 return true;
715             }
716         }
717
718         if (UNLIKELY(m_current == -1))
719             return false;
720
721         if (isLineTerminator(m_current))
722             shiftLineTerminator();
723         else
724             shift();
725     }
726 }
727
728 bool Lexer::nextTokenIsColon()
729 {
730     const UChar* code = m_code;
731     while (code < m_codeEnd && (isWhiteSpace(*code) || isLineTerminator(*code)))
732         code++;
733         
734     return code < m_codeEnd && *code == ':';
735 }
736
737 JSTokenType Lexer::lex(JSTokenData* lvalp, JSTokenInfo* llocp, unsigned lexType, bool strictMode)
738 {
739     ASSERT(!m_error);
740     ASSERT(m_buffer8.isEmpty());
741     ASSERT(m_buffer16.isEmpty());
742
743     JSTokenType token = ERRORTOK;
744     m_terminator = false;
745
746 start:
747     while (isWhiteSpace(m_current))
748         shift();
749
750     int startOffset = currentOffset();
751
752     if (UNLIKELY(m_current == -1))
753         return EOFTOK;
754
755     m_delimited = false;
756
757     CharacterType type;
758     if (LIKELY(isASCII(m_current)))
759         type = static_cast<CharacterType>(typesOfASCIICharacters[m_current]);
760     else if (isNonASCIIIdentStart(m_current))
761         type = CharacterIdentifierStart;
762     else if (isLineTerminator(m_current))
763         type = CharacterLineTerminator;
764     else
765         type = CharacterInvalid;
766
767     switch (type) {
768     case CharacterGreater:
769         shift();
770         if (m_current == '>') {
771             shift();
772             if (m_current == '>') {
773                 shift();
774                 if (m_current == '=') {
775                     shift();
776                     token = URSHIFTEQUAL;
777                     break;
778                 }
779                 token = URSHIFT;
780                 break;
781             }
782             if (m_current == '=') {
783                 shift();
784                 token = RSHIFTEQUAL;
785                 break;
786             }
787             token = RSHIFT;
788             break;
789         }
790         if (m_current == '=') {
791             shift();
792             token = GE;
793             break;
794         }
795         token = GT;
796         break;
797     case CharacterEqual:
798         shift();
799         if (m_current == '=') {
800             shift();
801             if (m_current == '=') {
802                 shift();
803                 token = STREQ;
804                 break;
805             }
806             token = EQEQ;
807             break;
808         }
809         token = EQUAL;
810         break;
811     case CharacterLess:
812         shift();
813         if (m_current == '!' && peek(1) == '-' && peek(2) == '-') {
814             // <!-- marks the beginning of a line comment (for www usage)
815             goto inSingleLineComment;
816         }
817         if (m_current == '<') {
818             shift();
819             if (m_current == '=') {
820                 shift();
821                 token = LSHIFTEQUAL;
822                 break;
823             }
824             token = LSHIFT;
825             break;
826         }
827         if (m_current == '=') {
828             shift();
829             token = LE;
830             break;
831         }
832         token = LT;
833         break;
834     case CharacterExclamationMark:
835         shift();
836         if (m_current == '=') {
837             shift();
838             if (m_current == '=') {
839                 shift();
840                 token = STRNEQ;
841                 break;
842             }
843             token = NE;
844             break;
845         }
846         token = EXCLAMATION;
847         break;
848     case CharacterAdd:
849         shift();
850         if (m_current == '+') {
851             shift();
852             token = (!m_terminator) ? PLUSPLUS : AUTOPLUSPLUS;
853             break;
854         }
855         if (m_current == '=') {
856             shift();
857             token = PLUSEQUAL;
858             break;
859         }
860         token = PLUS;
861         break;
862     case CharacterSub:
863         shift();
864         if (m_current == '-') {
865             shift();
866             if (m_atLineStart && m_current == '>') {
867                 shift();
868                 goto inSingleLineComment;
869             }
870             token = (!m_terminator) ? MINUSMINUS : AUTOMINUSMINUS;
871             break;
872         }
873         if (m_current == '=') {
874             shift();
875             token = MINUSEQUAL;
876             break;
877         }
878         token = MINUS;
879         break;
880     case CharacterMultiply:
881         shift();
882         if (m_current == '=') {
883             shift();
884             token = MULTEQUAL;
885             break;
886         }
887         token = TIMES;
888         break;
889     case CharacterSlash:
890         shift();
891         if (m_current == '/') {
892             shift();
893             goto inSingleLineComment;
894         }
895         if (m_current == '*') {
896             shift();
897             if (parseMultilineComment())
898                 goto start;
899             goto returnError;
900         }
901         if (m_current == '=') {
902             shift();
903             token = DIVEQUAL;
904             break;
905         }
906         token = DIVIDE;
907         break;
908     case CharacterAnd:
909         shift();
910         if (m_current == '&') {
911             shift();
912             token = AND;
913             break;
914         }
915         if (m_current == '=') {
916             shift();
917             token = ANDEQUAL;
918             break;
919         }
920         token = BITAND;
921         break;
922     case CharacterXor:
923         shift();
924         if (m_current == '=') {
925             shift();
926             token = XOREQUAL;
927             break;
928         }
929         token = BITXOR;
930         break;
931     case CharacterModulo:
932         shift();
933         if (m_current == '=') {
934             shift();
935             token = MODEQUAL;
936             break;
937         }
938         token = MOD;
939         break;
940     case CharacterOr:
941         shift();
942         if (m_current == '=') {
943             shift();
944             token = OREQUAL;
945             break;
946         }
947         if (m_current == '|') {
948             shift();
949             token = OR;
950             break;
951         }
952         token = BITOR;
953         break;
954     case CharacterOpenParen:
955         token = OPENPAREN;
956         shift();
957         break;
958     case CharacterCloseParen:
959         token = CLOSEPAREN;
960         shift();
961         break;
962     case CharacterOpenBracket:
963         token = OPENBRACKET;
964         shift();
965         break;
966     case CharacterCloseBracket:
967         token = CLOSEBRACKET;
968         shift();
969         break;
970     case CharacterComma:
971         token = COMMA;
972         shift();
973         break;
974     case CharacterColon:
975         token = COLON;
976         shift();
977         break;
978     case CharacterQuestion:
979         token = QUESTION;
980         shift();
981         break;
982     case CharacterTilde:
983         token = TILDE;
984         shift();
985         break;
986     case CharacterSemicolon:
987         m_delimited = true;
988         shift();
989         token = SEMICOLON;
990         break;
991     case CharacterOpenBrace:
992         lvalp->intValue = currentOffset();
993         shift();
994         token = OPENBRACE;
995         break;
996     case CharacterCloseBrace:
997         lvalp->intValue = currentOffset();
998         m_delimited = true;
999         shift();
1000         token = CLOSEBRACE;
1001         break;
1002     case CharacterDot:
1003         shift();
1004         if (!isASCIIDigit(m_current)) {
1005             token = DOT;
1006             break;
1007         }
1008         goto inNumberAfterDecimalPoint;
1009     case CharacterZero:
1010         shift();
1011         if ((m_current | 0x20) == 'x' && isASCIIHexDigit(peek(1))) {
1012             parseHex(lvalp->doubleValue);
1013             token = NUMBER;
1014         } else {
1015             record8('0');
1016             if (isASCIIOctalDigit(m_current)) {
1017                 if (parseOctal(lvalp->doubleValue)) {
1018                     if (strictMode)
1019                         goto returnError;
1020                     token = NUMBER;
1021                 }
1022             }
1023         }
1024         // Fall through into CharacterNumber
1025     case CharacterNumber:
1026         if (LIKELY(token != NUMBER)) {
1027             if (!parseDecimal(lvalp->doubleValue)) {
1028                 if (m_current == '.') {
1029                     shift();
1030 inNumberAfterDecimalPoint:
1031                     parseNumberAfterDecimalPoint();
1032                 }
1033                 if ((m_current | 0x20) == 'e')
1034                     if (!parseNumberAfterExponentIndicator())
1035                         goto returnError;
1036                 // Null-terminate string for strtod.
1037                 m_buffer8.append('\0');
1038                 lvalp->doubleValue = WTF::strtod(m_buffer8.data(), 0);
1039             }
1040             token = NUMBER;
1041         }
1042
1043         // No identifiers allowed directly after numeric literal, e.g. "3in" is bad.
1044         if (UNLIKELY(isIdentStart(m_current)))
1045             goto returnError;
1046         m_buffer8.resize(0);
1047         m_delimited = false;
1048         break;
1049     case CharacterQuote:
1050         if (lexType & DontBuildStrings) {
1051             if (UNLIKELY(!parseString<false>(lvalp, strictMode)))
1052                 goto returnError;
1053         } else {
1054             if (UNLIKELY(!parseString<true>(lvalp, strictMode)))
1055                 goto returnError;
1056         }
1057         shift();
1058         m_delimited = false;
1059         token = STRING;
1060         break;
1061     case CharacterIdentifierStart:
1062         ASSERT(isIdentStart(m_current));
1063         // Fall through into CharacterBackSlash.
1064     case CharacterBackSlash:
1065         if (lexType & DontBuildKeywords)
1066             token = parseIdentifier<false>(lvalp, lexType);
1067         else
1068             token = parseIdentifier<true>(lvalp, lexType);
1069         break;
1070     case CharacterLineTerminator:
1071         ASSERT(isLineTerminator(m_current));
1072         shiftLineTerminator();
1073         m_atLineStart = true;
1074         m_terminator = true;
1075         goto start;
1076     case CharacterInvalid:
1077         goto returnError;
1078     default:
1079         ASSERT_NOT_REACHED();
1080         goto returnError;
1081     }
1082
1083     m_atLineStart = false;
1084     goto returnToken;
1085
1086 inSingleLineComment:
1087     while (!isLineTerminator(m_current)) {
1088         if (UNLIKELY(m_current == -1))
1089             return EOFTOK;
1090         shift();
1091     }
1092     shiftLineTerminator();
1093     m_atLineStart = true;
1094     m_terminator = true;
1095     if (!lastTokenWasRestrKeyword())
1096         goto start;
1097
1098     token = SEMICOLON;
1099     m_delimited = true;
1100     // Fall through into returnToken.
1101
1102 returnToken:
1103     llocp->line = m_lineNumber;
1104     llocp->startOffset = startOffset;
1105     llocp->endOffset = currentOffset();
1106     m_lastToken = token;
1107     return token;
1108
1109 returnError:
1110     m_error = true;
1111     return ERRORTOK;
1112 }
1113
1114 bool Lexer::scanRegExp(const Identifier*& pattern, const Identifier*& flags, UChar patternPrefix)
1115 {
1116     ASSERT(m_buffer16.isEmpty());
1117
1118     bool lastWasEscape = false;
1119     bool inBrackets = false;
1120
1121     if (patternPrefix) {
1122         ASSERT(!isLineTerminator(patternPrefix));
1123         ASSERT(patternPrefix != '/');
1124         ASSERT(patternPrefix != '[');
1125         record16(patternPrefix);
1126     }
1127
1128     while (true) {
1129         int current = m_current;
1130
1131         if (isLineTerminator(current) || current == -1) {
1132             m_buffer16.resize(0);
1133             return false;
1134         }
1135
1136         shift();
1137
1138         if (current == '/' && !lastWasEscape && !inBrackets)
1139             break;
1140
1141         record16(current);
1142
1143         if (lastWasEscape) {
1144             lastWasEscape = false;
1145             continue;
1146         }
1147
1148         switch (current) {
1149         case '[':
1150             inBrackets = true;
1151             break;
1152         case ']':
1153             inBrackets = false;
1154             break;
1155         case '\\':
1156             lastWasEscape = true;
1157             break;
1158         }
1159     }
1160
1161     pattern = makeIdentifier(m_buffer16.data(), m_buffer16.size());
1162     m_buffer16.resize(0);
1163
1164     while (isIdentPart(m_current)) {
1165         record16(m_current);
1166         shift();
1167     }
1168
1169     flags = makeIdentifier(m_buffer16.data(), m_buffer16.size());
1170     m_buffer16.resize(0);
1171
1172     return true;
1173 }
1174
1175 bool Lexer::skipRegExp()
1176 {
1177     bool lastWasEscape = false;
1178     bool inBrackets = false;
1179
1180     while (true) {
1181         int current = m_current;
1182
1183         if (isLineTerminator(current) || current == -1)
1184             return false;
1185
1186         shift();
1187
1188         if (current == '/' && !lastWasEscape && !inBrackets)
1189             break;
1190
1191         if (lastWasEscape) {
1192             lastWasEscape = false;
1193             continue;
1194         }
1195
1196         switch (current) {
1197         case '[':
1198             inBrackets = true;
1199             break;
1200         case ']':
1201             inBrackets = false;
1202             break;
1203         case '\\':
1204             lastWasEscape = true;
1205             break;
1206         }
1207     }
1208
1209     while (isIdentPart(m_current))
1210         shift();
1211
1212     return true;
1213 }
1214
1215 void Lexer::clear()
1216 {
1217     m_arena = 0;
1218
1219     Vector<char> newBuffer8;
1220     m_buffer8.swap(newBuffer8);
1221
1222     Vector<UChar> newBuffer16;
1223     m_buffer16.swap(newBuffer16);
1224
1225     m_isReparsing = false;
1226 }
1227
1228 SourceCode Lexer::sourceCode(int openBrace, int closeBrace, int firstLine)
1229 {
1230     ASSERT(m_source->provider()->data()[openBrace] == '{');
1231     ASSERT(m_source->provider()->data()[closeBrace] == '}');
1232     return SourceCode(m_source->provider(), openBrace, closeBrace + 1, firstLine);
1233 }
1234
1235 } // namespace JSC