ES6 class syntax should allow static setters and getters
[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, FunctionParameters* parameters, 
195     const Identifier& name, JSParserBuiltinMode builtinMode, 
196     JSParserStrictMode strictMode, JSParserCodeType codeType, 
197     ConstructorKind defaultConstructorKind, ThisTDZMode thisTDZMode)
198     : m_vm(vm)
199     , m_source(&source)
200     , m_hasStackOverflow(false)
201     , m_allowsIn(true)
202     , m_assignmentCount(0)
203     , m_nonLHSCount(0)
204     , m_syntaxAlreadyValidated(source.provider()->isValid())
205     , m_statementDepth(0)
206     , m_nonTrivialExpressionCount(0)
207     , m_lastIdentifier(0)
208     , m_lastFunctionName(nullptr)
209     , m_sourceElements(0)
210     , m_parsingBuiltin(builtinMode == JSParserBuiltinMode::Builtin)
211     , m_defaultConstructorKind(defaultConstructorKind)
212     , m_thisTDZMode(thisTDZMode)
213 {
214     m_lexer = std::make_unique<LexerType>(vm, builtinMode);
215     m_lexer->setCode(source, &m_parserArena);
216     m_token.m_location.line = source.firstLine();
217     m_token.m_location.startOffset = source.startOffset();
218     m_token.m_location.endOffset = source.startOffset();
219     m_token.m_location.lineStartOffset = source.startOffset();
220     m_functionCache = vm->addSourceProviderCache(source.provider());
221     ScopeRef scope = pushScope();
222     if (codeType == JSParserCodeType::Function)
223         scope->setIsFunction();
224     if (strictMode == JSParserStrictMode::Strict)
225         scope->setStrictMode();
226     if (parameters) {
227         bool hadBindingParameters = false;
228         for (unsigned i = 0; i < parameters->size(); i++) {
229             auto parameter = parameters->at(i);
230             if (!parameter->isBindingNode()) {
231                 hadBindingParameters = true;
232                 continue;
233             }
234             scope->declareParameter(&static_cast<BindingNode*>(parameter)->boundProperty());
235         }
236         if (hadBindingParameters) {
237             Vector<Identifier> boundParameterNames;
238             for (unsigned i = 0; i < parameters->size(); i++) {
239                 auto parameter = parameters->at(i);
240                 if (parameter->isBindingNode())
241                     continue;
242                 parameter->collectBoundIdentifiers(boundParameterNames);
243             }
244             for (auto& boundParameterName : boundParameterNames)
245                 scope->declareVariable(&boundParameterName);
246         }
247     }
248     if (!name.isNull())
249         scope->declareCallee(&name);
250     next();
251 }
252
253 template <typename LexerType>
254 Parser<LexerType>::~Parser()
255 {
256 }
257
258 template <typename LexerType>
259 String Parser<LexerType>::parseInner()
260 {
261     String parseError = String();
262     
263     ASTBuilder context(const_cast<VM*>(m_vm), m_parserArena, const_cast<SourceCode*>(m_source));
264     if (m_lexer->isReparsing())
265         m_statementDepth--;
266     ScopeRef scope = currentScope();
267     SourceElements* sourceElements = parseSourceElements(context, CheckForStrictMode);
268     if (!sourceElements || !consume(EOFTOK)) {
269         if (hasError())
270             parseError = m_errorMessage;
271         else
272             parseError = ASCIILiteral("Parser error");
273     }
274
275     IdentifierSet capturedVariables;
276     bool modifiedParameter = false;
277     bool modifiedArguments = false;
278     scope->getCapturedVariables(capturedVariables, modifiedParameter, modifiedArguments);
279     
280     CodeFeatures features = context.features();
281     if (scope->strictMode())
282         features |= StrictModeFeature;
283     if (scope->shadowsArguments())
284         features |= ShadowsArgumentsFeature;
285     if (modifiedParameter)
286         features |= ModifiedParameterFeature;
287     if (modifiedArguments)
288         features |= ModifiedArgumentsFeature;
289     Vector<RefPtr<StringImpl>> closedVariables;
290     if (m_parsingBuiltin) {
291         RELEASE_ASSERT(!capturedVariables.size());
292         IdentifierSet usedVariables;
293         scope->getUsedVariables(usedVariables);
294         for (const auto& variable : usedVariables) {
295             if (scope->hasDeclaredVariable(Identifier::fromUid(m_vm, variable.get())))
296                 continue;
297             
298             if (scope->hasDeclaredParameter(Identifier::fromUid(m_vm, variable.get())))
299                 continue;
300
301             if (variable == m_vm->propertyNames->arguments.impl())
302                 continue;
303
304             closedVariables.append(variable);
305         }
306     }
307     didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), features,
308         context.numConstants(), capturedVariables, WTF::move(closedVariables));
309
310     return parseError;
311 }
312
313 template <typename LexerType>
314 void Parser<LexerType>::didFinishParsing(SourceElements* sourceElements, DeclarationStacks::VarStack& varStack, 
315     DeclarationStacks::FunctionStack& funcStack, CodeFeatures features, int numConstants, IdentifierSet& capturedVars, const Vector<RefPtr<StringImpl>>&& closedVariables)
316 {
317     m_sourceElements = sourceElements;
318     m_varDeclarations.swap(varStack);
319     m_funcDeclarations.swap(funcStack);
320     m_capturedVariables.swap(capturedVars);
321     m_closedVariables = closedVariables;
322     m_features = features;
323     m_numConstants = numConstants;
324 }
325
326 template <typename LexerType>
327 bool Parser<LexerType>::allowAutomaticSemicolon()
328 {
329     return match(CLOSEBRACE) || match(EOFTOK) || m_lexer->prevTerminator();
330 }
331
332 template <typename LexerType>
333 template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseSourceElements(TreeBuilder& context, SourceElementsMode mode)
334 {
335     const unsigned lengthOfUseStrictLiteral = 12; // "use strict".length
336     TreeSourceElements sourceElements = context.createSourceElements();
337     bool seenNonDirective = false;
338     const Identifier* directive = 0;
339     unsigned directiveLiteralLength = 0;
340     auto savePoint = createSavePoint();
341     bool hasSetStrict = false;
342     while (TreeStatement statement = parseStatement(context, directive, &directiveLiteralLength)) {
343         if (mode == CheckForStrictMode && !seenNonDirective) {
344             if (directive) {
345                 // "use strict" must be the exact literal without escape sequences or line continuation.
346                 if (!hasSetStrict && directiveLiteralLength == lengthOfUseStrictLiteral && m_vm->propertyNames->useStrictIdentifier == *directive) {
347                     setStrictMode();
348                     hasSetStrict = true;
349                     if (!isValidStrictMode()) {
350                         if (m_lastFunctionName) {
351                             if (m_vm->propertyNames->arguments == *m_lastFunctionName)
352                                 semanticFail("Cannot name a function 'arguments' in strict mode");
353                             if (m_vm->propertyNames->eval == *m_lastFunctionName)
354                                 semanticFail("Cannot name a function 'eval' in strict mode");
355                         }
356                         if (hasDeclaredVariable(m_vm->propertyNames->arguments))
357                             semanticFail("Cannot declare a variable named 'arguments' in strict mode");
358                         if (hasDeclaredVariable(m_vm->propertyNames->eval))
359                             semanticFail("Cannot declare a variable named 'eval' in strict mode");
360                         semanticFailIfFalse(isValidStrictMode(), "Invalid parameters or function name in strict mode");
361                     }
362                     restoreSavePoint(savePoint);
363                     propagateError();
364                     continue;
365                 }
366             } else
367                 seenNonDirective = true;
368         }
369         context.appendStatement(sourceElements, statement);
370     }
371
372     propagateError();
373     return sourceElements;
374 }
375
376 template <typename LexerType>
377 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseVarDeclaration(TreeBuilder& context)
378 {
379     ASSERT(match(VAR));
380     JSTokenLocation location(tokenLocation());
381     int start = tokenLine();
382     int end = 0;
383     int scratch;
384     TreeDeconstructionPattern scratch1 = 0;
385     TreeExpression scratch2 = 0;
386     JSTextPosition scratch3;
387     TreeExpression varDecls = parseVarDeclarationList(context, scratch, scratch1, scratch2, scratch3, scratch3, scratch3, VarDeclarationContext);
388     propagateError();
389     failIfFalse(autoSemiColon(), "Expected ';' after var declaration");
390     
391     return context.createVarStatement(location, varDecls, start, end);
392 }
393
394 template <typename LexerType>
395 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseConstDeclaration(TreeBuilder& context)
396 {
397     ASSERT(match(CONSTTOKEN));
398     JSTokenLocation location(tokenLocation());
399     int start = tokenLine();
400     int end = 0;
401     TreeConstDeclList constDecls = parseConstDeclarationList(context);
402     propagateError();
403     failIfFalse(autoSemiColon(), "Expected ';' after const declaration");
404     
405     return context.createConstStatement(location, constDecls, start, end);
406 }
407
408 template <typename LexerType>
409 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseDoWhileStatement(TreeBuilder& context)
410 {
411     ASSERT(match(DO));
412     int startLine = tokenLine();
413     next();
414     const Identifier* unused = 0;
415     startLoop();
416     TreeStatement statement = parseStatement(context, unused);
417     endLoop();
418     failIfFalse(statement, "Expected a statement following 'do'");
419     int endLine = tokenLine();
420     JSTokenLocation location(tokenLocation());
421     handleProductionOrFail(WHILE, "while", "end", "do-while loop");
422     handleProductionOrFail(OPENPAREN, "(", "start", "do-while loop condition");
423     semanticFailIfTrue(match(CLOSEPAREN), "Must provide an expression as a do-while loop condition");
424     TreeExpression expr = parseExpression(context);
425     failIfFalse(expr, "Unable to parse do-while loop condition");
426     handleProductionOrFail(CLOSEPAREN, ")", "end", "do-while loop condition");
427     if (match(SEMICOLON))
428         next(); // Always performs automatic semicolon insertion.
429     return context.createDoWhileStatement(location, statement, expr, startLine, endLine);
430 }
431
432 template <typename LexerType>
433 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWhileStatement(TreeBuilder& context)
434 {
435     ASSERT(match(WHILE));
436     JSTokenLocation location(tokenLocation());
437     int startLine = tokenLine();
438     next();
439     
440     handleProductionOrFail(OPENPAREN, "(", "start", "while loop condition");
441     semanticFailIfTrue(match(CLOSEPAREN), "Must provide an expression as a while loop condition");
442     TreeExpression expr = parseExpression(context);
443     failIfFalse(expr, "Unable to parse while loop condition");
444     int endLine = tokenLine();
445     handleProductionOrFail(CLOSEPAREN, ")", "end", "while loop condition");
446     
447     const Identifier* unused = 0;
448     startLoop();
449     TreeStatement statement = parseStatement(context, unused);
450     endLoop();
451     failIfFalse(statement, "Expected a statement as the body of a while loop");
452     return context.createWhileStatement(location, expr, statement, startLine, endLine);
453 }
454
455 template <typename LexerType>
456 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseVarDeclarationList(TreeBuilder& context, int& declarations, TreeDeconstructionPattern& lastPattern, TreeExpression& lastInitializer, JSTextPosition& identStart, JSTextPosition& initStart, JSTextPosition& initEnd, VarDeclarationListContext declarationListContext)
457 {
458     TreeExpression head = 0;
459     TreeExpression tail = 0;
460     const Identifier* lastIdent;
461     JSToken lastIdentToken; 
462     do {
463         lastIdent = 0;
464         lastPattern = 0;
465         JSTokenLocation location(tokenLocation());
466         next();
467         TreeExpression node = 0;
468         declarations++;
469         bool hasInitializer = false;
470         if (match(IDENT)) {
471             JSTextPosition varStart = tokenStartPosition();
472             JSTokenLocation varStartLocation(tokenLocation());
473             identStart = varStart;
474             const Identifier* name = m_token.m_data.ident;
475             lastIdent = name;
476             lastIdentToken = m_token;
477             next();
478             hasInitializer = match(EQUAL);
479             failIfFalseIfStrict(declareVariable(name), "Cannot declare a variable named ", name->impl(), " in strict mode");
480             context.addVar(name, (hasInitializer || (!m_allowsIn && (match(INTOKEN) || isofToken()))) ? DeclarationStacks::HasInitializer : 0);
481             if (hasInitializer) {
482                 JSTextPosition varDivot = tokenStartPosition() + 1;
483                 initStart = tokenStartPosition();
484                 next(TreeBuilder::DontBuildStrings); // consume '='
485                 TreeExpression initializer = parseAssignmentExpression(context);
486                 initEnd = lastTokenEndPosition();
487                 lastInitializer = initializer;
488                 failIfFalse(initializer, "Expected expression as the intializer for the variable '", name->impl(), "'");
489                 
490                 node = context.createAssignResolve(location, *name, initializer, varStart, varDivot, lastTokenEndPosition());
491             } else
492                 node = context.createEmptyVarExpression(varStartLocation, *name);
493         } else {
494             lastIdent = 0;
495             auto pattern = parseDeconstructionPattern(context, DeconstructToVariables);
496             failIfFalse(pattern, "Cannot parse this deconstruction pattern");
497             hasInitializer = match(EQUAL);
498             failIfTrue(declarationListContext == VarDeclarationContext && !hasInitializer, "Expected an initializer in destructuring variable declaration");
499             lastPattern = pattern;
500             if (hasInitializer) {
501                 next(TreeBuilder::DontBuildStrings); // consume '='
502                 TreeExpression rhs = parseAssignmentExpression(context);
503                 node = context.createDeconstructingAssignment(location, pattern, rhs);
504                 lastInitializer = rhs;
505             }
506         }
507         
508         if (!head)
509             head = node;
510         else if (!tail) {
511             head = context.createCommaExpr(location, head);
512             tail = context.appendToCommaExpr(location, head, head, node);
513         } else
514             tail = context.appendToCommaExpr(location, head, tail, node);
515     } while (match(COMMA));
516     if (lastIdent)
517         lastPattern = createBindingPattern(context, DeconstructToVariables, *lastIdent, 0, lastIdentToken);
518     return head;
519 }
520
521 template <typename LexerType>
522 template <class TreeBuilder> TreeDeconstructionPattern Parser<LexerType>::createBindingPattern(TreeBuilder& context, DeconstructionKind kind, const Identifier& name, int depth, JSToken token)
523 {
524     ASSERT(!name.isEmpty());
525     ASSERT(!name.isNull());
526     
527     ASSERT(name.impl()->isAtomic() || name.impl()->isSymbol());
528     if (depth) {
529         if (kind == DeconstructToVariables)
530             failIfFalseIfStrict(declareVariable(&name), "Cannot deconstruct to a variable named '", name.impl(), "' in strict mode");
531         if (kind == DeconstructToParameters) {
532             auto bindingResult = declareBoundParameter(&name);
533             if (bindingResult == Scope::StrictBindingFailed && strictMode()) {
534                 semanticFailIfTrue(m_vm->propertyNames->arguments == name || m_vm->propertyNames->eval == name, "Cannot deconstruct to a parameter name '", name.impl(), "' in strict mode");
535                 if (m_lastFunctionName && name == *m_lastFunctionName)
536                     semanticFail("Cannot deconstruct to '", name.impl(), "' as it shadows the name of a strict mode function");
537                 semanticFailureDueToKeyword("bound parameter name");
538                 if (hasDeclaredParameter(name))
539                     semanticFail("Cannot deconstruct to '", name.impl(), "' as it has already been declared");
540                 semanticFail("Cannot bind to a parameter named '", name.impl(), "' in strict mode");
541             }
542             if (bindingResult == Scope::BindingFailed) {
543                 semanticFailureDueToKeyword("bound parameter name");
544                 if (hasDeclaredParameter(name))
545                     semanticFail("Cannot deconstruct to '", name.impl(), "' as it has already been declared");
546                 semanticFail("Cannot deconstruct to a parameter named '", name.impl(), "'");
547             }
548         }
549         if (kind != DeconstructToExpressions)
550             context.addVar(&name, DeclarationStacks::HasInitializer);
551
552     } else {
553         if (kind == DeconstructToVariables) {
554             failIfFalseIfStrict(declareVariable(&name), "Cannot declare a variable named '", name.impl(), "' in strict mode");
555             context.addVar(&name, DeclarationStacks::HasInitializer);
556         }
557         
558         if (kind == DeconstructToParameters) {
559             bool declarationResult = declareParameter(&name);
560             if (!declarationResult && strictMode()) {
561                 semanticFailIfTrue(m_vm->propertyNames->arguments == name || m_vm->propertyNames->eval == name, "Cannot deconstruct to a parameter name '", name.impl(), "' in strict mode");
562                 if (m_lastFunctionName && name == *m_lastFunctionName)
563                     semanticFail("Cannot declare a parameter named '", name.impl(), "' as it shadows the name of a strict mode function");
564                 semanticFailureDueToKeyword("parameter name");
565                 if (hasDeclaredParameter(name))
566                     semanticFail("Cannot declare a parameter named '", name.impl(), "' in strict mode as it has already been declared");
567                 semanticFail("Cannot declare a parameter named '", name.impl(), "' in strict mode");
568             }
569         }
570     }
571     return context.createBindingLocation(token.m_location, name, token.m_startPosition, token.m_endPosition);
572 }
573
574 template <typename LexerType>
575 template <class TreeBuilder> TreeDeconstructionPattern Parser<LexerType>::tryParseDeconstructionPatternExpression(TreeBuilder& context)
576 {
577     return parseDeconstructionPattern(context, DeconstructToExpressions);
578 }
579
580 template <typename LexerType>
581 template <class TreeBuilder> TreeDeconstructionPattern Parser<LexerType>::parseDeconstructionPattern(TreeBuilder& context, DeconstructionKind kind, int depth)
582 {
583     failIfStackOverflow();
584     int nonLHSCount = m_nonLHSCount;
585     TreeDeconstructionPattern pattern;
586     switch (m_token.m_type) {
587     case OPENBRACKET: {
588         auto arrayPattern = context.createArrayPattern(m_token.m_location);
589         next();
590         if (kind == DeconstructToExpressions && match(CLOSEBRACKET))
591             return 0;
592         failIfTrue(match(CLOSEBRACKET), "There must be at least one bound property in an array deconstruction pattern");
593         do {
594             while (match(COMMA)) {
595                 context.appendArrayPatternSkipEntry(arrayPattern, m_token.m_location);
596                 next();
597             }
598             propagateError();
599             JSTokenLocation location = m_token.m_location;
600             auto innerPattern = parseDeconstructionPattern(context, kind, depth + 1);
601             if (kind == DeconstructToExpressions && !innerPattern)
602                 return 0;
603             failIfFalse(innerPattern, "Cannot parse this deconstruction pattern");
604             context.appendArrayPatternEntry(arrayPattern, location, innerPattern);
605         } while (consume(COMMA));
606         
607         if (kind == DeconstructToExpressions && !match(CLOSEBRACKET))
608             return 0;
609
610         consumeOrFail(CLOSEBRACKET, "Expected either a closing ']' or a ',' following an element deconstruction pattern");
611         pattern = arrayPattern;
612         break;
613     }
614     case OPENBRACE: {
615         next();
616         
617         if (kind == DeconstructToExpressions && match(CLOSEBRACE))
618             return 0;
619
620         failIfTrue(match(CLOSEBRACE), "There must be at least one bound property in an object deconstruction pattern");
621         auto objectPattern = context.createObjectPattern(m_token.m_location);
622         bool wasString = false;
623         do {
624             Identifier propertyName;
625             TreeDeconstructionPattern innerPattern = 0;
626             JSTokenLocation location = m_token.m_location;
627             if (match(IDENT)) {
628                 propertyName = *m_token.m_data.ident;
629                 JSToken identifierToken = m_token;
630                 next();
631                 if (consume(COLON))
632                     innerPattern = parseDeconstructionPattern(context, kind, depth + 1);
633                 else
634                     innerPattern = createBindingPattern(context, kind, propertyName, depth, identifierToken);
635             } else {
636                 JSTokenType tokenType = m_token.m_type;
637                 switch (m_token.m_type) {
638                 case DOUBLE:
639                 case INTEGER:
640                     propertyName = Identifier::from(m_vm, m_token.m_data.doubleValue);
641                     break;
642                 case STRING:
643                     propertyName = *m_token.m_data.ident;
644                     wasString = true;
645                     break;
646                 default:
647                     if (m_token.m_type != RESERVED && m_token.m_type != RESERVED_IF_STRICT && !(m_token.m_type & KeywordTokenFlag)) {
648                         if (kind == DeconstructToExpressions)
649                             return 0;
650                         failWithMessage("Expected a property name");
651                     }
652                     propertyName = *m_token.m_data.ident;
653                     break;
654                 }
655                 next();
656                 if (!consume(COLON)) {
657                     if (kind == DeconstructToExpressions)
658                         return 0;
659                     semanticFailIfTrue(tokenType == RESERVED, "Cannot use abbreviated deconstruction syntax for reserved name '", propertyName.impl(), "'");
660                     semanticFailIfTrue(tokenType == RESERVED_IF_STRICT, "Cannot use abbreviated deconstruction syntax for reserved name '", propertyName.impl(), "' in strict mode");
661                     semanticFailIfTrue(tokenType & KeywordTokenFlag, "Cannot use abbreviated deconstruction syntax for keyword '", propertyName.impl(), "'");
662                     
663                     failWithMessage("Expected a ':' prior to named property deconstruction");
664                 }
665                 innerPattern = parseDeconstructionPattern(context, kind, depth + 1);
666             }
667             if (kind == DeconstructToExpressions && !innerPattern)
668                 return 0;
669             failIfFalse(innerPattern, "Cannot parse this deconstruction pattern");
670             context.appendObjectPatternEntry(objectPattern, location, wasString, propertyName, innerPattern);
671         } while (consume(COMMA));
672         if (kind == DeconstructToExpressions && !match(CLOSEBRACE))
673             return 0;
674         consumeOrFail(CLOSEBRACE, "Expected either a closing '}' or an ',' after a property deconstruction pattern");
675         pattern = objectPattern;
676         break;
677     }
678
679     default: {
680         if (!match(IDENT)) {
681             if (kind == DeconstructToExpressions)
682                 return 0;
683             semanticFailureDueToKeyword("variable name");
684             failWithMessage("Expected a parameter pattern or a ')' in parameter list");
685         }
686         pattern = createBindingPattern(context, kind, *m_token.m_data.ident, depth, m_token);
687         next();
688         break;
689     }
690     }
691     m_nonLHSCount = nonLHSCount;
692     return pattern;
693 }
694
695 template <typename LexerType>
696 template <class TreeBuilder> TreeConstDeclList Parser<LexerType>::parseConstDeclarationList(TreeBuilder& context)
697 {
698     failIfTrue(strictMode(), "Const declarations are not supported in strict mode");
699     TreeConstDeclList constDecls = 0;
700     TreeConstDeclList tail = 0;
701     do {
702         JSTokenLocation location(tokenLocation());
703         next();
704         matchOrFail(IDENT, "Expected an identifier name in const declaration");
705         const Identifier* name = m_token.m_data.ident;
706         next();
707         bool hasInitializer = match(EQUAL);
708         declareVariable(name);
709         context.addVar(name, DeclarationStacks::IsConstant | (hasInitializer ? DeclarationStacks::HasInitializer : 0));
710
711         TreeExpression initializer = 0;
712         if (hasInitializer) {
713             next(TreeBuilder::DontBuildStrings); // consume '='
714             initializer = parseAssignmentExpression(context);
715             failIfFalse(!!initializer, "Unable to parse initializer");
716         }
717         tail = context.appendConstDecl(location, tail, name, initializer);
718         if (!constDecls)
719             constDecls = tail;
720     } while (match(COMMA));
721     return constDecls;
722 }
723
724 template <typename LexerType>
725 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseForStatement(TreeBuilder& context)
726 {
727     ASSERT(match(FOR));
728     JSTokenLocation location(tokenLocation());
729     int startLine = tokenLine();
730     next();
731     handleProductionOrFail(OPENPAREN, "(", "start", "for-loop header");
732     int nonLHSCount = m_nonLHSCount;
733     int declarations = 0;
734     JSTextPosition declsStart;
735     JSTextPosition declsEnd;
736     TreeExpression decls = 0;
737     TreeDeconstructionPattern pattern = 0;
738     if (match(VAR)) {
739         /*
740          for (var IDENT in expression) statement
741          for (var varDeclarationList; expressionOpt; expressionOpt)
742          */
743         TreeDeconstructionPattern forInTarget = 0;
744         TreeExpression forInInitializer = 0;
745         m_allowsIn = false;
746         JSTextPosition initStart;
747         JSTextPosition initEnd;
748         decls = parseVarDeclarationList(context, declarations, forInTarget, forInInitializer, declsStart, initStart, initEnd, ForLoopContext);
749         m_allowsIn = true;
750         propagateError();
751
752         // Remainder of a standard for loop is handled identically
753         if (match(SEMICOLON))
754             goto standardForLoop;
755         
756         failIfFalse(declarations == 1, "can only declare a single variable in an enumeration");
757         failIfTrueIfStrict(forInInitializer, "Cannot use initialiser syntax in a strict mode enumeration");
758
759         if (forInInitializer)
760             failIfFalse(context.isBindingNode(forInTarget), "Cannot use initialiser syntax when binding to a pattern during enumeration");
761
762         // Handle for-in with var declaration
763         JSTextPosition inLocation = tokenStartPosition();
764         bool isOfEnumeration = false;
765         if (!consume(INTOKEN)) {
766             failIfFalse(match(IDENT) && *m_token.m_data.ident == m_vm->propertyNames->of, "Expected either 'in' or 'of' in enumeration syntax");
767             isOfEnumeration = true;
768             failIfTrue(forInInitializer, "Cannot use initialiser syntax in a for-of enumeration");
769             next();
770         }
771         TreeExpression expr = parseExpression(context);
772         failIfFalse(expr, "Expected expression to enumerate");
773         JSTextPosition exprEnd = lastTokenEndPosition();
774         
775         int endLine = tokenLine();
776         
777         handleProductionOrFail(CLOSEPAREN, ")", "end", (isOfEnumeration ? "for-of header" : "for-in header"));
778         
779         const Identifier* unused = 0;
780         startLoop();
781         TreeStatement statement = parseStatement(context, unused);
782         endLoop();
783         failIfFalse(statement, "Expected statement as body of for-", isOfEnumeration ? "of" : "in", " statement");
784         if (isOfEnumeration)
785             return context.createForOfLoop(location, forInTarget, expr, statement, declsStart, inLocation, exprEnd, startLine, endLine);
786         return context.createForInLoop(location, forInTarget, expr, statement, declsStart, inLocation, exprEnd, startLine, endLine);
787     }
788     
789     if (!match(SEMICOLON)) {
790         if (match(OPENBRACE) || match(OPENBRACKET)) {
791             SavePoint savePoint = createSavePoint();
792             declsStart = tokenStartPosition();
793             pattern = tryParseDeconstructionPatternExpression(context);
794             declsEnd = lastTokenEndPosition();
795             if (pattern && (match(INTOKEN) || (match(IDENT) && *m_token.m_data.ident == m_vm->propertyNames->of)))
796                 goto enumerationLoop;
797             pattern = 0;
798             restoreSavePoint(savePoint);
799         }
800         m_allowsIn = false;
801         declsStart = tokenStartPosition();
802         decls = parseExpression(context);
803         declsEnd = lastTokenEndPosition();
804         m_allowsIn = true;
805         failIfFalse(decls, "Cannot parse for loop declarations");
806     }
807     
808     if (match(SEMICOLON)) {
809     standardForLoop:
810         // Standard for loop
811         next();
812         TreeExpression condition = 0;
813         
814         if (!match(SEMICOLON)) {
815             condition = parseExpression(context);
816             failIfFalse(condition, "Cannot parse for loop condition expression");
817         }
818         consumeOrFail(SEMICOLON, "Expected a ';' after the for loop condition expression");
819         
820         TreeExpression increment = 0;
821         if (!match(CLOSEPAREN)) {
822             increment = parseExpression(context);
823             failIfFalse(increment, "Cannot parse for loop iteration expression");
824         }
825         int endLine = tokenLine();
826         handleProductionOrFail(CLOSEPAREN, ")", "end", "for-loop header");
827         const Identifier* unused = 0;
828         startLoop();
829         TreeStatement statement = parseStatement(context, unused);
830         endLoop();
831         failIfFalse(statement, "Expected a statement as the body of a for loop");
832         return context.createForLoop(location, decls, condition, increment, statement, startLine, endLine);
833     }
834     
835     // For-in loop
836 enumerationLoop:
837     failIfFalse(nonLHSCount == m_nonLHSCount, "Expected a reference on the left hand side of an enumeration statement");
838     bool isOfEnumeration = false;
839     if (!consume(INTOKEN)) {
840         failIfFalse(match(IDENT) && *m_token.m_data.ident == m_vm->propertyNames->of, "Expected either 'in' or 'of' in enumeration syntax");
841         isOfEnumeration = true;
842         next();
843     }
844     TreeExpression expr = parseExpression(context);
845     failIfFalse(expr, "Cannot parse subject for-", isOfEnumeration ? "of" : "in", " statement");
846     JSTextPosition exprEnd = lastTokenEndPosition();
847     int endLine = tokenLine();
848     
849     handleProductionOrFail(CLOSEPAREN, ")", "end", (isOfEnumeration ? "for-of header" : "for-in header"));
850     const Identifier* unused = 0;
851     startLoop();
852     TreeStatement statement = parseStatement(context, unused);
853     endLoop();
854     failIfFalse(statement, "Expected a statement as the body of a for-", isOfEnumeration ? "of" : "in", "loop");
855     if (pattern) {
856         ASSERT(!decls);
857         if (isOfEnumeration)
858             return context.createForOfLoop(location, pattern, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine);
859         return context.createForInLoop(location, pattern, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine);
860     }
861     if (isOfEnumeration)
862         return context.createForOfLoop(location, decls, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine);
863     return context.createForInLoop(location, decls, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine);
864 }
865
866 template <typename LexerType>
867 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBreakStatement(TreeBuilder& context)
868 {
869     ASSERT(match(BREAK));
870     JSTokenLocation location(tokenLocation());
871     JSTextPosition start = tokenStartPosition();
872     JSTextPosition end = tokenEndPosition();
873     next();
874     
875     if (autoSemiColon()) {
876         semanticFailIfFalse(breakIsValid(), "'break' is only valid inside a switch or loop statement");
877         return context.createBreakStatement(location, &m_vm->propertyNames->nullIdentifier, start, end);
878     }
879     matchOrFail(IDENT, "Expected an identifier as the target for a break statement");
880     const Identifier* ident = m_token.m_data.ident;
881     semanticFailIfFalse(getLabel(ident), "Cannot use the undeclared label '", ident->impl(), "'");
882     end = tokenEndPosition();
883     next();
884     failIfFalse(autoSemiColon(), "Expected a ';' following a targeted break statement");
885     return context.createBreakStatement(location, ident, start, end);
886 }
887
888 template <typename LexerType>
889 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseContinueStatement(TreeBuilder& context)
890 {
891     ASSERT(match(CONTINUE));
892     JSTokenLocation location(tokenLocation());
893     JSTextPosition start = tokenStartPosition();
894     JSTextPosition end = tokenEndPosition();
895     next();
896     
897     if (autoSemiColon()) {
898         semanticFailIfFalse(continueIsValid(), "'continue' is only valid inside a loop statement");
899         return context.createContinueStatement(location, &m_vm->propertyNames->nullIdentifier, start, end);
900     }
901     matchOrFail(IDENT, "Expected an identifier as the target for a continue statement");
902     const Identifier* ident = m_token.m_data.ident;
903     ScopeLabelInfo* label = getLabel(ident);
904     semanticFailIfFalse(label, "Cannot use the undeclared label '", ident->impl(), "'");
905     semanticFailIfFalse(label->m_isLoop, "Cannot continue to the label '", ident->impl(), "' as it is not targeting a loop");
906     end = tokenEndPosition();
907     next();
908     failIfFalse(autoSemiColon(), "Expected a ';' following a targeted continue statement");
909     return context.createContinueStatement(location, ident, start, end);
910 }
911
912 template <typename LexerType>
913 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseReturnStatement(TreeBuilder& context)
914 {
915     ASSERT(match(RETURN));
916     JSTokenLocation location(tokenLocation());
917     semanticFailIfFalse(currentScope()->isFunction(), "Return statements are only valid inside functions");
918     JSTextPosition start = tokenStartPosition();
919     JSTextPosition end = tokenEndPosition();
920     next();
921     // We do the auto semicolon check before attempting to parse expression
922     // as we need to ensure the a line break after the return correctly terminates
923     // the statement
924     if (match(SEMICOLON))
925         end = tokenEndPosition();
926
927     if (autoSemiColon())
928         return context.createReturnStatement(location, 0, start, end);
929     TreeExpression expr = parseExpression(context);
930     failIfFalse(expr, "Cannot parse the return expression");
931     end = lastTokenEndPosition();
932     if (match(SEMICOLON))
933         end  = tokenEndPosition();
934     if (!autoSemiColon())
935         failWithMessage("Expected a ';' following a return statement");
936     return context.createReturnStatement(location, expr, start, end);
937 }
938
939 template <typename LexerType>
940 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseThrowStatement(TreeBuilder& context)
941 {
942     ASSERT(match(THROW));
943     JSTokenLocation location(tokenLocation());
944     JSTextPosition start = tokenStartPosition();
945     next();
946     failIfTrue(match(SEMICOLON), "Expected expression after 'throw'");
947     semanticFailIfTrue(autoSemiColon(), "Cannot have a newline after 'throw'");
948     
949     TreeExpression expr = parseExpression(context);
950     failIfFalse(expr, "Cannot parse expression for throw statement");
951     JSTextPosition end = lastTokenEndPosition();
952     failIfFalse(autoSemiColon(), "Expected a ';' after a throw statement");
953     
954     return context.createThrowStatement(location, expr, start, end);
955 }
956
957 template <typename LexerType>
958 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWithStatement(TreeBuilder& context)
959 {
960     ASSERT(match(WITH));
961     JSTokenLocation location(tokenLocation());
962     semanticFailIfTrue(strictMode(), "'with' statements are not valid in strict mode");
963     currentScope()->setNeedsFullActivation();
964     int startLine = tokenLine();
965     next();
966
967     handleProductionOrFail(OPENPAREN, "(", "start", "subject of a 'with' statement");
968     int start = tokenStart();
969     TreeExpression expr = parseExpression(context);
970     failIfFalse(expr, "Cannot parse 'with' subject expression");
971     JSTextPosition end = lastTokenEndPosition();
972     int endLine = tokenLine();
973     handleProductionOrFail(CLOSEPAREN, ")", "start", "subject of a 'with' statement");
974     const Identifier* unused = 0;
975     TreeStatement statement = parseStatement(context, unused);
976     failIfFalse(statement, "A 'with' statement must have a body");
977     
978     return context.createWithStatement(location, expr, statement, start, end, startLine, endLine);
979 }
980
981 template <typename LexerType>
982 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseSwitchStatement(TreeBuilder& context)
983 {
984     ASSERT(match(SWITCH));
985     JSTokenLocation location(tokenLocation());
986     int startLine = tokenLine();
987     next();
988     handleProductionOrFail(OPENPAREN, "(", "start", "subject of a 'switch'");
989     TreeExpression expr = parseExpression(context);
990     failIfFalse(expr, "Cannot parse switch subject expression");
991     int endLine = tokenLine();
992     
993     handleProductionOrFail(CLOSEPAREN, ")", "end", "subject of a 'switch'");
994     handleProductionOrFail(OPENBRACE, "{", "start", "body of a 'switch'");
995     startSwitch();
996     TreeClauseList firstClauses = parseSwitchClauses(context);
997     propagateError();
998     
999     TreeClause defaultClause = parseSwitchDefaultClause(context);
1000     propagateError();
1001     
1002     TreeClauseList secondClauses = parseSwitchClauses(context);
1003     propagateError();
1004     endSwitch();
1005     handleProductionOrFail(CLOSEBRACE, "}", "end", "body of a 'switch'");
1006     
1007     return context.createSwitchStatement(location, expr, firstClauses, defaultClause, secondClauses, startLine, endLine);
1008     
1009 }
1010
1011 template <typename LexerType>
1012 template <class TreeBuilder> TreeClauseList Parser<LexerType>::parseSwitchClauses(TreeBuilder& context)
1013 {
1014     if (!match(CASE))
1015         return 0;
1016     unsigned startOffset = tokenStart();
1017     next();
1018     TreeExpression condition = parseExpression(context);
1019     failIfFalse(condition, "Cannot parse switch clause");
1020     consumeOrFail(COLON, "Expected a ':' after switch clause expression");
1021     TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode);
1022     failIfFalse(statements, "Cannot parse the body of a switch clause");
1023     TreeClause clause = context.createClause(condition, statements);
1024     context.setStartOffset(clause, startOffset);
1025     TreeClauseList clauseList = context.createClauseList(clause);
1026     TreeClauseList tail = clauseList;
1027     
1028     while (match(CASE)) {
1029         startOffset = tokenStart();
1030         next();
1031         TreeExpression condition = parseExpression(context);
1032         failIfFalse(condition, "Cannot parse switch case expression");
1033         consumeOrFail(COLON, "Expected a ':' after switch clause expression");
1034         TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode);
1035         failIfFalse(statements, "Cannot parse the body of a switch clause");
1036         clause = context.createClause(condition, statements);
1037         context.setStartOffset(clause, startOffset);
1038         tail = context.createClauseList(tail, clause);
1039     }
1040     return clauseList;
1041 }
1042
1043 template <typename LexerType>
1044 template <class TreeBuilder> TreeClause Parser<LexerType>::parseSwitchDefaultClause(TreeBuilder& context)
1045 {
1046     if (!match(DEFAULT))
1047         return 0;
1048     unsigned startOffset = tokenStart();
1049     next();
1050     consumeOrFail(COLON, "Expected a ':' after switch default clause");
1051     TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode);
1052     failIfFalse(statements, "Cannot parse the body of a switch default clause");
1053     TreeClause result = context.createClause(0, statements);
1054     context.setStartOffset(result, startOffset);
1055     return result;
1056 }
1057
1058 template <typename LexerType>
1059 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseTryStatement(TreeBuilder& context)
1060 {
1061     ASSERT(match(TRY));
1062     JSTokenLocation location(tokenLocation());
1063     TreeStatement tryBlock = 0;
1064     const Identifier* ident = &m_vm->propertyNames->nullIdentifier;
1065     TreeStatement catchBlock = 0;
1066     TreeStatement finallyBlock = 0;
1067     int firstLine = tokenLine();
1068     next();
1069     matchOrFail(OPENBRACE, "Expected a block statement as body of a try statement");
1070     
1071     tryBlock = parseBlockStatement(context);
1072     failIfFalse(tryBlock, "Cannot parse the body of try block");
1073     int lastLine = m_lastTokenEndPosition.line;
1074     
1075     if (match(CATCH)) {
1076         currentScope()->setNeedsFullActivation();
1077         next();
1078         
1079         handleProductionOrFail(OPENPAREN, "(", "start", "'catch' target");
1080         if (!match(IDENT)) {
1081             semanticFailureDueToKeyword("catch variable name");
1082             failWithMessage("Expected identifier name as catch target");
1083         }
1084         ident = m_token.m_data.ident;
1085         next();
1086         AutoPopScopeRef catchScope(this, pushScope());
1087         failIfFalseIfStrict(declareVariable(ident), "Cannot declare a catch variable named '", ident->impl(), "' in strict mode");
1088         catchScope->preventNewDecls();
1089         handleProductionOrFail(CLOSEPAREN, ")", "end", "'catch' target");
1090         matchOrFail(OPENBRACE, "Expected exception handler to be a block statement");
1091         catchBlock = parseBlockStatement(context);
1092         failIfFalse(catchBlock, "Unable to parse 'catch' block");
1093         failIfFalse(popScope(catchScope, TreeBuilder::NeedsFreeVariableInfo), "Parse error");
1094     }
1095     
1096     if (match(FINALLY)) {
1097         next();
1098         matchOrFail(OPENBRACE, "Expected block statement for finally body");
1099         finallyBlock = parseBlockStatement(context);
1100         failIfFalse(finallyBlock, "Cannot parse finally body");
1101     }
1102     failIfFalse(catchBlock || finallyBlock, "Try statements must have at least a catch or finally block");
1103     return context.createTryStatement(location, tryBlock, ident, catchBlock, finallyBlock, firstLine, lastLine);
1104 }
1105
1106 template <typename LexerType>
1107 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseDebuggerStatement(TreeBuilder& context)
1108 {
1109     ASSERT(match(DEBUGGER));
1110     JSTokenLocation location(tokenLocation());
1111     int startLine = tokenLine();
1112     int endLine = startLine;
1113     next();
1114     if (match(SEMICOLON))
1115         startLine = tokenLine();
1116     failIfFalse(autoSemiColon(), "Debugger keyword must be followed by a ';'");
1117     return context.createDebugger(location, startLine, endLine);
1118 }
1119
1120 template <typename LexerType>
1121 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBlockStatement(TreeBuilder& context)
1122 {
1123     ASSERT(match(OPENBRACE));
1124     JSTokenLocation location(tokenLocation());
1125     int startOffset = m_token.m_data.offset;
1126     int start = tokenLine();
1127     next();
1128     if (match(CLOSEBRACE)) {
1129         int endOffset = m_token.m_data.offset;
1130         next();
1131         TreeStatement result = context.createBlockStatement(location, 0, start, m_lastTokenEndPosition.line);
1132         context.setStartOffset(result, startOffset);
1133         context.setEndOffset(result, endOffset);
1134         return result;
1135     }
1136     TreeSourceElements subtree = parseSourceElements(context, DontCheckForStrictMode);
1137     failIfFalse(subtree, "Cannot parse the body of the block statement");
1138     matchOrFail(CLOSEBRACE, "Expected a closing '}' at the end of a block statement");
1139     int endOffset = m_token.m_data.offset;
1140     next();
1141     TreeStatement result = context.createBlockStatement(location, subtree, start, m_lastTokenEndPosition.line);
1142     context.setStartOffset(result, startOffset);
1143     context.setEndOffset(result, endOffset);
1144     return result;
1145 }
1146
1147 template <typename LexerType>
1148 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseStatement(TreeBuilder& context, const Identifier*& directive, unsigned* directiveLiteralLength)
1149 {
1150     DepthManager statementDepth(&m_statementDepth);
1151     m_statementDepth++;
1152     directive = 0;
1153     int nonTrivialExpressionCount = 0;
1154     failIfStackOverflow();
1155     TreeStatement result = 0;
1156     bool shouldSetEndOffset = true;
1157     switch (m_token.m_type) {
1158     case OPENBRACE:
1159         result = parseBlockStatement(context);
1160         shouldSetEndOffset = false;
1161         break;
1162     case VAR:
1163         result = parseVarDeclaration(context);
1164         break;
1165     case CONSTTOKEN:
1166         result = parseConstDeclaration(context);
1167         break;
1168 #if ENABLE(ES6_CLASS_SYNTAX)
1169     case CLASSTOKEN:
1170         failIfFalse(m_statementDepth == 1, "Class declaration is not allowed in a lexically nested statement");
1171         result = parseClassDeclaration(context);
1172         break;
1173 #endif
1174     case FUNCTION:
1175         failIfFalseIfStrict(m_statementDepth == 1, "Strict mode does not allow function declarations in a lexically nested statement");
1176         result = parseFunctionDeclaration(context);
1177         break;
1178     case SEMICOLON: {
1179         JSTokenLocation location(tokenLocation());
1180         next();
1181         result = context.createEmptyStatement(location);
1182         break;
1183     }
1184     case IF:
1185         result = parseIfStatement(context);
1186         break;
1187     case DO:
1188         result = parseDoWhileStatement(context);
1189         break;
1190     case WHILE:
1191         result = parseWhileStatement(context);
1192         break;
1193     case FOR:
1194         result = parseForStatement(context);
1195         break;
1196     case CONTINUE:
1197         result = parseContinueStatement(context);
1198         break;
1199     case BREAK:
1200         result = parseBreakStatement(context);
1201         break;
1202     case RETURN:
1203         result = parseReturnStatement(context);
1204         break;
1205     case WITH:
1206         result = parseWithStatement(context);
1207         break;
1208     case SWITCH:
1209         result = parseSwitchStatement(context);
1210         break;
1211     case THROW:
1212         result = parseThrowStatement(context);
1213         break;
1214     case TRY:
1215         result = parseTryStatement(context);
1216         break;
1217     case DEBUGGER:
1218         result = parseDebuggerStatement(context);
1219         break;
1220     case EOFTOK:
1221     case CASE:
1222     case CLOSEBRACE:
1223     case DEFAULT:
1224         // These tokens imply the end of a set of source elements
1225         return 0;
1226     case IDENT:
1227         result = parseExpressionOrLabelStatement(context);
1228         break;
1229     case STRING:
1230         directive = m_token.m_data.ident;
1231         if (directiveLiteralLength)
1232             *directiveLiteralLength = m_token.m_location.endOffset - m_token.m_location.startOffset;
1233         nonTrivialExpressionCount = m_nonTrivialExpressionCount;
1234         FALLTHROUGH;
1235     default:
1236         TreeStatement exprStatement = parseExpressionStatement(context);
1237         if (directive && nonTrivialExpressionCount != m_nonTrivialExpressionCount)
1238             directive = 0;
1239         result = exprStatement;
1240         break;
1241     }
1242
1243     if (result && shouldSetEndOffset)
1244         context.setEndOffset(result, m_lastTokenEndPosition.offset);
1245     return result;
1246 }
1247
1248 template <typename LexerType>
1249 template <class TreeBuilder> TreeFormalParameterList Parser<LexerType>::parseFormalParameters(TreeBuilder& context)
1250 {
1251     auto parameter = parseDeconstructionPattern(context, DeconstructToParameters);
1252     failIfFalse(parameter, "Cannot parse parameter pattern");
1253     TreeFormalParameterList list = context.createFormalParameterList(parameter);
1254     TreeFormalParameterList tail = list;
1255     while (consume(COMMA)) {
1256         parameter = parseDeconstructionPattern(context, DeconstructToParameters);
1257         failIfFalse(parameter, "Cannot parse parameter pattern");
1258         tail = context.createFormalParameterList(tail, parameter);
1259     }
1260     return list;
1261 }
1262
1263 template <typename LexerType>
1264 template <class TreeBuilder> TreeFunctionBody Parser<LexerType>::parseFunctionBody(
1265     TreeBuilder& context, int functionKeywordStart, int functionNameStart, 
1266     int parametersStart, ConstructorKind constructorKind)
1267 {
1268     JSTokenLocation startLocation(tokenLocation());
1269     unsigned startColumn = tokenColumn();
1270     next();
1271
1272     if (match(CLOSEBRACE)) {
1273         unsigned endColumn = tokenColumn();
1274         return context.createFunctionBody(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind);
1275     }
1276     DepthManager statementDepth(&m_statementDepth);
1277     m_statementDepth = 0;
1278     typename TreeBuilder::FunctionBodyBuilder bodyBuilder(const_cast<VM*>(m_vm), m_lexer.get());
1279     failIfFalse(parseSourceElements(bodyBuilder, CheckForStrictMode), "Cannot parse body of this function");
1280     unsigned endColumn = tokenColumn();
1281     return context.createFunctionBody(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind);
1282 }
1283
1284 static const char* stringForFunctionMode(FunctionParseMode mode)
1285 {
1286     switch (mode) {
1287     case GetterMode:
1288         return "getter";
1289     case SetterMode:
1290         return "setter";
1291     case FunctionMode:
1292         return "function";
1293     case MethodMode:
1294         return "method";
1295     }
1296     RELEASE_ASSERT_NOT_REACHED();
1297     return nullptr;
1298 }
1299
1300 template <typename LexerType>
1301 template <class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuilder& context, FunctionRequirements requirements, FunctionParseMode mode,
1302     bool nameIsInContainingScope, ConstructorKind ownerClassKind, int functionKeywordStart, ParserFunctionInfo<TreeBuilder>& info)
1303 {
1304     AutoPopScopeRef functionScope(this, pushScope());
1305     functionScope->setIsFunction();
1306     int functionNameStart = m_token.m_location.startOffset;
1307     const Identifier* lastFunctionName = m_lastFunctionName;
1308     m_lastFunctionName = nullptr;
1309     if (match(IDENT)) {
1310         info.name = m_token.m_data.ident;
1311         m_lastFunctionName = info.name;
1312         next();
1313         if (!nameIsInContainingScope)
1314             failIfFalseIfStrict(functionScope->declareVariable(info.name), "'", info.name->impl(), "' is not a valid ", stringForFunctionMode(mode), " name in strict mode");
1315     } else if (requirements == FunctionNeedsName) {
1316         if (match(OPENPAREN) && mode == FunctionMode)
1317             semanticFail("Function statements must have a name");
1318         semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
1319         failDueToUnexpectedToken();
1320         return false;
1321     }
1322     int parametersStart = m_token.m_location.startOffset;
1323     if (!consume(OPENPAREN)) {
1324         semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
1325         failWithMessage("Expected an opening '(' before a ", stringForFunctionMode(mode), "'s parameter list");
1326     }
1327
1328     if (mode == GetterMode)
1329         consumeOrFail(CLOSEPAREN, "getter functions must have no parameters");
1330     else if (mode == SetterMode) {
1331         failIfTrue(match(CLOSEPAREN), "setter functions must have one parameter");
1332         auto parameter = parseDeconstructionPattern(context, DeconstructToParameters);
1333         failIfFalse(parameter, "setter functions must have one parameter");
1334         info.parameters = context.createFormalParameterList(parameter);
1335         failIfTrue(match(COMMA), "setter functions must have one parameter");
1336         consumeOrFail(CLOSEPAREN, "Expected a ')' after a parameter declaration");
1337     } else {
1338         if (!match(CLOSEPAREN)) {
1339             info.parameters = parseFormalParameters(context);
1340             failIfFalse(info.parameters, "Cannot parse parameters for this ", stringForFunctionMode(mode));
1341         }
1342         consumeOrFail(CLOSEPAREN, "Expected a ')' or a ',' after a parameter declaration");
1343     }
1344
1345     matchOrFail(OPENBRACE, "Expected an opening '{' at the start of a ", stringForFunctionMode(mode), " body");
1346
1347     // BytecodeGenerator emits code to throw TypeError when a class constructor is "call"ed.
1348     // Set ConstructorKind to None for non-constructor methods of classes.
1349     bool isClassConstructor = mode == MethodMode && info.name && *info.name == m_vm->propertyNames->constructor;
1350     if (m_defaultConstructorKind != ConstructorKind::None) {
1351         ownerClassKind = m_defaultConstructorKind;
1352         isClassConstructor = true;
1353     }
1354     ConstructorKind constructorKind = isClassConstructor ? ownerClassKind : ConstructorKind::None;
1355
1356     info.openBraceOffset = m_token.m_data.offset;
1357     info.bodyStartLine = tokenLine();
1358     info.bodyStartColumn = m_token.m_data.offset - m_token.m_data.lineStartOffset;
1359     JSTokenLocation startLocation(tokenLocation());
1360     
1361     // If we know about this function already, we can use the cached info and skip the parser to the end of the function.
1362     if (const SourceProviderCacheItem* cachedInfo = TreeBuilder::CanUseFunctionCache ? findCachedFunctionInfo(info.openBraceOffset) : 0) {
1363         // If we're in a strict context, the cached function info must say it was strict too.
1364         ASSERT(!strictMode() || cachedInfo->strictMode);
1365         JSTokenLocation endLocation;
1366
1367         endLocation.line = cachedInfo->closeBraceLine;
1368         endLocation.startOffset = cachedInfo->closeBraceOffset;
1369         endLocation.lineStartOffset = cachedInfo->closeBraceLineStartOffset;
1370
1371         bool endColumnIsOnStartLine = (endLocation.line == info.bodyStartLine);
1372         ASSERT(endLocation.startOffset >= endLocation.lineStartOffset);
1373         unsigned bodyEndColumn = endColumnIsOnStartLine ?
1374             endLocation.startOffset - m_token.m_data.lineStartOffset :
1375             endLocation.startOffset - endLocation.lineStartOffset;
1376         unsigned currentLineStartOffset = m_token.m_location.lineStartOffset;
1377
1378         info.body = context.createFunctionBody(
1379             startLocation, endLocation, info.bodyStartColumn, bodyEndColumn, 
1380             functionKeywordStart, functionNameStart, parametersStart, 
1381             cachedInfo->strictMode, constructorKind);
1382         
1383         functionScope->restoreFromSourceProviderCache(cachedInfo);
1384         failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo), "Parser error");
1385         
1386         info.closeBraceOffset = cachedInfo->closeBraceOffset;
1387
1388         m_token = cachedInfo->closeBraceToken();
1389         if (endColumnIsOnStartLine)
1390             m_token.m_location.lineStartOffset = currentLineStartOffset;
1391
1392         m_lexer->setOffset(m_token.m_location.endOffset, m_token.m_location.lineStartOffset);
1393         m_lexer->setLineNumber(m_token.m_location.line);
1394
1395         context.setEndOffset(info.body, m_lexer->currentOffset());
1396         
1397         next();
1398         info.bodyEndLine = m_lastTokenEndPosition.line;
1399         return true;
1400     }
1401     m_lastFunctionName = lastFunctionName;
1402     ParserState oldState = saveState();
1403     info.body = parseFunctionBody(context, functionKeywordStart, functionNameStart, parametersStart, constructorKind);
1404     restoreState(oldState);
1405     failIfFalse(info.body, "Cannot parse the body of this ", stringForFunctionMode(mode));
1406     context.setEndOffset(info.body, m_lexer->currentOffset());
1407     if (functionScope->strictMode() && info.name) {
1408         RELEASE_ASSERT(mode == FunctionMode || mode == MethodMode);
1409         semanticFailIfTrue(m_vm->propertyNames->arguments == *info.name, "'", info.name->impl(), "' is not a valid function name in strict mode");
1410         semanticFailIfTrue(m_vm->propertyNames->eval == *info.name, "'", info.name->impl(), "' is not a valid function name in strict mode");
1411     }
1412     if (functionScope->hasDirectSuper()) {
1413         semanticFailIfTrue(!isClassConstructor, "Cannot call super() outside of a class constructor");
1414         semanticFailIfTrue(ownerClassKind != ConstructorKind::Derived, "Cannot call super() in a base class constructor");
1415     }
1416     if (functionScope->needsSuperBinding())
1417         semanticFailIfTrue(ownerClassKind != ConstructorKind::Derived, "super can only be used in a method of a derived class");
1418
1419     info.closeBraceOffset = m_token.m_data.offset;
1420     unsigned closeBraceLine = m_token.m_data.line;
1421     unsigned closeBraceLineStartOffset = m_token.m_data.lineStartOffset;
1422     
1423     // Cache the tokenizer state and the function scope the first time the function is parsed.
1424     // Any future reparsing can then skip the function.
1425     static const int minimumFunctionLengthToCache = 16;
1426     std::unique_ptr<SourceProviderCacheItem> newInfo;
1427     int functionLength = info.closeBraceOffset - info.openBraceOffset;
1428     if (TreeBuilder::CanUseFunctionCache && m_functionCache && functionLength > minimumFunctionLengthToCache) {
1429         SourceProviderCacheItemCreationParameters parameters;
1430         parameters.functionNameStart = functionNameStart;
1431         parameters.closeBraceLine = closeBraceLine;
1432         parameters.closeBraceOffset = info.closeBraceOffset;
1433         parameters.closeBraceLineStartOffset = closeBraceLineStartOffset;
1434         functionScope->fillParametersForSourceProviderCache(parameters);
1435         newInfo = SourceProviderCacheItem::create(parameters);
1436
1437     }
1438     
1439     failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo), "Parser error");
1440     matchOrFail(CLOSEBRACE, "Expected a closing '}' after a ", stringForFunctionMode(mode), " body");
1441     
1442     if (newInfo)
1443         m_functionCache->add(info.openBraceOffset, WTF::move(newInfo));
1444     
1445     next();
1446     info.bodyEndLine = m_lastTokenEndPosition.line;
1447     return true;
1448 }
1449
1450 template <typename LexerType>
1451 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDeclaration(TreeBuilder& context)
1452 {
1453     ASSERT(match(FUNCTION));
1454     JSTokenLocation location(tokenLocation());
1455     unsigned functionKeywordStart = tokenStart();
1456     next();
1457     ParserFunctionInfo<TreeBuilder> info;
1458     failIfFalse((parseFunctionInfo(context, FunctionNeedsName, FunctionMode, true, ConstructorKind::None, functionKeywordStart, info)), "Cannot parse this function");
1459     failIfFalse(info.name, "Function statements must have a name");
1460     failIfFalseIfStrict(declareVariable(info.name), "Cannot declare a function named '", info.name->impl(), "' in strict mode");
1461     return context.createFuncDeclStatement(location, info);
1462 }
1463
1464 #if ENABLE(ES6_CLASS_SYNTAX)
1465 template <typename LexerType>
1466 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseClassDeclaration(TreeBuilder& context)
1467 {
1468     ASSERT(match(CLASSTOKEN));
1469     JSTokenLocation location(tokenLocation());
1470     JSTextPosition classStart = tokenStartPosition();
1471     unsigned classStartLine = tokenLine();
1472
1473     ParserClassInfo<TreeBuilder> info;
1474     TreeClassExpression classExpr = parseClass(context, FunctionNeedsName, info);
1475     failIfFalse(classExpr, "Failed to parse class");
1476     declareVariable(info.className);
1477
1478     // FIXME: This should be like `let`, not `var`.
1479     context.addVar(info.className, DeclarationStacks::HasInitializer);
1480
1481     JSTextPosition classEnd = lastTokenEndPosition();
1482     unsigned classEndLine = tokenLine();
1483
1484     return context.createClassDeclStatement(location, classExpr, classStart, classEnd, classStartLine, classEndLine);
1485 }
1486
1487 template <typename LexerType>
1488 template <class TreeBuilder> TreeClassExpression Parser<LexerType>::parseClass(TreeBuilder& context, FunctionRequirements requirements, ParserClassInfo<TreeBuilder>& info)
1489 {
1490     ASSERT(match(CLASSTOKEN));
1491     JSTokenLocation location(tokenLocation());
1492     next();
1493
1494     AutoPopScopeRef classScope(this, pushScope());
1495     classScope->setStrictMode();
1496
1497     const Identifier* className = nullptr;
1498     if (match(IDENT)) {
1499         className = m_token.m_data.ident;
1500         info.className = className;
1501         next();
1502         failIfFalse(classScope->declareVariable(className), "'", className->impl(), "' is not a valid class name");
1503     } else if (requirements == FunctionNeedsName) {
1504         if (match(OPENBRACE))
1505             semanticFail("Class statements must have a name");
1506         semanticFailureDueToKeyword("class name");
1507         failDueToUnexpectedToken();
1508     } else
1509         className = &m_vm->propertyNames->nullIdentifier;
1510     ASSERT(className);
1511
1512     TreeExpression parentClass = 0;
1513     if (consume(EXTENDS)) {
1514         parentClass = parseMemberExpression(context);
1515         failIfFalse(parentClass, "Cannot parse the parent class name");
1516     }
1517     const ConstructorKind constructorKind = parentClass ? ConstructorKind::Derived : ConstructorKind::Base;
1518
1519     consumeOrFailWithFlags(OPENBRACE, TreeBuilder::DontBuildStrings, "Expected opening '{' at the start of a class body");
1520
1521     TreeExpression constructor = 0;
1522     TreePropertyList staticMethods = 0;
1523     TreePropertyList instanceMethods = 0;
1524     TreePropertyList instanceMethodsTail = 0;
1525     TreePropertyList staticMethodsTail = 0;
1526     while (!match(CLOSEBRACE)) {
1527         if (match(SEMICOLON))
1528             next();
1529
1530         JSTokenLocation methodLocation(tokenLocation());
1531         unsigned methodStart = tokenStart();
1532
1533         // For backwards compatibility, "static" is a non-reserved keyword in non-strict mode.
1534         bool isStaticMethod = match(RESERVED_IF_STRICT) && *m_token.m_data.ident == m_vm->propertyNames->staticKeyword;
1535         if (isStaticMethod)
1536             next();
1537
1538         matchOrFail(IDENT, "Expected an identifier");
1539
1540         const CommonIdentifiers& propertyNames = *m_vm->propertyNames;
1541         const Identifier& ident = *m_token.m_data.ident;
1542         bool isGetter = ident == propertyNames.get;
1543         bool isSetter = ident == propertyNames.set;
1544
1545         TreeProperty property;
1546         const bool alwaysStrictInsideClass = true;
1547         if (isGetter || isSetter) {
1548             nextExpectIdentifier(LexerFlagsIgnoreReservedWords);
1549             property = parseGetterSetter(context, alwaysStrictInsideClass, isGetter ? PropertyNode::Getter : PropertyNode::Setter, methodStart, constructorKind, SuperBinding::Needed);
1550             failIfFalse(property, "Cannot parse this method");
1551         } else {
1552             ParserFunctionInfo<TreeBuilder> methodInfo;
1553             failIfFalse((parseFunctionInfo(context, FunctionNeedsName, isStaticMethod ? FunctionMode : MethodMode, false, constructorKind, methodStart, methodInfo)), "Cannot parse this method");
1554             failIfFalse(methodInfo.name, "method must have a name");
1555             failIfFalse(declareVariable(methodInfo.name), "Cannot declare a method named '", methodInfo.name->impl(), "'");
1556
1557             bool isConstructor = !isStaticMethod && *methodInfo.name == propertyNames.constructor;
1558             if (isConstructor)
1559                 methodInfo.name = className;
1560
1561             TreeExpression method = context.createFunctionExpr(methodLocation, methodInfo);
1562             if (isConstructor) {
1563                 semanticFailIfTrue(constructor, "Cannot declare multiple constructors in a single class");
1564                 constructor = method;
1565                 continue;
1566             }
1567
1568             // FIXME: Syntax error when super() is called
1569             semanticFailIfTrue(isStaticMethod && *methodInfo.name == propertyNames.prototype,
1570                 "Cannot declare a static method named 'prototype'");
1571             property = context.createProperty(methodInfo.name, method, PropertyNode::Constant, PropertyNode::Unknown, alwaysStrictInsideClass, SuperBinding::Needed);
1572         }
1573
1574         TreePropertyList& tail = isStaticMethod ? staticMethodsTail : instanceMethodsTail;
1575         if (tail)
1576             tail = context.createPropertyList(methodLocation, property, tail);
1577         else {
1578             tail = context.createPropertyList(methodLocation, property);
1579             if (isStaticMethod)
1580                 staticMethods = tail;
1581             else
1582                 instanceMethods = tail;
1583         }
1584     }
1585
1586     failIfFalse(popScope(classScope, TreeBuilder::NeedsFreeVariableInfo), "Parser error");
1587     consumeOrFail(CLOSEBRACE, "Expected a closing '}' after a class body");
1588
1589     return context.createClassExpr(location, *className, constructor, parentClass, instanceMethods, staticMethods);
1590 }
1591 #endif
1592
1593 struct LabelInfo {
1594     LabelInfo(const Identifier* ident, const JSTextPosition& start, const JSTextPosition& end)
1595     : m_ident(ident)
1596     , m_start(start)
1597     , m_end(end)
1598     {
1599     }
1600     
1601     const Identifier* m_ident;
1602     JSTextPosition m_start;
1603     JSTextPosition m_end;
1604 };
1605
1606 template <typename LexerType>
1607 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionOrLabelStatement(TreeBuilder& context)
1608 {
1609     
1610     /* Expression and Label statements are ambiguous at LL(1), so we have a
1611      * special case that looks for a colon as the next character in the input.
1612      */
1613     Vector<LabelInfo> labels;
1614     JSTokenLocation location;
1615     do {
1616         JSTextPosition start = tokenStartPosition();
1617         location = tokenLocation();
1618         if (!nextTokenIsColon()) {
1619             // If we hit this path we're making a expression statement, which
1620             // by definition can't make use of continue/break so we can just
1621             // ignore any labels we might have accumulated.
1622             TreeExpression expression = parseExpression(context);
1623             failIfFalse(expression, "Cannot parse expression statement");
1624             if (!autoSemiColon())
1625                 failDueToUnexpectedToken();
1626             return context.createExprStatement(location, expression, start, m_lastTokenEndPosition.line);
1627         }
1628         const Identifier* ident = m_token.m_data.ident;
1629         JSTextPosition end = tokenEndPosition();
1630         next();
1631         consumeOrFail(COLON, "Labels must be followed by a ':'");
1632         if (!m_syntaxAlreadyValidated) {
1633             // This is O(N^2) over the current list of consecutive labels, but I
1634             // have never seen more than one label in a row in the real world.
1635             for (size_t i = 0; i < labels.size(); i++)
1636                 failIfTrue(ident->impl() == labels[i].m_ident->impl(), "Attempted to redeclare the label '", ident->impl(), "'");
1637             failIfTrue(getLabel(ident), "Cannot find scope for the label '", ident->impl(), "'");
1638             labels.append(LabelInfo(ident, start, end));
1639         }
1640     } while (match(IDENT));
1641     bool isLoop = false;
1642     switch (m_token.m_type) {
1643     case FOR:
1644     case WHILE:
1645     case DO:
1646         isLoop = true;
1647         break;
1648         
1649     default:
1650         break;
1651     }
1652     const Identifier* unused = 0;
1653     if (!m_syntaxAlreadyValidated) {
1654         for (size_t i = 0; i < labels.size(); i++)
1655             pushLabel(labels[i].m_ident, isLoop);
1656     }
1657     TreeStatement statement = parseStatement(context, unused);
1658     if (!m_syntaxAlreadyValidated) {
1659         for (size_t i = 0; i < labels.size(); i++)
1660             popLabel();
1661     }
1662     failIfFalse(statement, "Cannot parse statement");
1663     for (size_t i = 0; i < labels.size(); i++) {
1664         const LabelInfo& info = labels[labels.size() - i - 1];
1665         statement = context.createLabelStatement(location, info.m_ident, statement, info.m_start, info.m_end);
1666     }
1667     return statement;
1668 }
1669
1670 template <typename LexerType>
1671 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionStatement(TreeBuilder& context)
1672 {
1673     JSTextPosition start = tokenStartPosition();
1674     JSTokenLocation location(tokenLocation());
1675     TreeExpression expression = parseExpression(context);
1676     failIfFalse(expression, "Cannot parse expression statement");
1677     failIfFalse(autoSemiColon(), "Parse error");
1678     return context.createExprStatement(location, expression, start, m_lastTokenEndPosition.line);
1679 }
1680
1681 template <typename LexerType>
1682 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseIfStatement(TreeBuilder& context)
1683 {
1684     ASSERT(match(IF));
1685     JSTokenLocation ifLocation(tokenLocation());
1686     int start = tokenLine();
1687     next();
1688     handleProductionOrFail(OPENPAREN, "(", "start", "'if' condition");
1689
1690     TreeExpression condition = parseExpression(context);
1691     failIfFalse(condition, "Expected a expression as the condition for an if statement");
1692     int end = tokenLine();
1693     handleProductionOrFail(CLOSEPAREN, ")", "end", "'if' condition");
1694
1695     const Identifier* unused = 0;
1696     TreeStatement trueBlock = parseStatement(context, unused);
1697     failIfFalse(trueBlock, "Expected a statement as the body of an if block");
1698
1699     if (!match(ELSE))
1700         return context.createIfStatement(ifLocation, condition, trueBlock, 0, start, end);
1701
1702     Vector<TreeExpression> exprStack;
1703     Vector<std::pair<int, int>> posStack;
1704     Vector<JSTokenLocation> tokenLocationStack;
1705     Vector<TreeStatement> statementStack;
1706     bool trailingElse = false;
1707     do {
1708         JSTokenLocation tempLocation = tokenLocation();
1709         next();
1710         if (!match(IF)) {
1711             const Identifier* unused = 0;
1712             TreeStatement block = parseStatement(context, unused);
1713             failIfFalse(block, "Expected a statement as the body of an else block");
1714             statementStack.append(block);
1715             trailingElse = true;
1716             break;
1717         }
1718         int innerStart = tokenLine();
1719         next();
1720         
1721         handleProductionOrFail(OPENPAREN, "(", "start", "'if' condition");
1722
1723         TreeExpression innerCondition = parseExpression(context);
1724         failIfFalse(innerCondition, "Expected a expression as the condition for an if statement");
1725         int innerEnd = tokenLine();
1726         handleProductionOrFail(CLOSEPAREN, ")", "end", "'if' condition");
1727         const Identifier* unused = 0;
1728         TreeStatement innerTrueBlock = parseStatement(context, unused);
1729         failIfFalse(innerTrueBlock, "Expected a statement as the body of an if block");
1730         tokenLocationStack.append(tempLocation);
1731         exprStack.append(innerCondition);
1732         posStack.append(std::make_pair(innerStart, innerEnd));
1733         statementStack.append(innerTrueBlock);
1734     } while (match(ELSE));
1735
1736     if (!trailingElse) {
1737         TreeExpression condition = exprStack.last();
1738         exprStack.removeLast();
1739         TreeStatement trueBlock = statementStack.last();
1740         statementStack.removeLast();
1741         std::pair<int, int> pos = posStack.last();
1742         posStack.removeLast();
1743         JSTokenLocation elseLocation = tokenLocationStack.last();
1744         tokenLocationStack.removeLast();
1745         TreeStatement ifStatement = context.createIfStatement(elseLocation, condition, trueBlock, 0, pos.first, pos.second);
1746         context.setEndOffset(ifStatement, context.endOffset(trueBlock));
1747         statementStack.append(ifStatement);
1748     }
1749
1750     while (!exprStack.isEmpty()) {
1751         TreeExpression condition = exprStack.last();
1752         exprStack.removeLast();
1753         TreeStatement falseBlock = statementStack.last();
1754         statementStack.removeLast();
1755         TreeStatement trueBlock = statementStack.last();
1756         statementStack.removeLast();
1757         std::pair<int, int> pos = posStack.last();
1758         posStack.removeLast();
1759         JSTokenLocation elseLocation = tokenLocationStack.last();
1760         tokenLocationStack.removeLast();
1761         TreeStatement ifStatement = context.createIfStatement(elseLocation, condition, trueBlock, falseBlock, pos.first, pos.second);
1762         context.setEndOffset(ifStatement, context.endOffset(falseBlock));
1763         statementStack.append(ifStatement);
1764     }
1765
1766     return context.createIfStatement(ifLocation, condition, trueBlock, statementStack.last(), start, end);
1767 }
1768
1769 template <typename LexerType>
1770 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseExpression(TreeBuilder& context)
1771 {
1772     failIfStackOverflow();
1773     JSTokenLocation location(tokenLocation());
1774     TreeExpression node = parseAssignmentExpression(context);
1775     failIfFalse(node, "Cannot parse expression");
1776     context.setEndOffset(node, m_lastTokenEndPosition.offset);
1777     if (!match(COMMA))
1778         return node;
1779     next();
1780     m_nonTrivialExpressionCount++;
1781     m_nonLHSCount++;
1782     TreeExpression right = parseAssignmentExpression(context);
1783     failIfFalse(right, "Cannot parse expression in a comma expression");
1784     context.setEndOffset(right, m_lastTokenEndPosition.offset);
1785     typename TreeBuilder::Comma head = context.createCommaExpr(location, node);
1786     typename TreeBuilder::Comma tail = context.appendToCommaExpr(location, head, head, right);
1787     while (match(COMMA)) {
1788         next(TreeBuilder::DontBuildStrings);
1789         right = parseAssignmentExpression(context);
1790         failIfFalse(right, "Cannot parse expression in a comma expression");
1791         context.setEndOffset(right, m_lastTokenEndPosition.offset);
1792         tail = context.appendToCommaExpr(location, head, tail, right);
1793     }
1794     context.setEndOffset(head, m_lastTokenEndPosition.offset);
1795     return head;
1796 }
1797
1798 template <typename LexerType>
1799 template <typename TreeBuilder> TreeExpression Parser<LexerType>::parseAssignmentExpression(TreeBuilder& context)
1800 {
1801     failIfStackOverflow();
1802     JSTextPosition start = tokenStartPosition();
1803     JSTokenLocation location(tokenLocation());
1804     int initialAssignmentCount = m_assignmentCount;
1805     int initialNonLHSCount = m_nonLHSCount;
1806     if (match(OPENBRACE) || match(OPENBRACKET)) {
1807         SavePoint savePoint = createSavePoint();
1808         auto pattern = tryParseDeconstructionPatternExpression(context);
1809         if (pattern && consume(EQUAL)) {
1810             auto rhs = parseAssignmentExpression(context);
1811             if (rhs)
1812                 return context.createDeconstructingAssignment(location, pattern, rhs);
1813         }
1814         restoreSavePoint(savePoint);
1815     }
1816     TreeExpression lhs = parseConditionalExpression(context);
1817     failIfFalse(lhs, "Cannot parse expression");
1818     if (initialNonLHSCount != m_nonLHSCount) {
1819         if (m_token.m_type >= EQUAL && m_token.m_type <= OREQUAL)
1820             semanticFail("Left hand side of operator '", getToken(), "' must be a reference");
1821
1822         return lhs;
1823     }
1824     
1825     int assignmentStack = 0;
1826     Operator op;
1827     bool hadAssignment = false;
1828     while (true) {
1829         switch (m_token.m_type) {
1830         case EQUAL: op = OpEqual; break;
1831         case PLUSEQUAL: op = OpPlusEq; break;
1832         case MINUSEQUAL: op = OpMinusEq; break;
1833         case MULTEQUAL: op = OpMultEq; break;
1834         case DIVEQUAL: op = OpDivEq; break;
1835         case LSHIFTEQUAL: op = OpLShift; break;
1836         case RSHIFTEQUAL: op = OpRShift; break;
1837         case URSHIFTEQUAL: op = OpURShift; break;
1838         case ANDEQUAL: op = OpAndEq; break;
1839         case XOREQUAL: op = OpXOrEq; break;
1840         case OREQUAL: op = OpOrEq; break;
1841         case MODEQUAL: op = OpModEq; break;
1842         default:
1843             goto end;
1844         }
1845         m_nonTrivialExpressionCount++;
1846         hadAssignment = true;
1847         context.assignmentStackAppend(assignmentStack, lhs, start, tokenStartPosition(), m_assignmentCount, op);
1848         start = tokenStartPosition();
1849         m_assignmentCount++;
1850         next(TreeBuilder::DontBuildStrings);
1851         if (strictMode() && m_lastIdentifier && context.isResolve(lhs)) {
1852             failIfTrueIfStrict(m_vm->propertyNames->eval == *m_lastIdentifier, "Cannot modify 'eval' in strict mode");
1853             failIfTrueIfStrict(m_vm->propertyNames->arguments == *m_lastIdentifier, "Cannot modify 'arguments' in strict mode");
1854             declareWrite(m_lastIdentifier);
1855             m_lastIdentifier = 0;
1856         }
1857         lhs = parseAssignmentExpression(context);
1858         failIfFalse(lhs, "Cannot parse the right hand side of an assignment expression");
1859         if (initialNonLHSCount != m_nonLHSCount) {
1860             if (m_token.m_type >= EQUAL && m_token.m_type <= OREQUAL)
1861                 semanticFail("Left hand side of operator '", getToken(), "' must be a reference");
1862             break;
1863         }
1864     }
1865 end:
1866     if (hadAssignment)
1867         m_nonLHSCount++;
1868     
1869     if (!TreeBuilder::CreatesAST)
1870         return lhs;
1871     
1872     while (assignmentStack)
1873         lhs = context.createAssignment(location, assignmentStack, lhs, initialAssignmentCount, m_assignmentCount, lastTokenEndPosition());
1874     
1875     return lhs;
1876 }
1877
1878 template <typename LexerType>
1879 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseConditionalExpression(TreeBuilder& context)
1880 {
1881     JSTokenLocation location(tokenLocation());
1882     TreeExpression cond = parseBinaryExpression(context);
1883     failIfFalse(cond, "Cannot parse expression");
1884     if (!match(QUESTION))
1885         return cond;
1886     m_nonTrivialExpressionCount++;
1887     m_nonLHSCount++;
1888     next(TreeBuilder::DontBuildStrings);
1889     TreeExpression lhs = parseAssignmentExpression(context);
1890     failIfFalse(lhs, "Cannot parse left hand side of ternary operator");
1891     context.setEndOffset(lhs, m_lastTokenEndPosition.offset);
1892     consumeOrFailWithFlags(COLON, TreeBuilder::DontBuildStrings, "Expected ':' in ternary operator");
1893     
1894     TreeExpression rhs = parseAssignmentExpression(context);
1895     failIfFalse(rhs, "Cannot parse right hand side of ternary operator");
1896     context.setEndOffset(rhs, m_lastTokenEndPosition.offset);
1897     return context.createConditionalExpr(location, cond, lhs, rhs);
1898 }
1899
1900 ALWAYS_INLINE static bool isUnaryOp(JSTokenType token)
1901 {
1902     return token & UnaryOpTokenFlag;
1903 }
1904
1905 template <typename LexerType>
1906 int Parser<LexerType>::isBinaryOperator(JSTokenType token)
1907 {
1908     if (m_allowsIn)
1909         return token & (BinaryOpTokenPrecedenceMask << BinaryOpTokenAllowsInPrecedenceAdditionalShift);
1910     return token & BinaryOpTokenPrecedenceMask;
1911 }
1912
1913 template <typename LexerType>
1914 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseBinaryExpression(TreeBuilder& context)
1915 {
1916     int operandStackDepth = 0;
1917     int operatorStackDepth = 0;
1918     typename TreeBuilder::BinaryExprContext binaryExprContext(context);
1919     JSTokenLocation location(tokenLocation());
1920     while (true) {
1921         JSTextPosition exprStart = tokenStartPosition();
1922         int initialAssignments = m_assignmentCount;
1923         TreeExpression current = parseUnaryExpression(context);
1924         failIfFalse(current, "Cannot parse expression");
1925         
1926         context.appendBinaryExpressionInfo(operandStackDepth, current, exprStart, lastTokenEndPosition(), lastTokenEndPosition(), initialAssignments != m_assignmentCount);
1927         int precedence = isBinaryOperator(m_token.m_type);
1928         if (!precedence)
1929             break;
1930         m_nonTrivialExpressionCount++;
1931         m_nonLHSCount++;
1932         int operatorToken = m_token.m_type;
1933         next(TreeBuilder::DontBuildStrings);
1934         
1935         while (operatorStackDepth &&  context.operatorStackHasHigherPrecedence(operatorStackDepth, precedence)) {
1936             ASSERT(operandStackDepth > 1);
1937             
1938             typename TreeBuilder::BinaryOperand rhs = context.getFromOperandStack(-1);
1939             typename TreeBuilder::BinaryOperand lhs = context.getFromOperandStack(-2);
1940             context.shrinkOperandStackBy(operandStackDepth, 2);
1941             context.appendBinaryOperation(location, operandStackDepth, operatorStackDepth, lhs, rhs);
1942             context.operatorStackPop(operatorStackDepth);
1943         }
1944         context.operatorStackAppend(operatorStackDepth, operatorToken, precedence);
1945     }
1946     while (operatorStackDepth) {
1947         ASSERT(operandStackDepth > 1);
1948         
1949         typename TreeBuilder::BinaryOperand rhs = context.getFromOperandStack(-1);
1950         typename TreeBuilder::BinaryOperand lhs = context.getFromOperandStack(-2);
1951         context.shrinkOperandStackBy(operandStackDepth, 2);
1952         context.appendBinaryOperation(location, operandStackDepth, operatorStackDepth, lhs, rhs);
1953         context.operatorStackPop(operatorStackDepth);
1954     }
1955     return context.popOperandStack(operandStackDepth);
1956 }
1957
1958 template <typename LexerType>
1959 template <class TreeBuilder> TreeProperty Parser<LexerType>::parseProperty(TreeBuilder& context, bool complete)
1960 {
1961     bool wasIdent = false;
1962     switch (m_token.m_type) {
1963     namedProperty:
1964     case IDENT:
1965         wasIdent = true;
1966         FALLTHROUGH;
1967     case STRING: {
1968         const Identifier* ident = m_token.m_data.ident;
1969         unsigned getterOrSetterStartOffset = tokenStart();
1970         if (complete || (wasIdent && (*ident == m_vm->propertyNames->get || *ident == m_vm->propertyNames->set)))
1971             nextExpectIdentifier(LexerFlagsIgnoreReservedWords);
1972         else
1973             nextExpectIdentifier(LexerFlagsIgnoreReservedWords | TreeBuilder::DontBuildKeywords);
1974
1975         if (match(COLON)) {
1976             next();
1977             TreeExpression node = parseAssignmentExpression(context);
1978             failIfFalse(node, "Cannot parse expression for property declaration");
1979             context.setEndOffset(node, m_lexer->currentOffset());
1980             return context.createProperty(ident, node, PropertyNode::Constant, PropertyNode::Unknown, complete);
1981         }
1982
1983         if (match(OPENPAREN)) {
1984             auto method = parsePropertyMethod(context, ident);
1985             propagateError();
1986             return context.createProperty(ident, method, PropertyNode::Constant, PropertyNode::KnownDirect, complete);
1987         }
1988
1989         failIfFalse(wasIdent, "Expected an identifier as property name");
1990
1991         if (match(COMMA) || match(CLOSEBRACE)) {
1992             JSTextPosition start = tokenStartPosition();
1993             JSTokenLocation location(tokenLocation());
1994             currentScope()->useVariable(ident, m_vm->propertyNames->eval == *ident);
1995             TreeExpression node = context.createResolve(location, ident, start);
1996             return context.createProperty(ident, node, PropertyNode::Constant, PropertyNode::KnownDirect, complete);
1997         }
1998
1999         PropertyNode::Type type;
2000         if (*ident == m_vm->propertyNames->get)
2001             type = PropertyNode::Getter;
2002         else if (*ident == m_vm->propertyNames->set)
2003             type = PropertyNode::Setter;
2004         else
2005             failWithMessage("Expected a ':' following the property name '", ident->impl(), "'");
2006         return parseGetterSetter(context, complete, type, getterOrSetterStartOffset);
2007     }
2008     case DOUBLE:
2009     case INTEGER: {
2010         double propertyName = m_token.m_data.doubleValue;
2011         next();
2012
2013         if (match(OPENPAREN)) {
2014             const Identifier& ident = m_parserArena.identifierArena().makeNumericIdentifier(const_cast<VM*>(m_vm), propertyName);
2015             auto method = parsePropertyMethod(context, &ident);
2016             propagateError();
2017             return context.createProperty(&ident, method, PropertyNode::Constant, PropertyNode::Unknown, complete);
2018         }
2019
2020         consumeOrFail(COLON, "Expected ':' after property name");
2021         TreeExpression node = parseAssignmentExpression(context);
2022         failIfFalse(node, "Cannot parse expression for property declaration");
2023         context.setEndOffset(node, m_lexer->currentOffset());
2024         return context.createProperty(const_cast<VM*>(m_vm), m_parserArena, propertyName, node, PropertyNode::Constant, PropertyNode::Unknown, complete);
2025     }
2026     case OPENBRACKET: {
2027         next();
2028         auto propertyName = parseAssignmentExpression(context);
2029         failIfFalse(propertyName, "Cannot parse computed property name");
2030         handleProductionOrFail(CLOSEBRACKET, "]", "end", "computed property name");
2031
2032         if (match(OPENPAREN)) {
2033             auto method = parsePropertyMethod(context, &m_vm->propertyNames->nullIdentifier);
2034             propagateError();
2035             return context.createProperty(propertyName, method, PropertyNode::Constant, PropertyNode::KnownDirect, complete);
2036         }
2037
2038         consumeOrFail(COLON, "Expected ':' after property name");
2039         TreeExpression node = parseAssignmentExpression(context);
2040         failIfFalse(node, "Cannot parse expression for property declaration");
2041         context.setEndOffset(node, m_lexer->currentOffset());
2042         return context.createProperty(propertyName, node, PropertyNode::Constant, PropertyNode::Unknown, complete);
2043     }
2044     default:
2045         failIfFalse(m_token.m_type & KeywordTokenFlag, "Expected a property name");
2046         goto namedProperty;
2047     }
2048 }
2049
2050 template <typename LexerType>
2051 template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePropertyMethod(TreeBuilder& context, const Identifier* methodName)
2052 {
2053     JSTokenLocation methodLocation(tokenLocation());
2054     unsigned methodStart = tokenStart();
2055     ParserFunctionInfo<TreeBuilder> methodInfo;
2056     failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, MethodMode, false, ConstructorKind::None, methodStart, methodInfo)), "Cannot parse this method");
2057     methodInfo.name = methodName;
2058     return context.createFunctionExpr(methodLocation, methodInfo);
2059 }
2060
2061 template <typename LexerType>
2062 template <class TreeBuilder> TreeProperty Parser<LexerType>::parseGetterSetter(TreeBuilder& context, bool strict, PropertyNode::Type type, unsigned getterOrSetterStartOffset,
2063     ConstructorKind constructorKind, SuperBinding superBinding)
2064 {
2065     const Identifier* stringPropertyName = 0;
2066     double numericPropertyName = 0;
2067     if (m_token.m_type == IDENT || m_token.m_type == STRING)
2068         stringPropertyName = m_token.m_data.ident;
2069     else if (m_token.m_type == DOUBLE || m_token.m_type == INTEGER)
2070         numericPropertyName = m_token.m_data.doubleValue;
2071     else
2072         failDueToUnexpectedToken();
2073     JSTokenLocation location(tokenLocation());
2074     next();
2075     ParserFunctionInfo<TreeBuilder> info;
2076     if (type == PropertyNode::Getter) {
2077         failIfFalse(match(OPENPAREN), "Expected a parameter list for getter definition");
2078         failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, GetterMode, false, constructorKind, getterOrSetterStartOffset, info)), "Cannot parse getter definition");
2079     } else {
2080         failIfFalse(match(OPENPAREN), "Expected a parameter list for setter definition");
2081         failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, SetterMode, false, constructorKind, getterOrSetterStartOffset, info)), "Cannot parse setter definition");
2082     }
2083     if (stringPropertyName)
2084         return context.createGetterOrSetterProperty(location, type, strict, stringPropertyName, info, superBinding);
2085     return context.createGetterOrSetterProperty(const_cast<VM*>(m_vm), m_parserArena, location, type, strict, numericPropertyName, info, superBinding);
2086 }
2087
2088 template <typename LexerType>
2089 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseObjectLiteral(TreeBuilder& context)
2090 {
2091     auto savePoint = createSavePoint();
2092     consumeOrFailWithFlags(OPENBRACE, TreeBuilder::DontBuildStrings, "Expected opening '{' at the start of an object literal");
2093     JSTokenLocation location(tokenLocation());
2094
2095     int oldNonLHSCount = m_nonLHSCount;
2096     
2097     if (match(CLOSEBRACE)) {
2098         next();
2099         return context.createObjectLiteral(location);
2100     }
2101     
2102     TreeProperty property = parseProperty(context, false);
2103     failIfFalse(property, "Cannot parse object literal property");
2104     if (!m_syntaxAlreadyValidated && context.getType(property) != PropertyNode::Constant) {
2105         restoreSavePoint(savePoint);
2106         return parseStrictObjectLiteral(context);
2107     }
2108     TreePropertyList propertyList = context.createPropertyList(location, property);
2109     TreePropertyList tail = propertyList;
2110     while (match(COMMA)) {
2111         next(TreeBuilder::DontBuildStrings);
2112         // allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939
2113         if (match(CLOSEBRACE))
2114             break;
2115         JSTokenLocation propertyLocation(tokenLocation());
2116         property = parseProperty(context, false);
2117         failIfFalse(property, "Cannot parse object literal property");
2118         if (!m_syntaxAlreadyValidated && context.getType(property) != PropertyNode::Constant) {
2119             restoreSavePoint(savePoint);
2120             return parseStrictObjectLiteral(context);
2121         }
2122         tail = context.createPropertyList(propertyLocation, property, tail);
2123     }
2124
2125     location = tokenLocation();
2126     handleProductionOrFail(CLOSEBRACE, "}", "end", "object literal");
2127     
2128     m_nonLHSCount = oldNonLHSCount;
2129     
2130     return context.createObjectLiteral(location, propertyList);
2131 }
2132
2133 template <typename LexerType>
2134 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseStrictObjectLiteral(TreeBuilder& context)
2135 {
2136     consumeOrFail(OPENBRACE, "Expected opening '{' at the start of an object literal");
2137     
2138     int oldNonLHSCount = m_nonLHSCount;
2139
2140     JSTokenLocation location(tokenLocation());
2141     if (match(CLOSEBRACE)) {
2142         next();
2143         return context.createObjectLiteral(location);
2144     }
2145     
2146     TreeProperty property = parseProperty(context, true);
2147     failIfFalse(property, "Cannot parse object literal property");
2148     
2149     typedef HashMap<RefPtr<StringImpl>, unsigned, IdentifierRepHash> ObjectValidationMap;
2150     ObjectValidationMap objectValidator;
2151     // Add the first property
2152     if (!m_syntaxAlreadyValidated && context.getName(property))
2153         objectValidator.add(context.getName(property)->impl(), context.getType(property));
2154     
2155     TreePropertyList propertyList = context.createPropertyList(location, property);
2156     TreePropertyList tail = propertyList;
2157     while (match(COMMA)) {
2158         next();
2159         // allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939
2160         if (match(CLOSEBRACE))
2161             break;
2162         JSTokenLocation propertyLocation(tokenLocation());
2163         property = parseProperty(context, true);
2164         failIfFalse(property, "Cannot parse object literal property");
2165         if (!m_syntaxAlreadyValidated && context.getName(property)) {
2166             ObjectValidationMap::AddResult propertyEntry = objectValidator.add(context.getName(property)->impl(), context.getType(property));
2167             if (!propertyEntry.isNewEntry) {
2168                 semanticFailIfTrue(propertyEntry.iterator->value == PropertyNode::Constant, "Attempted to redefine property '", propertyEntry.iterator->key.get(), "'");
2169                 semanticFailIfTrue(context.getType(property) == PropertyNode::Constant, "Attempted to redefine property '", propertyEntry.iterator->key.get(), "'");
2170                 semanticFailIfTrue(context.getType(property) & propertyEntry.iterator->value, "Attempted to redefine property '", propertyEntry.iterator->key.get(), "'");
2171                 propertyEntry.iterator->value |= context.getType(property);
2172             }
2173         }
2174         tail = context.createPropertyList(propertyLocation, property, tail);
2175     }
2176
2177     location = tokenLocation();
2178     handleProductionOrFail(CLOSEBRACE, "}", "end", "object literal");
2179
2180     m_nonLHSCount = oldNonLHSCount;
2181
2182     return context.createObjectLiteral(location, propertyList);
2183 }
2184
2185 template <typename LexerType>
2186 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseArrayLiteral(TreeBuilder& context)
2187 {
2188     consumeOrFailWithFlags(OPENBRACKET, TreeBuilder::DontBuildStrings, "Expected an opening '[' at the beginning of an array literal");
2189     
2190     int oldNonLHSCount = m_nonLHSCount;
2191     
2192     int elisions = 0;
2193     while (match(COMMA)) {
2194         next(TreeBuilder::DontBuildStrings);
2195         elisions++;
2196     }
2197     if (match(CLOSEBRACKET)) {
2198         JSTokenLocation location(tokenLocation());
2199         next(TreeBuilder::DontBuildStrings);
2200         return context.createArray(location, elisions);
2201     }
2202     
2203     TreeExpression elem;
2204     if (UNLIKELY(match(DOTDOTDOT))) {
2205         auto spreadLocation = m_token.m_location;
2206         auto start = m_token.m_startPosition;
2207         auto divot = m_token.m_endPosition;
2208         next();
2209         auto spreadExpr = parseAssignmentExpression(context);
2210         failIfFalse(spreadExpr, "Cannot parse subject of a spread operation");
2211         elem = context.createSpreadExpression(spreadLocation, spreadExpr, start, divot, m_lastTokenEndPosition);
2212     } else
2213         elem = parseAssignmentExpression(context);
2214     failIfFalse(elem, "Cannot parse array literal element");
2215     typename TreeBuilder::ElementList elementList = context.createElementList(elisions, elem);
2216     typename TreeBuilder::ElementList tail = elementList;
2217     elisions = 0;
2218     while (match(COMMA)) {
2219         next(TreeBuilder::DontBuildStrings);
2220         elisions = 0;
2221         
2222         while (match(COMMA)) {
2223             next();
2224             elisions++;
2225         }
2226         
2227         if (match(CLOSEBRACKET)) {
2228             JSTokenLocation location(tokenLocation());
2229             next(TreeBuilder::DontBuildStrings);
2230             return context.createArray(location, elisions, elementList);
2231         }
2232         if (UNLIKELY(match(DOTDOTDOT))) {
2233             auto spreadLocation = m_token.m_location;
2234             auto start = m_token.m_startPosition;
2235             auto divot = m_token.m_endPosition;
2236             next();
2237             TreeExpression elem = parseAssignmentExpression(context);
2238             failIfFalse(elem, "Cannot parse subject of a spread operation");
2239             auto spread = context.createSpreadExpression(spreadLocation, elem, start, divot, m_lastTokenEndPosition);
2240             tail = context.createElementList(tail, elisions, spread);
2241             continue;
2242         }
2243         TreeExpression elem = parseAssignmentExpression(context);
2244         failIfFalse(elem, "Cannot parse array literal element");
2245         tail = context.createElementList(tail, elisions, elem);
2246     }
2247
2248     JSTokenLocation location(tokenLocation());
2249     if (!consume(CLOSEBRACKET)) {
2250         failIfFalse(match(DOTDOTDOT), "Expected either a closing ']' or a ',' following an array element");
2251         semanticFail("The '...' operator should come before a target expression");
2252     }
2253     
2254     m_nonLHSCount = oldNonLHSCount;
2255     
2256     return context.createArray(location, elementList);
2257 }
2258
2259 template <typename LexerType>
2260 template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePrimaryExpression(TreeBuilder& context)
2261 {
2262     failIfStackOverflow();
2263     switch (m_token.m_type) {
2264     case FUNCTION: {
2265         JSTokenLocation location(tokenLocation());
2266         unsigned functionKeywordStart = tokenStart();
2267         next();
2268         ParserFunctionInfo<TreeBuilder> info;
2269         info.name = &m_vm->propertyNames->nullIdentifier;
2270         failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, FunctionMode, false, ConstructorKind::None, functionKeywordStart, info)), "Cannot parse function expression");
2271         return context.createFunctionExpr(location, info);
2272     }
2273 #if ENABLE(ES6_CLASS_SYNTAX)
2274     case CLASSTOKEN: {
2275         ParserClassInfo<TreeBuilder> info;
2276         return parseClass(context, FunctionNoRequirements, info);
2277     }
2278 #endif
2279     case OPENBRACE:
2280         if (strictMode())
2281             return parseStrictObjectLiteral(context);
2282         return parseObjectLiteral(context);
2283     case OPENBRACKET:
2284         return parseArrayLiteral(context);
2285     case OPENPAREN: {
2286         next();
2287         int oldNonLHSCount = m_nonLHSCount;
2288         TreeExpression result = parseExpression(context);
2289         m_nonLHSCount = oldNonLHSCount;
2290         handleProductionOrFail(CLOSEPAREN, ")", "end", "compound expression");
2291         return result;
2292     }
2293     case THISTOKEN: {
2294         JSTokenLocation location(tokenLocation());
2295         next();
2296         return context.thisExpr(location, m_thisTDZMode);
2297     }
2298     case IDENT: {
2299         JSTextPosition start = tokenStartPosition();
2300         const Identifier* ident = m_token.m_data.ident;
2301         JSTokenLocation location(tokenLocation());
2302         next();
2303         currentScope()->useVariable(ident, m_vm->propertyNames->eval == *ident);
2304         m_lastIdentifier = ident;
2305         return context.createResolve(location, ident, start);
2306     }
2307     case STRING: {
2308         const Identifier* ident = m_token.m_data.ident;
2309         JSTokenLocation location(tokenLocation());
2310         next();
2311         return context.createString(location, ident);
2312     }
2313     case DOUBLE: {
2314         double d = m_token.m_data.doubleValue;
2315         JSTokenLocation location(tokenLocation());
2316         next();
2317         return context.createDoubleExpr(location, d);
2318     }
2319     case INTEGER: {
2320         double d = m_token.m_data.doubleValue;
2321         JSTokenLocation location(tokenLocation());
2322         next();
2323         return context.createIntegerExpr(location, d);
2324     }
2325     case NULLTOKEN: {
2326         JSTokenLocation location(tokenLocation());
2327         next();
2328         return context.createNull(location);
2329     }
2330     case TRUETOKEN: {
2331         JSTokenLocation location(tokenLocation());
2332         next();
2333         return context.createBoolean(location, true);
2334     }
2335     case FALSETOKEN: {
2336         JSTokenLocation location(tokenLocation());
2337         next();
2338         return context.createBoolean(location, false);
2339     }
2340     case DIVEQUAL:
2341     case DIVIDE: {
2342         /* regexp */
2343         const Identifier* pattern;
2344         const Identifier* flags;
2345         if (match(DIVEQUAL))
2346             failIfFalse(m_lexer->scanRegExp(pattern, flags, '='), "Invalid regular expression");
2347         else
2348             failIfFalse(m_lexer->scanRegExp(pattern, flags), "Invalid regular expression");
2349         
2350         JSTextPosition start = tokenStartPosition();
2351         JSTokenLocation location(tokenLocation());
2352         next();
2353         TreeExpression re = context.createRegExp(location, *pattern, *flags, start);
2354         if (!re) {
2355             const char* yarrErrorMsg = Yarr::checkSyntax(pattern->string());
2356             regexFail(yarrErrorMsg);
2357         }
2358         return re;
2359     }
2360     default:
2361         failDueToUnexpectedToken();
2362     }
2363 }
2364
2365 template <typename LexerType>
2366 template <class TreeBuilder> TreeArguments Parser<LexerType>::parseArguments(TreeBuilder& context, SpreadMode mode)
2367 {
2368     consumeOrFailWithFlags(OPENPAREN, TreeBuilder::DontBuildStrings, "Expected opening '(' at start of argument list");
2369     JSTokenLocation location(tokenLocation());
2370     if (match(CLOSEPAREN)) {
2371         next(TreeBuilder::DontBuildStrings);
2372         return context.createArguments();
2373     }
2374     if (match(DOTDOTDOT) && mode == AllowSpread) {
2375         JSTokenLocation spreadLocation(tokenLocation());
2376         auto start = m_token.m_startPosition;
2377         auto divot = m_token.m_endPosition;
2378         next();
2379         auto spreadExpr = parseAssignmentExpression(context);
2380         auto end = m_lastTokenEndPosition;
2381         if (!spreadExpr)
2382             failWithMessage("Cannot parse spread expression");
2383         if (!consume(CLOSEPAREN)) {
2384             if (match(COMMA))
2385                 semanticFail("Spread operator may only be applied to the last argument passed to a function");
2386             handleProductionOrFail(CLOSEPAREN, ")", "end", "argument list");
2387         }
2388         auto spread = context.createSpreadExpression(spreadLocation, spreadExpr, start, divot, end);
2389         TreeArgumentsList argList = context.createArgumentsList(location, spread);
2390         return context.createArguments(argList);
2391     }
2392     TreeExpression firstArg = parseAssignmentExpression(context);
2393     failIfFalse(firstArg, "Cannot parse function argument");
2394     
2395     TreeArgumentsList argList = context.createArgumentsList(location, firstArg);
2396     TreeArgumentsList tail = argList;
2397     while (match(COMMA)) {
2398         JSTokenLocation argumentLocation(tokenLocation());
2399         next(TreeBuilder::DontBuildStrings);
2400         TreeExpression arg = parseAssignmentExpression(context);
2401         failIfFalse(arg, "Cannot parse function argument");
2402         tail = context.createArgumentsList(argumentLocation, tail, arg);
2403     }
2404     semanticFailIfTrue(match(DOTDOTDOT), "The '...' operator should come before the target expression");
2405     handleProductionOrFail(CLOSEPAREN, ")", "end", "argument list");
2406     return context.createArguments(argList);
2407 }
2408
2409 template <typename LexerType>
2410 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseMemberExpression(TreeBuilder& context)
2411 {
2412     TreeExpression base = 0;
2413     JSTextPosition expressionStart = tokenStartPosition();
2414     int newCount = 0;
2415     JSTokenLocation startLocation = tokenLocation();
2416     JSTokenLocation location;
2417     while (match(NEW)) {
2418         next();
2419         newCount++;
2420     }
2421
2422 #if ENABLE(ES6_CLASS_SYNTAX)
2423     bool baseIsSuper = match(SUPER);
2424 #else
2425     bool baseIsSuper = false;
2426 #endif
2427
2428     if (baseIsSuper) {
2429         base = context.superExpr(location);
2430         next();
2431         currentScope()->setNeedsSuperBinding();
2432     } else
2433         base = parsePrimaryExpression(context);
2434
2435     failIfFalse(base, "Cannot parse base expression");
2436     while (true) {
2437         location = tokenLocation();
2438         switch (m_token.m_type) {
2439         case OPENBRACKET: {
2440             m_nonTrivialExpressionCount++;
2441             JSTextPosition expressionEnd = lastTokenEndPosition();
2442             next();
2443             int nonLHSCount = m_nonLHSCount;
2444             int initialAssignments = m_assignmentCount;
2445             TreeExpression property = parseExpression(context);
2446             failIfFalse(property, "Cannot parse subscript expression");
2447             base = context.createBracketAccess(location, base, property, initialAssignments != m_assignmentCount, expressionStart, expressionEnd, tokenEndPosition());
2448             handleProductionOrFail(CLOSEBRACKET, "]", "end", "subscript expression");
2449             m_nonLHSCount = nonLHSCount;
2450             break;
2451         }
2452         case OPENPAREN: {
2453             m_nonTrivialExpressionCount++;
2454             int nonLHSCount = m_nonLHSCount;
2455             if (newCount) {
2456                 newCount--;
2457                 JSTextPosition expressionEnd = lastTokenEndPosition();
2458                 TreeArguments arguments = parseArguments(context, AllowSpread);
2459                 failIfFalse(arguments, "Cannot parse call arguments");
2460                 base = context.createNewExpr(location, base, arguments, expressionStart, expressionEnd, lastTokenEndPosition());
2461             } else {
2462                 JSTextPosition expressionEnd = lastTokenEndPosition();
2463                 TreeArguments arguments = parseArguments(context, AllowSpread);
2464                 failIfFalse(arguments, "Cannot parse call arguments");
2465                 if (baseIsSuper)
2466                     currentScope()->setHasDirectSuper();
2467                 base = context.makeFunctionCallNode(startLocation, base, arguments, expressionStart, expressionEnd, lastTokenEndPosition());
2468             }
2469             m_nonLHSCount = nonLHSCount;
2470             break;
2471         }
2472         case DOT: {
2473             m_nonTrivialExpressionCount++;
2474             JSTextPosition expressionEnd = lastTokenEndPosition();
2475             nextExpectIdentifier(LexerFlagsIgnoreReservedWords | TreeBuilder::DontBuildKeywords);
2476             matchOrFail(IDENT, "Expected a property name after '.'");
2477             base = context.createDotAccess(location, base, m_token.m_data.ident, expressionStart, expressionEnd, tokenEndPosition());
2478             next();
2479             break;
2480         }
2481         default:
2482             goto endMemberExpression;
2483         }
2484         baseIsSuper = false;
2485     }
2486 endMemberExpression:
2487     semanticFailIfTrue(baseIsSuper && !newCount, "Cannot reference super");
2488     while (newCount--)
2489         base = context.createNewExpr(location, base, expressionStart, lastTokenEndPosition());
2490     return base;
2491 }
2492
2493 static const char* operatorString(bool prefix, unsigned tok)
2494 {
2495     switch (tok) {
2496     case MINUSMINUS:
2497     case AUTOMINUSMINUS:
2498         return prefix ? "prefix-decrement" : "decrement";
2499
2500     case PLUSPLUS:
2501     case AUTOPLUSPLUS:
2502         return prefix ? "prefix-increment" : "increment";
2503
2504     case EXCLAMATION:
2505         return "logical-not";
2506
2507     case TILDE:
2508         return "bitwise-not";
2509     
2510     case TYPEOF:
2511         return "typeof";
2512     
2513     case VOIDTOKEN:
2514         return "void";
2515     
2516     case DELETETOKEN:
2517         return "delete";
2518     }
2519     RELEASE_ASSERT_NOT_REACHED();
2520     return "error";
2521 }
2522
2523 template <typename LexerType>
2524 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseUnaryExpression(TreeBuilder& context)
2525 {
2526     typename TreeBuilder::UnaryExprContext unaryExprContext(context);
2527     AllowInOverride allowInOverride(this);
2528     int tokenStackDepth = 0;
2529     bool modifiesExpr = false;
2530     bool requiresLExpr = false;
2531     unsigned lastOperator = 0;
2532     while (isUnaryOp(m_token.m_type)) {
2533         if (strictMode()) {
2534             switch (m_token.m_type) {
2535             case PLUSPLUS:
2536             case MINUSMINUS:
2537             case AUTOPLUSPLUS:
2538             case AUTOMINUSMINUS:
2539                 semanticFailIfTrue(requiresLExpr, "The ", operatorString(true, lastOperator), " operator requires a reference expression");
2540                 modifiesExpr = true;
2541                 requiresLExpr = true;
2542                 break;
2543             case DELETETOKEN:
2544                 semanticFailIfTrue(requiresLExpr, "The ", operatorString(true, lastOperator), " operator requires a reference expression");
2545                 requiresLExpr = true;
2546                 break;
2547             default:
2548                 semanticFailIfTrue(requiresLExpr, "The ", operatorString(true, lastOperator), " operator requires a reference expression");
2549                 break;
2550             }
2551         }
2552         lastOperator = m_token.m_type;
2553         m_nonLHSCount++;
2554         context.appendUnaryToken(tokenStackDepth, m_token.m_type, tokenStartPosition());
2555         next();
2556         m_nonTrivialExpressionCount++;
2557     }
2558     JSTextPosition subExprStart = tokenStartPosition();
2559     ASSERT(subExprStart.offset >= subExprStart.lineStartOffset);
2560     JSTokenLocation location(tokenLocation());
2561     TreeExpression expr = parseMemberExpression(context);
2562     if (!expr) {
2563         if (lastOperator)
2564             failWithMessage("Cannot parse subexpression of ", operatorString(true, lastOperator), "operator");
2565         failWithMessage("Cannot parse member expression");
2566     }
2567     bool isEvalOrArguments = false;
2568     if (strictMode() && !m_syntaxAlreadyValidated) {
2569         if (context.isResolve(expr))
2570             isEvalOrArguments = *m_lastIdentifier == m_vm->propertyNames->eval || *m_lastIdentifier == m_vm->propertyNames->arguments;
2571     }
2572     failIfTrueIfStrict(isEvalOrArguments && modifiesExpr, "Cannot modify '", m_lastIdentifier->impl(), "' in strict mode");
2573     switch (m_token.m_type) {
2574     case PLUSPLUS:
2575         m_nonTrivialExpressionCount++;
2576         m_nonLHSCount++;
2577         expr = context.makePostfixNode(location, expr, OpPlusPlus, subExprStart, lastTokenEndPosition(), tokenEndPosition());
2578         m_assignmentCount++;
2579         failIfTrueIfStrict(isEvalOrArguments, "Cannot modify '", m_lastIdentifier->impl(), "' in strict mode");
2580         semanticFailIfTrue(requiresLExpr, "The ", operatorString(false, lastOperator), " operator requires a reference expression");
2581         lastOperator = PLUSPLUS;
2582         next();
2583         break;
2584     case MINUSMINUS:
2585         m_nonTrivialExpressionCount++;
2586         m_nonLHSCount++;
2587         expr = context.makePostfixNode(location, expr, OpMinusMinus, subExprStart, lastTokenEndPosition(), tokenEndPosition());
2588         m_assignmentCount++;
2589         failIfTrueIfStrict(isEvalOrArguments, "'", m_lastIdentifier->impl(), "' cannot be modified in strict mode");
2590         semanticFailIfTrue(requiresLExpr, "The ", operatorString(false, lastOperator), " operator requires a reference expression");
2591         lastOperator = PLUSPLUS;
2592         next();
2593         break;
2594     default:
2595         break;
2596     }
2597     
2598     JSTextPosition end = lastTokenEndPosition();
2599
2600     if (!TreeBuilder::CreatesAST && (m_syntaxAlreadyValidated || !strictMode()))
2601         return expr;
2602
2603     location = tokenLocation();
2604     location.line = m_lexer->lastLineNumber();
2605     while (tokenStackDepth) {
2606         switch (context.unaryTokenStackLastType(tokenStackDepth)) {
2607         case EXCLAMATION:
2608             expr = context.createLogicalNot(location, expr);
2609             break;
2610         case TILDE:
2611             expr = context.makeBitwiseNotNode(location, expr);
2612             break;
2613         case MINUS:
2614             expr = context.makeNegateNode(location, expr);
2615             break;
2616         case PLUS:
2617             expr = context.createUnaryPlus(location, expr);
2618             break;
2619         case PLUSPLUS:
2620         case AUTOPLUSPLUS:
2621             expr = context.makePrefixNode(location, expr, OpPlusPlus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end);
2622             m_assignmentCount++;
2623             break;
2624         case MINUSMINUS:
2625         case AUTOMINUSMINUS:
2626             expr = context.makePrefixNode(location, expr, OpMinusMinus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end);
2627             m_assignmentCount++;
2628             break;
2629         case TYPEOF:
2630             expr = context.makeTypeOfNode(location, expr);
2631             break;
2632         case VOIDTOKEN:
2633             expr = context.createVoid(location, expr);
2634             break;
2635         case DELETETOKEN:
2636             failIfTrueIfStrict(context.isResolve(expr), "Cannot delete unqualified property '", m_lastIdentifier->impl(), "' in strict mode");
2637             expr = context.makeDeleteNode(location, expr, context.unaryTokenStackLastStart(tokenStackDepth), end, end);
2638             break;
2639         default:
2640             // If we get here something has gone horribly horribly wrong
2641             CRASH();
2642         }
2643         subExprStart = context.unaryTokenStackLastStart(tokenStackDepth);
2644         context.unaryTokenStackRemoveLast(tokenStackDepth);
2645     }
2646     return expr;
2647 }
2648
2649
2650 template <typename LexerType> void Parser<LexerType>::printUnexpectedTokenText(WTF::PrintStream& out)
2651 {
2652     switch (m_token.m_type) {
2653     case EOFTOK:
2654         out.print("Unexpected end of script");
2655         return;
2656     case UNTERMINATED_IDENTIFIER_ESCAPE_ERRORTOK:
2657     case UNTERMINATED_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK:
2658         out.print("Incomplete unicode escape in identifier: '", getToken(), "'");
2659         return;
2660     case UNTERMINATED_MULTILINE_COMMENT_ERRORTOK:
2661         out.print("Unterminated multiline comment");
2662         return;
2663     case UNTERMINATED_NUMERIC_LITERAL_ERRORTOK:
2664         out.print("Unterminated numeric literal '", getToken(), "'");
2665         return;
2666     case UNTERMINATED_STRING_LITERAL_ERRORTOK:
2667         out.print("Unterminated string literal '", getToken(), "'");
2668         return;
2669     case INVALID_IDENTIFIER_ESCAPE_ERRORTOK:
2670         out.print("Invalid escape in identifier: '", getToken(), "'");
2671         return;
2672     case INVALID_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK:
2673         out.print("Invalid unicode escape in identifier: '", getToken(), "'");
2674         return;
2675     case INVALID_NUMERIC_LITERAL_ERRORTOK:
2676         out.print("Invalid numeric literal: '", getToken(), "'");
2677         return;
2678     case INVALID_OCTAL_NUMBER_ERRORTOK:
2679         out.print("Invalid use of octal: '", getToken(), "'");
2680         return;
2681     case INVALID_STRING_LITERAL_ERRORTOK:
2682         out.print("Invalid string literal: '", getToken(), "'");
2683         return;
2684     case ERRORTOK:
2685         out.print("Unrecognized token '", getToken(), "'");
2686         return;
2687     case STRING:
2688         out.print("Unexpected string literal ", getToken());
2689         return;
2690     case INTEGER:
2691     case DOUBLE:
2692         out.print("Unexpected number '", getToken(), "'");
2693         return;
2694     
2695     case RESERVED_IF_STRICT:
2696         out.print("Unexpected use of reserved word '", getToken(), "' in strict mode");
2697         return;
2698         
2699     case RESERVED:
2700         out.print("Unexpected use of reserved word '", getToken(), "'");
2701         return;
2702
2703     case INVALID_PRIVATE_NAME_ERRORTOK:
2704         out.print("Invalid private name '", getToken(), "'");
2705         return;
2706             
2707     case IDENT:
2708         out.print("Unexpected identifier '", getToken(), "'");
2709         return;
2710
2711     default:
2712         break;
2713     }
2714
2715     if (m_token.m_type & KeywordTokenFlag) {
2716         out.print("Unexpected keyword '", getToken(), "'");
2717         return;
2718     }
2719     
2720     out.print("Unexpected token '", getToken(), "'");
2721 }
2722
2723 // Instantiate the two flavors of Parser we need instead of putting most of this file in Parser.h
2724 template class Parser<Lexer<LChar>>;
2725 template class Parser<Lexer<UChar>>;
2726     
2727 } // namespace JSC