d84db17653f226105793bc9ddac3e0402abfa7be
[WebKit-https.git] / Source / JavaScriptCore / parser / Parser.cpp
1 /*
2  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
3  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
4  *  Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc. All rights reserved.
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Library General Public
8  *  License as published by the Free Software Foundation; either
9  *  version 2 of the License, or (at your option) any later version.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Library General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Library General Public License
17  *  along with this library; see the file COPYING.LIB.  If not, write to
18  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  *  Boston, MA 02110-1301, USA.
20  *
21  */
22
23 #include "config.h"
24 #include "Parser.h"
25
26 #include "ASTBuilder.h"
27 #include "CodeBlock.h"
28 #include "Debugger.h"
29 #include "JSCJSValueInlines.h"
30 #include "Lexer.h"
31 #include "JSCInlines.h"
32 #include "SourceProvider.h"
33 #include "VM.h"
34 #include <utility>
35 #include <wtf/HashFunctions.h>
36 #include <wtf/StringPrintStream.h>
37 #include <wtf/WTFThreadData.h>
38
39
40 #define updateErrorMessage(shouldPrintToken, ...) do {\
41     propagateError(); \
42     logError(shouldPrintToken, __VA_ARGS__); \
43 } while (0)
44
45 #define propagateError() do { if (hasError()) return 0; } while (0)
46 #define internalFailWithMessage(shouldPrintToken, ...) do { updateErrorMessage(shouldPrintToken, __VA_ARGS__); return 0; } while (0)
47 #define handleErrorToken() do { if (m_token.m_type == EOFTOK || m_token.m_type & ErrorTokenFlag) { failDueToUnexpectedToken(); } } while (0)
48 #define failWithMessage(...) do { { handleErrorToken(); updateErrorMessage(true, __VA_ARGS__); } return 0; } while (0)
49 #define failWithStackOverflow() do { updateErrorMessage(false, "Stack exhausted"); m_hasStackOverflow = true; return 0; } while (0)
50 #define failIfFalse(cond, ...) do { if (!(cond)) { handleErrorToken(); internalFailWithMessage(true, __VA_ARGS__); } } while (0)
51 #define failIfTrue(cond, ...) do { if (cond) { handleErrorToken(); internalFailWithMessage(true, __VA_ARGS__); } } while (0)
52 #define failIfTrueIfStrict(cond, ...) do { if ((cond) && strictMode()) internalFailWithMessage(false, __VA_ARGS__); } while (0)
53 #define failIfFalseIfStrict(cond, ...) do { if ((!(cond)) && strictMode()) internalFailWithMessage(false, __VA_ARGS__); } while (0)
54 #define consumeOrFail(tokenType, ...) do { if (!consume(tokenType)) { handleErrorToken(); internalFailWithMessage(true, __VA_ARGS__); } } while (0)
55 #define consumeOrFailWithFlags(tokenType, flags, ...) do { if (!consume(tokenType, flags)) { handleErrorToken(); internalFailWithMessage(true, __VA_ARGS__); } } while (0)
56 #define matchOrFail(tokenType, ...) do { if (!match(tokenType)) { handleErrorToken(); internalFailWithMessage(true, __VA_ARGS__); } } while (0)
57 #define failIfStackOverflow() do { if (!canRecurse()) failWithStackOverflow(); } while (0)
58 #define semanticFail(...) do { internalFailWithMessage(false, __VA_ARGS__); } while (0)
59 #define semanticFailIfTrue(cond, ...) do { if (cond) internalFailWithMessage(false, __VA_ARGS__); } while (0)
60 #define semanticFailIfFalse(cond, ...) do { if (!(cond)) internalFailWithMessage(false, __VA_ARGS__); } while (0)
61 #define regexFail(failure) do { setErrorMessage(failure); return 0; } while (0)
62 #define failDueToUnexpectedToken() do {\
63         logError(true);\
64     return 0;\
65 } while (0)
66
67 #define handleProductionOrFail(token, tokenString, operation, production) do {\
68     consumeOrFail(token, "Expected '", tokenString, "' to ", operation, " a ", production);\
69 } while (0)
70
71 #define semanticFailureDueToKeyword(...) do { \
72     if (strictMode() && m_token.m_type == RESERVED_IF_STRICT) \
73         semanticFail("Cannot use the reserved word '", getToken(), "' as a ", __VA_ARGS__, " in strict mode"); \
74     if (m_token.m_type == RESERVED || m_token.m_type == RESERVED_IF_STRICT) \
75         semanticFail("Cannot use the reserved word '", getToken(), "' as a ", __VA_ARGS__); \
76     if (m_token.m_type & KeywordTokenFlag) \
77         semanticFail("Cannot use the keyword '", getToken(), "' as a ", __VA_ARGS__); \
78 } while (0)
79
80 using namespace std;
81
82 namespace JSC {
83
84 template <typename LexerType>
85 void Parser<LexerType>::logError(bool)
86 {
87     if (hasError())
88         return;
89     StringPrintStream stream;
90     printUnexpectedTokenText(stream);
91     setErrorMessage(stream.toString());
92 }
93
94 template <typename LexerType> template <typename A>
95 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1)
96 {
97     if (hasError())
98         return;
99     StringPrintStream stream;
100     if (shouldPrintToken) {
101         printUnexpectedTokenText(stream);
102         stream.print(". ");
103     }
104     stream.print(value1, ".");
105     setErrorMessage(stream.toString());
106 }
107
108 template <typename LexerType> template <typename A, typename B>
109 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2)
110 {
111     if (hasError())
112         return;
113     StringPrintStream stream;
114     if (shouldPrintToken) {
115         printUnexpectedTokenText(stream);
116         stream.print(". ");
117     }
118     stream.print(value1, value2, ".");
119     setErrorMessage(stream.toString());
120 }
121
122 template <typename LexerType> template <typename A, typename B, typename C>
123 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2, const C& value3)
124 {
125     if (hasError())
126         return;
127     StringPrintStream stream;
128     if (shouldPrintToken) {
129         printUnexpectedTokenText(stream);
130         stream.print(". ");
131     }
132     stream.print(value1, value2, value3, ".");
133     setErrorMessage(stream.toString());
134 }
135
136 template <typename LexerType> template <typename A, typename B, typename C, typename D>
137 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2, const C& value3, const D& value4)
138 {
139     if (hasError())
140         return;
141     StringPrintStream stream;
142     if (shouldPrintToken) {
143         printUnexpectedTokenText(stream);
144         stream.print(". ");
145     }
146     stream.print(value1, value2, value3, value4, ".");
147     setErrorMessage(stream.toString());
148 }
149
150 template <typename LexerType> template <typename A, typename B, typename C, typename D, typename E>
151 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2, const C& value3, const D& value4, const E& value5)
152 {
153     if (hasError())
154         return;
155     StringPrintStream stream;
156     if (shouldPrintToken) {
157         printUnexpectedTokenText(stream);
158         stream.print(". ");
159     }
160     stream.print(value1, value2, value3, value4, value5, ".");
161     setErrorMessage(stream.toString());
162 }
163
164 template <typename LexerType> template <typename A, typename B, typename C, typename D, typename E, typename F>
165 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2, const C& value3, const D& value4, const E& value5, const F& value6)
166 {
167     if (hasError())
168         return;
169     StringPrintStream stream;
170     if (shouldPrintToken) {
171         printUnexpectedTokenText(stream);
172         stream.print(". ");
173     }
174     stream.print(value1, value2, value3, value4, value5, value6, ".");
175     setErrorMessage(stream.toString());
176 }
177
178 template <typename LexerType> template <typename A, typename B, typename C, typename D, typename E, typename F, typename G>
179 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2, const C& value3, const D& value4, const E& value5, const F& value6, const G& value7)
180 {
181     if (hasError())
182         return;
183     StringPrintStream stream;
184     if (shouldPrintToken) {
185         printUnexpectedTokenText(stream);
186         stream.print(". ");
187     }
188     stream.print(value1, value2, value3, value4, value5, value6, value7, ".");
189     setErrorMessage(stream.toString());
190 }
191
192 template <typename LexerType>
193 Parser<LexerType>::Parser(
194     VM* vm, const SourceCode& source, JSParserBuiltinMode builtinMode, 
195     JSParserStrictMode strictMode, SourceParseMode parseMode, 
196     ConstructorKind defaultConstructorKind, ThisTDZMode thisTDZMode)
197     : m_vm(vm)
198     , m_source(&source)
199     , m_hasStackOverflow(false)
200     , m_allowsIn(true)
201     , m_assignmentCount(0)
202     , m_nonLHSCount(0)
203     , m_syntaxAlreadyValidated(source.provider()->isValid())
204     , m_statementDepth(0)
205     , m_nonTrivialExpressionCount(0)
206     , m_lastIdentifier(0)
207     , m_lastFunctionName(nullptr)
208     , m_sourceElements(0)
209     , m_parsingBuiltin(builtinMode == JSParserBuiltinMode::Builtin)
210     , m_defaultConstructorKind(defaultConstructorKind)
211     , m_thisTDZMode(thisTDZMode)
212 {
213     m_lexer = std::make_unique<LexerType>(vm, builtinMode);
214     m_lexer->setCode(source, &m_parserArena);
215     m_token.m_location.line = source.firstLine();
216     m_token.m_location.startOffset = source.startOffset();
217     m_token.m_location.endOffset = source.startOffset();
218     m_token.m_location.lineStartOffset = source.startOffset();
219     m_functionCache = vm->addSourceProviderCache(source.provider());
220     ScopeRef scope = pushScope();
221     if (isFunctionParseMode(parseMode))
222         scope->setIsFunction();
223     if (isModuleParseMode(parseMode))
224         scope->setIsModule();
225     if (strictMode == JSParserStrictMode::Strict)
226         scope->setStrictMode();
227
228     next();
229 }
230
231 template <typename LexerType>
232 Parser<LexerType>::~Parser()
233 {
234 }
235
236 template <typename LexerType>
237 String Parser<LexerType>::parseInner(const Identifier& calleeName, SourceParseMode parseMode)
238 {
239     String parseError = String();
240
241     ASTBuilder context(const_cast<VM*>(m_vm), m_parserArena, const_cast<SourceCode*>(m_source));
242     ScopeRef scope = currentScope();
243     scope->setIsLexicalScope();
244
245     bool isArrowFunctionBodyExpression = false;
246     if (m_lexer->isReparsingFunction()) {
247         ParserFunctionInfo<ASTBuilder> functionInfo;
248         parseFunctionParameters(context, parseMode, functionInfo);
249         m_parameters = functionInfo.parameters;
250
251 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
252         if (parseMode == SourceParseMode::ArrowFunctionMode && !hasError()) {
253             // The only way we could have an error wile reparsing is if we run out of stack space.
254             RELEASE_ASSERT(match(ARROWFUNCTION));
255             next();
256             isArrowFunctionBodyExpression = !match(OPENBRACE);
257         }
258 #endif
259     }
260
261     if (!calleeName.isNull())
262         scope->declareCallee(&calleeName);
263
264     if (m_lexer->isReparsingFunction())
265         m_statementDepth--;
266
267     SourceElements* sourceElements = nullptr;
268     // The only way we can error this early is if we reparse a function and we run out of stack space.
269     if (!hasError()) {
270         if (isArrowFunctionBodyExpression)
271             sourceElements = parseArrowFunctionSingleExpressionBodySourceElements(context);
272         else if (isModuleParseMode(parseMode))
273             sourceElements = parseModuleSourceElements(context, parseMode);
274         else
275             sourceElements = parseSourceElements(context, CheckForStrictMode);
276     }
277
278     bool validEnding;
279     if (isArrowFunctionBodyExpression) {
280         ASSERT(m_lexer->isReparsingFunction());
281         // When we reparse and stack overflow, we're not guaranteed a valid ending. If we don't run out of stack space,
282         // then of course this will always be valid because we already parsed for syntax errors. But we must
283         // be cautious in case we run out of stack space.
284         validEnding = isEndOfArrowFunction(); 
285     } else
286         validEnding = consume(EOFTOK);
287
288     if (!sourceElements || !validEnding) {
289         if (hasError())
290             parseError = m_errorMessage;
291         else
292             parseError = ASCIILiteral("Parser error");
293     }
294
295     IdentifierSet capturedVariables;
296     bool modifiedParameter = false;
297     bool modifiedArguments = false;
298     scope->getCapturedVars(capturedVariables, modifiedParameter, modifiedArguments);
299     VariableEnvironment& varDeclarations = scope->declaredVariables();
300     for (auto& entry : capturedVariables)
301         varDeclarations.markVariableAsCaptured(entry);
302     
303     CodeFeatures features = context.features();
304     if (scope->strictMode())
305         features |= StrictModeFeature;
306     if (scope->shadowsArguments())
307         features |= ShadowsArgumentsFeature;
308     if (modifiedParameter)
309         features |= ModifiedParameterFeature;
310     if (modifiedArguments)
311         features |= ModifiedArgumentsFeature;
312     Vector<RefPtr<UniquedStringImpl>> closedVariables;
313     if (m_parsingBuiltin) {
314         IdentifierSet usedVariables;
315         scope->getUsedVariables(usedVariables);
316         // FIXME: This needs to be changed if we want to allow builtins to use lexical declarations.
317         for (const auto& variable : usedVariables) {
318             Identifier identifier = Identifier::fromUid(m_vm, variable.get());
319             if (scope->hasDeclaredVariable(identifier))
320                 continue;
321             
322             if (scope->hasDeclaredParameter(identifier))
323                 continue;
324
325             if (variable == m_vm->propertyNames->arguments.impl())
326                 continue;
327
328             closedVariables.append(variable);
329         }
330
331         if (!capturedVariables.isEmpty()) {
332             for (const auto& capturedVariable : capturedVariables) {
333                 if (scope->hasDeclaredVariable(capturedVariable))
334                     continue;
335
336                 if (scope->hasDeclaredParameter(capturedVariable))
337                     continue;
338
339                 RELEASE_ASSERT_NOT_REACHED();
340             }
341         }
342     }
343     didFinishParsing(sourceElements, context.funcDeclarations(), varDeclarations, features, context.numConstants(), WTF::move(closedVariables));
344
345     return parseError;
346 }
347
348 template <typename LexerType>
349 void Parser<LexerType>::didFinishParsing(SourceElements* sourceElements, DeclarationStacks::FunctionStack& funcStack, 
350     VariableEnvironment& varDeclarations, CodeFeatures features, int numConstants, const Vector<RefPtr<UniquedStringImpl>>&& closedVariables)
351 {
352     m_sourceElements = sourceElements;
353     m_funcDeclarations.swap(funcStack);
354     m_varDeclarations.swap(varDeclarations);
355     m_closedVariables = closedVariables;
356     m_features = features;
357     m_numConstants = numConstants;
358 }
359
360 template <typename LexerType>
361 bool Parser<LexerType>::allowAutomaticSemicolon()
362 {
363     return match(CLOSEBRACE) || match(EOFTOK) || m_lexer->prevTerminator();
364 }
365
366 template <typename LexerType>
367 template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseSourceElements(TreeBuilder& context, SourceElementsMode mode)
368 {
369     const unsigned lengthOfUseStrictLiteral = 12; // "use strict".length
370     TreeSourceElements sourceElements = context.createSourceElements();
371     bool seenNonDirective = false;
372     const Identifier* directive = 0;
373     unsigned directiveLiteralLength = 0;
374     auto savePoint = createSavePoint();
375     bool hasSetStrict = false;
376     
377     while (TreeStatement statement = parseStatementListItem(context, directive, &directiveLiteralLength)) {
378         if (mode == CheckForStrictMode && !seenNonDirective) {
379             if (directive) {
380                 // "use strict" must be the exact literal without escape sequences or line continuation.
381                 if (!hasSetStrict && directiveLiteralLength == lengthOfUseStrictLiteral && m_vm->propertyNames->useStrictIdentifier == *directive) {
382                     setStrictMode();
383                     hasSetStrict = true;
384                     if (!isValidStrictMode()) {
385                         if (m_lastFunctionName) {
386                             if (m_vm->propertyNames->arguments == *m_lastFunctionName)
387                                 semanticFail("Cannot name a function 'arguments' in strict mode");
388                             if (m_vm->propertyNames->eval == *m_lastFunctionName)
389                                 semanticFail("Cannot name a function 'eval' in strict mode");
390                         }
391                         if (hasDeclaredVariable(m_vm->propertyNames->arguments))
392                             semanticFail("Cannot declare a variable named 'arguments' in strict mode");
393                         if (hasDeclaredVariable(m_vm->propertyNames->eval))
394                             semanticFail("Cannot declare a variable named 'eval' in strict mode");
395                         semanticFailIfFalse(isValidStrictMode(), "Invalid parameters or function name in strict mode");
396                     }
397                     restoreSavePoint(savePoint);
398                     propagateError();
399                     continue;
400                 }
401             } else
402                 seenNonDirective = true;
403         }
404         context.appendStatement(sourceElements, statement);
405     }
406
407     propagateError();
408     return sourceElements;
409 }
410
411 template <typename LexerType>
412 template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseModuleSourceElements(TreeBuilder& context, SourceParseMode parseMode)
413 {
414     TreeSourceElements sourceElements = context.createSourceElements();
415     SyntaxChecker syntaxChecker(const_cast<VM*>(m_vm), m_lexer.get());
416
417     while (true) {
418         TreeStatement statement = 0;
419         if (match(IMPORT))
420             statement = parseImportDeclaration(context);
421         else if (match(EXPORT))
422             statement = parseExportDeclaration(context);
423         else {
424             const Identifier* directive = 0;
425             unsigned directiveLiteralLength = 0;
426             if (parseMode == SourceParseMode::ModuleAnalyzeMode) {
427                 if (!parseStatementListItem(syntaxChecker, directive, &directiveLiteralLength))
428                     break;
429                 continue;
430             }
431             statement = parseStatementListItem(context, directive, &directiveLiteralLength);
432         }
433
434         if (!statement)
435             break;
436         context.appendStatement(sourceElements, statement);
437     }
438
439     propagateError();
440
441     for (const auto& uid : currentScope()->moduleScopeData().exportedBindings()) {
442         if (currentScope()->hasDeclaredVariable(uid)) {
443             currentScope()->declaredVariables().markVariableAsExported(uid);
444             continue;
445         }
446
447         if (currentScope()->hasLexicallyDeclaredVariable(uid)) {
448             currentScope()->lexicalVariables().markVariableAsExported(uid);
449             continue;
450         }
451
452         semanticFail("Exported binding '", uid.get(), "' needs to refer to a top-level declared variable");
453     }
454
455     return sourceElements;
456 }
457
458 template <typename LexerType>
459 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseStatementListItem(TreeBuilder& context, const Identifier*& directive, unsigned* directiveLiteralLength)
460 {
461     // The grammar is documented here:
462     // http://www.ecma-international.org/ecma-262/6.0/index.html#sec-statements
463     DepthManager statementDepth(&m_statementDepth);
464     m_statementDepth++;
465     TreeStatement result = 0;
466     bool shouldSetEndOffset = true;
467     switch (m_token.m_type) {
468     case CONSTTOKEN:
469         result = parseVariableDeclaration(context, DeclarationType::ConstDeclaration);
470         break;
471     case LET: {
472         bool shouldParseVariableDeclaration = true;
473         if (!strictMode()) {
474             SavePoint savePoint = createSavePoint();
475             next();
476             if (!match(IDENT) && !match(OPENBRACE) && !match(OPENBRACKET))
477                 shouldParseVariableDeclaration = false;
478             restoreSavePoint(savePoint);
479         }
480         if (shouldParseVariableDeclaration)
481             result = parseVariableDeclaration(context, DeclarationType::LetDeclaration);
482         else
483             result = parseExpressionOrLabelStatement(context); // Treat this as an IDENT. This is how ::parseStatement() handles IDENT.
484
485         break;
486     }
487 #if ENABLE(ES6_CLASS_SYNTAX)
488     case CLASSTOKEN:
489         result = parseClassDeclaration(context);
490         break;
491 #endif
492     default:
493         m_statementDepth--; // parseStatement() increments the depth.
494         result = parseStatement(context, directive, directiveLiteralLength);
495         shouldSetEndOffset = false;
496         break;
497     }
498
499     if (result && shouldSetEndOffset)
500         context.setEndOffset(result, m_lastTokenEndPosition.offset);
501
502     return result;
503 }
504
505 template <typename LexerType>
506 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseVariableDeclaration(TreeBuilder& context, DeclarationType declarationType, ExportType exportType)
507 {
508     ASSERT(match(VAR) || match(LET) || match(CONSTTOKEN));
509     JSTokenLocation location(tokenLocation());
510     int start = tokenLine();
511     int end = 0;
512     int scratch;
513     TreeDestructuringPattern scratch1 = 0;
514     TreeExpression scratch2 = 0;
515     JSTextPosition scratch3;
516     bool scratchBool;
517     TreeExpression variableDecls = parseVariableDeclarationList(context, scratch, scratch1, scratch2, scratch3, scratch3, scratch3, VarDeclarationContext, declarationType, exportType, scratchBool);
518     propagateError();
519     failIfFalse(autoSemiColon(), "Expected ';' after variable declaration");
520     
521     return context.createDeclarationStatement(location, variableDecls, start, end);
522 }
523
524 template <typename LexerType>
525 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseDoWhileStatement(TreeBuilder& context)
526 {
527     ASSERT(match(DO));
528     int startLine = tokenLine();
529     next();
530     const Identifier* unused = 0;
531     startLoop();
532     TreeStatement statement = parseStatement(context, unused);
533     endLoop();
534     failIfFalse(statement, "Expected a statement following 'do'");
535     int endLine = tokenLine();
536     JSTokenLocation location(tokenLocation());
537     handleProductionOrFail(WHILE, "while", "end", "do-while loop");
538     handleProductionOrFail(OPENPAREN, "(", "start", "do-while loop condition");
539     semanticFailIfTrue(match(CLOSEPAREN), "Must provide an expression as a do-while loop condition");
540     TreeExpression expr = parseExpression(context);
541     failIfFalse(expr, "Unable to parse do-while loop condition");
542     handleProductionOrFail(CLOSEPAREN, ")", "end", "do-while loop condition");
543     if (match(SEMICOLON))
544         next(); // Always performs automatic semicolon insertion.
545     return context.createDoWhileStatement(location, statement, expr, startLine, endLine);
546 }
547
548 template <typename LexerType>
549 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWhileStatement(TreeBuilder& context)
550 {
551     ASSERT(match(WHILE));
552     JSTokenLocation location(tokenLocation());
553     int startLine = tokenLine();
554     next();
555     
556     handleProductionOrFail(OPENPAREN, "(", "start", "while loop condition");
557     semanticFailIfTrue(match(CLOSEPAREN), "Must provide an expression as a while loop condition");
558     TreeExpression expr = parseExpression(context);
559     failIfFalse(expr, "Unable to parse while loop condition");
560     int endLine = tokenLine();
561     handleProductionOrFail(CLOSEPAREN, ")", "end", "while loop condition");
562     
563     const Identifier* unused = 0;
564     startLoop();
565     TreeStatement statement = parseStatement(context, unused);
566     endLoop();
567     failIfFalse(statement, "Expected a statement as the body of a while loop");
568     return context.createWhileStatement(location, expr, statement, startLine, endLine);
569 }
570
571 template <typename LexerType>
572 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseVariableDeclarationList(TreeBuilder& context, int& declarations, TreeDestructuringPattern& lastPattern, TreeExpression& lastInitializer, JSTextPosition& identStart, JSTextPosition& initStart, JSTextPosition& initEnd, VarDeclarationListContext declarationListContext, DeclarationType declarationType, ExportType exportType, bool& forLoopConstDoesNotHaveInitializer)
573 {
574     ASSERT(declarationType == DeclarationType::LetDeclaration || declarationType == DeclarationType::VarDeclaration || declarationType == DeclarationType::ConstDeclaration);
575     TreeExpression head = 0;
576     TreeExpression tail = 0;
577     const Identifier* lastIdent;
578     JSToken lastIdentToken; 
579     AssignmentContext assignmentContext = assignmentContextFromDeclarationType(declarationType);
580     do {
581         lastIdent = 0;
582         lastPattern = TreeDestructuringPattern(0);
583         JSTokenLocation location(tokenLocation());
584         next();
585         TreeExpression node = 0;
586         declarations++;
587         bool hasInitializer = false;
588         if (match(IDENT) || isLETMaskedAsIDENT()) {
589             failIfTrue(match(LET) && (declarationType == DeclarationType::LetDeclaration || declarationType == DeclarationType::ConstDeclaration), 
590                 "Can't use 'let' as an identifier name for a LexicalDeclaration");
591             JSTextPosition varStart = tokenStartPosition();
592             JSTokenLocation varStartLocation(tokenLocation());
593             identStart = varStart;
594             const Identifier* name = m_token.m_data.ident;
595             lastIdent = name;
596             lastIdentToken = m_token;
597             next();
598             hasInitializer = match(EQUAL);
599             DeclarationResultMask declarationResult = declareVariable(name, declarationType);
600             if (declarationResult != DeclarationResult::Valid) {
601                 failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot declare a variable named ", name->impl(), " in strict mode");
602                 if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration) {
603                     if (declarationType == DeclarationType::LetDeclaration) 
604                         internalFailWithMessage(false, "Cannot declare a let variable twice: '", name->impl(), "'");
605                     if (declarationType == DeclarationType::ConstDeclaration)
606                         internalFailWithMessage(false, "Cannot declare a const variable twice: '", name->impl(), "'");
607                     ASSERT(declarationType == DeclarationType::VarDeclaration);
608                     internalFailWithMessage(false, "Cannot declare a var variable that shadows a let/const/class variable: '", name->impl(), "'");
609                 }
610             }
611             if (exportType == ExportType::Exported) {
612                 semanticFailIfFalse(exportName(*name), "Cannot export a duplicate name '", name->impl(), "'");
613                 currentScope()->moduleScopeData().exportBinding(*name);
614             }
615
616             if (hasInitializer) {
617                 JSTextPosition varDivot = tokenStartPosition() + 1;
618                 initStart = tokenStartPosition();
619                 next(TreeBuilder::DontBuildStrings); // consume '='
620                 TreeExpression initializer = parseAssignmentExpression(context);
621                 initEnd = lastTokenEndPosition();
622                 lastInitializer = initializer;
623                 failIfFalse(initializer, "Expected expression as the intializer for the variable '", name->impl(), "'");
624                 
625                 node = context.createAssignResolve(location, *name, initializer, varStart, varDivot, lastTokenEndPosition(), assignmentContext);
626             } else {
627                 if (declarationListContext == ForLoopContext && declarationType == DeclarationType::ConstDeclaration)
628                     forLoopConstDoesNotHaveInitializer = true;
629                 failIfTrue(declarationListContext != ForLoopContext && declarationType == DeclarationType::ConstDeclaration, "const declared variable '", name->impl(), "'", " must have an initializer");
630                 if (declarationType == DeclarationType::VarDeclaration)
631                     node = context.createEmptyVarExpression(varStartLocation, *name);
632                 else
633                     node = context.createEmptyLetExpression(varStartLocation, *name);
634             }
635         } else {
636             lastIdent = 0;
637             auto pattern = parseDestructuringPattern(context, destructuringKindFromDeclarationType(declarationType), exportType, nullptr, nullptr, assignmentContext);
638             failIfFalse(pattern, "Cannot parse this destructuring pattern");
639             hasInitializer = match(EQUAL);
640             failIfTrue(declarationListContext == VarDeclarationContext && !hasInitializer, "Expected an initializer in destructuring variable declaration");
641             lastPattern = pattern;
642             if (hasInitializer) {
643                 next(TreeBuilder::DontBuildStrings); // consume '='
644                 TreeExpression rhs = parseAssignmentExpression(context);
645                 node = context.createDestructuringAssignment(location, pattern, rhs);
646                 lastInitializer = rhs;
647             }
648         }
649         
650         if (!head)
651             head = node;
652         else if (!tail) {
653             head = context.createCommaExpr(location, head);
654             tail = context.appendToCommaExpr(location, head, head, node);
655         } else
656             tail = context.appendToCommaExpr(location, head, tail, node);
657     } while (match(COMMA));
658     if (lastIdent)
659         lastPattern = context.createBindingLocation(lastIdentToken.m_location, *lastIdent, lastIdentToken.m_startPosition, lastIdentToken.m_endPosition, assignmentContext);
660
661     return head;
662 }
663
664 template <typename LexerType>
665 template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::createBindingPattern(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier& name, int depth, JSToken token, AssignmentContext bindingContext, const Identifier** duplicateIdentifier)
666 {
667     ASSERT(!name.isNull());
668     
669     ASSERT(name.impl()->isAtomic() || name.impl()->isSymbol());
670
671     if (kind == DestructureToVariables) {
672         DeclarationResultMask declarationResult = declareVariable(&name);
673         failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot declare a variable named '", name.impl(), "' in strict mode");
674         if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration)
675             internalFailWithMessage(false, "Cannot declare a var variable that shadows a let/const/class variable: '", name.impl(), "'");
676     } else if (kind == DestructureToLet || kind == DestructureToConst) {
677         DeclarationResultMask declarationResult = declareVariable(&name, kind == DestructureToLet ? DeclarationType::LetDeclaration : DeclarationType::ConstDeclaration);
678         if (declarationResult != DeclarationResult::Valid) {
679             failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot destructure to a variable named '", name.impl(), "' in strict mode");
680             failIfTrue(declarationResult & DeclarationResult::InvalidDuplicateDeclaration, "Cannot declare a lexical variable twice: '", name.impl(), "'");
681         }
682     } else if (kind == DestructureToParameters) {
683         if (depth) {
684             auto bindingResult = declareBoundParameter(&name);
685             if (bindingResult == Scope::StrictBindingFailed && strictMode()) {
686                 semanticFailIfTrue(isEvalOrArguments(&name), "Cannot destructure to a parameter name '", name.impl(), "' in strict mode");
687                 if (m_lastFunctionName && name == *m_lastFunctionName)
688                     semanticFail("Cannot destructure to '", name.impl(), "' as it shadows the name of a strict mode function");
689                 semanticFailureDueToKeyword("bound parameter name");
690                 if (hasDeclaredParameter(name))
691                     semanticFail("Cannot destructure to '", name.impl(), "' as it has already been declared");
692                 semanticFail("Cannot bind to a parameter named '", name.impl(), "' in strict mode");
693             }
694             if (bindingResult == Scope::BindingFailed) {
695                 semanticFailureDueToKeyword("bound parameter name");
696                 if (hasDeclaredParameter(name))
697                     semanticFail("Cannot destructure to '", name.impl(), "' as it has already been declared");
698                 semanticFail("Cannot destructure to a parameter named '", name.impl(), "'");
699             }
700         } else {
701             DeclarationResultMask declarationResult = declareParameter(&name);
702             if ((declarationResult & DeclarationResult::InvalidStrictMode) && strictMode()) {
703                 semanticFailIfTrue(isEvalOrArguments(&name), "Cannot destructure to a parameter name '", name.impl(), "' in strict mode");
704                 if (m_lastFunctionName && name == *m_lastFunctionName)
705                     semanticFail("Cannot declare a parameter named '", name.impl(), "' as it shadows the name of a strict mode function");
706                 semanticFailureDueToKeyword("parameter name");
707                 if (hasDeclaredParameter(name))
708                     semanticFail("Cannot declare a parameter named '", name.impl(), "' in strict mode as it has already been declared");
709                 semanticFail("Cannot declare a parameter named '", name.impl(), "' in strict mode");
710             }
711             if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration) {
712                 // It's not always an error to define a duplicate parameter.
713                 // It's only an error when there are default parameter values or destructuring parameters.
714                 // We note this value now so we can check it later.
715                 if (duplicateIdentifier)
716                     *duplicateIdentifier = &name;
717             }
718         }
719     }
720
721     if (exportType == ExportType::Exported) {
722         semanticFailIfFalse(exportName(name), "Cannot export a duplicate name '", name.impl(), "'");
723         currentScope()->moduleScopeData().exportBinding(name);
724     }
725     return context.createBindingLocation(token.m_location, name, token.m_startPosition, token.m_endPosition, bindingContext);
726 }
727
728 template <typename LexerType>
729 template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseArrowFunctionSingleExpressionBodySourceElements(TreeBuilder& context)
730 {
731     ASSERT(!match(OPENBRACE));
732
733     JSTokenLocation location(tokenLocation());
734     JSTextPosition start = tokenStartPosition();
735
736     failIfStackOverflow();
737     TreeExpression expr = parseAssignmentExpression(context);
738     failIfFalse(expr, "Cannot parse the arrow function expression");
739     
740     context.setEndOffset(expr, m_lastTokenEndPosition.offset);
741
742     failIfFalse(isEndOfArrowFunction(), "Expected a ';', ']', '}', ')', ',', line terminator or EOF following a arrow function statement");
743
744     JSTextPosition end = tokenEndPosition();
745     
746     if (!m_lexer->prevTerminator())
747         setEndOfStatement();
748
749     TreeSourceElements sourceElements = context.createSourceElements();
750     TreeStatement body = context.createReturnStatement(location, expr, start, end);
751     context.setEndOffset(body, m_lastTokenEndPosition.offset);
752     context.appendStatement(sourceElements, body);
753
754     return sourceElements;
755 }
756
757 template <typename LexerType>
758 template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::tryParseDestructuringPatternExpression(TreeBuilder& context, AssignmentContext bindingContext)
759 {
760     return parseDestructuringPattern(context, DestructureToExpressions, ExportType::NotExported, nullptr, nullptr, bindingContext);
761 }
762
763 template <typename LexerType>
764 template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseDestructuringPattern(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth)
765 {
766     failIfStackOverflow();
767     int nonLHSCount = m_nonLHSCount;
768     TreeDestructuringPattern pattern;
769     switch (m_token.m_type) {
770     case OPENBRACKET: {
771         JSTextPosition divotStart = tokenStartPosition();
772         auto arrayPattern = context.createArrayPattern(m_token.m_location);
773         next();
774
775         if (hasDestructuringPattern)
776             *hasDestructuringPattern = true;
777
778         bool restElementWasFound = false;
779
780         do {
781             while (match(COMMA)) {
782                 context.appendArrayPatternSkipEntry(arrayPattern, m_token.m_location);
783                 next();
784             }
785             propagateError();
786
787             if (match(CLOSEBRACKET))
788                 break;
789
790             if (UNLIKELY(match(DOTDOTDOT))) {
791                 JSTokenLocation location = m_token.m_location;
792                 next();
793                 auto innerPattern = parseDestructuringPattern(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
794                 if (kind == DestructureToExpressions && !innerPattern)
795                     return 0;
796                 failIfFalse(innerPattern, "Cannot parse this destructuring pattern");
797
798                 failIfTrue(kind != DestructureToExpressions && !context.isBindingNode(innerPattern),  "Expected identifier for a rest element destructuring pattern");
799
800                 context.appendArrayPatternRestEntry(arrayPattern, location, innerPattern);
801                 restElementWasFound = true;
802                 break;
803             }
804
805             JSTokenLocation location = m_token.m_location;
806             auto innerPattern = parseDestructuringPattern(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
807             if (kind == DestructureToExpressions && !innerPattern)
808                 return 0;
809             failIfFalse(innerPattern, "Cannot parse this destructuring pattern");
810             TreeExpression defaultValue = parseDefaultValueForDestructuringPattern(context);
811             context.appendArrayPatternEntry(arrayPattern, location, innerPattern, defaultValue);
812         } while (consume(COMMA));
813
814         if (kind == DestructureToExpressions && !match(CLOSEBRACKET))
815             return 0;
816         consumeOrFail(CLOSEBRACKET, restElementWasFound ? "Expected a closing ']' following a rest element destructuring pattern" : "Expected either a closing ']' or a ',' following an element destructuring pattern");
817         context.finishArrayPattern(arrayPattern, divotStart, divotStart, lastTokenEndPosition());
818         pattern = arrayPattern;
819         break;
820     }
821     case OPENBRACE: {
822         auto objectPattern = context.createObjectPattern(m_token.m_location);
823         next();
824
825         if (hasDestructuringPattern)
826             *hasDestructuringPattern = true;
827
828         do {
829             bool wasString = false;
830
831             if (match(CLOSEBRACE))
832                 break;
833
834             const Identifier* propertyName = nullptr;
835             TreeDestructuringPattern innerPattern = 0;
836             JSTokenLocation location = m_token.m_location;
837             if (match(IDENT) || isLETMaskedAsIDENT()) {
838                 failIfTrue(match(LET) && (kind == DestructureToLet || kind == DestructureToConst), "Can't use 'let' as an identifier name for a LexicalDeclaration");
839                 propertyName = m_token.m_data.ident;
840                 JSToken identifierToken = m_token;
841                 next();
842                 if (consume(COLON))
843                     innerPattern = parseDestructuringPattern(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
844                 else
845                     innerPattern = createBindingPattern(context, kind, exportType, *propertyName, depth + 1, identifierToken, bindingContext, duplicateIdentifier);
846             } else {
847                 JSTokenType tokenType = m_token.m_type;
848                 switch (m_token.m_type) {
849                 case DOUBLE:
850                 case INTEGER:
851                     propertyName = &m_parserArena.identifierArena().makeNumericIdentifier(const_cast<VM*>(m_vm), m_token.m_data.doubleValue);
852                     break;
853                 case STRING:
854                     propertyName = m_token.m_data.ident;
855                     wasString = true;
856                     break;
857                 default:
858                     if (m_token.m_type != RESERVED && m_token.m_type != RESERVED_IF_STRICT && !(m_token.m_type & KeywordTokenFlag)) {
859                         if (kind == DestructureToExpressions)
860                             return 0;
861                         failWithMessage("Expected a property name");
862                     }
863                     propertyName = m_token.m_data.ident;
864                     break;
865                 }
866                 next();
867                 if (!consume(COLON)) {
868                     if (kind == DestructureToExpressions)
869                         return 0;
870                     semanticFailIfTrue(tokenType == RESERVED, "Cannot use abbreviated destructuring syntax for reserved name '", propertyName->impl(), "'");
871                     semanticFailIfTrue(tokenType == RESERVED_IF_STRICT, "Cannot use abbreviated destructuring syntax for reserved name '", propertyName->impl(), "' in strict mode");
872                     semanticFailIfTrue(tokenType & KeywordTokenFlag, "Cannot use abbreviated destructuring syntax for keyword '", propertyName->impl(), "'");
873                     
874                     failWithMessage("Expected a ':' prior to a named destructuring property");
875                 }
876                 innerPattern = parseDestructuringPattern(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
877             }
878             if (kind == DestructureToExpressions && !innerPattern)
879                 return 0;
880             failIfFalse(innerPattern, "Cannot parse this destructuring pattern");
881             TreeExpression defaultValue = parseDefaultValueForDestructuringPattern(context);
882             ASSERT(propertyName);
883             context.appendObjectPatternEntry(objectPattern, location, wasString, *propertyName, innerPattern, defaultValue);
884         } while (consume(COMMA));
885
886         if (kind == DestructureToExpressions && !match(CLOSEBRACE))
887             return 0;
888         consumeOrFail(CLOSEBRACE, "Expected either a closing '}' or an ',' after a property destructuring pattern");
889         pattern = objectPattern;
890         break;
891     }
892
893     default: {
894         if (!match(IDENT) && !isLETMaskedAsIDENT()) {
895             if (kind == DestructureToExpressions)
896                 return 0;
897             semanticFailureDueToKeyword("variable name");
898             failWithMessage("Expected a parameter pattern or a ')' in parameter list");
899         }
900         failIfTrue(match(LET) && (kind == DestructureToLet || kind == DestructureToConst), "Can't use 'let' as an identifier name for a LexicalDeclaration");
901         pattern = createBindingPattern(context, kind, exportType, *m_token.m_data.ident, depth, m_token, bindingContext, duplicateIdentifier);
902         next();
903         break;
904     }
905     }
906     m_nonLHSCount = nonLHSCount;
907     return pattern;
908 }
909
910 template <typename LexerType>
911 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseDefaultValueForDestructuringPattern(TreeBuilder& context)
912 {
913     if (!match(EQUAL))
914         return 0;
915
916     next(TreeBuilder::DontBuildStrings); // consume '='
917     return parseAssignmentExpression(context);
918 }
919
920 template <typename LexerType>
921 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseForStatement(TreeBuilder& context)
922 {
923     ASSERT(match(FOR));
924     JSTokenLocation location(tokenLocation());
925     int startLine = tokenLine();
926     next();
927     handleProductionOrFail(OPENPAREN, "(", "start", "for-loop header");
928     int nonLHSCount = m_nonLHSCount;
929     int declarations = 0;
930     JSTextPosition declsStart;
931     JSTextPosition declsEnd;
932     TreeExpression decls = 0;
933     TreeDestructuringPattern pattern = 0;
934     bool isVarDeclaraton = match(VAR);
935     bool isLetDeclaration = match(LET);
936     bool isConstDeclaration = match(CONSTTOKEN);
937     bool forLoopConstDoesNotHaveInitializer = false;
938
939     VariableEnvironment dummySet;
940     VariableEnvironment* lexicalVariables = nullptr;
941     AutoCleanupLexicalScope lexicalScope;
942
943     auto gatherLexicalVariablesIfNecessary = [&] {
944         if (isLetDeclaration || isConstDeclaration) {
945             ScopeRef scope = lexicalScope.scope();
946             lexicalVariables = &scope->finalizeLexicalEnvironment();
947         } else
948             lexicalVariables = &dummySet;
949     };
950
951     auto popLexicalScopeIfNecessary = [&] {
952         if (isLetDeclaration || isConstDeclaration)
953             popScope(lexicalScope, TreeBuilder::NeedsFreeVariableInfo);
954     };
955
956     if (isVarDeclaraton || isLetDeclaration || isConstDeclaration) {
957         /*
958          for (var/let/const IDENT in/of expression) statement
959          for (var/let/const varDeclarationList; expressionOpt; expressionOpt)
960          */
961         if (isLetDeclaration || isConstDeclaration) {
962             ScopeRef newScope = pushScope();
963             newScope->setIsLexicalScope();
964             newScope->preventVarDeclarations();
965             lexicalScope.setIsValid(newScope, this);
966         }
967
968         TreeDestructuringPattern forInTarget = 0;
969         TreeExpression forInInitializer = 0;
970         m_allowsIn = false;
971         JSTextPosition initStart;
972         JSTextPosition initEnd;
973         DeclarationType declarationType;
974         if (isVarDeclaraton)
975             declarationType = DeclarationType::VarDeclaration;
976         else if (isLetDeclaration)
977             declarationType = DeclarationType::LetDeclaration;
978         else if (isConstDeclaration)
979             declarationType = DeclarationType::ConstDeclaration;
980         else
981             RELEASE_ASSERT_NOT_REACHED();
982         decls = parseVariableDeclarationList(context, declarations, forInTarget, forInInitializer, declsStart, initStart, initEnd, ForLoopContext, declarationType, ExportType::NotExported, forLoopConstDoesNotHaveInitializer);
983         m_allowsIn = true;
984         propagateError();
985
986         // Remainder of a standard for loop is handled identically
987         if (match(SEMICOLON))
988             goto standardForLoop;
989         
990         failIfFalse(declarations == 1, "can only declare a single variable in an enumeration");
991         failIfTrueIfStrict(forInInitializer, "Cannot use initialiser syntax in a strict mode enumeration");
992
993         if (forInInitializer)
994             failIfFalse(context.isBindingNode(forInTarget), "Cannot use initialiser syntax when binding to a pattern during enumeration");
995
996         // Handle for-in with var declaration
997         JSTextPosition inLocation = tokenStartPosition();
998         bool isOfEnumeration = false;
999         if (!consume(INTOKEN)) {
1000             failIfFalse(match(IDENT) && *m_token.m_data.ident == m_vm->propertyNames->of, "Expected either 'in' or 'of' in enumeration syntax");
1001             isOfEnumeration = true;
1002             failIfTrue(forInInitializer, "Cannot use initialiser syntax in a for-of enumeration");
1003             next();
1004         }
1005         TreeExpression expr = parseExpression(context);
1006         failIfFalse(expr, "Expected expression to enumerate");
1007         JSTextPosition exprEnd = lastTokenEndPosition();
1008         
1009         int endLine = tokenLine();
1010         
1011         handleProductionOrFail(CLOSEPAREN, ")", "end", (isOfEnumeration ? "for-of header" : "for-in header"));
1012         
1013         const Identifier* unused = 0;
1014         startLoop();
1015         TreeStatement statement = parseStatement(context, unused);
1016         endLoop();
1017         failIfFalse(statement, "Expected statement as body of for-", isOfEnumeration ? "of" : "in", " statement");
1018         gatherLexicalVariablesIfNecessary();
1019         TreeStatement result;
1020         if (isOfEnumeration)
1021             result = context.createForOfLoop(location, forInTarget, expr, statement, declsStart, inLocation, exprEnd, startLine, endLine, *lexicalVariables);
1022         else
1023             result = context.createForInLoop(location, forInTarget, expr, statement, declsStart, inLocation, exprEnd, startLine, endLine, *lexicalVariables);
1024         popLexicalScopeIfNecessary();
1025         return result;
1026     }
1027     
1028     if (!match(SEMICOLON)) {
1029         if (match(OPENBRACE) || match(OPENBRACKET)) {
1030             SavePoint savePoint = createSavePoint();
1031             declsStart = tokenStartPosition();
1032             pattern = tryParseDestructuringPatternExpression(context, AssignmentContext::DeclarationStatement);
1033             declsEnd = lastTokenEndPosition();
1034             if (pattern && (match(INTOKEN) || (match(IDENT) && *m_token.m_data.ident == m_vm->propertyNames->of)))
1035                 goto enumerationLoop;
1036             pattern = TreeDestructuringPattern(0);
1037             restoreSavePoint(savePoint);
1038         }
1039         m_allowsIn = false;
1040         declsStart = tokenStartPosition();
1041         decls = parseExpression(context);
1042         declsEnd = lastTokenEndPosition();
1043         m_allowsIn = true;
1044         failIfFalse(decls, "Cannot parse for loop declarations");
1045     }
1046     
1047     if (match(SEMICOLON)) {
1048     standardForLoop:
1049         // Standard for loop
1050         next();
1051         TreeExpression condition = 0;
1052         failIfTrue(forLoopConstDoesNotHaveInitializer && isConstDeclaration, "const variables in for loops must have initializers");
1053         
1054         if (!match(SEMICOLON)) {
1055             condition = parseExpression(context);
1056             failIfFalse(condition, "Cannot parse for loop condition expression");
1057         }
1058         consumeOrFail(SEMICOLON, "Expected a ';' after the for loop condition expression");
1059         
1060         TreeExpression increment = 0;
1061         if (!match(CLOSEPAREN)) {
1062             increment = parseExpression(context);
1063             failIfFalse(increment, "Cannot parse for loop iteration expression");
1064         }
1065         int endLine = tokenLine();
1066         handleProductionOrFail(CLOSEPAREN, ")", "end", "for-loop header");
1067         const Identifier* unused = 0;
1068         startLoop();
1069         TreeStatement statement = parseStatement(context, unused);
1070         endLoop();
1071         failIfFalse(statement, "Expected a statement as the body of a for loop");
1072         gatherLexicalVariablesIfNecessary();
1073         TreeStatement result = context.createForLoop(location, decls, condition, increment, statement, startLine, endLine, *lexicalVariables);
1074         popLexicalScopeIfNecessary();
1075         return result;
1076     }
1077     
1078     // For-in and For-of loop
1079 enumerationLoop:
1080     failIfFalse(nonLHSCount == m_nonLHSCount, "Expected a reference on the left hand side of an enumeration statement");
1081     bool isOfEnumeration = false;
1082     if (!consume(INTOKEN)) {
1083         failIfFalse(match(IDENT) && *m_token.m_data.ident == m_vm->propertyNames->of, "Expected either 'in' or 'of' in enumeration syntax");
1084         isOfEnumeration = true;
1085         next();
1086     }
1087     TreeExpression expr = parseExpression(context);
1088     failIfFalse(expr, "Cannot parse subject for-", isOfEnumeration ? "of" : "in", " statement");
1089     JSTextPosition exprEnd = lastTokenEndPosition();
1090     int endLine = tokenLine();
1091     
1092     handleProductionOrFail(CLOSEPAREN, ")", "end", (isOfEnumeration ? "for-of header" : "for-in header"));
1093     const Identifier* unused = 0;
1094     startLoop();
1095     TreeStatement statement = parseStatement(context, unused);
1096     endLoop();
1097     failIfFalse(statement, "Expected a statement as the body of a for-", isOfEnumeration ? "of" : "in", "loop");
1098     gatherLexicalVariablesIfNecessary();
1099     TreeStatement result;
1100     if (pattern) {
1101         ASSERT(!decls);
1102         if (isOfEnumeration)
1103             result = context.createForOfLoop(location, pattern, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
1104         else 
1105             result = context.createForInLoop(location, pattern, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
1106
1107         popLexicalScopeIfNecessary();
1108         return result;
1109     }
1110     if (isOfEnumeration)
1111         result = context.createForOfLoop(location, decls, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
1112     else
1113         result = context.createForInLoop(location, decls, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
1114     popLexicalScopeIfNecessary();
1115     return result;
1116 }
1117
1118 template <typename LexerType>
1119 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBreakStatement(TreeBuilder& context)
1120 {
1121     ASSERT(match(BREAK));
1122     JSTokenLocation location(tokenLocation());
1123     JSTextPosition start = tokenStartPosition();
1124     JSTextPosition end = tokenEndPosition();
1125     next();
1126     
1127     if (autoSemiColon()) {
1128         semanticFailIfFalse(breakIsValid(), "'break' is only valid inside a switch or loop statement");
1129         return context.createBreakStatement(location, &m_vm->propertyNames->nullIdentifier, start, end);
1130     }
1131     failIfFalse(match(IDENT) || isLETMaskedAsIDENT(), "Expected an identifier as the target for a break statement");
1132     const Identifier* ident = m_token.m_data.ident;
1133     semanticFailIfFalse(getLabel(ident), "Cannot use the undeclared label '", ident->impl(), "'");
1134     end = tokenEndPosition();
1135     next();
1136     failIfFalse(autoSemiColon(), "Expected a ';' following a targeted break statement");
1137     return context.createBreakStatement(location, ident, start, end);
1138 }
1139
1140 template <typename LexerType>
1141 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseContinueStatement(TreeBuilder& context)
1142 {
1143     ASSERT(match(CONTINUE));
1144     JSTokenLocation location(tokenLocation());
1145     JSTextPosition start = tokenStartPosition();
1146     JSTextPosition end = tokenEndPosition();
1147     next();
1148     
1149     if (autoSemiColon()) {
1150         semanticFailIfFalse(continueIsValid(), "'continue' is only valid inside a loop statement");
1151         return context.createContinueStatement(location, &m_vm->propertyNames->nullIdentifier, start, end);
1152     }
1153     failIfFalse(match(IDENT) || isLETMaskedAsIDENT(), "Expected an identifier as the target for a continue statement");
1154     const Identifier* ident = m_token.m_data.ident;
1155     ScopeLabelInfo* label = getLabel(ident);
1156     semanticFailIfFalse(label, "Cannot use the undeclared label '", ident->impl(), "'");
1157     semanticFailIfFalse(label->isLoop, "Cannot continue to the label '", ident->impl(), "' as it is not targeting a loop");
1158     end = tokenEndPosition();
1159     next();
1160     failIfFalse(autoSemiColon(), "Expected a ';' following a targeted continue statement");
1161     return context.createContinueStatement(location, ident, start, end);
1162 }
1163
1164 template <typename LexerType>
1165 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseReturnStatement(TreeBuilder& context)
1166 {
1167     ASSERT(match(RETURN));
1168     JSTokenLocation location(tokenLocation());
1169     semanticFailIfFalse(currentScope()->isFunction(), "Return statements are only valid inside functions");
1170     JSTextPosition start = tokenStartPosition();
1171     JSTextPosition end = tokenEndPosition();
1172     next();
1173     // We do the auto semicolon check before attempting to parse expression
1174     // as we need to ensure the a line break after the return correctly terminates
1175     // the statement
1176     if (match(SEMICOLON))
1177         end = tokenEndPosition();
1178
1179     if (autoSemiColon())
1180         return context.createReturnStatement(location, 0, start, end);
1181     TreeExpression expr = parseExpression(context);
1182     failIfFalse(expr, "Cannot parse the return expression");
1183     end = lastTokenEndPosition();
1184     if (match(SEMICOLON))
1185         end  = tokenEndPosition();
1186     if (!autoSemiColon())
1187         failWithMessage("Expected a ';' following a return statement");
1188     return context.createReturnStatement(location, expr, start, end);
1189 }
1190
1191 template <typename LexerType>
1192 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseThrowStatement(TreeBuilder& context)
1193 {
1194     ASSERT(match(THROW));
1195     JSTokenLocation location(tokenLocation());
1196     JSTextPosition start = tokenStartPosition();
1197     next();
1198     failIfTrue(match(SEMICOLON), "Expected expression after 'throw'");
1199     semanticFailIfTrue(autoSemiColon(), "Cannot have a newline after 'throw'");
1200     
1201     TreeExpression expr = parseExpression(context);
1202     failIfFalse(expr, "Cannot parse expression for throw statement");
1203     JSTextPosition end = lastTokenEndPosition();
1204     failIfFalse(autoSemiColon(), "Expected a ';' after a throw statement");
1205     
1206     return context.createThrowStatement(location, expr, start, end);
1207 }
1208
1209 template <typename LexerType>
1210 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWithStatement(TreeBuilder& context)
1211 {
1212     ASSERT(match(WITH));
1213     JSTokenLocation location(tokenLocation());
1214     semanticFailIfTrue(strictMode(), "'with' statements are not valid in strict mode");
1215     currentScope()->setNeedsFullActivation();
1216     int startLine = tokenLine();
1217     next();
1218
1219     handleProductionOrFail(OPENPAREN, "(", "start", "subject of a 'with' statement");
1220     int start = tokenStart();
1221     TreeExpression expr = parseExpression(context);
1222     failIfFalse(expr, "Cannot parse 'with' subject expression");
1223     JSTextPosition end = lastTokenEndPosition();
1224     int endLine = tokenLine();
1225     handleProductionOrFail(CLOSEPAREN, ")", "start", "subject of a 'with' statement");
1226     const Identifier* unused = 0;
1227     TreeStatement statement = parseStatement(context, unused);
1228     failIfFalse(statement, "A 'with' statement must have a body");
1229     
1230     return context.createWithStatement(location, expr, statement, start, end, startLine, endLine);
1231 }
1232
1233 template <typename LexerType>
1234 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseSwitchStatement(TreeBuilder& context)
1235 {
1236     ASSERT(match(SWITCH));
1237     JSTokenLocation location(tokenLocation());
1238     int startLine = tokenLine();
1239     next();
1240     handleProductionOrFail(OPENPAREN, "(", "start", "subject of a 'switch'");
1241     TreeExpression expr = parseExpression(context);
1242     failIfFalse(expr, "Cannot parse switch subject expression");
1243     int endLine = tokenLine();
1244     
1245     handleProductionOrFail(CLOSEPAREN, ")", "end", "subject of a 'switch'");
1246     handleProductionOrFail(OPENBRACE, "{", "start", "body of a 'switch'");
1247     AutoPopScopeRef lexicalScope(this, pushScope());
1248     lexicalScope->setIsLexicalScope();
1249     lexicalScope->preventVarDeclarations();
1250     startSwitch();
1251     TreeClauseList firstClauses = parseSwitchClauses(context);
1252     propagateError();
1253     
1254     TreeClause defaultClause = parseSwitchDefaultClause(context);
1255     propagateError();
1256     
1257     TreeClauseList secondClauses = parseSwitchClauses(context);
1258     propagateError();
1259     endSwitch();
1260     handleProductionOrFail(CLOSEBRACE, "}", "end", "body of a 'switch'");
1261     
1262     TreeStatement result = context.createSwitchStatement(location, expr, firstClauses, defaultClause, secondClauses, startLine, endLine, lexicalScope->finalizeLexicalEnvironment());
1263     popScope(lexicalScope, TreeBuilder::NeedsFreeVariableInfo);
1264     return result;
1265 }
1266
1267 template <typename LexerType>
1268 template <class TreeBuilder> TreeClauseList Parser<LexerType>::parseSwitchClauses(TreeBuilder& context)
1269 {
1270     if (!match(CASE))
1271         return 0;
1272     unsigned startOffset = tokenStart();
1273     next();
1274     TreeExpression condition = parseExpression(context);
1275     failIfFalse(condition, "Cannot parse switch clause");
1276     consumeOrFail(COLON, "Expected a ':' after switch clause expression");
1277     TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode);
1278     failIfFalse(statements, "Cannot parse the body of a switch clause");
1279     TreeClause clause = context.createClause(condition, statements);
1280     context.setStartOffset(clause, startOffset);
1281     TreeClauseList clauseList = context.createClauseList(clause);
1282     TreeClauseList tail = clauseList;
1283     
1284     while (match(CASE)) {
1285         startOffset = tokenStart();
1286         next();
1287         TreeExpression condition = parseExpression(context);
1288         failIfFalse(condition, "Cannot parse switch case expression");
1289         consumeOrFail(COLON, "Expected a ':' after switch clause expression");
1290         TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode);
1291         failIfFalse(statements, "Cannot parse the body of a switch clause");
1292         clause = context.createClause(condition, statements);
1293         context.setStartOffset(clause, startOffset);
1294         tail = context.createClauseList(tail, clause);
1295     }
1296     return clauseList;
1297 }
1298
1299 template <typename LexerType>
1300 template <class TreeBuilder> TreeClause Parser<LexerType>::parseSwitchDefaultClause(TreeBuilder& context)
1301 {
1302     if (!match(DEFAULT))
1303         return 0;
1304     unsigned startOffset = tokenStart();
1305     next();
1306     consumeOrFail(COLON, "Expected a ':' after switch default clause");
1307     TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode);
1308     failIfFalse(statements, "Cannot parse the body of a switch default clause");
1309     TreeClause result = context.createClause(0, statements);
1310     context.setStartOffset(result, startOffset);
1311     return result;
1312 }
1313
1314 template <typename LexerType>
1315 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseTryStatement(TreeBuilder& context)
1316 {
1317     ASSERT(match(TRY));
1318     JSTokenLocation location(tokenLocation());
1319     TreeStatement tryBlock = 0;
1320     const Identifier* ident = &m_vm->propertyNames->nullIdentifier;
1321     TreeStatement catchBlock = 0;
1322     TreeStatement finallyBlock = 0;
1323     int firstLine = tokenLine();
1324     next();
1325     matchOrFail(OPENBRACE, "Expected a block statement as body of a try statement");
1326     
1327     tryBlock = parseBlockStatement(context);
1328     failIfFalse(tryBlock, "Cannot parse the body of try block");
1329     int lastLine = m_lastTokenEndPosition.line;
1330     VariableEnvironment catchEnvironment; 
1331     if (match(CATCH)) {
1332         next();
1333         
1334         handleProductionOrFail(OPENPAREN, "(", "start", "'catch' target");
1335         if (!(match(IDENT) || isLETMaskedAsIDENT())) {
1336             semanticFailureDueToKeyword("catch variable name");
1337             failWithMessage("Expected identifier name as catch target");
1338         }
1339         ident = m_token.m_data.ident;
1340         next();
1341         AutoPopScopeRef catchScope(this, pushScope());
1342         catchScope->setIsLexicalScope();
1343         catchScope->preventVarDeclarations();
1344         failIfTrueIfStrict(catchScope->declareLexicalVariable(ident, false) & DeclarationResult::InvalidStrictMode, "Cannot declare a catch variable named '", ident->impl(), "' in strict mode");
1345         handleProductionOrFail(CLOSEPAREN, ")", "end", "'catch' target");
1346         matchOrFail(OPENBRACE, "Expected exception handler to be a block statement");
1347         catchBlock = parseBlockStatement(context);
1348         failIfFalse(catchBlock, "Unable to parse 'catch' block");
1349         catchEnvironment = catchScope->finalizeLexicalEnvironment();
1350         RELEASE_ASSERT(catchEnvironment.size() == 1 && catchEnvironment.contains(ident->impl()));
1351         popScope(catchScope, TreeBuilder::NeedsFreeVariableInfo);
1352     }
1353     
1354     if (match(FINALLY)) {
1355         next();
1356         matchOrFail(OPENBRACE, "Expected block statement for finally body");
1357         finallyBlock = parseBlockStatement(context);
1358         failIfFalse(finallyBlock, "Cannot parse finally body");
1359     }
1360     failIfFalse(catchBlock || finallyBlock, "Try statements must have at least a catch or finally block");
1361     return context.createTryStatement(location, tryBlock, ident, catchBlock, finallyBlock, firstLine, lastLine, catchEnvironment);
1362 }
1363
1364 template <typename LexerType>
1365 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseDebuggerStatement(TreeBuilder& context)
1366 {
1367     ASSERT(match(DEBUGGER));
1368     JSTokenLocation location(tokenLocation());
1369     int startLine = tokenLine();
1370     int endLine = startLine;
1371     next();
1372     if (match(SEMICOLON))
1373         startLine = tokenLine();
1374     failIfFalse(autoSemiColon(), "Debugger keyword must be followed by a ';'");
1375     return context.createDebugger(location, startLine, endLine);
1376 }
1377
1378 template <typename LexerType>
1379 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBlockStatement(TreeBuilder& context)
1380 {
1381     ASSERT(match(OPENBRACE));
1382
1383     // We should treat the first block statement of the function (the body of the function) as the lexical 
1384     // scope of the function itself, and not the lexical scope of a 'block' statement within the function.
1385     AutoCleanupLexicalScope lexicalScope;
1386     bool shouldPushLexicalScope = m_statementDepth > 0;
1387     if (shouldPushLexicalScope) {
1388         ScopeRef newScope = pushScope();
1389         newScope->setIsLexicalScope();
1390         newScope->preventVarDeclarations();
1391         lexicalScope.setIsValid(newScope, this);
1392     }
1393     JSTokenLocation location(tokenLocation());
1394     int startOffset = m_token.m_data.offset;
1395     int start = tokenLine();
1396     VariableEnvironment emptyEnvironment;
1397     next();
1398     if (match(CLOSEBRACE)) {
1399         int endOffset = m_token.m_data.offset;
1400         next();
1401         TreeStatement result = context.createBlockStatement(location, 0, start, m_lastTokenEndPosition.line, shouldPushLexicalScope ? currentScope()->finalizeLexicalEnvironment() : emptyEnvironment);
1402         context.setStartOffset(result, startOffset);
1403         context.setEndOffset(result, endOffset);
1404         if (shouldPushLexicalScope)
1405             popScope(lexicalScope, TreeBuilder::NeedsFreeVariableInfo);
1406         return result;
1407     }
1408     TreeSourceElements subtree = parseSourceElements(context, DontCheckForStrictMode);
1409     failIfFalse(subtree, "Cannot parse the body of the block statement");
1410     matchOrFail(CLOSEBRACE, "Expected a closing '}' at the end of a block statement");
1411     int endOffset = m_token.m_data.offset;
1412     next();
1413     TreeStatement result = context.createBlockStatement(location, subtree, start, m_lastTokenEndPosition.line, shouldPushLexicalScope ? currentScope()->finalizeLexicalEnvironment() : emptyEnvironment);
1414     context.setStartOffset(result, startOffset);
1415     context.setEndOffset(result, endOffset);
1416     if (shouldPushLexicalScope)
1417         popScope(lexicalScope, TreeBuilder::NeedsFreeVariableInfo);
1418
1419     return result;
1420 }
1421
1422 template <typename LexerType>
1423 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseStatement(TreeBuilder& context, const Identifier*& directive, unsigned* directiveLiteralLength)
1424 {
1425     DepthManager statementDepth(&m_statementDepth);
1426     m_statementDepth++;
1427     directive = 0;
1428     int nonTrivialExpressionCount = 0;
1429     failIfStackOverflow();
1430     TreeStatement result = 0;
1431     bool shouldSetEndOffset = true;
1432
1433     switch (m_token.m_type) {
1434     case OPENBRACE:
1435         result = parseBlockStatement(context);
1436         shouldSetEndOffset = false;
1437         break;
1438     case VAR:
1439         result = parseVariableDeclaration(context, DeclarationType::VarDeclaration);
1440         break;
1441     case FUNCTION:
1442         failIfFalseIfStrict(m_statementDepth == 1, "Strict mode does not allow function declarations in a lexically nested statement");
1443         result = parseFunctionDeclaration(context);
1444         break;
1445     case SEMICOLON: {
1446         JSTokenLocation location(tokenLocation());
1447         next();
1448         result = context.createEmptyStatement(location);
1449         break;
1450     }
1451     case IF:
1452         result = parseIfStatement(context);
1453         break;
1454     case DO:
1455         result = parseDoWhileStatement(context);
1456         break;
1457     case WHILE:
1458         result = parseWhileStatement(context);
1459         break;
1460     case FOR:
1461         result = parseForStatement(context);
1462         break;
1463     case CONTINUE:
1464         result = parseContinueStatement(context);
1465         break;
1466     case BREAK:
1467         result = parseBreakStatement(context);
1468         break;
1469     case RETURN:
1470         result = parseReturnStatement(context);
1471         break;
1472     case WITH:
1473         result = parseWithStatement(context);
1474         break;
1475     case SWITCH:
1476         result = parseSwitchStatement(context);
1477         break;
1478     case THROW:
1479         result = parseThrowStatement(context);
1480         break;
1481     case TRY:
1482         result = parseTryStatement(context);
1483         break;
1484     case DEBUGGER:
1485         result = parseDebuggerStatement(context);
1486         break;
1487     case EOFTOK:
1488     case CASE:
1489     case CLOSEBRACE:
1490     case DEFAULT:
1491         // These tokens imply the end of a set of source elements
1492         return 0;
1493     case IDENT:
1494         result = parseExpressionOrLabelStatement(context);
1495         break;
1496     case STRING:
1497         directive = m_token.m_data.ident;
1498         if (directiveLiteralLength)
1499             *directiveLiteralLength = m_token.m_location.endOffset - m_token.m_location.startOffset;
1500         nonTrivialExpressionCount = m_nonTrivialExpressionCount;
1501         FALLTHROUGH;
1502     default:
1503         TreeStatement exprStatement = parseExpressionStatement(context);
1504         if (directive && nonTrivialExpressionCount != m_nonTrivialExpressionCount)
1505             directive = 0;
1506         result = exprStatement;
1507         break;
1508     }
1509
1510     if (result && shouldSetEndOffset)
1511         context.setEndOffset(result, m_lastTokenEndPosition.offset);
1512     return result;
1513 }
1514
1515 template <typename LexerType>
1516 template <class TreeBuilder> bool Parser<LexerType>::parseFormalParameters(TreeBuilder& context, TreeFormalParameterList list, unsigned& parameterCount)
1517 {
1518 #define failFromDuplicate() \
1519     if (duplicateParameter) {\
1520         semanticFailIfTrue(defaultValue, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in function with default parameter values");\
1521         semanticFailIfTrue(hasDestructuringPattern, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in function with destructuring parameters");\
1522     }
1523
1524     const Identifier* duplicateParameter = nullptr;
1525     bool hasDestructuringPattern = false;
1526     auto parameter = parseDestructuringPattern(context, DestructureToParameters, ExportType::NotExported, &duplicateParameter, &hasDestructuringPattern);
1527     failIfFalse(parameter, "Cannot parse parameter pattern");
1528     auto defaultValue = parseDefaultValueForDestructuringPattern(context);
1529     propagateError();
1530     failFromDuplicate();
1531     context.appendParameter(list, parameter, defaultValue);
1532     parameterCount++;
1533     while (consume(COMMA)) {
1534         parameter = parseDestructuringPattern(context, DestructureToParameters, ExportType::NotExported, &duplicateParameter, &hasDestructuringPattern);
1535         failIfFalse(parameter, "Cannot parse parameter pattern");
1536         defaultValue = parseDefaultValueForDestructuringPattern(context);
1537         propagateError();
1538         failFromDuplicate();
1539         context.appendParameter(list, parameter, defaultValue);
1540         parameterCount++;
1541     }
1542     return true;
1543 #undef failFromDuplicate
1544 }
1545
1546 template <typename LexerType>
1547 template <class TreeBuilder> TreeFunctionBody Parser<LexerType>::parseFunctionBody(
1548     TreeBuilder& context, const JSTokenLocation& startLocation, int startColumn, int functionKeywordStart, int functionNameStart, int parametersStart, 
1549     ConstructorKind constructorKind, FunctionBodyType bodyType, unsigned parameterCount, SourceParseMode parseMode)
1550 {
1551     bool isArrowFunction = FunctionBodyType::StandardFunctionBodyBlock != bodyType;
1552     bool isArrowFunctionBodyExpression = bodyType == ArrowFunctionBodyExpression;
1553     if (!isArrowFunctionBodyExpression) {
1554         next();
1555         if (match(CLOSEBRACE)) {
1556             unsigned endColumn = tokenColumn();
1557             return context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind, parameterCount, parseMode, isArrowFunction, isArrowFunctionBodyExpression);
1558         }
1559     }
1560
1561     DepthManager statementDepth(&m_statementDepth);
1562     m_statementDepth = 0;
1563     SyntaxChecker syntaxChecker(const_cast<VM*>(m_vm), m_lexer.get());
1564     if (bodyType == ArrowFunctionBodyExpression)
1565         failIfFalse(parseArrowFunctionSingleExpressionBodySourceElements(syntaxChecker), "Cannot parse body of this arrow function");
1566     else
1567         failIfFalse(parseSourceElements(syntaxChecker, CheckForStrictMode), bodyType == StandardFunctionBodyBlock ? "Cannot parse body of this function" : "Cannot parse body of this arrow function");
1568     unsigned endColumn = tokenColumn();
1569     return context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind, parameterCount, parseMode, isArrowFunction, isArrowFunctionBodyExpression);
1570 }
1571
1572 static const char* stringForFunctionMode(SourceParseMode mode)
1573 {
1574     switch (mode) {
1575     case SourceParseMode::GetterMode:
1576         return "getter";
1577     case SourceParseMode::SetterMode:
1578         return "setter";
1579     case SourceParseMode::NormalFunctionMode:
1580         return "function";
1581     case SourceParseMode::MethodMode:
1582         return "method";
1583     case SourceParseMode::ArrowFunctionMode:
1584         return "arrow function";
1585     case SourceParseMode::ProgramMode:
1586     case SourceParseMode::ModuleAnalyzeMode:
1587     case SourceParseMode::ModuleEvaluateMode:
1588         RELEASE_ASSERT_NOT_REACHED();
1589         return "";
1590     }
1591     RELEASE_ASSERT_NOT_REACHED();
1592     return nullptr;
1593 }
1594
1595 template <typename LexerType> template <class TreeBuilder> int Parser<LexerType>::parseFunctionParameters(TreeBuilder& context, SourceParseMode mode, ParserFunctionInfo<TreeBuilder>& functionInfo)
1596 {
1597     RELEASE_ASSERT(mode != SourceParseMode::ProgramMode && mode != SourceParseMode::ModuleAnalyzeMode && mode != SourceParseMode::ModuleEvaluateMode);
1598     int parametersStart = m_token.m_location.startOffset;
1599     TreeFormalParameterList parameterList = context.createFormalParameterList();
1600     functionInfo.parameters = parameterList;
1601     functionInfo.startOffset = parametersStart;
1602     
1603     if (mode == SourceParseMode::ArrowFunctionMode) {
1604         if (!match(IDENT) && !match(OPENPAREN)) {
1605             semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
1606             failWithMessage("Expected an arrow function input parameter");
1607         } else {
1608             if (match(OPENPAREN)) {
1609                 next();
1610                 
1611                 if (match(CLOSEPAREN))
1612                     functionInfo.parameterCount = 0;
1613                 else
1614                     failIfFalse(parseFormalParameters(context, parameterList, functionInfo.parameterCount), "Cannot parse parameters for this ", stringForFunctionMode(mode));
1615                 
1616                 consumeOrFail(CLOSEPAREN, "Expected a ')' or a ',' after a parameter declaration");
1617             } else {
1618                 functionInfo.parameterCount = 1;
1619                 auto parameter = parseDestructuringPattern(context, DestructureToParameters, ExportType::NotExported);
1620                 failIfFalse(parameter, "Cannot parse parameter pattern");
1621                 context.appendParameter(parameterList, parameter, 0);
1622             }
1623         }
1624
1625         return parametersStart;
1626     }
1627
1628     if (!consume(OPENPAREN)) {
1629         semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
1630         failWithMessage("Expected an opening '(' before a ", stringForFunctionMode(mode), "'s parameter list");
1631     }
1632
1633     if (mode == SourceParseMode::GetterMode) {
1634         consumeOrFail(CLOSEPAREN, "getter functions must have no parameters");
1635         functionInfo.parameterCount = 0;
1636     } else if (mode == SourceParseMode::SetterMode) {
1637         failIfTrue(match(CLOSEPAREN), "setter functions must have one parameter");
1638         const Identifier* duplicateParameter = nullptr;
1639         auto parameter = parseDestructuringPattern(context, DestructureToParameters, ExportType::NotExported, &duplicateParameter);
1640         failIfFalse(parameter, "setter functions must have one parameter");
1641         auto defaultValue = parseDefaultValueForDestructuringPattern(context);
1642         propagateError();
1643         semanticFailIfTrue(duplicateParameter && defaultValue, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in function with default parameter values");
1644         context.appendParameter(parameterList, parameter, defaultValue);
1645         functionInfo.parameterCount = 1;
1646         failIfTrue(match(COMMA), "setter functions must have one parameter");
1647         consumeOrFail(CLOSEPAREN, "Expected a ')' after a parameter declaration");
1648     } else {
1649         if (match(CLOSEPAREN))
1650             functionInfo.parameterCount = 0;
1651         else
1652             failIfFalse(parseFormalParameters(context, parameterList, functionInfo.parameterCount), "Cannot parse parameters for this ", stringForFunctionMode(mode));
1653         consumeOrFail(CLOSEPAREN, "Expected a ')' or a ',' after a parameter declaration");
1654     }
1655
1656     return parametersStart;
1657 }
1658
1659 template <typename LexerType>
1660 template <class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuilder& context, FunctionRequirements requirements, SourceParseMode mode, bool nameIsInContainingScope, ConstructorKind constructorKind, SuperBinding expectedSuperBinding, int functionKeywordStart, ParserFunctionInfo<TreeBuilder>& functionInfo, FunctionParseType parseType)
1661 {
1662     RELEASE_ASSERT(isFunctionParseMode(mode));
1663
1664     AutoPopScopeRef functionScope(this, pushScope());
1665     functionScope->setIsFunction();
1666     int functionNameStart = m_token.m_location.startOffset;
1667     const Identifier* lastFunctionName = m_lastFunctionName;
1668     m_lastFunctionName = nullptr;
1669     int parametersStart;
1670     JSTokenLocation startLocation;
1671     int startColumn;
1672     FunctionBodyType functionBodyType;
1673     
1674     switch (parseType) {
1675     case StandardFunctionParseType: {
1676         RELEASE_ASSERT(mode != SourceParseMode::ArrowFunctionMode);
1677         if (match(IDENT) || isLETMaskedAsIDENT()) {
1678             functionInfo.name = m_token.m_data.ident;
1679             m_lastFunctionName = functionInfo.name;
1680             next();
1681             if (!nameIsInContainingScope)
1682                 failIfTrueIfStrict(functionScope->declareVariable(functionInfo.name) & DeclarationResult::InvalidStrictMode, "'", functionInfo.name->impl(), "' is not a valid ", stringForFunctionMode(mode), " name in strict mode");
1683         } else if (requirements == FunctionNeedsName) {
1684             if (match(OPENPAREN) && mode == SourceParseMode::NormalFunctionMode)
1685                 semanticFail("Function statements must have a name");
1686             semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
1687             failDueToUnexpectedToken();
1688             return false;
1689         }
1690
1691         startLocation = tokenLocation();
1692         functionInfo.startLine = tokenLine();
1693         startColumn = tokenColumn();
1694
1695         parametersStart = parseFunctionParameters(context, mode, functionInfo);
1696         propagateError();
1697         
1698         matchOrFail(OPENBRACE, "Expected an opening '{' at the start of a ", stringForFunctionMode(mode), " body");
1699         
1700         // BytecodeGenerator emits code to throw TypeError when a class constructor is "call"ed.
1701         // Set ConstructorKind to None for non-constructor methods of classes.
1702     
1703         if (m_defaultConstructorKind != ConstructorKind::None) {
1704             constructorKind = m_defaultConstructorKind;
1705             expectedSuperBinding = m_defaultConstructorKind == ConstructorKind::Derived ? SuperBinding::Needed : SuperBinding::NotNeeded;
1706         }
1707
1708         functionBodyType = StandardFunctionBodyBlock;
1709         
1710         break;
1711     }
1712 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
1713     case ArrowFunctionParseType: {
1714         RELEASE_ASSERT(mode == SourceParseMode::ArrowFunctionMode);
1715
1716         startLocation = tokenLocation();
1717         functionInfo.startLine = tokenLine();
1718         startColumn = tokenColumn();
1719
1720         parametersStart = parseFunctionParameters(context, mode, functionInfo);
1721         propagateError();
1722         
1723         matchOrFail(ARROWFUNCTION, "Expected a '=>' after arrow function parameter declaration");
1724         
1725         if (m_lexer->prevTerminator())
1726             failDueToUnexpectedToken();
1727
1728         ASSERT(constructorKind == ConstructorKind::None);
1729         
1730         // Check if arrow body start with {. If it true it mean that arrow function is Fat arrow function
1731         // and we need use common approach to parse function body
1732         next();
1733         functionBodyType = match(OPENBRACE) ? ArrowFunctionBodyBlock : ArrowFunctionBodyExpression;
1734         
1735         break;
1736     }
1737 #else
1738     default:
1739         RELEASE_ASSERT_NOT_REACHED();
1740 #endif
1741     }
1742     
1743     bool isClassConstructor = constructorKind != ConstructorKind::None;
1744     
1745     functionInfo.bodyStartColumn = startColumn;
1746     
1747     // If we know about this function already, we can use the cached info and skip the parser to the end of the function.
1748     if (const SourceProviderCacheItem* cachedInfo = TreeBuilder::CanUseFunctionCache ? findCachedFunctionInfo(functionInfo.startOffset) : 0) {
1749         // If we're in a strict context, the cached function info must say it was strict too.
1750         ASSERT(!strictMode() || cachedInfo->strictMode);
1751         JSTokenLocation endLocation;
1752
1753         endLocation.line = cachedInfo->lastTockenLine;
1754         endLocation.startOffset = cachedInfo->lastTockenStartOffset;
1755         endLocation.lineStartOffset = cachedInfo->lastTockenLineStartOffset;
1756
1757         bool endColumnIsOnStartLine = (endLocation.line == functionInfo.startLine);
1758         ASSERT(endLocation.startOffset >= endLocation.lineStartOffset);
1759         unsigned bodyEndColumn = endColumnIsOnStartLine ?
1760             endLocation.startOffset - m_token.m_data.lineStartOffset :
1761             endLocation.startOffset - endLocation.lineStartOffset;
1762         unsigned currentLineStartOffset = m_token.m_location.lineStartOffset;
1763         
1764         bool isArrowFunction = parseType == ArrowFunctionParseType;
1765         
1766         functionInfo.body = context.createFunctionMetadata(
1767             startLocation, endLocation, functionInfo.bodyStartColumn, bodyEndColumn, 
1768             functionKeywordStart, functionNameStart, parametersStart, 
1769             cachedInfo->strictMode, constructorKind, cachedInfo->parameterCount, mode, isArrowFunction,  functionBodyType == ArrowFunctionBodyExpression);
1770         
1771         functionScope->restoreFromSourceProviderCache(cachedInfo);
1772         popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo);
1773         
1774         m_token = cachedInfo->endFunctionToken();
1775         
1776         if (endColumnIsOnStartLine)
1777             m_token.m_location.lineStartOffset = currentLineStartOffset;
1778
1779         m_lexer->setOffset(m_token.m_location.endOffset, m_token.m_location.lineStartOffset);
1780         m_lexer->setLineNumber(m_token.m_location.line);
1781         functionInfo.endOffset = cachedInfo->endFunctionOffset;
1782
1783         if (isArrowFunction)
1784             functionBodyType = cachedInfo->isBodyArrowExpression ?  ArrowFunctionBodyExpression : ArrowFunctionBodyBlock;
1785         else
1786             functionBodyType = StandardFunctionBodyBlock;
1787         
1788         switch (functionBodyType) {
1789         case ArrowFunctionBodyExpression:
1790             next();
1791             context.setEndOffset(functionInfo.body, m_lexer->currentOffset());
1792             break;
1793         case ArrowFunctionBodyBlock:
1794         case StandardFunctionBodyBlock:
1795             context.setEndOffset(functionInfo.body, m_lexer->currentOffset());
1796             next();
1797             break;
1798         }
1799         functionInfo.endLine = m_lastTokenEndPosition.line;
1800         return true;
1801     }
1802     
1803     m_lastFunctionName = lastFunctionName;
1804     ParserState oldState = saveState();
1805     
1806     functionInfo.body = parseFunctionBody(context, startLocation, startColumn, functionKeywordStart, functionNameStart, parametersStart, constructorKind, functionBodyType, functionInfo.parameterCount, mode);
1807     
1808     restoreState(oldState);
1809     failIfFalse(functionInfo.body, "Cannot parse the body of this ", stringForFunctionMode(mode));
1810     context.setEndOffset(functionInfo.body, m_lexer->currentOffset());
1811     if (functionScope->strictMode() && functionInfo.name) {
1812         RELEASE_ASSERT(mode == SourceParseMode::NormalFunctionMode || mode == SourceParseMode::MethodMode || mode == SourceParseMode::ArrowFunctionMode);
1813         semanticFailIfTrue(m_vm->propertyNames->arguments == *functionInfo.name, "'", functionInfo.name->impl(), "' is not a valid function name in strict mode");
1814         semanticFailIfTrue(m_vm->propertyNames->eval == *functionInfo.name, "'", functionInfo.name->impl(), "' is not a valid function name in strict mode");
1815     }
1816     if (functionScope->hasDirectSuper()) {
1817         semanticFailIfTrue(!isClassConstructor, "Cannot call super() outside of a class constructor");
1818         semanticFailIfTrue(constructorKind != ConstructorKind::Derived, "Cannot call super() in a base class constructor");
1819     }
1820     if (functionScope->needsSuperBinding())
1821         semanticFailIfTrue(expectedSuperBinding == SuperBinding::NotNeeded, "super can only be used in a method of a derived class");
1822
1823     JSTokenLocation location = JSTokenLocation(m_token.m_location);
1824     functionInfo.endOffset = m_token.m_data.offset;
1825     
1826     if (functionBodyType == ArrowFunctionBodyExpression) {
1827         location = locationBeforeLastToken();
1828         functionInfo.endOffset = location.endOffset;
1829     }
1830     
1831     // Cache the tokenizer state and the function scope the first time the function is parsed.
1832     // Any future reparsing can then skip the function.
1833     static const int minimumFunctionLengthToCache = 16;
1834     std::unique_ptr<SourceProviderCacheItem> newInfo;
1835     int functionLength = functionInfo.endOffset - functionInfo.startOffset;
1836     if (TreeBuilder::CanUseFunctionCache && m_functionCache && functionLength > minimumFunctionLengthToCache) {
1837         SourceProviderCacheItemCreationParameters parameters;
1838         parameters.endFunctionOffset = functionInfo.endOffset;
1839         parameters.functionNameStart = functionNameStart;
1840         parameters.lastTockenLine = location.line;
1841         parameters.lastTockenStartOffset = location.startOffset;
1842         parameters.lastTockenEndOffset = location.endOffset;
1843         parameters.lastTockenLineStartOffset = location.lineStartOffset;
1844         parameters.parameterCount = functionInfo.parameterCount;
1845         if (functionBodyType == ArrowFunctionBodyExpression) {
1846             parameters.isBodyArrowExpression = true;
1847             parameters.tokenType = m_token.m_type;
1848         }
1849         functionScope->fillParametersForSourceProviderCache(parameters);
1850         newInfo = SourceProviderCacheItem::create(parameters);
1851     }
1852     
1853     popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo);
1854     
1855     if (functionBodyType == ArrowFunctionBodyExpression)
1856         failIfFalse(isEndOfArrowFunction(), "Expected the closing ';' ',' ']' ')' '}', line terminator or EOF after arrow function");
1857     else {
1858         matchOrFail(CLOSEBRACE, "Expected a closing '}' after a ", stringForFunctionMode(mode), " body");
1859         next();
1860     }
1861     
1862     if (newInfo)
1863         m_functionCache->add(functionInfo.startOffset, WTF::move(newInfo));
1864     
1865     functionInfo.endLine = m_lastTokenEndPosition.line;
1866     return true;
1867 }
1868
1869 template <typename LexerType>
1870 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDeclaration(TreeBuilder& context, ExportType exportType)
1871 {
1872     ASSERT(match(FUNCTION));
1873     JSTokenLocation location(tokenLocation());
1874     unsigned functionKeywordStart = tokenStart();
1875     next();
1876     ParserFunctionInfo<TreeBuilder> functionInfo;
1877     failIfFalse((parseFunctionInfo(context, FunctionNeedsName, SourceParseMode::NormalFunctionMode, true, ConstructorKind::None, SuperBinding::NotNeeded,
1878         functionKeywordStart, functionInfo, StandardFunctionParseType)), "Cannot parse this function");
1879     failIfFalse(functionInfo.name, "Function statements must have a name");
1880     DeclarationResultMask declarationResult = declareVariable(functionInfo.name);
1881     failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot declare a function named '", functionInfo.name->impl(), "' in strict mode");
1882     if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration)
1883         internalFailWithMessage(false, "Cannot declare a function that shadows a let/const/class variable '", functionInfo.name->impl(), "' in strict mode");
1884     if (exportType == ExportType::Exported) {
1885         semanticFailIfFalse(exportName(*functionInfo.name), "Cannot export a duplicate function name: '", functionInfo.name->impl(), "'");
1886         currentScope()->moduleScopeData().exportBinding(*functionInfo.name);
1887     }
1888     return context.createFuncDeclStatement(location, functionInfo);
1889 }
1890
1891 #if ENABLE(ES6_CLASS_SYNTAX)
1892 template <typename LexerType>
1893 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseClassDeclaration(TreeBuilder& context, ExportType exportType)
1894 {
1895     ASSERT(match(CLASSTOKEN));
1896     JSTokenLocation location(tokenLocation());
1897     JSTextPosition classStart = tokenStartPosition();
1898     unsigned classStartLine = tokenLine();
1899
1900     ParserClassInfo<TreeBuilder> info;
1901     TreeClassExpression classExpr = parseClass(context, FunctionNeedsName, info);
1902     failIfFalse(classExpr, "Failed to parse class");
1903
1904     DeclarationResultMask declarationResult = declareVariable(info.className, DeclarationType::LetDeclaration);
1905     if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration)
1906         internalFailWithMessage(false, "Cannot declare a class twice: '", info.className->impl(), "'");
1907     if (exportType == ExportType::Exported) {
1908         semanticFailIfFalse(exportName(*info.className), "Cannot export a duplicate class name: '", info.className->impl(), "'");
1909         currentScope()->moduleScopeData().exportBinding(*info.className);
1910     }
1911
1912     JSTextPosition classEnd = lastTokenEndPosition();
1913     unsigned classEndLine = tokenLine();
1914
1915     return context.createClassDeclStatement(location, classExpr, classStart, classEnd, classStartLine, classEndLine);
1916 }
1917
1918 template <typename LexerType>
1919 template <class TreeBuilder> TreeClassExpression Parser<LexerType>::parseClass(TreeBuilder& context, FunctionRequirements requirements, ParserClassInfo<TreeBuilder>& info)
1920 {
1921     ASSERT(match(CLASSTOKEN));
1922     JSTokenLocation location(tokenLocation());
1923     next();
1924
1925     AutoPopScopeRef classScope(this, pushScope());
1926     classScope->setIsLexicalScope();
1927     classScope->preventVarDeclarations();
1928     classScope->setStrictMode();
1929
1930     const Identifier* className = nullptr;
1931     if (match(IDENT)) {
1932         className = m_token.m_data.ident;
1933         info.className = className;
1934         next();
1935         failIfTrue(classScope->declareLexicalVariable(className, true) & DeclarationResult::InvalidStrictMode, "'", className->impl(), "' is not a valid class name");
1936     } else if (requirements == FunctionNeedsName) {
1937         if (match(OPENBRACE))
1938             semanticFail("Class statements must have a name");
1939         semanticFailureDueToKeyword("class name");
1940         failDueToUnexpectedToken();
1941     } else
1942         className = &m_vm->propertyNames->nullIdentifier;
1943     ASSERT(className);
1944
1945     TreeExpression parentClass = 0;
1946     if (consume(EXTENDS)) {
1947         parentClass = parseMemberExpression(context);
1948         failIfFalse(parentClass, "Cannot parse the parent class name");
1949     }
1950     const ConstructorKind constructorKind = parentClass ? ConstructorKind::Derived : ConstructorKind::Base;
1951
1952     consumeOrFail(OPENBRACE, "Expected opening '{' at the start of a class body");
1953
1954     TreeExpression constructor = 0;
1955     TreePropertyList staticMethods = 0;
1956     TreePropertyList instanceMethods = 0;
1957     TreePropertyList instanceMethodsTail = 0;
1958     TreePropertyList staticMethodsTail = 0;
1959     while (!match(CLOSEBRACE)) {
1960         if (match(SEMICOLON)) {
1961             next();
1962             continue;
1963         }
1964
1965         JSTokenLocation methodLocation(tokenLocation());
1966         unsigned methodStart = tokenStart();
1967
1968         // For backwards compatibility, "static" is a non-reserved keyword in non-strict mode.
1969         bool isStaticMethod = match(RESERVED_IF_STRICT) && *m_token.m_data.ident == m_vm->propertyNames->staticKeyword;
1970         if (isStaticMethod)
1971             next();
1972
1973         // FIXME: Figure out a way to share more code with parseProperty.
1974         const CommonIdentifiers& propertyNames = *m_vm->propertyNames;
1975         const Identifier* ident = &propertyNames.nullIdentifier;
1976         TreeExpression computedPropertyName = 0;
1977         bool isGetter = false;
1978         bool isSetter = false;
1979         switch (m_token.m_type) {
1980         case STRING:
1981             ident = m_token.m_data.ident;
1982             ASSERT(ident);
1983             next();
1984             break;
1985         case IDENT:
1986             ident = m_token.m_data.ident;
1987             ASSERT(ident);
1988             next();
1989             if (match(IDENT) || match(STRING) || match(DOUBLE) || match(INTEGER) || match(OPENBRACKET)) {
1990                 isGetter = *ident == propertyNames.get;
1991                 isSetter = *ident == propertyNames.set;
1992             }
1993             break;
1994         case DOUBLE:
1995         case INTEGER:
1996             ident = &m_parserArena.identifierArena().makeNumericIdentifier(const_cast<VM*>(m_vm), m_token.m_data.doubleValue);
1997             ASSERT(ident);
1998             next();
1999             break;
2000         case OPENBRACKET:
2001             next();
2002             computedPropertyName = parseAssignmentExpression(context);
2003             failIfFalse(computedPropertyName, "Cannot parse computed property name");
2004             handleProductionOrFail(CLOSEBRACKET, "]", "end", "computed property name");
2005             break;
2006         default:
2007             failDueToUnexpectedToken();
2008         }
2009
2010         TreeProperty property;
2011         const bool alwaysStrictInsideClass = true;
2012         if (isGetter || isSetter) {
2013             property = parseGetterSetter(context, alwaysStrictInsideClass, isGetter ? PropertyNode::Getter : PropertyNode::Setter, methodStart,
2014                 ConstructorKind::None, SuperBinding::Needed);
2015             failIfFalse(property, "Cannot parse this method");
2016         } else {
2017             ParserFunctionInfo<TreeBuilder> methodInfo;
2018             bool isConstructor = !isStaticMethod && *ident == propertyNames.constructor;
2019             failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, SourceParseMode::MethodMode, false, isConstructor ? constructorKind : ConstructorKind::None, SuperBinding::Needed, methodStart, methodInfo, StandardFunctionParseType)), "Cannot parse this method");
2020             methodInfo.name = isConstructor ? className : ident;
2021
2022             TreeExpression method = context.createFunctionExpr(methodLocation, methodInfo);
2023             if (isConstructor) {
2024                 semanticFailIfTrue(constructor, "Cannot declare multiple constructors in a single class");
2025                 constructor = method;
2026                 continue;
2027             }
2028
2029             // FIXME: Syntax error when super() is called
2030             semanticFailIfTrue(isStaticMethod && methodInfo.name && *methodInfo.name == propertyNames.prototype,
2031                 "Cannot declare a static method named 'prototype'");
2032             if (computedPropertyName) {
2033                 property = context.createProperty(computedPropertyName, method, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Computed),
2034                     PropertyNode::Unknown, alwaysStrictInsideClass, SuperBinding::Needed);
2035             } else
2036                 property = context.createProperty(methodInfo.name, method, PropertyNode::Constant, PropertyNode::Unknown, alwaysStrictInsideClass, SuperBinding::Needed);
2037         }
2038
2039         TreePropertyList& tail = isStaticMethod ? staticMethodsTail : instanceMethodsTail;
2040         if (tail)
2041             tail = context.createPropertyList(methodLocation, property, tail);
2042         else {
2043             tail = context.createPropertyList(methodLocation, property);
2044             if (isStaticMethod)
2045                 staticMethods = tail;
2046             else
2047                 instanceMethods = tail;
2048         }
2049     }
2050
2051     consumeOrFail(CLOSEBRACE, "Expected a closing '}' after a class body");
2052
2053     auto classExpression = context.createClassExpr(location, *className, classScope->finalizeLexicalEnvironment(), constructor, parentClass, instanceMethods, staticMethods);
2054     popScope(classScope, TreeBuilder::NeedsFreeVariableInfo);
2055     return classExpression;
2056 }
2057 #endif
2058
2059 struct LabelInfo {
2060     LabelInfo(const Identifier* ident, const JSTextPosition& start, const JSTextPosition& end)
2061     : m_ident(ident)
2062     , m_start(start)
2063     , m_end(end)
2064     {
2065     }
2066     
2067     const Identifier* m_ident;
2068     JSTextPosition m_start;
2069     JSTextPosition m_end;
2070 };
2071
2072 template <typename LexerType>
2073 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionOrLabelStatement(TreeBuilder& context)
2074 {
2075     
2076     /* Expression and Label statements are ambiguous at LL(1), so we have a
2077      * special case that looks for a colon as the next character in the input.
2078      */
2079     Vector<LabelInfo> labels;
2080     JSTokenLocation location;
2081     do {
2082         JSTextPosition start = tokenStartPosition();
2083         location = tokenLocation();
2084         if (!nextTokenIsColon()) {
2085             // If we hit this path we're making a expression statement, which
2086             // by definition can't make use of continue/break so we can just
2087             // ignore any labels we might have accumulated.
2088             TreeExpression expression = parseExpression(context);
2089             failIfFalse(expression, "Cannot parse expression statement");
2090             if (!autoSemiColon())
2091                 failDueToUnexpectedToken();
2092             return context.createExprStatement(location, expression, start, m_lastTokenEndPosition.line);
2093         }
2094         const Identifier* ident = m_token.m_data.ident;
2095         JSTextPosition end = tokenEndPosition();
2096         next();
2097         consumeOrFail(COLON, "Labels must be followed by a ':'");
2098         if (!m_syntaxAlreadyValidated) {
2099             // This is O(N^2) over the current list of consecutive labels, but I
2100             // have never seen more than one label in a row in the real world.
2101             for (size_t i = 0; i < labels.size(); i++)
2102                 failIfTrue(ident->impl() == labels[i].m_ident->impl(), "Attempted to redeclare the label '", ident->impl(), "'");
2103             failIfTrue(getLabel(ident), "Cannot find scope for the label '", ident->impl(), "'");
2104             labels.append(LabelInfo(ident, start, end));
2105         }
2106     } while (match(IDENT) || isLETMaskedAsIDENT());
2107     bool isLoop = false;
2108     switch (m_token.m_type) {
2109     case FOR:
2110     case WHILE:
2111     case DO:
2112         isLoop = true;
2113         break;
2114         
2115     default:
2116         break;
2117     }
2118     const Identifier* unused = 0;
2119     ScopeRef labelScope = currentScope();
2120     if (!m_syntaxAlreadyValidated) {
2121         for (size_t i = 0; i < labels.size(); i++)
2122             pushLabel(labels[i].m_ident, isLoop);
2123     }
2124     TreeStatement statement = parseStatement(context, unused);
2125     if (!m_syntaxAlreadyValidated) {
2126         for (size_t i = 0; i < labels.size(); i++)
2127             popLabel(labelScope);
2128     }
2129     failIfFalse(statement, "Cannot parse statement");
2130     for (size_t i = 0; i < labels.size(); i++) {
2131         const LabelInfo& info = labels[labels.size() - i - 1];
2132         statement = context.createLabelStatement(location, info.m_ident, statement, info.m_start, info.m_end);
2133     }
2134     return statement;
2135 }
2136
2137 template <typename LexerType>
2138 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionStatement(TreeBuilder& context)
2139 {
2140     switch (m_token.m_type) {
2141     // Consult: http://www.ecma-international.org/ecma-262/6.0/index.html#sec-expression-statement
2142     // The ES6 spec mandates that we should fail from FUNCTION token here. We handle this case 
2143     // in parseStatement() which is the only caller of parseExpressionStatement().
2144     // We actually allow FUNCTION in situations where it should not be allowed unless we're in strict mode.
2145     case CLASSTOKEN:
2146         failWithMessage("'class' declaration is not directly within a block statement");
2147         break;
2148     default:
2149         // FIXME: when implementing 'let' we should fail when we see the token sequence "let [".
2150         // https://bugs.webkit.org/show_bug.cgi?id=142944
2151         break;
2152     }
2153     JSTextPosition start = tokenStartPosition();
2154     JSTokenLocation location(tokenLocation());
2155     TreeExpression expression = parseExpression(context);
2156     failIfFalse(expression, "Cannot parse expression statement");
2157     failIfFalse(autoSemiColon(), "Parse error");
2158     return context.createExprStatement(location, expression, start, m_lastTokenEndPosition.line);
2159 }
2160
2161 template <typename LexerType>
2162 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseIfStatement(TreeBuilder& context)
2163 {
2164     ASSERT(match(IF));
2165     JSTokenLocation ifLocation(tokenLocation());
2166     int start = tokenLine();
2167     next();
2168     handleProductionOrFail(OPENPAREN, "(", "start", "'if' condition");
2169
2170     TreeExpression condition = parseExpression(context);
2171     failIfFalse(condition, "Expected a expression as the condition for an if statement");
2172     int end = tokenLine();
2173     handleProductionOrFail(CLOSEPAREN, ")", "end", "'if' condition");
2174
2175     const Identifier* unused = 0;
2176     TreeStatement trueBlock = parseStatement(context, unused);
2177     failIfFalse(trueBlock, "Expected a statement as the body of an if block");
2178
2179     if (!match(ELSE))
2180         return context.createIfStatement(ifLocation, condition, trueBlock, 0, start, end);
2181
2182     Vector<TreeExpression> exprStack;
2183     Vector<std::pair<int, int>> posStack;
2184     Vector<JSTokenLocation> tokenLocationStack;
2185     Vector<TreeStatement> statementStack;
2186     bool trailingElse = false;
2187     do {
2188         JSTokenLocation tempLocation = tokenLocation();
2189         next();
2190         if (!match(IF)) {
2191             const Identifier* unused = 0;
2192             TreeStatement block = parseStatement(context, unused);
2193             failIfFalse(block, "Expected a statement as the body of an else block");
2194             statementStack.append(block);
2195             trailingElse = true;
2196             break;
2197         }
2198         int innerStart = tokenLine();
2199         next();
2200         
2201         handleProductionOrFail(OPENPAREN, "(", "start", "'if' condition");
2202
2203         TreeExpression innerCondition = parseExpression(context);
2204         failIfFalse(innerCondition, "Expected a expression as the condition for an if statement");
2205         int innerEnd = tokenLine();
2206         handleProductionOrFail(CLOSEPAREN, ")", "end", "'if' condition");
2207         const Identifier* unused = 0;
2208         TreeStatement innerTrueBlock = parseStatement(context, unused);
2209         failIfFalse(innerTrueBlock, "Expected a statement as the body of an if block");
2210         tokenLocationStack.append(tempLocation);
2211         exprStack.append(innerCondition);
2212         posStack.append(std::make_pair(innerStart, innerEnd));
2213         statementStack.append(innerTrueBlock);
2214     } while (match(ELSE));
2215
2216     if (!trailingElse) {
2217         TreeExpression condition = exprStack.last();
2218         exprStack.removeLast();
2219         TreeStatement trueBlock = statementStack.last();
2220         statementStack.removeLast();
2221         std::pair<int, int> pos = posStack.last();
2222         posStack.removeLast();
2223         JSTokenLocation elseLocation = tokenLocationStack.last();
2224         tokenLocationStack.removeLast();
2225         TreeStatement ifStatement = context.createIfStatement(elseLocation, condition, trueBlock, 0, pos.first, pos.second);
2226         context.setEndOffset(ifStatement, context.endOffset(trueBlock));
2227         statementStack.append(ifStatement);
2228     }
2229
2230     while (!exprStack.isEmpty()) {
2231         TreeExpression condition = exprStack.last();
2232         exprStack.removeLast();
2233         TreeStatement falseBlock = statementStack.last();
2234         statementStack.removeLast();
2235         TreeStatement trueBlock = statementStack.last();
2236         statementStack.removeLast();
2237         std::pair<int, int> pos = posStack.last();
2238         posStack.removeLast();
2239         JSTokenLocation elseLocation = tokenLocationStack.last();
2240         tokenLocationStack.removeLast();
2241         TreeStatement ifStatement = context.createIfStatement(elseLocation, condition, trueBlock, falseBlock, pos.first, pos.second);
2242         context.setEndOffset(ifStatement, context.endOffset(falseBlock));
2243         statementStack.append(ifStatement);
2244     }
2245
2246     return context.createIfStatement(ifLocation, condition, trueBlock, statementStack.last(), start, end);
2247 }
2248
2249 template <typename LexerType>
2250 template <class TreeBuilder> typename TreeBuilder::ModuleName Parser<LexerType>::parseModuleName(TreeBuilder& context)
2251 {
2252     // ModuleName (ModuleSpecifier in the spec) represents the module name imported by the script.
2253     // http://www.ecma-international.org/ecma-262/6.0/#sec-imports
2254     // http://www.ecma-international.org/ecma-262/6.0/#sec-exports
2255     JSTokenLocation specifierLocation(tokenLocation());
2256     failIfFalse(match(STRING), "Imported modules names must be string literals");
2257     const Identifier* moduleName = m_token.m_data.ident;
2258     next();
2259     return context.createModuleName(specifierLocation, *moduleName);
2260 }
2261
2262 template <typename LexerType>
2263 template <class TreeBuilder> typename TreeBuilder::ImportSpecifier Parser<LexerType>::parseImportClauseItem(TreeBuilder& context, ImportSpecifierType specifierType)
2264 {
2265     // Produced node is the item of the ImportClause.
2266     // That is the ImportSpecifier, ImportedDefaultBinding or NameSpaceImport.
2267     // http://www.ecma-international.org/ecma-262/6.0/#sec-imports
2268     JSTokenLocation specifierLocation(tokenLocation());
2269     JSToken localNameToken;
2270     const Identifier* importedName = nullptr;
2271     const Identifier* localName = nullptr;
2272
2273     switch (specifierType) {
2274     case ImportSpecifierType::NamespaceImport: {
2275         // NameSpaceImport :
2276         // * as ImportedBinding
2277         // e.g.
2278         //     * as namespace
2279         ASSERT(match(TIMES));
2280         importedName = &m_vm->propertyNames->timesIdentifier;
2281         next();
2282
2283         failIfFalse(matchContextualKeyword(m_vm->propertyNames->as), "Expected 'as' before imported binding name");
2284         next();
2285
2286         matchOrFail(IDENT, "Expected a variable name for the import declaration");
2287         localNameToken = m_token;
2288         localName = m_token.m_data.ident;
2289         next();
2290         break;
2291     }
2292
2293     case ImportSpecifierType::NamedImport: {
2294         // ImportSpecifier :
2295         // ImportedBinding
2296         // IdentifierName as ImportedBinding
2297         // e.g.
2298         //     A
2299         //     A as B
2300         ASSERT(matchIdentifierOrKeyword());
2301         localNameToken = m_token;
2302         localName = m_token.m_data.ident;
2303         importedName = localName;
2304         next();
2305
2306         if (matchContextualKeyword(m_vm->propertyNames->as)) {
2307             next();
2308             matchOrFail(IDENT, "Expected a variable name for the import declaration");
2309             localNameToken = m_token;
2310             localName = m_token.m_data.ident;
2311             next();
2312         }
2313         break;
2314     }
2315
2316     case ImportSpecifierType::DefaultImport: {
2317         // ImportedDefaultBinding :
2318         // ImportedBinding
2319         ASSERT(match(IDENT));
2320         localNameToken = m_token;
2321         localName = m_token.m_data.ident;
2322         importedName = &m_vm->propertyNames->defaultKeyword;
2323         next();
2324         break;
2325     }
2326     }
2327
2328     semanticFailIfTrue(localNameToken.m_type & KeywordTokenFlag, "Cannot use keyword as imported binding name");
2329     DeclarationResultMask declarationResult = declareVariable(localName, DeclarationType::ConstDeclaration, (specifierType == ImportSpecifierType::NamespaceImport) ? DeclarationImportType::ImportedNamespace : DeclarationImportType::Imported);
2330     if (declarationResult != DeclarationResult::Valid) {
2331         failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot declare an imported binding named ", localName->impl(), " in strict mode");
2332         if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration)
2333             internalFailWithMessage(false, "Cannot declare an imported binding name twice: '", localName->impl(), "'");
2334     }
2335
2336     return context.createImportSpecifier(specifierLocation, *importedName, *localName);
2337 }
2338
2339 template <typename LexerType>
2340 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseImportDeclaration(TreeBuilder& context)
2341 {
2342     // http://www.ecma-international.org/ecma-262/6.0/#sec-imports
2343     ASSERT(match(IMPORT));
2344     JSTokenLocation importLocation(tokenLocation());
2345     next();
2346
2347     auto specifierList = context.createImportSpecifierList();
2348
2349     if (match(STRING)) {
2350         // import ModuleSpecifier ;
2351         auto moduleName = parseModuleName(context);
2352         failIfFalse(moduleName, "Cannot parse the module name");
2353         failIfFalse(autoSemiColon(), "Expected a ';' following a targeted import declaration");
2354         return context.createImportDeclaration(importLocation, specifierList, moduleName);
2355     }
2356
2357     bool isFinishedParsingImport = false;
2358     if (match(IDENT)) {
2359         // ImportedDefaultBinding :
2360         // ImportedBinding
2361         auto specifier = parseImportClauseItem(context, ImportSpecifierType::DefaultImport);
2362         failIfFalse(specifier, "Cannot parse the default import");
2363         context.appendImportSpecifier(specifierList, specifier);
2364         if (match(COMMA))
2365             next();
2366         else
2367             isFinishedParsingImport = true;
2368     }
2369
2370     if (!isFinishedParsingImport) {
2371         if (match(TIMES)) {
2372             // import NameSpaceImport FromClause ;
2373             auto specifier = parseImportClauseItem(context, ImportSpecifierType::NamespaceImport);
2374             failIfFalse(specifier, "Cannot parse the namespace import");
2375             context.appendImportSpecifier(specifierList, specifier);
2376         } else if (match(OPENBRACE)) {
2377             // NamedImports :
2378             // { }
2379             // { ImportsList }
2380             // { ImportsList , }
2381             next();
2382
2383             while (!match(CLOSEBRACE)) {
2384                 failIfFalse(matchIdentifierOrKeyword(), "Expected an imported name for the import declaration");
2385                 auto specifier = parseImportClauseItem(context, ImportSpecifierType::NamedImport);
2386                 failIfFalse(specifier, "Cannot parse the named import");
2387                 context.appendImportSpecifier(specifierList, specifier);
2388                 if (!consume(COMMA))
2389                     break;
2390             }
2391             handleProductionOrFail(CLOSEBRACE, "}", "end", "import list");
2392         } else
2393             failWithMessage("Expected namespace import or import list");
2394     }
2395
2396     // FromClause :
2397     // from ModuleSpecifier
2398
2399     failIfFalse(matchContextualKeyword(m_vm->propertyNames->from), "Expected 'from' before imported module name");
2400     next();
2401
2402     auto moduleName = parseModuleName(context);
2403     failIfFalse(moduleName, "Cannot parse the module name");
2404     failIfFalse(autoSemiColon(), "Expected a ';' following a targeted import declaration");
2405
2406     return context.createImportDeclaration(importLocation, specifierList, moduleName);
2407 }
2408
2409 template <typename LexerType>
2410 template <class TreeBuilder> typename TreeBuilder::ExportSpecifier Parser<LexerType>::parseExportSpecifier(TreeBuilder& context, Vector<const Identifier*>& maybeLocalNames, bool& hasKeywordForLocalBindings)
2411 {
2412     // ExportSpecifier :
2413     // IdentifierName
2414     // IdentifierName as IdentifierName
2415     // http://www.ecma-international.org/ecma-262/6.0/#sec-exports
2416     ASSERT(matchIdentifierOrKeyword());
2417     JSTokenLocation specifierLocation(tokenLocation());
2418     if (m_token.m_type & KeywordTokenFlag)
2419         hasKeywordForLocalBindings = true;
2420     const Identifier* localName = m_token.m_data.ident;
2421     const Identifier* exportedName = localName;
2422     next();
2423
2424     if (matchContextualKeyword(m_vm->propertyNames->as)) {
2425         next();
2426         failIfFalse(matchIdentifierOrKeyword(), "Expected an exported name for the export declaration");
2427         exportedName = m_token.m_data.ident;
2428         next();
2429     }
2430
2431     semanticFailIfFalse(exportName(*exportedName), "Cannot export a duplicate name '", exportedName->impl(), "'");
2432     maybeLocalNames.append(localName);
2433     return context.createExportSpecifier(specifierLocation, *localName, *exportedName);
2434 }
2435
2436 template <typename LexerType>
2437 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExportDeclaration(TreeBuilder& context)
2438 {
2439     // http://www.ecma-international.org/ecma-262/6.0/#sec-exports
2440     ASSERT(match(EXPORT));
2441     JSTokenLocation exportLocation(tokenLocation());
2442     next();
2443
2444     switch (m_token.m_type) {
2445     case TIMES: {
2446         // export * FromClause ;
2447         next();
2448
2449         failIfFalse(matchContextualKeyword(m_vm->propertyNames->from), "Expected 'from' before exported module name");
2450         next();
2451         auto moduleName = parseModuleName(context);
2452         failIfFalse(moduleName, "Cannot parse the 'from' clause");
2453         failIfFalse(autoSemiColon(), "Expected a ';' following a targeted export declaration");
2454
2455         return context.createExportAllDeclaration(exportLocation, moduleName);
2456     }
2457
2458     case DEFAULT: {
2459         // export default HoistableDeclaration[Default]
2460         // export default ClassDeclaration[Default]
2461         // export default [lookahead not-in {function, class}] AssignmentExpression[In] ;
2462
2463         next();
2464
2465         TreeStatement result = 0;
2466         bool isFunctionOrClassDeclaration = false;
2467         const Identifier* localName = nullptr;
2468         SavePoint savePoint = createSavePoint();
2469         if (match(FUNCTION)
2470 #if ENABLE(ES6_CLASS_SYNTAX)
2471                 || match(CLASSTOKEN)
2472 #endif
2473                 ) {
2474             isFunctionOrClassDeclaration = true;
2475             next();
2476             // FIXME: When landing ES6 generators, we need to take care of that '*' comes.
2477             if (match(IDENT))
2478                 localName = m_token.m_data.ident;
2479             restoreSavePoint(savePoint);
2480         }
2481
2482         if (localName) {
2483             if (match(FUNCTION))
2484                 result = parseFunctionDeclaration(context);
2485 #if ENABLE(ES6_CLASS_SYNTAX)
2486             else {
2487                 ASSERT(match(CLASSTOKEN));
2488                 result = parseClassDeclaration(context);
2489             }
2490 #endif
2491         } else {
2492             // export default expr;
2493             //
2494             // It should be treated as the same to the following.
2495             //
2496             // const *default* = expr;
2497             // export { *default* as default }
2498             //
2499             // In the above example, *default* is the invisible variable to the users.
2500             // We use the private symbol to represent the name of this variable.
2501             JSTokenLocation location(tokenLocation());
2502             JSTextPosition start = tokenStartPosition();
2503             TreeExpression expression = parseAssignmentExpression(context);
2504             failIfFalse(expression, "Cannot parse expression");
2505
2506             DeclarationResultMask declarationResult = declareVariable(&m_vm->propertyNames->starDefaultPrivateName, DeclarationType::ConstDeclaration);
2507             if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration)
2508                 internalFailWithMessage(false, "Only one 'default' export is allowed");
2509
2510             TreeExpression assignment = context.createAssignResolve(location, m_vm->propertyNames->starDefaultPrivateName, expression, start, start, tokenEndPosition(), AssignmentContext::ConstDeclarationStatement);
2511             result = context.createExprStatement(location, assignment, start, tokenEndPosition());
2512             if (!isFunctionOrClassDeclaration)
2513                 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted export declaration");
2514             localName = &m_vm->propertyNames->starDefaultPrivateName;
2515         }
2516         failIfFalse(result, "Cannot parse the declaration");
2517
2518         semanticFailIfFalse(exportName(m_vm->propertyNames->defaultKeyword), "Only one 'default' export is allowed");
2519         currentScope()->moduleScopeData().exportBinding(*localName);
2520         return context.createExportDefaultDeclaration(exportLocation, result, *localName);
2521     }
2522
2523     case OPENBRACE: {
2524         // export ExportClause FromClause ;
2525         // export ExportClause ;
2526         //
2527         // ExportClause :
2528         // { }
2529         // { ExportsList }
2530         // { ExportsList , }
2531         //
2532         // ExportsList :
2533         // ExportSpecifier
2534         // ExportsList , ExportSpecifier
2535
2536         next();
2537
2538         auto specifierList = context.createExportSpecifierList();
2539         Vector<const Identifier*> maybeLocalNames;
2540
2541         bool hasKeywordForLocalBindings = false;
2542         while (!match(CLOSEBRACE)) {
2543             failIfFalse(matchIdentifierOrKeyword(), "Expected a variable name for the export declaration");
2544             auto specifier = parseExportSpecifier(context, maybeLocalNames, hasKeywordForLocalBindings);
2545             failIfFalse(specifier, "Cannot parse the named export");
2546             context.appendExportSpecifier(specifierList, specifier);
2547             if (!consume(COMMA))
2548                 break;
2549         }
2550         handleProductionOrFail(CLOSEBRACE, "}", "end", "export list");
2551
2552         typename TreeBuilder::ModuleName moduleName = 0;
2553         if (matchContextualKeyword(m_vm->propertyNames->from)) {
2554             next();
2555             moduleName = parseModuleName(context);
2556             failIfFalse(moduleName, "Cannot parse the 'from' clause");
2557         }
2558         failIfFalse(autoSemiColon(), "Expected a ';' following a targeted export declaration");
2559
2560         if (!moduleName) {
2561             semanticFailIfTrue(hasKeywordForLocalBindings, "Cannot use keyword as exported variable name");
2562             // Since this export declaration does not have module specifier part, it exports the local bindings.
2563             // While the export declaration with module specifier does not have any effect on the current module's scope,
2564             // the export named declaration without module specifier references the the local binding names.
2565             // For example,
2566             //   export { A, B, C as D } from "mod"
2567             // does not have effect on the current module's scope. But,
2568             //   export { A, B, C as D }
2569             // will reference the current module's bindings.
2570             for (const Identifier* localName : maybeLocalNames)
2571                 currentScope()->moduleScopeData().exportBinding(*localName);
2572         }
2573
2574         return context.createExportNamedDeclaration(exportLocation, specifierList, moduleName);
2575     }
2576
2577     default: {
2578         // export VariableStatement
2579         // export Declaration
2580         TreeStatement result = 0;
2581         switch (m_token.m_type) {
2582         case VAR:
2583             result = parseVariableDeclaration(context, DeclarationType::VarDeclaration, ExportType::Exported);
2584             break;
2585
2586         case CONSTTOKEN:
2587             result = parseVariableDeclaration(context, DeclarationType::ConstDeclaration, ExportType::Exported);
2588             break;
2589
2590         case LET:
2591             result = parseVariableDeclaration(context, DeclarationType::LetDeclaration, ExportType::Exported);
2592             break;
2593
2594         case FUNCTION:
2595             result = parseFunctionDeclaration(context, ExportType::Exported);
2596             break;
2597
2598 #if ENABLE(ES6_CLASS_SYNTAX)
2599         case CLASSTOKEN:
2600             result = parseClassDeclaration(context, ExportType::Exported);
2601             break;
2602 #endif
2603
2604         default:
2605             failWithMessage("Expected either a declaration or a variable statement");
2606             break;
2607         }
2608         failIfFalse(result, "Cannot parse the declaration");
2609         return context.createExportLocalDeclaration(exportLocation, result);
2610     }
2611     }
2612
2613     RELEASE_ASSERT_NOT_REACHED();
2614     return 0;
2615 }
2616
2617 template <typename LexerType>
2618 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseExpression(TreeBuilder& context)
2619 {
2620     failIfStackOverflow();
2621     JSTokenLocation location(tokenLocation());
2622     TreeExpression node = parseAssignmentExpression(context);
2623     failIfFalse(node, "Cannot parse expression");
2624     context.setEndOffset(node, m_lastTokenEndPosition.offset);
2625     if (!match(COMMA))
2626         return node;
2627     next();
2628     m_nonTrivialExpressionCount++;
2629     m_nonLHSCount++;
2630     TreeExpression right = parseAssignmentExpression(context);
2631     failIfFalse(right, "Cannot parse expression in a comma expression");
2632     context.setEndOffset(right, m_lastTokenEndPosition.offset);
2633     typename TreeBuilder::Comma head = context.createCommaExpr(location, node);
2634     typename TreeBuilder::Comma tail = context.appendToCommaExpr(location, head, head, right);
2635     while (match(COMMA)) {
2636         next(TreeBuilder::DontBuildStrings);
2637         right = parseAssignmentExpression(context);
2638         failIfFalse(right, "Cannot parse expression in a comma expression");
2639         context.setEndOffset(right, m_lastTokenEndPosition.offset);
2640         tail = context.appendToCommaExpr(location, head, tail, right);
2641     }
2642     context.setEndOffset(head, m_lastTokenEndPosition.offset);
2643     return head;
2644 }
2645
2646     
2647 template <typename LexerType>
2648 template <typename TreeBuilder> TreeExpression Parser<LexerType>::parseAssignmentExpression(TreeBuilder& context)
2649 {
2650     failIfStackOverflow();
2651     JSTextPosition start = tokenStartPosition();
2652     JSTokenLocation location(tokenLocation());
2653     int initialAssignmentCount = m_assignmentCount;
2654     int initialNonLHSCount = m_nonLHSCount;
2655     if (match(OPENBRACE) || match(OPENBRACKET)) {
2656         SavePoint savePoint = createSavePoint();
2657         auto pattern = tryParseDestructuringPatternExpression(context, AssignmentContext::AssignmentExpression);
2658         if (pattern && consume(EQUAL)) {
2659             auto rhs = parseAssignmentExpression(context);
2660             if (rhs)
2661                 return context.createDestructuringAssignment(location, pattern, rhs);
2662         }
2663         restoreSavePoint(savePoint);
2664     }
2665     
2666 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
2667     if (isArrowFunctionParamters())
2668         return parseArrowFunctionExpression(context);
2669 #endif
2670     
2671     TreeExpression lhs = parseConditionalExpression(context);
2672     failIfFalse(lhs, "Cannot parse expression");
2673     if (initialNonLHSCount != m_nonLHSCount) {
2674         if (m_token.m_type >= EQUAL && m_token.m_type <= OREQUAL)
2675             semanticFail("Left hand side of operator '", getToken(), "' must be a reference");
2676
2677         return lhs;
2678     }
2679     
2680     int assignmentStack = 0;
2681     Operator op;
2682     bool hadAssignment = false;
2683     while (true) {
2684         switch (m_token.m_type) {
2685         case EQUAL: op = OpEqual; break;
2686         case PLUSEQUAL: op = OpPlusEq; break;
2687         case MINUSEQUAL: op = OpMinusEq; break;
2688         case MULTEQUAL: op = OpMultEq; break;
2689         case DIVEQUAL: op = OpDivEq; break;
2690         case LSHIFTEQUAL: op = OpLShift; break;
2691         case RSHIFTEQUAL: op = OpRShift; break;
2692         case URSHIFTEQUAL: op = OpURShift; break;
2693         case ANDEQUAL: op = OpAndEq; break;
2694         case XOREQUAL: op = OpXOrEq; break;
2695         case OREQUAL: op = OpOrEq; break;
2696         case MODEQUAL: op = OpModEq; break;
2697         default:
2698             goto end;
2699         }
2700         m_nonTrivialExpressionCount++;
2701         hadAssignment = true;
2702         context.assignmentStackAppend(assignmentStack, lhs, start, tokenStartPosition(), m_assignmentCount, op);
2703         start = tokenStartPosition();
2704         m_assignmentCount++;
2705         next(TreeBuilder::DontBuildStrings);
2706         if (strictMode() && m_lastIdentifier && context.isResolve(lhs)) {
2707             failIfTrueIfStrict(m_vm->propertyNames->eval == *m_lastIdentifier, "Cannot modify 'eval' in strict mode");
2708             failIfTrueIfStrict(m_vm->propertyNames->arguments == *m_lastIdentifier, "Cannot modify 'arguments' in strict mode");
2709             declareWrite(m_lastIdentifier);
2710             m_lastIdentifier = 0;
2711         }
2712         lhs = parseAssignmentExpression(context);
2713         failIfFalse(lhs, "Cannot parse the right hand side of an assignment expression");
2714         if (initialNonLHSCount != m_nonLHSCount) {
2715             if (m_token.m_type >= EQUAL && m_token.m_type <= OREQUAL)
2716                 semanticFail("Left hand side of operator '", getToken(), "' must be a reference");
2717             break;
2718         }
2719     }
2720 end:
2721     if (hadAssignment)
2722         m_nonLHSCount++;
2723     
2724     if (!TreeBuilder::CreatesAST)
2725         return lhs;
2726     
2727     while (assignmentStack)
2728         lhs = context.createAssignment(location, assignmentStack, lhs, initialAssignmentCount, m_assignmentCount, lastTokenEndPosition());
2729     
2730     return lhs;
2731 }
2732
2733 template <typename LexerType>
2734 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseConditionalExpression(TreeBuilder& context)
2735 {
2736     JSTokenLocation location(tokenLocation());
2737     TreeExpression cond = parseBinaryExpression(context);
2738     failIfFalse(cond, "Cannot parse expression");
2739     if (!match(QUESTION))
2740         return cond;
2741     m_nonTrivialExpressionCount++;
2742     m_nonLHSCount++;
2743     next(TreeBuilder::DontBuildStrings);
2744     TreeExpression lhs = parseAssignmentExpression(context);
2745     failIfFalse(lhs, "Cannot parse left hand side of ternary operator");
2746     context.setEndOffset(lhs, m_lastTokenEndPosition.offset);
2747     consumeOrFailWithFlags(COLON, TreeBuilder::DontBuildStrings, "Expected ':' in ternary operator");
2748     
2749     TreeExpression rhs = parseAssignmentExpression(context);
2750     failIfFalse(rhs, "Cannot parse right hand side of ternary operator");
2751     context.setEndOffset(rhs, m_lastTokenEndPosition.offset);
2752     return context.createConditionalExpr(location, cond, lhs, rhs);
2753 }
2754
2755 ALWAYS_INLINE static bool isUnaryOp(JSTokenType token)
2756 {
2757     return token & UnaryOpTokenFlag;
2758 }
2759
2760 template <typename LexerType>
2761 int Parser<LexerType>::isBinaryOperator(JSTokenType token)
2762 {
2763     if (m_allowsIn)
2764         return token & (BinaryOpTokenPrecedenceMask << BinaryOpTokenAllowsInPrecedenceAdditionalShift);
2765     return token & BinaryOpTokenPrecedenceMask;
2766 }
2767
2768 template <typename LexerType>
2769 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseBinaryExpression(TreeBuilder& context)
2770 {
2771     int operandStackDepth = 0;
2772     int operatorStackDepth = 0;
2773     typename TreeBuilder::BinaryExprContext binaryExprContext(context);
2774     JSTokenLocation location(tokenLocation());
2775     while (true) {
2776         JSTextPosition exprStart = tokenStartPosition();
2777         int initialAssignments = m_assignmentCount;
2778         TreeExpression current = parseUnaryExpression(context);
2779         failIfFalse(current, "Cannot parse expression");
2780         
2781         context.appendBinaryExpressionInfo(operandStackDepth, current, exprStart, lastTokenEndPosition(), lastTokenEndPosition(), initialAssignments != m_assignmentCount);
2782         int precedence = isBinaryOperator(m_token.m_type);
2783         if (!precedence)
2784             break;
2785         m_nonTrivialExpressionCount++;
2786         m_nonLHSCount++;
2787         int operatorToken = m_token.m_type;
2788         next(TreeBuilder::DontBuildStrings);
2789         
2790         while (operatorStackDepth &&  context.operatorStackHasHigherPrecedence(operatorStackDepth, precedence)) {
2791             ASSERT(operandStackDepth > 1);
2792             
2793             typename TreeBuilder::BinaryOperand rhs = context.getFromOperandStack(-1);
2794             typename TreeBuilder::BinaryOperand lhs = context.getFromOperandStack(-2);
2795             context.shrinkOperandStackBy(operandStackDepth, 2);
2796             context.appendBinaryOperation(location, operandStackDepth, operatorStackDepth, lhs, rhs);
2797             context.operatorStackPop(operatorStackDepth);
2798         }
2799         context.operatorStackAppend(operatorStackDepth, operatorToken, precedence);
2800     }
2801     while (operatorStackDepth) {
2802         ASSERT(operandStackDepth > 1);
2803         
2804         typename TreeBuilder::BinaryOperand rhs = context.getFromOperandStack(-1);
2805         typename TreeBuilder::BinaryOperand lhs = context.getFromOperandStack(-2);
2806         context.shrinkOperandStackBy(operandStackDepth, 2);
2807         context.appendBinaryOperation(location, operandStackDepth, operatorStackDepth, lhs, rhs);
2808         context.operatorStackPop(operatorStackDepth);
2809     }
2810     return context.popOperandStack(operandStackDepth);
2811 }
2812
2813 template <typename LexerType>
2814 template <class TreeBuilder> TreeProperty Parser<LexerType>::parseProperty(TreeBuilder& context, bool complete)
2815 {
2816     bool wasIdent = false;
2817     switch (m_token.m_type) {
2818     namedProperty:
2819     case IDENT:
2820         wasIdent = true;
2821         FALLTHROUGH;
2822     case STRING: {
2823         const Identifier* ident = m_token.m_data.ident;
2824         unsigned getterOrSetterStartOffset = tokenStart();
2825         if (complete || (wasIdent && (*ident == m_vm->propertyNames->get || *ident == m_vm->propertyNames->set)))
2826             nextExpectIdentifier(LexerFlagsIgnoreReservedWords);
2827         else
2828             nextExpectIdentifier(LexerFlagsIgnoreReservedWords | TreeBuilder::DontBuildKeywords);
2829
2830         if (match(COLON)) {
2831             next();
2832             TreeExpression node = parseAssignmentExpression(context);
2833             failIfFalse(node, "Cannot parse expression for property declaration");
2834             context.setEndOffset(node, m_lexer->currentOffset());
2835             return context.createProperty(ident, node, PropertyNode::Constant, PropertyNode::Unknown, complete);
2836         }
2837
2838         if (match(OPENPAREN)) {
2839             auto method = parsePropertyMethod(context, ident);
2840             propagateError();
2841             return context.createProperty(ident, method, PropertyNode::Constant, PropertyNode::KnownDirect, complete);
2842         }
2843
2844         failIfFalse(wasIdent, "Expected an identifier as property name");
2845
2846         if (match(COMMA) || match(CLOSEBRACE)) {
2847             JSTextPosition start = tokenStartPosition();
2848             JSTokenLocation location(tokenLocation());
2849             currentScope()->useVariable(ident, m_vm->propertyNames->eval == *ident);
2850             TreeExpression node = context.createResolve(location, ident, start);
2851             return context.createProperty(ident, node, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Shorthand), PropertyNode::KnownDirect, complete);
2852         }
2853
2854         PropertyNode::Type type;
2855         if (*ident == m_vm->propertyNames->get)
2856             type = PropertyNode::Getter;
2857         else if (*ident == m_vm->propertyNames->set)
2858             type = PropertyNode::Setter;
2859         else
2860             failWithMessage("Expected a ':' following the property name '", ident->impl(), "'");
2861         return parseGetterSetter(context, complete, type, getterOrSetterStartOffset);
2862     }
2863     case DOUBLE:
2864     case INTEGER: {
2865         double propertyName = m_token.m_data.doubleValue;
2866         next();
2867
2868         if (match(OPENPAREN)) {
2869             const Identifier& ident = m_parserArena.identifierArena().makeNumericIdentifier(const_cast<VM*>(m_vm), propertyName);
2870             auto method = parsePropertyMethod(context, &ident);
2871             propagateError();
2872             return context.createProperty(&ident, method, PropertyNode::Constant, PropertyNode::Unknown, complete);
2873         }
2874
2875         consumeOrFail(COLON, "Expected ':' after property name");
2876         TreeExpression node = parseAssignmentExpression(context);
2877         failIfFalse(node, "Cannot parse expression for property declaration");
2878         context.setEndOffset(node, m_lexer->currentOffset());
2879         return context.createProperty(const_cast<VM*>(m_vm), m_parserArena, propertyName, node, PropertyNode::Constant, PropertyNode::Unknown, complete);
2880     }
2881     case OPENBRACKET: {
2882         next();
2883         auto propertyName = parseAssignmentExpression(context);
2884         failIfFalse(propertyName, "Cannot parse computed property name");
2885         handleProductionOrFail(CLOSEBRACKET, "]", "end", "computed property name");
2886
2887         if (match(OPENPAREN)) {
2888             auto method = parsePropertyMethod(context, &m_vm->propertyNames->nullIdentifier);
2889             propagateError();
2890             return context.createProperty(propertyName, method, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Computed), PropertyNode::KnownDirect, complete);
2891         }
2892
2893         consumeOrFail(COLON, "Expected ':' after property name");
2894         TreeExpression node = parseAssignmentExpression(context);
2895         failIfFalse(node, "Cannot parse expression for property declaration");
2896         context.setEndOffset(node, m_lexer->currentOffset());
2897         return context.createProperty(propertyName, node, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Computed), PropertyNode::Unknown, complete);
2898     }
2899     default:
2900         failIfFalse(m_token.m_type & KeywordTokenFlag, "Expected a property name");
2901         goto namedProperty;
2902     }
2903 }
2904
2905 template <typename LexerType>
2906 template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePropertyMethod(TreeBuilder& context, const Identifier* methodName)
2907 {
2908     JSTokenLocation methodLocation(tokenLocation());
2909     unsigned methodStart = tokenStart();
2910     ParserFunctionInfo<TreeBuilder> methodInfo;
2911     failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, SourceParseMode::MethodMode, false, ConstructorKind::None, SuperBinding::NotNeeded, methodStart, methodInfo, StandardFunctionParseType)), "Cannot parse this method");
2912     methodInfo.name = methodName;
2913     return context.createFunctionExpr(methodLocation, methodInfo);
2914 }
2915
2916 template <typename LexerType>
2917 template <class TreeBuilder> TreeProperty Parser<LexerType>::parseGetterSetter(TreeBuilder& context, bool strict, PropertyNode::Type type, unsigned getterOrSetterStartOffset,
2918     ConstructorKind constructorKind, SuperBinding superBinding)
2919 {
2920     const Identifier* stringPropertyName = 0;
2921     double numericPropertyName = 0;
2922     TreeExpression computedPropertyName = 0;
2923
2924     JSTokenLocation location(tokenLocation());
2925
2926     if (match(IDENT) || match(STRING) || isLETMaskedAsIDENT()) {
2927         stringPropertyName = m_token.m_data.ident;
2928         semanticFailIfTrue(superBinding == SuperBinding::Needed && *stringPropertyName == m_vm->propertyNames->prototype,
2929             "Cannot declare a static method named 'prototype'");
2930         semanticFailIfTrue(superBinding == SuperBinding::Needed && *stringPropertyName == m_vm->propertyNames->constructor,
2931             "Cannot declare a getter or setter named 'constructor'");
2932         next();
2933     } else if (match(DOUBLE) || match(INTEGER)) {
2934         numericPropertyName = m_token.m_data.doubleValue;
2935         next();
2936     } else if (match(OPENBRACKET)) {
2937         next();
2938         computedPropertyName = parseAssignmentExpression(context);
2939         failIfFalse(computedPropertyName, "Cannot parse computed property name");
2940         handleProductionOrFail(CLOSEBRACKET, "]", "end", "computed property name");
2941     } else
2942         failDueToUnexpectedToken();
2943
2944     ParserFunctionInfo<TreeBuilder> info;
2945     if (type & PropertyNode::Getter) {
2946         failIfFalse(match(OPENPAREN), "Expected a parameter list for getter definition");
2947         failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, SourceParseMode::GetterMode, false, constructorKind, superBinding,
2948             getterOrSetterStartOffset, info, StandardFunctionParseType)), "Cannot parse getter definition");
2949     } else {
2950         failIfFalse(match(OPENPAREN), "Expected a parameter list for setter definition");
2951         failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, SourceParseMode::SetterMode, false, constructorKind, superBinding,
2952             getterOrSetterStartOffset, info, StandardFunctionParseType)), "Cannot parse setter definition");
2953     }
2954
2955     if (stringPropertyName)
2956         return context.createGetterOrSetterProperty(location, type, strict, stringPropertyName, info, superBinding);
2957
2958     if (computedPropertyName)
2959         return context.createGetterOrSetterProperty(location, static_cast<PropertyNode::Type>(type | PropertyNode::Computed), strict, computedPropertyName, info, superBinding);
2960
2961     return context.createGetterOrSetterProperty(const_cast<VM*>(m_vm), m_parserArena, location, type, strict, numericPropertyName, info, superBinding);
2962 }
2963
2964 template <typename LexerType>
2965 template <class TreeBuilder> bool Parser<LexerType>::shouldCheckPropertyForUnderscoreProtoDuplicate(TreeBuilder& context, const TreeProperty& property)
2966 {
2967     if (m_syntaxAlreadyValidated)
2968         return false;
2969
2970     if (!context.getName(property))
2971         return false;
2972
2973     // A Constant property that is not a Computed or Shorthand Constant property.
2974     return context.getType(property) == PropertyNode::Constant;
2975 }
2976
2977 template <typename LexerType>
2978 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseObjectLiteral(TreeBuilder& context)
2979 {
2980     auto savePoint = createSavePoint();
2981     consumeOrFailWithFlags(OPENBRACE, TreeBuilder::DontBuildStrings, "Expected opening '{' at the start of an object literal");
2982
2983     int oldNonLHSCount = m_nonLHSCount;
2984
2985     JSTokenLocation location(tokenLocation());    
2986     if (match(CLOSEBRACE)) {
2987         next();
2988         return context.createObjectLiteral(location);
2989     }
2990     
2991     TreeProperty property = parseProperty(context, false);
2992     failIfFalse(property, "Cannot parse object literal property");
2993
2994     if (!m_syntaxAlreadyValidated && context.getType(property) & (PropertyNode::Getter | PropertyNode::Setter)) {
2995         restoreSavePoint(savePoint);
2996         return parseStrictObjectLiteral(context);
2997     }
2998
2999     bool seenUnderscoreProto = false;
3000     if (shouldCheckPropertyForUnderscoreProtoDuplicate(context, property))
3001         seenUnderscoreProto = *context.getName(property) == m_vm->propertyNames->underscoreProto;
3002
3003     TreePropertyList propertyList = context.createPropertyList(location, property);
3004     TreePropertyList tail = propertyList;
3005     while (match(COMMA)) {
3006         next(TreeBuilder::DontBuildStrings);
3007         if (match(CLOSEBRACE))
3008             break;
3009         JSTokenLocation propertyLocation(tokenLocation());
3010         property = parseProperty(context, false);
3011         failIfFalse(property, "Cannot parse object literal property");
3012         if (!m_syntaxAlreadyValidated && context.getType(property) & (PropertyNode::Getter | PropertyNode::Setter)) {
3013             restoreSavePoint(savePoint);
3014             return parseStrictObjectLiteral(context);
3015         }
3016         if (shouldCheckPropertyForUnderscoreProtoDuplicate(context, property)) {
3017             if (*context.getName(property) == m_vm->propertyNames->underscoreProto) {
3018                 semanticFailIfTrue(seenUnderscoreProto, "Attempted to redefine __proto__ property");
3019                 seenUnderscoreProto = true;
3020             }
3021         }
3022         tail = context.createPropertyList(propertyLocation, property, tail);
3023     }
3024
3025     location = tokenLocation();
3026     handleProductionOrFail(CLOSEBRACE, "}", "end", "object literal");
3027     
3028     m_nonLHSCount = oldNonLHSCount;
3029     
3030     return context.createObjectLiteral(location, propertyList);
3031 }
3032
3033 template <typename LexerType>
3034 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseStrictObjectLiteral(TreeBuilder& context)
3035 {
3036     consumeOrFail(OPENBRACE, "Expected opening '{' at the start of an object literal");
3037     
3038     int oldNonLHSCount = m_nonLHSCount;
3039
3040     JSTokenLocation location(tokenLocation());
3041     if (match(CLOSEBRACE)) {
3042         next();
3043         return context.createObjectLiteral(location);
3044     }
3045     
3046     TreeProperty property = parseProperty(context, true);
3047     failIfFalse(property, "Cannot parse object literal property");
3048
3049     bool seenUnderscoreProto = false;
3050     if (shouldCheckPropertyForUnderscoreProtoDuplicate(context, property))
3051         seenUnderscoreProto = *context.getName(property) == m_vm->propertyNames->underscoreProto;
3052
3053     TreePropertyList propertyList = context.createPropertyList(location, property);
3054     TreePropertyList tail = propertyList;
3055     while (match(COMMA)) {
3056         next();
3057         if (match(CLOSEBRACE))
3058             break;
3059         JSTokenLocation propertyLocation(tokenLocation());
3060         property = parseProperty(context, true);
3061         failIfFalse(property, "Cannot parse object literal property");
3062         if (shouldCheckPropertyForUnderscoreProtoDuplicate(context, property)) {
3063             if (*context.getName(property) == m_vm->propertyNames->underscoreProto) {
3064                 semanticFailIfTrue(seenUnderscoreProto, "Attempted to redefine __proto__ property");
3065                 seenUnderscoreProto = true;
3066             }
3067         }
3068         tail = context.createPropertyList(propertyLocation, property, tail);
3069     }
3070
3071     location = tokenLocation();
3072     handleProductionOrFail(CLOSEBRACE, "}", "end", "object literal");
3073
3074     m_nonLHSCount = oldNonLHSCount;
3075
3076     return context.createObjectLiteral(location, propertyList);
3077 }
3078
3079 template <typename LexerType>
3080 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseArrayLiteral(TreeBuilder& context)
3081 {
3082     consumeOrFailWithFlags(OPENBRACKET, TreeBuilder::DontBuildStrings, "Expected an opening '[' at the beginning of an array literal");
3083     
3084     int oldNonLHSCount = m_nonLHSCount;
3085     
3086     int elisions = 0;
3087     while (match(COMMA)) {
3088         next(TreeBuilder::DontBuildStrings);
3089         elisions++;
3090     }
3091     if (match(CLOSEBRACKET)) {
3092         JSTokenLocation location(tokenLocation());
3093         next(TreeBuilder::DontBuildStrings);
3094         return context.createArray(location, elisions);
3095     }
3096     
3097     TreeExpression elem;
3098     if (UNLIKELY(match(DOTDOTDOT))) {
3099         auto spreadLocation = m_token.m_location;
3100         auto start = m_token.m_startPosition;
3101         auto divot = m_token.m_endPosition;
3102         next();
3103         auto spreadExpr = parseAssignmentExpression(context);
3104         failIfFalse(spreadExpr, "Cannot parse subject of a spread operation");
3105         elem = context.createSpreadExpression(spreadLocation, spreadExpr, start, divot, m_lastTokenEndPosition);
3106     } else
3107         elem = parseAssignmentExpression(context);
3108     failIfFalse(elem, "Cannot parse array literal element");
3109     typename TreeBuilder::ElementList elementList = context.createElementList(elisions, elem);
3110     typename TreeBuilder::ElementList tail = elementList;
3111     elisions = 0;
3112     while (match(COMMA)) {
3113         next(TreeBuilder::DontBuildStrings);
3114         elisions = 0;
3115         
3116         while (match(COMMA)) {
3117             next();
3118             elisions++;
3119         }
3120         
3121         if (match(CLOSEBRACKET)) {
3122             JSTokenLocation location(tokenLocation());
3123             next(TreeBuilder::DontBuildStrings);
3124             return context.createArray(location, elisions, elementList);
3125         }
3126         if (UNLIKELY(match(DOTDOTDOT))) {
3127             auto spreadLocation = m_token.m_location;
3128             auto start = m_token.m_startPosition;
3129             auto divot = m_token.m_endPosition;
3130             next();
3131             TreeExpression elem = parseAssignmentExpression(context);
3132             failIfFalse(elem, "Cannot parse subject of a spread operation");
3133             auto spread = context.createSpreadExpression(spreadLocation, elem, start, divot, m_lastTokenEndPosition);
3134             tail = context.createElementList(tail, elisions, spread);
3135             continue;
3136         }
3137         TreeExpression elem = parseAssignmentExpression(context);
3138         failIfFalse(elem, "Cannot parse array literal element");
3139         tail = context.createElementList(tail, elisions, elem);
3140     }
3141
3142     JSTokenLocation location(tokenLocation());
3143     if (!consume(CLOSEBRACKET)) {
3144         failIfFalse(match(DOTDOTDOT), "Expected either a closing ']' or a ',' following an array element");
3145         semanticFail("The '...' operator should come before a target expression");
3146     }
3147     
3148     m_nonLHSCount = oldNonLHSCount;
3149     
3150     return context.createArray(location, elementList);
3151 }
3152
3153 #if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
3154 template <typename LexerType>
3155 template <class TreeBuilder> typename TreeBuilder::TemplateString Parser<LexerType>::parseTemplateString(TreeBuilder& context, bool isTemplateHead, typename LexerType::RawStringsBuildMode rawStringsBuildMode, bool& elementIsTail)
3156 {
3157     if (!isTemplateHead) {
3158         matchOrFail(CLOSEBRACE, "Expected a closing '}' following an expression in template literal");
3159         // Re-scan the token to recognize it as Template Element.
3160         m_token.m_type = m_lexer->scanTrailingTemplateString(&m_token, rawStringsBuildMode);
3161     }
3162     matchOrFail(TEMPLATE, "Expected an template element");
3163     const Identifier* cooked = m_token.m_data.cooked;
3164     const Identifier* raw = m_token.m_data.raw;
3165     elementIsTail = m_token.m_data.isTail;
3166     JSTokenLocation location(tokenLocation());
3167     next();
3168     return context.createTemplateString(location, *cooked, *raw);
3169 }
3170
3171 template <typename LexerType>
3172 template <class TreeBuilder> typename TreeBuilder::TemplateLiteral Parser<LexerType>::parseTemplateLiteral(TreeBuilder& context, typename LexerType::RawStringsBuildMode rawStringsBuildMode)
3173 {
3174     JSTokenLocation location(tokenLocation());
3175     bool elementIsTail = false;
3176
3177     auto headTemplateString = parseTemplateString(context, true, rawStringsBuildMode, elementIsTail);
3178     failIfFalse(headTemplateString, "Cannot parse head template element");
3179
3180     typename TreeBuilder::TemplateStringList templateStringList = context.createTemplateStringList(headTemplateString);
3181     typename TreeBuilder::TemplateStringList templateStringTail = templateStringList;
3182
3183     if (elementIsTail)
3184         return context.createTemplateLiteral(location, templateStringList);
3185
3186     failIfTrue(match(CLOSEBRACE), "Template literal expression cannot be empty");
3187     TreeExpression expression = parseExpression(context);
3188     failIfFalse(expression, "Cannot parse expression in template literal");
3189
3190     typename TreeBuilder::TemplateExpressionList templateExpressionList = context.createTemplateExpressionList(expression);
3191     typename TreeBuilder::TemplateExpressionList templateExpressionTail = templateExpressionList;
3192
3193     auto templateString = parseTemplateString(context, false, rawStringsBuildMode, elementIsTail);
3194     failIfFalse(templateString, "Cannot parse template element");
3195     templateStringTail = context.createTemplateStringList(templateStringTail, templateString);
3196
3197     while (!elementIsTail) {
3198         failIfTrue(match(CLOSEBRACE), "Template literal expression cannot be empty");
3199         TreeExpression expression = parseExpression(context);
3200         failIfFalse(expression, "Cannot parse expression in template literal");
3201
3202         templateExpressionTail = context.createTemplateExpressionList(templateExpressionTail, expression);
3203
3204         auto templateString = parseTemplateString(context, false, rawStringsBuildMode, elementIsTail);
3205         failIfFalse(templateString, "Cannot parse template element");
3206         templateStringTail = context.createTemplateStringList(templateStringTail, templateString);
3207     }
3208
3209     return context.createTemplateLiteral(location, templateStringList, templateExpressionList);
3210 }
3211 #endif
3212
3213 template <typename LexerType>
3214 template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePrimaryExpression(TreeBuilder& context)
3215 {
3216     failIfStackOverflow();
3217     switch (m_token.m_type) {
3218     case FUNCTION: {
3219         JSTokenLocation location(tokenLocation());
3220         unsigned functionKeywordStart = tokenStart();
3221         next();
3222         ParserFunctionInfo<TreeBuilder> info;
3223         info.name = &m_vm->propertyNames->nullIdentifier;
3224         failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, SourceParseMode::NormalFunctionMode, false, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, info, StandardFunctionParseType)), "Cannot parse function expression");
3225         return context.createFunctionExpr(location, info);
3226     }
3227 #if ENABLE(ES6_CLASS_SYNTAX)
3228     case CLASSTOKEN: {
3229         ParserClassInfo<TreeBuilder> info;
3230         return parseClass(context, FunctionNoRequirements, info);
3231     }
3232 #endif
3233     case OPENBRACE:
3234         if (strictMode())
3235             return parseStrictObjectLiteral(context);
3236         return parseObjectLiteral(context);
3237     case OPENBRACKET:
3238         return parseArrayLiteral(context);
3239     case OPENPAREN: {
3240         next();
3241         int oldNonLHSCount = m_nonLHSCount;
3242         TreeExpression result = parseExpression(context);
3243         m_nonLHSCount = oldNonLHSCount;
3244         handleProductionOrFail(CLOSEPAREN, ")", "end", "compound expression");
3245         return result;
3246     }
3247     case THISTOKEN: {
3248         JSTokenLocation location(tokenLocation());
3249         next();
3250         return context.createThisExpr(location, m_thisTDZMode);
3251     }
3252     case IDENT: {
3253     identifierExpression:
3254         JSTextPosition start = tokenStartPosition();
3255         const Identifier* ident = m_token.m_data.ident;
3256         JSTokenLocation location(tokenLocation());
3257         next();
3258         currentScope()->useVariable(ident, m_vm->propertyNames->eval == *ident);
3259         m_lastIdentifier = ident;
3260         return context.createResolve(location, ident, start);
3261     }
3262     case STRING: {
3263         const Identifier* ident = m_token.m_data.ident;
3264         JSTokenLocation location(tokenLocation());
3265         next();
3266         return context.createString(location, ident);
3267     }
3268     case DOUBLE: {
3269         double d = m_token.m_data.doubleValue;
3270         JSTokenLocation location(tokenLocation());
3271         next();
3272         return context.createDoubleExpr(location, d);
3273     }
3274     case INTEGER: {
3275         double d = m_token.m_data.doubleValue;
3276         JSTokenLocation location(tokenLocation());
3277         next();
3278         return context.createIntegerExpr(location, d);
3279     }
3280     case NULLTOKEN: {
3281         JSTokenLocation location(tokenLocation());
3282         next();
3283         return context.createNull(location);
3284     }
3285     case TRUETOKEN: {
3286         JSTokenLocation location(tokenLocation());
3287         next();
3288         return context.createBoolean(location, true);
3289     }
3290     case FALSETOKEN: {
3291         JSTokenLocation location(tokenLocation());
3292         next();
3293         return context.createBoolean(location, false);
3294     }
3295     case DIVEQUAL:
3296     case DIVIDE: {
3297         /* regexp */
3298         const Identifier* pattern;
3299         const Identifier* flags;
3300         if (match(DIVEQUAL))
3301             failIfFalse(m_lexer->scanRegExp(pattern, flags, '='), "Invalid regular expression");
3302         else
3303             failIfFalse(m_lexer->scanRegExp(pattern, flags), "Invalid regular expression");
3304         
3305         JSTextPosition start = tokenStartPosition();
3306         JSTokenLocation location(tokenLocation());
3307         next();
3308         TreeExpression re = context.createRegExp(location, *pattern, *flags, start);
3309         if (!re) {
3310             const char* yarrErrorMsg = Yarr::checkSyntax(pattern->string());
3311             regexFail(yarrErrorMsg);
3312         }
3313         return re;
3314     }
3315 #if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
3316     case TEMPLATE:
3317         return parseTemplateLiteral(context, LexerType::RawStringsBuildMode::DontBuildRawStrings);
3318 #endif
3319     case LET:
3320         if (!strictMode())
3321             goto identifierExpression;
3322         FALLTHROUGH;
3323     default:
3324         failDueToUnexpectedToken();
3325     }
3326 }
3327
3328 template <typename LexerType>
3329 template <class TreeBuilder> TreeArguments Parser<LexerType>::parseArguments(TreeBuilder& context, SpreadMode mode)
3330 {
3331     consumeOrFailWithFlags(OPENPAREN, TreeBuilder::DontBuildStrings, "Expected opening '(' at start of argument list");
3332     JSTokenLocation location(tokenLocation());
3333     if (match(CLOSEPAREN)) {
3334         next(TreeBuilder::DontBuildStrings);
3335         return context.createArguments();
3336     }
3337     if (match(DOTDOTDOT) && mode == AllowSpread) {
3338         JSTokenLocation spreadLocation(tokenLocation());
3339         auto start = m_token.m_startPosition;
3340         auto divot = m_token.m_endPosition;
3341         next();
3342         auto spreadExpr = parseAssignmentExpression(context);
3343         auto end = m_lastTokenEndPosition;
3344         if (!spreadExpr)
3345             failWithMessage("Cannot parse spread expression");
3346         if (!consume(CLOSEPAREN)) {
3347             if (match(COMMA))
3348                 semanticFail("Spread operator may only be applied to the last argument passed to a function");
3349             handleProductionOrFail(CLOSEPAREN, ")", "end", "argument list");
3350         }
3351         auto spread = context.createSpreadExpression(spreadLocation, spreadExpr, start, divot, end);
3352         TreeArgumentsList argList = context.createArgumentsList(location, spread);
3353         return context.createArguments(argList);
3354     }
3355     TreeExpression firstArg = parseAssignmentExpression(context);
3356     failIfFalse(firstArg, "Cannot parse function argument");
3357     
3358     TreeArgumentsList argList = context.createArgumentsList(location, firstArg);
3359     TreeArgumentsList tail = argList;
3360     while (match(COMMA)) {
3361         JSTokenLocation argumentLocation(tokenLocation());
3362         next(TreeBuilder::DontBuildStrings);
3363         TreeExpression arg = parseAssignmentExpression(context);
3364         failIfFalse(arg, "Cannot parse function argument");
3365         tail = context.createArgumentsList(argumentLocation, tail, arg);
3366     }
3367     semanticFailIfTrue(match(DOTDOTDOT), "The '...' operator should come before the target expression");
3368     handleProductionOrFail(CLOSEPAREN, ")", "end", "argument list");
3369     return context.createArguments(argList);
3370 }
3371
3372 template <typename LexerType>
3373 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseMemberExpression(TreeBuilder& context)
3374 {
3375     TreeExpression base = 0;
3376     JSTextPosition expressionStart = tokenStartPosition();
3377     int newCount = 0;
3378     JSTokenLocation startLocation = tokenLocation();
3379     JSTokenLocation location;
3380     while (match(NEW)) {
3381         next();
3382         newCount++;
3383     }
3384
3385 #if ENABLE(ES6_CLASS_SYNTAX)
3386     bool baseIsSuper = match(SUPER);
3387     semanticFailIfTrue(baseIsSuper && newCount, "Cannot use new with super");
3388 #else
3389     bool baseIsSuper = false;
3390 #endif
3391
3392     bool baseIsNewTarget = false;
3393     if (newCount && match(DOT)) {
3394         next();
3395         if (match(IDENT)) {
3396             const Identifier* ident = m_token.m_data.ident;
3397             if (m_vm->propertyNames->target == *ident) {
3398                 semanticFailIfFalse(currentScope()->isFunction(), "new.target is only valid inside functions");
3399                 baseIsNewTarget = true;
3400                 base = context.createNewTargetExpr(location);
3401                 newCount--;
3402                 next();
3403             } else
3404                 failWithMessage("\"new.\" can only followed with target");
3405         } else
3406             failDueToUnexpectedToken();
3407     }
3408
3409     if (baseIsSuper) {
3410         semanticFailIfFalse(currentScope()->isFunction(), "super is only valid inside functions");
3411         base = context.createSuperExpr(location);
3412         next();
3413         currentScope()->setNeedsSuperBinding();
3414     } else if (!baseIsNewTarget)
3415         base = parsePrimaryExpression(context);
3416
3417     failIfFalse(base, "Cannot parse base expression");
3418     while (true) {
3419         location = tokenLocation();
3420         switch (m_token.m_type) {
3421         case OPENBRACKET: {
3422             m_nonTrivialExpressionCount++;
3423             JSTextPosition expressionEnd = lastTokenEndPosition();
3424             next();
3425             int nonLHSCount = m_nonLHSCount;
3426             int initialAssignments = m_assignmentCount;
3427             TreeExpression property = parseExpression(context);
3428             failIfFalse(property, "Cannot parse subscript expression");
3429             base = context.createBracketAccess(location, base, property, initialAssignments != m_assignmentCount, expressionStart, expressionEnd, tokenEndPosition());
3430             handleProductionOrFail(CLOSEBRACKET, "]", "end", "subscript expression");
3431             m_nonLHSCount = nonLHSCount;
3432             break;
3433         }
3434         case OPENPAREN: {
3435             m_nonTrivialExpressionCount++;
3436             int nonLHSCount = m_nonLHSCount;
3437             if (newCount) {
3438                 newCount--;
3439                 JSTextPosition expressionEnd = lastTokenEndPosition();
3440                 TreeArguments arguments = parseArguments(context, AllowSpread);
3441                 failIfFalse(arguments, "Cannot parse call arguments");
3442                 base = context.createNewExpr(location, base, arguments, expressionStart, expressionEnd, lastTokenEndPosition());
3443             } else {
3444                 JSTextPosition expressionEnd = lastTokenEndPosition();
3445                 TreeArguments arguments = parseArguments(context, AllowSpread);
3446                 failIfFalse(arguments, "Cannot parse call arguments");
3447                 if (baseIsSuper)
3448                     currentScope()->setHasDirectSuper();
3449                 base = context.makeFunctionCallNode(startLocation, base, arguments, expressionStart, expressionEnd, lastTokenEndPosition());
3450             }
3451             m_nonLHSCount = nonLHSCount;
3452             break;
3453         }
3454         case DOT: {
3455             m_nonTrivialExpressionCount++;
3456             JSTextPosition expressionEnd = lastTokenEndPosition();
3457             nextExpectIdentifier(LexerFlagsIgnoreReservedWords | TreeBuilder::DontBuildKeywords);
3458             matchOrFail(IDENT, "Expected a property name after '.'");
3459             base = context.createDotAccess(location, base, m_token.m_data.ident, expressionStart, expressionEnd, tokenEndPosition());
3460             next();
3461             break;
3462         }
3463 #if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
3464         case TEMPLATE: {
3465             semanticFailIfTrue(baseIsSuper, "Cannot use super as tag for tagged templates");
3466             JSTextPosition expressionEnd = lastTokenEndPosition();
3467             int nonLHSCount = m_nonLHSCount;
3468             typename TreeBuilder::TemplateLiteral templateLiteral = parseTemplateLiteral(context, LexerType::RawStringsBuildMode::BuildRawStrings);
3469             failIfFalse(templateLiteral, "Cannot parse template literal");
3470             base = context.createTaggedTemplate(location, base, templateLiteral, expressionStart, expressionEnd, lastTokenEndPosition());
3471             m_nonLHSCount = nonLHSCount;
3472             break;
3473         }
3474 #endif
3475         default:
3476             goto endMemberExpression;
3477         }
3478         baseIsSuper = false;
3479     }
3480 endMemberExpression:
3481     semanticFailIfTrue(baseIsSuper, "Cannot reference super");
3482     while (newCount--)
3483         base = context.createNewExpr(location, base, expressionStart, lastTokenEndPosition());
3484     return base;
3485 }
3486
3487 template <typename LexerType>
3488 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseArrowFunctionExpression(TreeBuilder& context)
3489 {
3490     JSTokenLocation location;
3491
3492     unsigned functionKeywordStart = tokenStart();
3493     location = tokenLocation();
3494     ParserFunctionInfo<TreeBuilder> info;
3495     info.name = &m_vm->propertyNames->nullIdentifier;
3496     failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, SourceParseMode::ArrowFunctionMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, info, ArrowFunctionParseType)), "Cannot parse arrow function expression");
3497
3498     return context.createArrowFunctionExpr(location, info);
3499 }
3500
3501 static const char* operatorString(bool prefix, unsigned tok)
3502 {
3503     switch (tok) {
3504     case MINUSMINUS:
3505     case AUTOMINUSMINUS:
3506         return prefix ? "prefix-decrement" : "decrement";
3507
3508     case PLUSPLUS:
3509     case AUTOPLUSPLUS:
3510         return prefix ? "prefix-increment" : "increment";
3511
3512     case EXCLAMATION:
3513         return "logical-not";
3514
3515     case TILDE:
3516         return "bitwise-not";
3517     
3518     case TYPEOF:
3519         return "typeof";
3520     
3521     case VOIDTOKEN:
3522         return "void";
3523     
3524     case DELETETOKEN:
3525         return "delete";
3526     }
3527     RELEASE_ASSERT_NOT_REACHED();
3528     return "error";
3529 }
3530
3531 template <typename LexerType>
3532 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseUnaryExpression(TreeBuilder& context)
3533 {
3534     typename TreeBuilder::UnaryExprContext unaryExprContext(context);
3535     AllowInOverride allowInOverride(this);
3536     int tokenStackDepth = 0;
3537     bool modifiesExpr = false;
3538     bool requiresLExpr = false;
3539     unsigned lastOperator = 0;
3540     while (isUnaryOp(m_token.m_type)) {
3541         if (strictMode()) {
3542             switch (m_token.m_type) {
3543             case PLUSPLUS:
3544             case MINUSMINUS:
3545             case AUTOPLUSPLUS:
3546             case AUTOMINUSMINUS:
3547                 semanticFailIfTrue(requiresLExpr, "The ", operatorString(true, lastOperator), " operator requires a reference expression");
3548                 modifiesExpr = true;
3549                 requiresLExpr = true;
3550                 break;
3551             case DELETETOKEN:
3552                 semanticFailIfTrue(requiresLExpr, "The ", operatorString(true, lastOperator), " operator requires a reference expression");
3553                 requiresLExpr = true;
3554                 break;
3555             default:
3556                 semanticFailIfTrue(requiresLExpr, "The ", operatorString(true, lastOperator), " operator requires a reference expression");
3557                 break;
3558             }
3559         }
3560         lastOperator = m_token.m_type;
3561         m_nonLHSCount++;
3562         context.appendUnaryToken(tokenStackDepth, m_token.m_type, tokenStartPosition());
3563         next();
3564         m_nonTrivialExpressionCount++;
3565     }
3566     JSTextPosition subExprStart = tokenStartPosition();
3567     ASSERT(subExprStart.offset >= subExprStart.lineStartOffset);
3568     JSTokenLocation location(tokenLocation());
3569     TreeExpression expr = parseMemberExpression(context);
3570     if (!expr) {
3571         if (lastOperator)
3572             failWithMessage("Cannot parse subexpression of ", operatorString(true, lastOperator), "operator");
3573         failWithMessage("Cannot parse member expression");
3574     }
3575     bool isEvalOrArguments = false;
3576     if (strictMode() && !m_syntaxAlreadyValidated) {
3577         if (context.isResolve(expr))
3578             isEvalOrArguments = *m_lastIdentifier == m_vm->propertyNames->eval || *m_lastIdentifier == m_vm->propertyNames->arguments;
3579     }
3580     failIfTrueIfStrict(isEvalOrArguments && modifiesExpr, "Cannot modify '", m_lastIdentifier->impl(), "' in strict mode");
3581     switch (m_token.m_type) {
3582     case PLUSPLUS:
3583         m_nonTrivialExpressionCount++;
3584         m_nonLHSCount++;
3585         expr = context.makePostfixNode(location, expr, OpPlusPlus, subExprStart, lastTokenEndPosition(), tokenEndPosition());
3586         m_assignmentCount++;
3587         failIfTrueIfStrict(isEvalOrArguments, "Cannot modify '", m_lastIdentifier->impl(), "' in strict mode");
3588         semanticFailIfTrue(requiresLExpr, "The ", operatorString(false, lastOperator), " operator requires a reference expression");
3589         lastOperator = PLUSPLUS;
3590         next();
3591         break;
3592     case MINUSMINUS:
3593         m_nonTrivialExpressionCount++;
3594         m_nonLHSCount++;
3595         expr = context.makePostfixNode(location, expr, OpMinusMinus, subExprStart, lastTokenEndPosition(), tokenEndPosition());
3596         m_assignmentCount++;
3597         failIfTrueIfStrict(isEvalOrArguments, "'", m_lastIdentifier->impl(), "' cannot be modified in strict mode");
3598         semanticFailIfTrue(requiresLExpr, "The ", operatorString(false, lastOperator), " operator requires a reference expression");
3599         lastOperator = PLUSPLUS;
3600         next();
3601         break;
3602     default:
3603         break;
3604     }
3605     
3606     JSTextPosition end = lastTokenEndPosition();
3607
3608     if (!TreeBuilder::CreatesAST && (m_syntaxAlreadyValidated || !strictMode()))
3609         return expr;
3610
3611     location = tokenLocation();
3612     location.line = m_lexer->lastLineNumber();
3613     while (tokenStackDepth) {
3614         switch (context.unaryTokenStackLastType(tokenStackDepth)) {
3615         case EXCLAMATION:
3616             expr = context.createLogicalNot(location, expr);
3617             break;
3618         case TILDE:
3619             expr = context.makeBitwiseNotNode(location, expr);
3620             break;
3621         case MINUS:
3622             expr = context.makeNegateNode(location, expr);
3623             break;
3624         case PLUS:
3625             expr = context.createUnaryPlus(location, expr);
3626             break;
3627         case PLUSPLUS:
3628         case AUTOPLUSPLUS:
3629             expr = context.makePrefixNode(location, expr, OpPlusPlus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end);
3630             m_assignmentCount++;
3631             break;
3632         case MINUSMINUS:
3633         case AUTOMINUSMINUS:
3634             expr = context.makePrefixNode(location, expr, OpMinusMinus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end);
3635             m_assignmentCount++;
3636             break;
3637         case TYPEOF:
3638             expr = context.makeTypeOfNode(location, expr);
3639             break;
3640         case VOIDTOKEN:
3641             expr = context.createVoid(location, expr);
3642             break;
3643         case DELETETOKEN:
3644             failIfTrueIfStrict(context.isResolve(expr), "Cannot delete unqualified property '", m_lastIdentifier->impl(), "' in strict mode");
3645             expr = context.makeDeleteNode(location, expr, context.unaryTokenStackLastStart(tokenStackDepth), end, end);
3646             break;
3647         default:
3648             // If we get here something has gone horribly horribly wrong
3649             CRASH();
3650         }
3651         subExprStart = context.unaryTokenStackLastStart(tokenStackDepth);
3652         context.unaryTokenStackRemoveLast(tokenStackDepth);
3653     }
3654     return expr;
3655 }
3656
3657
3658 template <typename LexerType> void Parser<LexerType>::printUnexpectedTokenText(WTF::PrintStream& out)
3659 {
3660     switch (m_token.m_type) {
3661     case EOFTOK:
3662         out.print("Unexpected end of script");
3663         return;
3664     case UNTERMINATED_IDENTIFIER_ESCAPE_ERRORTOK:
3665     case UNTERMINATED_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK:
3666         out.print("Incomplete unicode escape in identifier: '", getToken(), "'");
3667         return;
3668     case UNTERMINATED_MULTILINE_COMMENT_ERRORTOK:
3669         out.print("Unterminated multiline comment");
3670         return;
3671     case UNTERMINATED_NUMERIC_LITERAL_ERRORTOK:
3672         out.print("Unterminated numeric literal '", getToken(), "'");
3673         return;
3674     case UNTERMINATED_STRING_LITERAL_ERRORTOK:
3675         out.print("Unterminated string literal '", getToken(), "'");
3676         return;
3677     case INVALID_IDENTIFIER_ESCAPE_ERRORTOK:
3678         out.print("Invalid escape in identifier: '", getToken(), "'");
3679         return;
3680     case INVALID_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK:
3681         out.print("Invalid unicode escape in identifier: '", getToken(), "'");
3682         return;
3683     case INVALID_NUMERIC_LITERAL_ERRORTOK:
3684         out.print("Invalid numeric literal: '", getToken(), "'");
3685         return;
3686     case UNTERMINATED_OCTAL_NUMBER_ERRORTOK:
3687         out.print("Invalid use of octal: '", getToken(), "'");
3688         return;
3689     case INVALID_STRING_LITERAL_ERRORTOK:
3690         out.print("Invalid string literal: '", getToken(), "'");
3691         return;
3692     case ERRORTOK:
3693         out.print("Unrecognized token '", getToken(), "'");
3694         return;
3695     case STRING:
3696         out.print("Unexpected string literal ", getToken());
3697         return;
3698     case INTEGER:
3699     case DOUBLE:
3700         out.print("Unexpected number '", getToken(), "'");
3701         return;
3702     
3703     case RESERVED_IF_STRICT:
3704         out.print("Unexpected use of reserved word '", getToken(), "' in strict mode");
3705         return;
3706         
3707     case RESERVED:
3708         out.print("Unexpected use of reserved word '", getToken(), "'");
3709         return;
3710
3711     case INVALID_PRIVATE_NAME_ERRORTOK:
3712         out.print("Invalid private name '", getToken(), "'");
3713         return;
3714             
3715     case IDENT:
3716         out.print("Unexpected identifier '", getToken(), "'");
3717         return;
3718
3719     default:
3720         break;
3721     }
3722
3723     if (m_token.m_type & KeywordTokenFlag) {
3724         out.print("Unexpected keyword '", getToken(), "'");
3725         return;
3726     }
3727     
3728     out.print("Unexpected token '", getToken(), "'");
3729 }
3730
3731 // Instantiate the two flavors of Parser we need instead of putting most of this file in Parser.h
3732 template class Parser<Lexer<LChar>>;
3733 template class Parser<Lexer<UChar>>;
3734     
3735 } // namespace JSC