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