2 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3 * Copyright (C) 2006, 2007, 2008, 2009, 2011, 2012 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 * Copyright (C) 2012 Mathias Bynens (mathias@qiwi.be)
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
28 #include "JSFunction.h"
30 #include "JSGlobalObjectFunctions.h"
31 #include "Identifier.h"
38 #include <wtf/Assertions.h>
41 using namespace Unicode
;
43 #include "KeywordLookup.h"
44 #include "Lexer.lut.h"
49 Keywords::Keywords(JSGlobalData
* globalData
)
50 : m_globalData(globalData
)
51 , m_keywordTable(JSC::mainTable
)
56 // Types for the main switch
58 // The first three types are fixed, and also used for identifying
59 // ASCII alpha and alphanumeric characters (see isIdentStart and isIdentPart).
60 CharacterIdentifierStart
,
65 CharacterLineTerminator
,
66 CharacterExclamationMark
,
70 CharacterCloseBracket
,
94 // Other types (only one so far)
99 static const unsigned short typesOfLatin1Characters
[256] = {
100 /* 0 - Null */ CharacterInvalid
,
101 /* 1 - Start of Heading */ CharacterInvalid
,
102 /* 2 - Start of Text */ CharacterInvalid
,
103 /* 3 - End of Text */ CharacterInvalid
,
104 /* 4 - End of Transm. */ CharacterInvalid
,
105 /* 5 - Enquiry */ CharacterInvalid
,
106 /* 6 - Acknowledgment */ CharacterInvalid
,
107 /* 7 - Bell */ CharacterInvalid
,
108 /* 8 - Back Space */ CharacterInvalid
,
109 /* 9 - Horizontal Tab */ CharacterWhiteSpace
,
110 /* 10 - Line Feed */ CharacterLineTerminator
,
111 /* 11 - Vertical Tab */ CharacterWhiteSpace
,
112 /* 12 - Form Feed */ CharacterWhiteSpace
,
113 /* 13 - Carriage Return */ CharacterLineTerminator
,
114 /* 14 - Shift Out */ CharacterInvalid
,
115 /* 15 - Shift In */ CharacterInvalid
,
116 /* 16 - Data Line Escape */ CharacterInvalid
,
117 /* 17 - Device Control 1 */ CharacterInvalid
,
118 /* 18 - Device Control 2 */ CharacterInvalid
,
119 /* 19 - Device Control 3 */ CharacterInvalid
,
120 /* 20 - Device Control 4 */ CharacterInvalid
,
121 /* 21 - Negative Ack. */ CharacterInvalid
,
122 /* 22 - Synchronous Idle */ CharacterInvalid
,
123 /* 23 - End of Transmit */ CharacterInvalid
,
124 /* 24 - Cancel */ CharacterInvalid
,
125 /* 25 - End of Medium */ CharacterInvalid
,
126 /* 26 - Substitute */ CharacterInvalid
,
127 /* 27 - Escape */ CharacterInvalid
,
128 /* 28 - File Separator */ CharacterInvalid
,
129 /* 29 - Group Separator */ CharacterInvalid
,
130 /* 30 - Record Separator */ CharacterInvalid
,
131 /* 31 - Unit Separator */ CharacterInvalid
,
132 /* 32 - Space */ CharacterWhiteSpace
,
133 /* 33 - ! */ CharacterExclamationMark
,
134 /* 34 - " */ CharacterQuote
,
135 /* 35 - # */ CharacterInvalid
,
136 /* 36 - $ */ CharacterIdentifierStart
,
137 /* 37 - % */ CharacterModulo
,
138 /* 38 - & */ CharacterAnd
,
139 /* 39 - ' */ CharacterQuote
,
140 /* 40 - ( */ CharacterOpenParen
,
141 /* 41 - ) */ CharacterCloseParen
,
142 /* 42 - * */ CharacterMultiply
,
143 /* 43 - + */ CharacterAdd
,
144 /* 44 - , */ CharacterComma
,
145 /* 45 - - */ CharacterSub
,
146 /* 46 - . */ CharacterDot
,
147 /* 47 - / */ CharacterSlash
,
148 /* 48 - 0 */ CharacterZero
,
149 /* 49 - 1 */ CharacterNumber
,
150 /* 50 - 2 */ CharacterNumber
,
151 /* 51 - 3 */ CharacterNumber
,
152 /* 52 - 4 */ CharacterNumber
,
153 /* 53 - 5 */ CharacterNumber
,
154 /* 54 - 6 */ CharacterNumber
,
155 /* 55 - 7 */ CharacterNumber
,
156 /* 56 - 8 */ CharacterNumber
,
157 /* 57 - 9 */ CharacterNumber
,
158 /* 58 - : */ CharacterColon
,
159 /* 59 - ; */ CharacterSemicolon
,
160 /* 60 - < */ CharacterLess
,
161 /* 61 - = */ CharacterEqual
,
162 /* 62 - > */ CharacterGreater
,
163 /* 63 - ? */ CharacterQuestion
,
164 /* 64 - @ */ CharacterInvalid
,
165 /* 65 - A */ CharacterIdentifierStart
,
166 /* 66 - B */ CharacterIdentifierStart
,
167 /* 67 - C */ CharacterIdentifierStart
,
168 /* 68 - D */ CharacterIdentifierStart
,
169 /* 69 - E */ CharacterIdentifierStart
,
170 /* 70 - F */ CharacterIdentifierStart
,
171 /* 71 - G */ CharacterIdentifierStart
,
172 /* 72 - H */ CharacterIdentifierStart
,
173 /* 73 - I */ CharacterIdentifierStart
,
174 /* 74 - J */ CharacterIdentifierStart
,
175 /* 75 - K */ CharacterIdentifierStart
,
176 /* 76 - L */ CharacterIdentifierStart
,
177 /* 77 - M */ CharacterIdentifierStart
,
178 /* 78 - N */ CharacterIdentifierStart
,
179 /* 79 - O */ CharacterIdentifierStart
,
180 /* 80 - P */ CharacterIdentifierStart
,
181 /* 81 - Q */ CharacterIdentifierStart
,
182 /* 82 - R */ CharacterIdentifierStart
,
183 /* 83 - S */ CharacterIdentifierStart
,
184 /* 84 - T */ CharacterIdentifierStart
,
185 /* 85 - U */ CharacterIdentifierStart
,
186 /* 86 - V */ CharacterIdentifierStart
,
187 /* 87 - W */ CharacterIdentifierStart
,
188 /* 88 - X */ CharacterIdentifierStart
,
189 /* 89 - Y */ CharacterIdentifierStart
,
190 /* 90 - Z */ CharacterIdentifierStart
,
191 /* 91 - [ */ CharacterOpenBracket
,
192 /* 92 - \ */ CharacterBackSlash
,
193 /* 93 - ] */ CharacterCloseBracket
,
194 /* 94 - ^ */ CharacterXor
,
195 /* 95 - _ */ CharacterIdentifierStart
,
196 /* 96 - ` */ CharacterInvalid
,
197 /* 97 - a */ CharacterIdentifierStart
,
198 /* 98 - b */ CharacterIdentifierStart
,
199 /* 99 - c */ CharacterIdentifierStart
,
200 /* 100 - d */ CharacterIdentifierStart
,
201 /* 101 - e */ CharacterIdentifierStart
,
202 /* 102 - f */ CharacterIdentifierStart
,
203 /* 103 - g */ CharacterIdentifierStart
,
204 /* 104 - h */ CharacterIdentifierStart
,
205 /* 105 - i */ CharacterIdentifierStart
,
206 /* 106 - j */ CharacterIdentifierStart
,
207 /* 107 - k */ CharacterIdentifierStart
,
208 /* 108 - l */ CharacterIdentifierStart
,
209 /* 109 - m */ CharacterIdentifierStart
,
210 /* 110 - n */ CharacterIdentifierStart
,
211 /* 111 - o */ CharacterIdentifierStart
,
212 /* 112 - p */ CharacterIdentifierStart
,
213 /* 113 - q */ CharacterIdentifierStart
,
214 /* 114 - r */ CharacterIdentifierStart
,
215 /* 115 - s */ CharacterIdentifierStart
,
216 /* 116 - t */ CharacterIdentifierStart
,
217 /* 117 - u */ CharacterIdentifierStart
,
218 /* 118 - v */ CharacterIdentifierStart
,
219 /* 119 - w */ CharacterIdentifierStart
,
220 /* 120 - x */ CharacterIdentifierStart
,
221 /* 121 - y */ CharacterIdentifierStart
,
222 /* 122 - z */ CharacterIdentifierStart
,
223 /* 123 - { */ CharacterOpenBrace
,
224 /* 124 - | */ CharacterOr
,
225 /* 125 - } */ CharacterCloseBrace
,
226 /* 126 - ~ */ CharacterTilde
,
227 /* 127 - Delete */ CharacterInvalid
,
228 /* 128 - Cc category */ CharacterInvalid
,
229 /* 129 - Cc category */ CharacterInvalid
,
230 /* 130 - Cc category */ CharacterInvalid
,
231 /* 131 - Cc category */ CharacterInvalid
,
232 /* 132 - Cc category */ CharacterInvalid
,
233 /* 133 - Cc category */ CharacterInvalid
,
234 /* 134 - Cc category */ CharacterInvalid
,
235 /* 135 - Cc category */ CharacterInvalid
,
236 /* 136 - Cc category */ CharacterInvalid
,
237 /* 137 - Cc category */ CharacterInvalid
,
238 /* 138 - Cc category */ CharacterInvalid
,
239 /* 139 - Cc category */ CharacterInvalid
,
240 /* 140 - Cc category */ CharacterInvalid
,
241 /* 141 - Cc category */ CharacterInvalid
,
242 /* 142 - Cc category */ CharacterInvalid
,
243 /* 143 - Cc category */ CharacterInvalid
,
244 /* 144 - Cc category */ CharacterInvalid
,
245 /* 145 - Cc category */ CharacterInvalid
,
246 /* 146 - Cc category */ CharacterInvalid
,
247 /* 147 - Cc category */ CharacterInvalid
,
248 /* 148 - Cc category */ CharacterInvalid
,
249 /* 149 - Cc category */ CharacterInvalid
,
250 /* 150 - Cc category */ CharacterInvalid
,
251 /* 151 - Cc category */ CharacterInvalid
,
252 /* 152 - Cc category */ CharacterInvalid
,
253 /* 153 - Cc category */ CharacterInvalid
,
254 /* 154 - Cc category */ CharacterInvalid
,
255 /* 155 - Cc category */ CharacterInvalid
,
256 /* 156 - Cc category */ CharacterInvalid
,
257 /* 157 - Cc category */ CharacterInvalid
,
258 /* 158 - Cc category */ CharacterInvalid
,
259 /* 159 - Cc category */ CharacterInvalid
,
260 /* 160 - Zs category (nbsp) */ CharacterWhiteSpace
,
261 /* 161 - Po category */ CharacterInvalid
,
262 /* 162 - Sc category */ CharacterInvalid
,
263 /* 163 - Sc category */ CharacterInvalid
,
264 /* 164 - Sc category */ CharacterInvalid
,
265 /* 165 - Sc category */ CharacterInvalid
,
266 /* 166 - So category */ CharacterInvalid
,
267 /* 167 - So category */ CharacterInvalid
,
268 /* 168 - Sk category */ CharacterInvalid
,
269 /* 169 - So category */ CharacterInvalid
,
270 /* 170 - Ll category */ CharacterIdentifierStart
,
271 /* 171 - Pi category */ CharacterInvalid
,
272 /* 172 - Sm category */ CharacterInvalid
,
273 /* 173 - Cf category */ CharacterInvalid
,
274 /* 174 - So category */ CharacterInvalid
,
275 /* 175 - Sk category */ CharacterInvalid
,
276 /* 176 - So category */ CharacterInvalid
,
277 /* 177 - Sm category */ CharacterInvalid
,
278 /* 178 - No category */ CharacterInvalid
,
279 /* 179 - No category */ CharacterInvalid
,
280 /* 180 - Sk category */ CharacterInvalid
,
281 /* 181 - Ll category */ CharacterIdentifierStart
,
282 /* 182 - So category */ CharacterInvalid
,
283 /* 183 - Po category */ CharacterInvalid
,
284 /* 184 - Sk category */ CharacterInvalid
,
285 /* 185 - No category */ CharacterInvalid
,
286 /* 186 - Ll category */ CharacterIdentifierStart
,
287 /* 187 - Pf category */ CharacterInvalid
,
288 /* 188 - No category */ CharacterInvalid
,
289 /* 189 - No category */ CharacterInvalid
,
290 /* 190 - No category */ CharacterInvalid
,
291 /* 191 - Po category */ CharacterInvalid
,
292 /* 192 - Lu category */ CharacterIdentifierStart
,
293 /* 193 - Lu category */ CharacterIdentifierStart
,
294 /* 194 - Lu category */ CharacterIdentifierStart
,
295 /* 195 - Lu category */ CharacterIdentifierStart
,
296 /* 196 - Lu category */ CharacterIdentifierStart
,
297 /* 197 - Lu category */ CharacterIdentifierStart
,
298 /* 198 - Lu category */ CharacterIdentifierStart
,
299 /* 199 - Lu category */ CharacterIdentifierStart
,
300 /* 200 - Lu category */ CharacterIdentifierStart
,
301 /* 201 - Lu category */ CharacterIdentifierStart
,
302 /* 202 - Lu category */ CharacterIdentifierStart
,
303 /* 203 - Lu category */ CharacterIdentifierStart
,
304 /* 204 - Lu category */ CharacterIdentifierStart
,
305 /* 205 - Lu category */ CharacterIdentifierStart
,
306 /* 206 - Lu category */ CharacterIdentifierStart
,
307 /* 207 - Lu category */ CharacterIdentifierStart
,
308 /* 208 - Lu category */ CharacterIdentifierStart
,
309 /* 209 - Lu category */ CharacterIdentifierStart
,
310 /* 210 - Lu category */ CharacterIdentifierStart
,
311 /* 211 - Lu category */ CharacterIdentifierStart
,
312 /* 212 - Lu category */ CharacterIdentifierStart
,
313 /* 213 - Lu category */ CharacterIdentifierStart
,
314 /* 214 - Lu category */ CharacterIdentifierStart
,
315 /* 215 - Sm category */ CharacterInvalid
,
316 /* 216 - Lu category */ CharacterIdentifierStart
,
317 /* 217 - Lu category */ CharacterIdentifierStart
,
318 /* 218 - Lu category */ CharacterIdentifierStart
,
319 /* 219 - Lu category */ CharacterIdentifierStart
,
320 /* 220 - Lu category */ CharacterIdentifierStart
,
321 /* 221 - Lu category */ CharacterIdentifierStart
,
322 /* 222 - Lu category */ CharacterIdentifierStart
,
323 /* 223 - Ll category */ CharacterIdentifierStart
,
324 /* 224 - Ll category */ CharacterIdentifierStart
,
325 /* 225 - Ll category */ CharacterIdentifierStart
,
326 /* 226 - Ll category */ CharacterIdentifierStart
,
327 /* 227 - Ll category */ CharacterIdentifierStart
,
328 /* 228 - Ll category */ CharacterIdentifierStart
,
329 /* 229 - Ll category */ CharacterIdentifierStart
,
330 /* 230 - Ll category */ CharacterIdentifierStart
,
331 /* 231 - Ll category */ CharacterIdentifierStart
,
332 /* 232 - Ll category */ CharacterIdentifierStart
,
333 /* 233 - Ll category */ CharacterIdentifierStart
,
334 /* 234 - Ll category */ CharacterIdentifierStart
,
335 /* 235 - Ll category */ CharacterIdentifierStart
,
336 /* 236 - Ll category */ CharacterIdentifierStart
,
337 /* 237 - Ll category */ CharacterIdentifierStart
,
338 /* 238 - Ll category */ CharacterIdentifierStart
,
339 /* 239 - Ll category */ CharacterIdentifierStart
,
340 /* 240 - Ll category */ CharacterIdentifierStart
,
341 /* 241 - Ll category */ CharacterIdentifierStart
,
342 /* 242 - Ll category */ CharacterIdentifierStart
,
343 /* 243 - Ll category */ CharacterIdentifierStart
,
344 /* 244 - Ll category */ CharacterIdentifierStart
,
345 /* 245 - Ll category */ CharacterIdentifierStart
,
346 /* 246 - Ll category */ CharacterIdentifierStart
,
347 /* 247 - Sm category */ CharacterInvalid
,
348 /* 248 - Ll category */ CharacterIdentifierStart
,
349 /* 249 - Ll category */ CharacterIdentifierStart
,
350 /* 250 - Ll category */ CharacterIdentifierStart
,
351 /* 251 - Ll category */ CharacterIdentifierStart
,
352 /* 252 - Ll category */ CharacterIdentifierStart
,
353 /* 253 - Ll category */ CharacterIdentifierStart
,
354 /* 254 - Ll category */ CharacterIdentifierStart
,
355 /* 255 - Ll category */ CharacterIdentifierStart
358 template <typename T
>
359 Lexer
<T
>::Lexer(JSGlobalData
* globalData
)
360 : m_isReparsing(false)
361 , m_globalData(globalData
)
365 template <typename T
>
370 template <typename T
>
371 UString Lexer
<T
>::invalidCharacterMessage() const
375 return "Invalid character: '\\0'";
377 return "Invalid character: '\\n'";
379 return "Invalid character: '\\v'";
381 return "Invalid character: '\\r'";
383 return "Invalid character: '#'";
385 return "Invalid character: '@'";
387 return "Invalid character: '`'";
389 return String::format("Invalid character '\\u%04u'", static_cast<unsigned>(m_current
)).impl();
393 template <typename T
>
394 ALWAYS_INLINE
const T
* Lexer
<T
>::currentCharacter() const
396 ASSERT(m_code
<= m_codeEnd
);
400 template <typename T
>
401 void Lexer
<T
>::setCode(const SourceCode
& source
, ParserArena
* arena
)
403 m_arena
= &arena
->identifierArena();
405 m_lineNumber
= source
.firstLine();
408 const StringImpl
* sourceString
= source
.provider()->data();
411 setCodeStart(sourceString
);
416 m_code
= m_codeStart
+ source
.startOffset();
417 m_codeEnd
= m_codeStart
+ source
.endOffset();
419 m_atLineStart
= true;
420 m_lexErrorMessage
= UString();
422 m_buffer8
.reserveInitialCapacity(initialReadBufferCapacity
);
423 m_buffer16
.reserveInitialCapacity((m_codeEnd
- m_code
) / 2);
425 if (LIKELY(m_code
< m_codeEnd
))
429 ASSERT(currentOffset() == source
.startOffset());
432 template <typename T
>
433 template <int shiftAmount
> ALWAYS_INLINE
void Lexer
<T
>::internalShift()
435 m_code
+= shiftAmount
;
439 template <typename T
>
440 ALWAYS_INLINE
void Lexer
<T
>::shift()
442 // At one point timing showed that setting m_current to 0 unconditionally was faster than an if-else sequence.
445 if (LIKELY(m_code
< m_codeEnd
))
449 template <typename T
>
450 ALWAYS_INLINE
bool Lexer
<T
>::atEnd() const
452 ASSERT(!m_current
|| m_code
< m_codeEnd
);
453 return UNLIKELY(UNLIKELY(!m_current
) && m_code
== m_codeEnd
);
456 template <typename T
>
457 ALWAYS_INLINE T Lexer
<T
>::peek(int offset
) const
459 ASSERT(offset
> 0 && offset
< 5);
460 const T
* code
= m_code
+ offset
;
461 return (code
< m_codeEnd
) ? *code
: 0;
464 template <typename T
>
465 int Lexer
<T
>::parseFourDigitUnicodeHex()
471 if (UNLIKELY(!isASCIIHexDigit(m_current
) || !isASCIIHexDigit(char1
) || !isASCIIHexDigit(char2
) || !isASCIIHexDigit(char3
)))
474 int result
= convertUnicode(m_current
, char1
, char2
, char3
);
482 template <typename T
>
483 void Lexer
<T
>::shiftLineTerminator()
485 ASSERT(isLineTerminator(m_current
));
490 // Allow both CRLF and LFCR.
491 if (prev
+ m_current
== '\n' + '\r')
497 template <typename T
>
498 ALWAYS_INLINE
bool Lexer
<T
>::lastTokenWasRestrKeyword() const
500 return m_lastToken
== CONTINUE
|| m_lastToken
== BREAK
|| m_lastToken
== RETURN
|| m_lastToken
== THROW
;
503 static NEVER_INLINE
bool isNonLatin1IdentStart(int c
)
505 return category(c
) & (Letter_Uppercase
| Letter_Lowercase
| Letter_Titlecase
| Letter_Modifier
| Letter_Other
);
508 static ALWAYS_INLINE
bool isLatin1(LChar
)
513 static ALWAYS_INLINE
bool isLatin1(UChar c
)
518 static inline bool isIdentStart(LChar c
)
520 return typesOfLatin1Characters
[c
] == CharacterIdentifierStart
;
523 static inline bool isIdentStart(UChar c
)
525 return isLatin1(c
) ? isIdentStart(static_cast<LChar
>(c
)) : isNonLatin1IdentStart(c
);
528 static NEVER_INLINE
bool isNonLatin1IdentPart(int c
)
530 return (category(c
) & (Letter_Uppercase
| Letter_Lowercase
| Letter_Titlecase
| Letter_Modifier
| Letter_Other
531 | Mark_NonSpacing
| Mark_SpacingCombining
| Number_DecimalDigit
| Punctuation_Connector
)) || c
== 0x200C || c
== 0x200D;
534 static ALWAYS_INLINE
bool isIdentPart(LChar c
)
536 // Character types are divided into two groups depending on whether they can be part of an
537 // identifier or not. Those whose type value is less or equal than CharacterNumber can be
538 // part of an identifier. (See the CharacterType definition for more details.)
539 return typesOfLatin1Characters
[c
] <= CharacterNumber
;
542 static ALWAYS_INLINE
bool isIdentPart(UChar c
)
544 return isLatin1(c
) ? isIdentPart(static_cast<LChar
>(c
)) : isNonLatin1IdentPart(c
);
547 static inline int singleEscape(int c
)
573 template <typename T
>
574 inline void Lexer
<T
>::record8(int c
)
578 m_buffer8
.append(static_cast<LChar
>(c
));
581 template <typename T
>
582 inline void assertCharIsIn8BitRange(T c
)
590 inline void assertCharIsIn8BitRange(UChar c
)
597 inline void assertCharIsIn8BitRange(LChar
)
601 template <typename T
>
602 inline void Lexer
<T
>::append8(const T
* p
, size_t length
)
604 size_t currentSize
= m_buffer8
.size();
605 m_buffer8
.grow(currentSize
+ length
);
606 LChar
* rawBuffer
= m_buffer8
.data() + currentSize
;
608 for (size_t i
= 0; i
< length
; i
++) {
610 assertCharIsIn8BitRange(c
);
615 template <typename T
>
616 inline void Lexer
<T
>::append16(const LChar
* p
, size_t length
)
618 size_t currentSize
= m_buffer16
.size();
619 m_buffer16
.grow(currentSize
+ length
);
620 UChar
* rawBuffer
= m_buffer16
.data() + currentSize
;
622 for (size_t i
= 0; i
< length
; i
++)
626 template <typename T
>
627 inline void Lexer
<T
>::record16(T c
)
629 m_buffer16
.append(c
);
632 template <typename T
>
633 inline void Lexer
<T
>::record16(int c
)
636 ASSERT(c
<= static_cast<int>(USHRT_MAX
));
637 m_buffer16
.append(static_cast<UChar
>(c
));
641 template <bool shouldCreateIdentifier
> ALWAYS_INLINE JSTokenType Lexer
<LChar
>::parseIdentifier(JSTokenData
* tokenData
, unsigned lexerFlags
, bool strictMode
)
643 const ptrdiff_t remaining
= m_codeEnd
- m_code
;
644 if ((remaining
>= maxTokenLength
) && !(lexerFlags
& LexerFlagsIgnoreReservedWords
)) {
645 JSTokenType keyword
= parseKeyword
<shouldCreateIdentifier
>(tokenData
);
646 if (keyword
!= IDENT
) {
647 ASSERT((!shouldCreateIdentifier
) || tokenData
->ident
);
648 return keyword
== RESERVED_IF_STRICT
&& !strictMode
? IDENT
: keyword
;
652 const LChar
* identifierStart
= currentCharacter();
654 while (isIdentPart(m_current
))
657 if (UNLIKELY(m_current
== '\\')) {
658 setOffsetFromCharOffset(identifierStart
);
659 return parseIdentifierSlowCase
<shouldCreateIdentifier
>(tokenData
, lexerFlags
, strictMode
);
662 const Identifier
* ident
= 0;
664 if (shouldCreateIdentifier
) {
665 int identifierLength
= currentCharacter() - identifierStart
;
666 ident
= makeIdentifier(identifierStart
, identifierLength
);
668 tokenData
->ident
= ident
;
670 tokenData
->ident
= 0;
672 if (UNLIKELY((remaining
< maxTokenLength
) && !(lexerFlags
& LexerFlagsIgnoreReservedWords
))) {
673 ASSERT(shouldCreateIdentifier
);
674 if (remaining
< maxTokenLength
) {
675 const HashEntry
* entry
= m_globalData
->keywords
->getKeyword(*ident
);
676 ASSERT((remaining
< maxTokenLength
) || !entry
);
679 JSTokenType token
= static_cast<JSTokenType
>(entry
->lexerValue());
680 return (token
!= RESERVED_IF_STRICT
) || strictMode
? token
: IDENT
;
689 template <bool shouldCreateIdentifier
> ALWAYS_INLINE JSTokenType Lexer
<UChar
>::parseIdentifier(JSTokenData
* tokenData
, unsigned lexerFlags
, bool strictMode
)
691 const ptrdiff_t remaining
= m_codeEnd
- m_code
;
692 if ((remaining
>= maxTokenLength
) && !(lexerFlags
& LexerFlagsIgnoreReservedWords
)) {
693 JSTokenType keyword
= parseKeyword
<shouldCreateIdentifier
>(tokenData
);
694 if (keyword
!= IDENT
) {
695 ASSERT((!shouldCreateIdentifier
) || tokenData
->ident
);
696 return keyword
== RESERVED_IF_STRICT
&& !strictMode
? IDENT
: keyword
;
700 const UChar
* identifierStart
= currentCharacter();
702 UChar orAllChars
= 0;
704 while (isIdentPart(m_current
)) {
705 orAllChars
|= m_current
;
709 if (UNLIKELY(m_current
== '\\')) {
710 setOffsetFromCharOffset(identifierStart
);
711 return parseIdentifierSlowCase
<shouldCreateIdentifier
>(tokenData
, lexerFlags
, strictMode
);
714 bool isAll8Bit
= false;
716 if (!(orAllChars
& ~0xff))
719 const Identifier
* ident
= 0;
721 if (shouldCreateIdentifier
) {
722 int identifierLength
= currentCharacter() - identifierStart
;
724 ident
= makeIdentifierLCharFromUChar(identifierStart
, identifierLength
);
726 ident
= makeIdentifier(identifierStart
, identifierLength
);
728 tokenData
->ident
= ident
;
730 tokenData
->ident
= 0;
732 if (UNLIKELY((remaining
< maxTokenLength
) && !(lexerFlags
& LexerFlagsIgnoreReservedWords
))) {
733 ASSERT(shouldCreateIdentifier
);
734 if (remaining
< maxTokenLength
) {
735 const HashEntry
* entry
= m_globalData
->keywords
->getKeyword(*ident
);
736 ASSERT((remaining
< maxTokenLength
) || !entry
);
739 JSTokenType token
= static_cast<JSTokenType
>(entry
->lexerValue());
740 return (token
!= RESERVED_IF_STRICT
) || strictMode
? token
: IDENT
;
748 template <typename T
>
749 template <bool shouldCreateIdentifier
> JSTokenType Lexer
<T
>::parseIdentifierSlowCase(JSTokenData
* tokenData
, unsigned lexerFlags
, bool strictMode
)
751 const ptrdiff_t remaining
= m_codeEnd
- m_code
;
752 const T
* identifierStart
= currentCharacter();
753 bool bufferRequired
= false;
756 if (LIKELY(isIdentPart(m_current
))) {
760 if (LIKELY(m_current
!= '\\'))
763 // \uXXXX unicode characters.
764 bufferRequired
= true;
765 if (identifierStart
!= currentCharacter())
766 m_buffer16
.append(identifierStart
, currentCharacter() - identifierStart
);
768 if (UNLIKELY(m_current
!= 'u'))
771 int character
= parseFourDigitUnicodeHex();
772 if (UNLIKELY(character
== -1))
774 UChar ucharacter
= static_cast<UChar
>(character
);
775 if (UNLIKELY(m_buffer16
.size() ? !isIdentPart(ucharacter
) : !isIdentStart(ucharacter
)))
777 if (shouldCreateIdentifier
)
778 record16(ucharacter
);
779 identifierStart
= currentCharacter();
782 int identifierLength
;
783 const Identifier
* ident
= 0;
784 if (shouldCreateIdentifier
) {
785 if (!bufferRequired
) {
786 identifierLength
= currentCharacter() - identifierStart
;
787 ident
= makeIdentifier(identifierStart
, identifierLength
);
789 if (identifierStart
!= currentCharacter())
790 m_buffer16
.append(identifierStart
, currentCharacter() - identifierStart
);
791 ident
= makeIdentifier(m_buffer16
.data(), m_buffer16
.size());
794 tokenData
->ident
= ident
;
796 tokenData
->ident
= 0;
798 if (LIKELY(!bufferRequired
&& !(lexerFlags
& LexerFlagsIgnoreReservedWords
))) {
799 ASSERT(shouldCreateIdentifier
);
800 // Keywords must not be recognized if there was an \uXXXX in the identifier.
801 if (remaining
< maxTokenLength
) {
802 const HashEntry
* entry
= m_globalData
->keywords
->getKeyword(*ident
);
803 ASSERT((remaining
< maxTokenLength
) || !entry
);
806 JSTokenType token
= static_cast<JSTokenType
>(entry
->lexerValue());
807 return (token
!= RESERVED_IF_STRICT
) || strictMode
? token
: IDENT
;
812 m_buffer16
.resize(0);
816 static ALWAYS_INLINE
bool characterRequiresParseStringSlowCase(LChar character
)
818 return character
< 0xE;
821 static ALWAYS_INLINE
bool characterRequiresParseStringSlowCase(UChar character
)
823 return character
< 0xE || character
> 0xFF;
826 template <typename T
>
827 template <bool shouldBuildStrings
> ALWAYS_INLINE
bool Lexer
<T
>::parseString(JSTokenData
* tokenData
, bool strictMode
)
829 int startingOffset
= currentOffset();
830 int startingLineNumber
= lineNumber();
831 T stringQuoteCharacter
= m_current
;
834 const T
* stringStart
= currentCharacter();
836 while (m_current
!= stringQuoteCharacter
) {
837 if (UNLIKELY(m_current
== '\\')) {
838 if (stringStart
!= currentCharacter() && shouldBuildStrings
)
839 append8(stringStart
, currentCharacter() - stringStart
);
842 int escape
= singleEscape(m_current
);
844 // Most common escape sequences first
846 if (shouldBuildStrings
)
849 } else if (UNLIKELY(isLineTerminator(m_current
)))
850 shiftLineTerminator();
851 else if (m_current
== 'x') {
853 if (!isASCIIHexDigit(m_current
) || !isASCIIHexDigit(peek(1))) {
854 m_lexErrorMessage
= "\\x can only be followed by a hex character sequence";
859 if (shouldBuildStrings
)
860 record8(convertHex(prev
, m_current
));
863 setOffset(startingOffset
);
864 setLineNumber(startingLineNumber
);
866 return parseStringSlowCase
<shouldBuildStrings
>(tokenData
, strictMode
);
868 stringStart
= currentCharacter();
872 if (UNLIKELY(characterRequiresParseStringSlowCase(m_current
))) {
873 setOffset(startingOffset
);
874 setLineNumber(startingLineNumber
);
876 return parseStringSlowCase
<shouldBuildStrings
>(tokenData
, strictMode
);
882 if (currentCharacter() != stringStart
&& shouldBuildStrings
)
883 append8(stringStart
, currentCharacter() - stringStart
);
884 if (shouldBuildStrings
) {
885 tokenData
->ident
= makeIdentifier(m_buffer8
.data(), m_buffer8
.size());
888 tokenData
->ident
= 0;
893 template <typename T
>
894 template <bool shouldBuildStrings
> bool Lexer
<T
>::parseStringSlowCase(JSTokenData
* tokenData
, bool strictMode
)
896 T stringQuoteCharacter
= m_current
;
899 const T
* stringStart
= currentCharacter();
901 while (m_current
!= stringQuoteCharacter
) {
902 if (UNLIKELY(m_current
== '\\')) {
903 if (stringStart
!= currentCharacter() && shouldBuildStrings
)
904 append16(stringStart
, currentCharacter() - stringStart
);
907 int escape
= singleEscape(m_current
);
909 // Most common escape sequences first
911 if (shouldBuildStrings
)
914 } else if (UNLIKELY(isLineTerminator(m_current
)))
915 shiftLineTerminator();
916 else if (m_current
== 'x') {
918 if (!isASCIIHexDigit(m_current
) || !isASCIIHexDigit(peek(1))) {
919 m_lexErrorMessage
= "\\x can only be followed by a hex character sequence";
924 if (shouldBuildStrings
)
925 record16(convertHex(prev
, m_current
));
927 } else if (m_current
== 'u') {
929 int character
= parseFourDigitUnicodeHex();
930 if (character
!= -1) {
931 if (shouldBuildStrings
)
933 } else if (m_current
== stringQuoteCharacter
) {
934 if (shouldBuildStrings
)
937 m_lexErrorMessage
= "\\u can only be followed by a Unicode character sequence";
940 } else if (strictMode
&& isASCIIDigit(m_current
)) {
941 // The only valid numeric escape in strict mode is '\0', and this must not be followed by a decimal digit.
942 int character1
= m_current
;
944 if (character1
!= '0' || isASCIIDigit(m_current
)) {
945 m_lexErrorMessage
= "The only valid numeric escape in strict mode is '\\0'";
948 if (shouldBuildStrings
)
950 } else if (!strictMode
&& isASCIIOctalDigit(m_current
)) {
951 // Octal character sequences
952 T character1
= m_current
;
954 if (isASCIIOctalDigit(m_current
)) {
955 // Two octal characters
956 T character2
= m_current
;
958 if (character1
>= '0' && character1
<= '3' && isASCIIOctalDigit(m_current
)) {
959 if (shouldBuildStrings
)
960 record16((character1
- '0') * 64 + (character2
- '0') * 8 + m_current
- '0');
963 if (shouldBuildStrings
)
964 record16((character1
- '0') * 8 + character2
- '0');
967 if (shouldBuildStrings
)
968 record16(character1
- '0');
970 } else if (!atEnd()) {
971 if (shouldBuildStrings
)
975 m_lexErrorMessage
= "Unterminated string constant";
979 stringStart
= currentCharacter();
982 // Fast check for characters that require special handling.
983 // Catches 0, \n, \r, 0x2028, and 0x2029 as efficiently
984 // as possible, and lets through all common ASCII characters.
985 if (UNLIKELY(((static_cast<unsigned>(m_current
) - 0xE) & 0x2000))) {
986 // New-line or end of input is not allowed
987 if (atEnd() || isLineTerminator(m_current
)) {
988 m_lexErrorMessage
= "Unexpected EOF";
991 // Anything else is just a normal character
996 if (currentCharacter() != stringStart
&& shouldBuildStrings
)
997 append16(stringStart
, currentCharacter() - stringStart
);
998 if (shouldBuildStrings
)
999 tokenData
->ident
= makeIdentifier(m_buffer16
.data(), m_buffer16
.size());
1001 tokenData
->ident
= 0;
1003 m_buffer16
.resize(0);
1007 template <typename T
>
1008 ALWAYS_INLINE
void Lexer
<T
>::parseHex(double& returnValue
)
1010 // Optimization: most hexadecimal values fit into 4 bytes.
1011 uint32_t hexValue
= 0;
1012 int maximumDigits
= 7;
1014 // Shift out the 'x' prefix.
1018 hexValue
= (hexValue
<< 4) + toASCIIHexValue(m_current
);
1021 } while (isASCIIHexDigit(m_current
) && maximumDigits
>= 0);
1023 if (maximumDigits
>= 0) {
1024 returnValue
= hexValue
;
1028 // No more place in the hexValue buffer.
1029 // The values are shifted out and placed into the m_buffer8 vector.
1030 for (int i
= 0; i
< 8; ++i
) {
1031 int digit
= hexValue
>> 28;
1033 record8(digit
+ '0');
1035 record8(digit
- 10 + 'a');
1039 while (isASCIIHexDigit(m_current
)) {
1044 returnValue
= parseIntOverflow(m_buffer8
.data(), m_buffer8
.size(), 16);
1047 template <typename T
>
1048 ALWAYS_INLINE
bool Lexer
<T
>::parseOctal(double& returnValue
)
1050 // Optimization: most octal values fit into 4 bytes.
1051 uint32_t octalValue
= 0;
1052 int maximumDigits
= 9;
1053 // Temporary buffer for the digits. Makes easier
1054 // to reconstruct the input characters when needed.
1058 octalValue
= octalValue
* 8 + (m_current
- '0');
1059 digits
[maximumDigits
] = m_current
;
1062 } while (isASCIIOctalDigit(m_current
) && maximumDigits
>= 0);
1064 if (!isASCIIDigit(m_current
) && maximumDigits
>= 0) {
1065 returnValue
= octalValue
;
1069 for (int i
= 9; i
> maximumDigits
; --i
)
1072 while (isASCIIOctalDigit(m_current
)) {
1077 if (isASCIIDigit(m_current
))
1080 returnValue
= parseIntOverflow(m_buffer8
.data(), m_buffer8
.size(), 8);
1084 template <typename T
>
1085 ALWAYS_INLINE
bool Lexer
<T
>::parseDecimal(double& returnValue
)
1087 // Optimization: most decimal values fit into 4 bytes.
1088 uint32_t decimalValue
= 0;
1090 // Since parseOctal may be executed before parseDecimal,
1091 // the m_buffer8 may hold ascii digits.
1092 if (!m_buffer8
.size()) {
1093 int maximumDigits
= 9;
1094 // Temporary buffer for the digits. Makes easier
1095 // to reconstruct the input characters when needed.
1099 decimalValue
= decimalValue
* 10 + (m_current
- '0');
1100 digits
[maximumDigits
] = m_current
;
1103 } while (isASCIIDigit(m_current
) && maximumDigits
>= 0);
1105 if (maximumDigits
>= 0 && m_current
!= '.' && (m_current
| 0x20) != 'e') {
1106 returnValue
= decimalValue
;
1110 for (int i
= 9; i
> maximumDigits
; --i
)
1114 while (isASCIIDigit(m_current
)) {
1122 template <typename T
>
1123 ALWAYS_INLINE
void Lexer
<T
>::parseNumberAfterDecimalPoint()
1126 while (isASCIIDigit(m_current
)) {
1132 template <typename T
>
1133 ALWAYS_INLINE
bool Lexer
<T
>::parseNumberAfterExponentIndicator()
1137 if (m_current
== '+' || m_current
== '-') {
1142 if (!isASCIIDigit(m_current
))
1148 } while (isASCIIDigit(m_current
));
1152 template <typename T
>
1153 ALWAYS_INLINE
bool Lexer
<T
>::parseMultilineComment()
1156 while (UNLIKELY(m_current
== '*')) {
1158 if (m_current
== '/') {
1167 if (isLineTerminator(m_current
)) {
1168 shiftLineTerminator();
1169 m_terminator
= true;
1175 template <typename T
>
1176 bool Lexer
<T
>::nextTokenIsColon()
1178 const T
* code
= m_code
;
1179 while (code
< m_codeEnd
&& (isWhiteSpace(*code
) || isLineTerminator(*code
)))
1182 return code
< m_codeEnd
&& *code
== ':';
1185 template <typename T
>
1186 JSTokenType Lexer
<T
>::lex(JSTokenData
* tokenData
, JSTokenInfo
* tokenInfo
, unsigned lexerFlags
, bool strictMode
)
1189 ASSERT(m_buffer8
.isEmpty());
1190 ASSERT(m_buffer16
.isEmpty());
1192 JSTokenType token
= ERRORTOK
;
1193 m_terminator
= false;
1196 while (isWhiteSpace(m_current
))
1202 tokenInfo
->startOffset
= currentOffset();
1205 if (LIKELY(isLatin1(m_current
)))
1206 type
= static_cast<CharacterType
>(typesOfLatin1Characters
[m_current
]);
1207 else if (isNonLatin1IdentStart(m_current
))
1208 type
= CharacterIdentifierStart
;
1209 else if (isLineTerminator(m_current
))
1210 type
= CharacterLineTerminator
;
1212 type
= CharacterInvalid
;
1215 case CharacterGreater
:
1217 if (m_current
== '>') {
1219 if (m_current
== '>') {
1221 if (m_current
== '=') {
1223 token
= URSHIFTEQUAL
;
1229 if (m_current
== '=') {
1231 token
= RSHIFTEQUAL
;
1237 if (m_current
== '=') {
1244 case CharacterEqual
:
1246 if (m_current
== '=') {
1248 if (m_current
== '=') {
1260 if (m_current
== '!' && peek(1) == '-' && peek(2) == '-') {
1261 // <!-- marks the beginning of a line comment (for www usage)
1262 goto inSingleLineComment
;
1264 if (m_current
== '<') {
1266 if (m_current
== '=') {
1268 token
= LSHIFTEQUAL
;
1274 if (m_current
== '=') {
1281 case CharacterExclamationMark
:
1283 if (m_current
== '=') {
1285 if (m_current
== '=') {
1293 token
= EXCLAMATION
;
1297 if (m_current
== '+') {
1299 token
= (!m_terminator
) ? PLUSPLUS
: AUTOPLUSPLUS
;
1302 if (m_current
== '=') {
1311 if (m_current
== '-') {
1313 if (m_atLineStart
&& m_current
== '>') {
1315 goto inSingleLineComment
;
1317 token
= (!m_terminator
) ? MINUSMINUS
: AUTOMINUSMINUS
;
1320 if (m_current
== '=') {
1327 case CharacterMultiply
:
1329 if (m_current
== '=') {
1336 case CharacterSlash
:
1338 if (m_current
== '/') {
1340 goto inSingleLineComment
;
1342 if (m_current
== '*') {
1344 if (parseMultilineComment())
1346 m_lexErrorMessage
= "Multiline comment was not closed properly";
1349 if (m_current
== '=') {
1358 if (m_current
== '&') {
1363 if (m_current
== '=') {
1372 if (m_current
== '=') {
1379 case CharacterModulo
:
1381 if (m_current
== '=') {
1390 if (m_current
== '=') {
1395 if (m_current
== '|') {
1402 case CharacterOpenParen
:
1406 case CharacterCloseParen
:
1410 case CharacterOpenBracket
:
1411 token
= OPENBRACKET
;
1414 case CharacterCloseBracket
:
1415 token
= CLOSEBRACKET
;
1418 case CharacterComma
:
1422 case CharacterColon
:
1426 case CharacterQuestion
:
1430 case CharacterTilde
:
1434 case CharacterSemicolon
:
1438 case CharacterOpenBrace
:
1439 tokenData
->intValue
= currentOffset();
1443 case CharacterCloseBrace
:
1444 tokenData
->intValue
= currentOffset();
1450 if (!isASCIIDigit(m_current
)) {
1454 goto inNumberAfterDecimalPoint
;
1457 if ((m_current
| 0x20) == 'x' && isASCIIHexDigit(peek(1))) {
1458 parseHex(tokenData
->doubleValue
);
1462 if (isASCIIOctalDigit(m_current
)) {
1463 if (parseOctal(tokenData
->doubleValue
)) {
1465 m_lexErrorMessage
= "Octal escapes are forbidden in strict mode";
1472 // Fall through into CharacterNumber
1473 case CharacterNumber
:
1474 if (LIKELY(token
!= NUMBER
)) {
1475 if (!parseDecimal(tokenData
->doubleValue
)) {
1476 if (m_current
== '.') {
1478 inNumberAfterDecimalPoint
:
1479 parseNumberAfterDecimalPoint();
1481 if ((m_current
| 0x20) == 'e') {
1482 if (!parseNumberAfterExponentIndicator()) {
1483 m_lexErrorMessage
= "Non-number found after exponent indicator";
1487 size_t parsedLength
;
1488 tokenData
->doubleValue
= parseDouble(m_buffer8
.data(), m_buffer8
.size(), parsedLength
);
1493 // No identifiers allowed directly after numeric literal, e.g. "3in" is bad.
1494 if (UNLIKELY(isIdentStart(m_current
))) {
1495 m_lexErrorMessage
= "At least one digit must occur after a decimal point";
1498 m_buffer8
.resize(0);
1500 case CharacterQuote
:
1501 if (lexerFlags
& LexerFlagsDontBuildStrings
) {
1502 if (UNLIKELY(!parseString
<false>(tokenData
, strictMode
)))
1505 if (UNLIKELY(!parseString
<true>(tokenData
, strictMode
)))
1511 case CharacterIdentifierStart
:
1512 ASSERT(isIdentStart(m_current
));
1513 // Fall through into CharacterBackSlash.
1514 case CharacterBackSlash
:
1515 if (lexerFlags
& LexexFlagsDontBuildKeywords
)
1516 token
= parseIdentifier
<false>(tokenData
, lexerFlags
, strictMode
);
1518 token
= parseIdentifier
<true>(tokenData
, lexerFlags
, strictMode
);
1520 case CharacterLineTerminator
:
1521 ASSERT(isLineTerminator(m_current
));
1522 shiftLineTerminator();
1523 m_atLineStart
= true;
1524 m_terminator
= true;
1526 case CharacterInvalid
:
1527 m_lexErrorMessage
= invalidCharacterMessage();
1530 ASSERT_NOT_REACHED();
1531 m_lexErrorMessage
= "Internal Error";
1535 m_atLineStart
= false;
1538 inSingleLineComment
:
1539 while (!isLineTerminator(m_current
)) {
1544 shiftLineTerminator();
1545 m_atLineStart
= true;
1546 m_terminator
= true;
1547 if (!lastTokenWasRestrKeyword())
1551 // Fall through into returnToken.
1554 tokenInfo
->line
= m_lineNumber
;
1555 tokenInfo
->endOffset
= currentOffset();
1556 m_lastToken
= token
;
1561 tokenInfo
->line
= m_lineNumber
;
1562 tokenInfo
->endOffset
= currentOffset();
1566 template <typename T
>
1567 bool Lexer
<T
>::scanRegExp(const Identifier
*& pattern
, const Identifier
*& flags
, UChar patternPrefix
)
1569 ASSERT(m_buffer16
.isEmpty());
1571 bool lastWasEscape
= false;
1572 bool inBrackets
= false;
1574 if (patternPrefix
) {
1575 ASSERT(!isLineTerminator(patternPrefix
));
1576 ASSERT(patternPrefix
!= '/');
1577 ASSERT(patternPrefix
!= '[');
1578 record16(patternPrefix
);
1582 if (isLineTerminator(m_current
) || atEnd()) {
1583 m_buffer16
.resize(0);
1591 if (prev
== '/' && !lastWasEscape
&& !inBrackets
)
1596 if (lastWasEscape
) {
1597 lastWasEscape
= false;
1609 lastWasEscape
= true;
1614 pattern
= makeIdentifier(m_buffer16
.data(), m_buffer16
.size());
1615 m_buffer16
.resize(0);
1617 while (isIdentPart(m_current
)) {
1618 record16(m_current
);
1622 flags
= makeIdentifier(m_buffer16
.data(), m_buffer16
.size());
1623 m_buffer16
.resize(0);
1628 template <typename T
>
1629 bool Lexer
<T
>::skipRegExp()
1631 bool lastWasEscape
= false;
1632 bool inBrackets
= false;
1635 if (isLineTerminator(m_current
) || atEnd())
1642 if (prev
== '/' && !lastWasEscape
&& !inBrackets
)
1645 if (lastWasEscape
) {
1646 lastWasEscape
= false;
1658 lastWasEscape
= true;
1663 while (isIdentPart(m_current
))
1669 template <typename T
>
1670 void Lexer
<T
>::clear()
1674 Vector
<LChar
> newBuffer8
;
1675 m_buffer8
.swap(newBuffer8
);
1677 Vector
<UChar
> newBuffer16
;
1678 m_buffer16
.swap(newBuffer16
);
1680 m_isReparsing
= false;
1683 template <typename T
>
1684 SourceCode Lexer
<T
>::sourceCode(int openBrace
, int closeBrace
, int firstLine
)
1686 ASSERT((*m_source
->provider()->data())[openBrace
] == '{');
1687 ASSERT((*m_source
->provider()->data())[closeBrace
] == '}');
1688 return SourceCode(m_source
->provider(), openBrace
, closeBrace
+ 1, firstLine
);
1691 // Instantiate the two flavors of Lexer we need instead of putting most of this file in Lexer.h
1692 template class Lexer
<LChar
>;
1693 template class Lexer
<UChar
>;