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.
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.
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.
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.
26 #include "ASTBuilder.h"
27 #include "CodeBlock.h"
29 #include "JSCJSValueInlines.h"
31 #include "JSCInlines.h"
32 #include "SourceProvider.h"
35 #include <wtf/HashFunctions.h>
36 #include <wtf/StringPrintStream.h>
37 #include <wtf/WTFThreadData.h>
40 #define updateErrorMessage(shouldPrintToken, ...) do {\
42 logError(shouldPrintToken, __VA_ARGS__); \
45 #define propagateError() do { if (hasError()) return 0; } while (0)
46 #define internalFailWithMessage(shouldPrintToken, ...) do { updateErrorMessage(shouldPrintToken, __VA_ARGS__); return 0; } while (0)
47 #define handleErrorToken() do { if (m_token.m_type == EOFTOK || m_token.m_type & ErrorTokenFlag) { failDueToUnexpectedToken(); } } while (0)
48 #define failWithMessage(...) do { { handleErrorToken(); updateErrorMessage(true, __VA_ARGS__); } return 0; } while (0)
49 #define failWithStackOverflow() do { updateErrorMessage(false, "Stack exhausted"); m_hasStackOverflow = true; return 0; } while (0)
50 #define failIfFalse(cond, ...) do { if (!(cond)) { handleErrorToken(); internalFailWithMessage(true, __VA_ARGS__); } } while (0)
51 #define failIfTrue(cond, ...) do { if (cond) { handleErrorToken(); internalFailWithMessage(true, __VA_ARGS__); } } while (0)
52 #define failIfTrueIfStrict(cond, ...) do { if ((cond) && strictMode()) internalFailWithMessage(false, __VA_ARGS__); } while (0)
53 #define failIfFalseIfStrict(cond, ...) do { if ((!(cond)) && strictMode()) internalFailWithMessage(false, __VA_ARGS__); } while (0)
54 #define consumeOrFail(tokenType, ...) do { if (!consume(tokenType)) { handleErrorToken(); internalFailWithMessage(true, __VA_ARGS__); } } while (0)
55 #define consumeOrFailWithFlags(tokenType, flags, ...) do { if (!consume(tokenType, flags)) { handleErrorToken(); internalFailWithMessage(true, __VA_ARGS__); } } while (0)
56 #define matchOrFail(tokenType, ...) do { if (!match(tokenType)) { handleErrorToken(); internalFailWithMessage(true, __VA_ARGS__); } } while (0)
57 #define failIfStackOverflow() do { if (!canRecurse()) failWithStackOverflow(); } while (0)
58 #define semanticFail(...) do { internalFailWithMessage(false, __VA_ARGS__); } while (0)
59 #define semanticFailIfTrue(cond, ...) do { if (cond) internalFailWithMessage(false, __VA_ARGS__); } while (0)
60 #define semanticFailIfFalse(cond, ...) do { if (!(cond)) internalFailWithMessage(false, __VA_ARGS__); } while (0)
61 #define regexFail(failure) do { setErrorMessage(failure); return 0; } while (0)
62 #define failDueToUnexpectedToken() do {\
67 #define handleProductionOrFail(token, tokenString, operation, production) do {\
68 consumeOrFail(token, "Expected '", tokenString, "' to ", operation, " a ", production);\
71 #define semanticFailureDueToKeyword(...) do { \
72 if (strictMode() && m_token.m_type == RESERVED_IF_STRICT) \
73 semanticFail("Cannot use the reserved word '", getToken(), "' as a ", __VA_ARGS__, " in strict mode"); \
74 if (m_token.m_type == RESERVED || m_token.m_type == RESERVED_IF_STRICT) \
75 semanticFail("Cannot use the reserved word '", getToken(), "' as a ", __VA_ARGS__); \
76 if (m_token.m_type & KeywordTokenFlag) \
77 semanticFail("Cannot use the keyword '", getToken(), "' as a ", __VA_ARGS__); \
84 template <typename LexerType>
85 void Parser<LexerType>::logError(bool)
89 StringPrintStream stream;
90 printUnexpectedTokenText(stream);
91 setErrorMessage(stream.toString());
94 template <typename LexerType> template <typename A>
95 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1)
99 StringPrintStream stream;
100 if (shouldPrintToken) {
101 printUnexpectedTokenText(stream);
104 stream.print(value1, ".");
105 setErrorMessage(stream.toString());
108 template <typename LexerType> template <typename A, typename B>
109 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2)
113 StringPrintStream stream;
114 if (shouldPrintToken) {
115 printUnexpectedTokenText(stream);
118 stream.print(value1, value2, ".");
119 setErrorMessage(stream.toString());
122 template <typename LexerType> template <typename A, typename B, typename C>
123 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2, const C& value3)
127 StringPrintStream stream;
128 if (shouldPrintToken) {
129 printUnexpectedTokenText(stream);
132 stream.print(value1, value2, value3, ".");
133 setErrorMessage(stream.toString());
136 template <typename LexerType> template <typename A, typename B, typename C, typename D>
137 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2, const C& value3, const D& value4)
141 StringPrintStream stream;
142 if (shouldPrintToken) {
143 printUnexpectedTokenText(stream);
146 stream.print(value1, value2, value3, value4, ".");
147 setErrorMessage(stream.toString());
150 template <typename LexerType> template <typename A, typename B, typename C, typename D, typename E>
151 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2, const C& value3, const D& value4, const E& value5)
155 StringPrintStream stream;
156 if (shouldPrintToken) {
157 printUnexpectedTokenText(stream);
160 stream.print(value1, value2, value3, value4, value5, ".");
161 setErrorMessage(stream.toString());
164 template <typename LexerType> template <typename A, typename B, typename C, typename D, typename E, typename F>
165 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2, const C& value3, const D& value4, const E& value5, const F& value6)
169 StringPrintStream stream;
170 if (shouldPrintToken) {
171 printUnexpectedTokenText(stream);
174 stream.print(value1, value2, value3, value4, value5, value6, ".");
175 setErrorMessage(stream.toString());
178 template <typename LexerType> template <typename A, typename B, typename C, typename D, typename E, typename F, typename G>
179 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2, const C& value3, const D& value4, const E& value5, const F& value6, const G& value7)
183 StringPrintStream stream;
184 if (shouldPrintToken) {
185 printUnexpectedTokenText(stream);
188 stream.print(value1, value2, value3, value4, value5, value6, value7, ".");
189 setErrorMessage(stream.toString());
192 template <typename LexerType>
193 Parser<LexerType>::Parser(
194 VM* vm, const SourceCode& source, FunctionParameters* parameters,
195 const Identifier& name, JSParserBuiltinMode builtinMode,
196 JSParserStrictMode strictMode, JSParserCodeType codeType,
197 ConstructorKind defaultConstructorKind, ThisTDZMode thisTDZMode)
200 , m_hasStackOverflow(false)
202 , m_assignmentCount(0)
204 , m_syntaxAlreadyValidated(source.provider()->isValid())
205 , m_statementDepth(0)
206 , m_nonTrivialExpressionCount(0)
207 , m_lastIdentifier(0)
208 , m_lastFunctionName(nullptr)
209 , m_sourceElements(0)
210 , m_parsingBuiltin(builtinMode == JSParserBuiltinMode::Builtin)
211 , m_defaultConstructorKind(defaultConstructorKind)
212 , m_thisTDZMode(thisTDZMode)
214 m_lexer = std::make_unique<LexerType>(vm, builtinMode);
215 m_lexer->setCode(source, &m_parserArena);
216 m_token.m_location.line = source.firstLine();
217 m_token.m_location.startOffset = source.startOffset();
218 m_token.m_location.endOffset = source.startOffset();
219 m_token.m_location.lineStartOffset = source.startOffset();
220 m_functionCache = vm->addSourceProviderCache(source.provider());
221 ScopeRef scope = pushScope();
222 if (codeType == JSParserCodeType::Function)
223 scope->setIsFunction();
224 if (strictMode == JSParserStrictMode::Strict)
225 scope->setStrictMode();
227 bool hadBindingParameters = false;
228 for (unsigned i = 0; i < parameters->size(); i++) {
229 auto parameter = parameters->at(i);
230 if (!parameter->isBindingNode()) {
231 hadBindingParameters = true;
234 scope->declareParameter(&static_cast<BindingNode*>(parameter)->boundProperty());
236 if (hadBindingParameters) {
237 Vector<Identifier> boundParameterNames;
238 for (unsigned i = 0; i < parameters->size(); i++) {
239 auto parameter = parameters->at(i);
240 if (parameter->isBindingNode())
242 parameter->collectBoundIdentifiers(boundParameterNames);
244 for (auto& boundParameterName : boundParameterNames)
245 scope->declareVariable(&boundParameterName);
249 scope->declareCallee(&name);
253 template <typename LexerType>
254 Parser<LexerType>::~Parser()
258 template <typename LexerType>
259 String Parser<LexerType>::parseInner()
261 String parseError = String();
263 ASTBuilder context(const_cast<VM*>(m_vm), m_parserArena, const_cast<SourceCode*>(m_source));
264 if (m_lexer->isReparsing())
266 ScopeRef scope = currentScope();
267 SourceElements* sourceElements = parseSourceElements(context, CheckForStrictMode);
268 if (!sourceElements || !consume(EOFTOK)) {
270 parseError = m_errorMessage;
272 parseError = ASCIILiteral("Parser error");
275 IdentifierSet capturedVariables;
276 bool modifiedParameter = false;
277 bool modifiedArguments = false;
278 scope->getCapturedVariables(capturedVariables, modifiedParameter, modifiedArguments);
280 CodeFeatures features = context.features();
281 if (scope->strictMode())
282 features |= StrictModeFeature;
283 if (scope->shadowsArguments())
284 features |= ShadowsArgumentsFeature;
285 if (modifiedParameter)
286 features |= ModifiedParameterFeature;
287 if (modifiedArguments)
288 features |= ModifiedArgumentsFeature;
289 Vector<RefPtr<StringImpl>> closedVariables;
290 if (m_parsingBuiltin) {
291 IdentifierSet usedVariables;
292 scope->getUsedVariables(usedVariables);
293 for (const auto& variable : usedVariables) {
294 Identifier identifier = Identifier::fromUid(m_vm, variable.get());
295 if (scope->hasDeclaredVariable(identifier))
298 if (scope->hasDeclaredParameter(identifier))
301 if (variable == m_vm->propertyNames->arguments.impl())
304 closedVariables.append(variable);
307 if (!capturedVariables.isEmpty()) {
308 for (const auto& capturedVariable : capturedVariables) {
309 Identifier identifier = Identifier::fromUid(m_vm, capturedVariable.get());
310 if (scope->hasDeclaredVariable(identifier))
313 if (scope->hasDeclaredParameter(identifier))
316 RELEASE_ASSERT_NOT_REACHED();
320 didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), features,
321 context.numConstants(), capturedVariables, WTF::move(closedVariables));
326 template <typename LexerType>
327 void Parser<LexerType>::didFinishParsing(SourceElements* sourceElements, DeclarationStacks::VarStack& varStack,
328 DeclarationStacks::FunctionStack& funcStack, CodeFeatures features, int numConstants, IdentifierSet& capturedVars, const Vector<RefPtr<StringImpl>>&& closedVariables)
330 m_sourceElements = sourceElements;
331 m_varDeclarations.swap(varStack);
332 m_funcDeclarations.swap(funcStack);
333 m_capturedVariables.swap(capturedVars);
334 m_closedVariables = closedVariables;
335 m_features = features;
336 m_numConstants = numConstants;
339 template <typename LexerType>
340 bool Parser<LexerType>::allowAutomaticSemicolon()
342 return match(CLOSEBRACE) || match(EOFTOK) || m_lexer->prevTerminator();
345 template <typename LexerType>
346 template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseSourceElements(TreeBuilder& context, SourceElementsMode mode)
348 const unsigned lengthOfUseStrictLiteral = 12; // "use strict".length
349 TreeSourceElements sourceElements = context.createSourceElements();
350 bool seenNonDirective = false;
351 const Identifier* directive = 0;
352 unsigned directiveLiteralLength = 0;
353 auto savePoint = createSavePoint();
354 bool hasSetStrict = false;
355 while (TreeStatement statement = parseStatement(context, directive, &directiveLiteralLength)) {
356 if (mode == CheckForStrictMode && !seenNonDirective) {
358 // "use strict" must be the exact literal without escape sequences or line continuation.
359 if (!hasSetStrict && directiveLiteralLength == lengthOfUseStrictLiteral && m_vm->propertyNames->useStrictIdentifier == *directive) {
362 if (!isValidStrictMode()) {
363 if (m_lastFunctionName) {
364 if (m_vm->propertyNames->arguments == *m_lastFunctionName)
365 semanticFail("Cannot name a function 'arguments' in strict mode");
366 if (m_vm->propertyNames->eval == *m_lastFunctionName)
367 semanticFail("Cannot name a function 'eval' in strict mode");
369 if (hasDeclaredVariable(m_vm->propertyNames->arguments))
370 semanticFail("Cannot declare a variable named 'arguments' in strict mode");
371 if (hasDeclaredVariable(m_vm->propertyNames->eval))
372 semanticFail("Cannot declare a variable named 'eval' in strict mode");
373 semanticFailIfFalse(isValidStrictMode(), "Invalid parameters or function name in strict mode");
375 restoreSavePoint(savePoint);
380 seenNonDirective = true;
382 context.appendStatement(sourceElements, statement);
386 return sourceElements;
389 template <typename LexerType>
390 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseVarDeclaration(TreeBuilder& context)
393 JSTokenLocation location(tokenLocation());
394 int start = tokenLine();
397 TreeDeconstructionPattern scratch1 = 0;
398 TreeExpression scratch2 = 0;
399 JSTextPosition scratch3;
400 TreeExpression varDecls = parseVarDeclarationList(context, scratch, scratch1, scratch2, scratch3, scratch3, scratch3, VarDeclarationContext);
402 failIfFalse(autoSemiColon(), "Expected ';' after var declaration");
404 return context.createVarStatement(location, varDecls, start, end);
407 template <typename LexerType>
408 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseConstDeclaration(TreeBuilder& context)
410 ASSERT(match(CONSTTOKEN));
411 JSTokenLocation location(tokenLocation());
412 int start = tokenLine();
414 TreeConstDeclList constDecls = parseConstDeclarationList(context);
416 failIfFalse(autoSemiColon(), "Expected ';' after const declaration");
418 return context.createConstStatement(location, constDecls, start, end);
421 template <typename LexerType>
422 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseDoWhileStatement(TreeBuilder& context)
425 int startLine = tokenLine();
427 const Identifier* unused = 0;
429 TreeStatement statement = parseStatement(context, unused);
431 failIfFalse(statement, "Expected a statement following 'do'");
432 int endLine = tokenLine();
433 JSTokenLocation location(tokenLocation());
434 handleProductionOrFail(WHILE, "while", "end", "do-while loop");
435 handleProductionOrFail(OPENPAREN, "(", "start", "do-while loop condition");
436 semanticFailIfTrue(match(CLOSEPAREN), "Must provide an expression as a do-while loop condition");
437 TreeExpression expr = parseExpression(context);
438 failIfFalse(expr, "Unable to parse do-while loop condition");
439 handleProductionOrFail(CLOSEPAREN, ")", "end", "do-while loop condition");
440 if (match(SEMICOLON))
441 next(); // Always performs automatic semicolon insertion.
442 return context.createDoWhileStatement(location, statement, expr, startLine, endLine);
445 template <typename LexerType>
446 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWhileStatement(TreeBuilder& context)
448 ASSERT(match(WHILE));
449 JSTokenLocation location(tokenLocation());
450 int startLine = tokenLine();
453 handleProductionOrFail(OPENPAREN, "(", "start", "while loop condition");
454 semanticFailIfTrue(match(CLOSEPAREN), "Must provide an expression as a while loop condition");
455 TreeExpression expr = parseExpression(context);
456 failIfFalse(expr, "Unable to parse while loop condition");
457 int endLine = tokenLine();
458 handleProductionOrFail(CLOSEPAREN, ")", "end", "while loop condition");
460 const Identifier* unused = 0;
462 TreeStatement statement = parseStatement(context, unused);
464 failIfFalse(statement, "Expected a statement as the body of a while loop");
465 return context.createWhileStatement(location, expr, statement, startLine, endLine);
468 template <typename LexerType>
469 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseVarDeclarationList(TreeBuilder& context, int& declarations, TreeDeconstructionPattern& lastPattern, TreeExpression& lastInitializer, JSTextPosition& identStart, JSTextPosition& initStart, JSTextPosition& initEnd, VarDeclarationListContext declarationListContext)
471 TreeExpression head = 0;
472 TreeExpression tail = 0;
473 const Identifier* lastIdent;
474 JSToken lastIdentToken;
478 JSTokenLocation location(tokenLocation());
480 TreeExpression node = 0;
482 bool hasInitializer = false;
484 JSTextPosition varStart = tokenStartPosition();
485 JSTokenLocation varStartLocation(tokenLocation());
486 identStart = varStart;
487 const Identifier* name = m_token.m_data.ident;
489 lastIdentToken = m_token;
491 hasInitializer = match(EQUAL);
492 failIfFalseIfStrict(declareVariable(name), "Cannot declare a variable named ", name->impl(), " in strict mode");
493 context.addVar(name, (hasInitializer || (!m_allowsIn && (match(INTOKEN) || isofToken()))) ? DeclarationStacks::HasInitializer : 0);
494 if (hasInitializer) {
495 JSTextPosition varDivot = tokenStartPosition() + 1;
496 initStart = tokenStartPosition();
497 next(TreeBuilder::DontBuildStrings); // consume '='
498 TreeExpression initializer = parseAssignmentExpression(context);
499 initEnd = lastTokenEndPosition();
500 lastInitializer = initializer;
501 failIfFalse(initializer, "Expected expression as the intializer for the variable '", name->impl(), "'");
503 node = context.createAssignResolve(location, *name, initializer, varStart, varDivot, lastTokenEndPosition());
505 node = context.createEmptyVarExpression(varStartLocation, *name);
508 auto pattern = parseDeconstructionPattern(context, DeconstructToVariables);
509 failIfFalse(pattern, "Cannot parse this deconstruction pattern");
510 hasInitializer = match(EQUAL);
511 failIfTrue(declarationListContext == VarDeclarationContext && !hasInitializer, "Expected an initializer in destructuring variable declaration");
512 lastPattern = pattern;
513 if (hasInitializer) {
514 next(TreeBuilder::DontBuildStrings); // consume '='
515 TreeExpression rhs = parseAssignmentExpression(context);
516 node = context.createDeconstructingAssignment(location, pattern, rhs);
517 lastInitializer = rhs;
524 head = context.createCommaExpr(location, head);
525 tail = context.appendToCommaExpr(location, head, head, node);
527 tail = context.appendToCommaExpr(location, head, tail, node);
528 } while (match(COMMA));
530 lastPattern = createBindingPattern(context, DeconstructToVariables, *lastIdent, 0, lastIdentToken);
534 template <typename LexerType>
535 template <class TreeBuilder> TreeDeconstructionPattern Parser<LexerType>::createBindingPattern(TreeBuilder& context, DeconstructionKind kind, const Identifier& name, int depth, JSToken token)
537 ASSERT(!name.isEmpty());
538 ASSERT(!name.isNull());
540 ASSERT(name.impl()->isAtomic() || name.impl()->isSymbol());
542 if (kind == DeconstructToVariables)
543 failIfFalseIfStrict(declareVariable(&name), "Cannot deconstruct to a variable named '", name.impl(), "' in strict mode");
544 if (kind == DeconstructToParameters) {
545 auto bindingResult = declareBoundParameter(&name);
546 if (bindingResult == Scope::StrictBindingFailed && strictMode()) {
547 semanticFailIfTrue(m_vm->propertyNames->arguments == name || m_vm->propertyNames->eval == name, "Cannot deconstruct to a parameter name '", name.impl(), "' in strict mode");
548 if (m_lastFunctionName && name == *m_lastFunctionName)
549 semanticFail("Cannot deconstruct to '", name.impl(), "' as it shadows the name of a strict mode function");
550 semanticFailureDueToKeyword("bound parameter name");
551 if (hasDeclaredParameter(name))
552 semanticFail("Cannot deconstruct to '", name.impl(), "' as it has already been declared");
553 semanticFail("Cannot bind to a parameter named '", name.impl(), "' in strict mode");
555 if (bindingResult == Scope::BindingFailed) {
556 semanticFailureDueToKeyword("bound parameter name");
557 if (hasDeclaredParameter(name))
558 semanticFail("Cannot deconstruct to '", name.impl(), "' as it has already been declared");
559 semanticFail("Cannot deconstruct to a parameter named '", name.impl(), "'");
562 if (kind != DeconstructToExpressions)
563 context.addVar(&name, DeclarationStacks::HasInitializer);
566 if (kind == DeconstructToVariables) {
567 failIfFalseIfStrict(declareVariable(&name), "Cannot declare a variable named '", name.impl(), "' in strict mode");
568 context.addVar(&name, DeclarationStacks::HasInitializer);
571 if (kind == DeconstructToParameters) {
572 bool declarationResult = declareParameter(&name);
573 if (!declarationResult && strictMode()) {
574 semanticFailIfTrue(m_vm->propertyNames->arguments == name || m_vm->propertyNames->eval == name, "Cannot deconstruct to a parameter name '", name.impl(), "' in strict mode");
575 if (m_lastFunctionName && name == *m_lastFunctionName)
576 semanticFail("Cannot declare a parameter named '", name.impl(), "' as it shadows the name of a strict mode function");
577 semanticFailureDueToKeyword("parameter name");
578 if (hasDeclaredParameter(name))
579 semanticFail("Cannot declare a parameter named '", name.impl(), "' in strict mode as it has already been declared");
580 semanticFail("Cannot declare a parameter named '", name.impl(), "' in strict mode");
584 return context.createBindingLocation(token.m_location, name, token.m_startPosition, token.m_endPosition);
587 template <typename LexerType>
588 template <class TreeBuilder> TreeDeconstructionPattern Parser<LexerType>::tryParseDeconstructionPatternExpression(TreeBuilder& context)
590 return parseDeconstructionPattern(context, DeconstructToExpressions);
593 template <typename LexerType>
594 template <class TreeBuilder> TreeDeconstructionPattern Parser<LexerType>::parseDeconstructionPattern(TreeBuilder& context, DeconstructionKind kind, int depth)
596 failIfStackOverflow();
597 int nonLHSCount = m_nonLHSCount;
598 TreeDeconstructionPattern pattern;
599 switch (m_token.m_type) {
601 auto arrayPattern = context.createArrayPattern(m_token.m_location);
603 if (kind == DeconstructToExpressions && match(CLOSEBRACKET))
605 failIfTrue(match(CLOSEBRACKET), "There must be at least one bound property in an array deconstruction pattern");
607 while (match(COMMA)) {
608 context.appendArrayPatternSkipEntry(arrayPattern, m_token.m_location);
612 JSTokenLocation location = m_token.m_location;
613 auto innerPattern = parseDeconstructionPattern(context, kind, depth + 1);
614 if (kind == DeconstructToExpressions && !innerPattern)
616 failIfFalse(innerPattern, "Cannot parse this deconstruction pattern");
617 context.appendArrayPatternEntry(arrayPattern, location, innerPattern);
618 } while (consume(COMMA));
620 if (kind == DeconstructToExpressions && !match(CLOSEBRACKET))
623 consumeOrFail(CLOSEBRACKET, "Expected either a closing ']' or a ',' following an element deconstruction pattern");
624 pattern = arrayPattern;
630 if (kind == DeconstructToExpressions && match(CLOSEBRACE))
633 failIfTrue(match(CLOSEBRACE), "There must be at least one bound property in an object deconstruction pattern");
634 auto objectPattern = context.createObjectPattern(m_token.m_location);
635 bool wasString = false;
637 Identifier propertyName;
638 TreeDeconstructionPattern innerPattern = 0;
639 JSTokenLocation location = m_token.m_location;
641 propertyName = *m_token.m_data.ident;
642 JSToken identifierToken = m_token;
645 innerPattern = parseDeconstructionPattern(context, kind, depth + 1);
647 innerPattern = createBindingPattern(context, kind, propertyName, depth, identifierToken);
649 JSTokenType tokenType = m_token.m_type;
650 switch (m_token.m_type) {
653 propertyName = Identifier::from(m_vm, m_token.m_data.doubleValue);
656 propertyName = *m_token.m_data.ident;
660 if (m_token.m_type != RESERVED && m_token.m_type != RESERVED_IF_STRICT && !(m_token.m_type & KeywordTokenFlag)) {
661 if (kind == DeconstructToExpressions)
663 failWithMessage("Expected a property name");
665 propertyName = *m_token.m_data.ident;
669 if (!consume(COLON)) {
670 if (kind == DeconstructToExpressions)
672 semanticFailIfTrue(tokenType == RESERVED, "Cannot use abbreviated deconstruction syntax for reserved name '", propertyName.impl(), "'");
673 semanticFailIfTrue(tokenType == RESERVED_IF_STRICT, "Cannot use abbreviated deconstruction syntax for reserved name '", propertyName.impl(), "' in strict mode");
674 semanticFailIfTrue(tokenType & KeywordTokenFlag, "Cannot use abbreviated deconstruction syntax for keyword '", propertyName.impl(), "'");
676 failWithMessage("Expected a ':' prior to named property deconstruction");
678 innerPattern = parseDeconstructionPattern(context, kind, depth + 1);
680 if (kind == DeconstructToExpressions && !innerPattern)
682 failIfFalse(innerPattern, "Cannot parse this deconstruction pattern");
683 context.appendObjectPatternEntry(objectPattern, location, wasString, propertyName, innerPattern);
684 } while (consume(COMMA));
685 if (kind == DeconstructToExpressions && !match(CLOSEBRACE))
687 consumeOrFail(CLOSEBRACE, "Expected either a closing '}' or an ',' after a property deconstruction pattern");
688 pattern = objectPattern;
694 if (kind == DeconstructToExpressions)
696 semanticFailureDueToKeyword("variable name");
697 failWithMessage("Expected a parameter pattern or a ')' in parameter list");
699 pattern = createBindingPattern(context, kind, *m_token.m_data.ident, depth, m_token);
704 m_nonLHSCount = nonLHSCount;
708 template <typename LexerType>
709 template <class TreeBuilder> TreeConstDeclList Parser<LexerType>::parseConstDeclarationList(TreeBuilder& context)
711 failIfTrue(strictMode(), "Const declarations are not supported in strict mode");
712 TreeConstDeclList constDecls = 0;
713 TreeConstDeclList tail = 0;
715 JSTokenLocation location(tokenLocation());
717 matchOrFail(IDENT, "Expected an identifier name in const declaration");
718 const Identifier* name = m_token.m_data.ident;
720 bool hasInitializer = match(EQUAL);
721 declareVariable(name);
722 context.addVar(name, DeclarationStacks::IsConstant | (hasInitializer ? DeclarationStacks::HasInitializer : 0));
724 TreeExpression initializer = 0;
725 if (hasInitializer) {
726 next(TreeBuilder::DontBuildStrings); // consume '='
727 initializer = parseAssignmentExpression(context);
728 failIfFalse(!!initializer, "Unable to parse initializer");
730 tail = context.appendConstDecl(location, tail, name, initializer);
733 } while (match(COMMA));
737 template <typename LexerType>
738 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseForStatement(TreeBuilder& context)
741 JSTokenLocation location(tokenLocation());
742 int startLine = tokenLine();
744 handleProductionOrFail(OPENPAREN, "(", "start", "for-loop header");
745 int nonLHSCount = m_nonLHSCount;
746 int declarations = 0;
747 JSTextPosition declsStart;
748 JSTextPosition declsEnd;
749 TreeExpression decls = 0;
750 TreeDeconstructionPattern pattern = 0;
753 for (var IDENT in expression) statement
754 for (var varDeclarationList; expressionOpt; expressionOpt)
756 TreeDeconstructionPattern forInTarget = 0;
757 TreeExpression forInInitializer = 0;
759 JSTextPosition initStart;
760 JSTextPosition initEnd;
761 decls = parseVarDeclarationList(context, declarations, forInTarget, forInInitializer, declsStart, initStart, initEnd, ForLoopContext);
765 // Remainder of a standard for loop is handled identically
766 if (match(SEMICOLON))
767 goto standardForLoop;
769 failIfFalse(declarations == 1, "can only declare a single variable in an enumeration");
770 failIfTrueIfStrict(forInInitializer, "Cannot use initialiser syntax in a strict mode enumeration");
772 if (forInInitializer)
773 failIfFalse(context.isBindingNode(forInTarget), "Cannot use initialiser syntax when binding to a pattern during enumeration");
775 // Handle for-in with var declaration
776 JSTextPosition inLocation = tokenStartPosition();
777 bool isOfEnumeration = false;
778 if (!consume(INTOKEN)) {
779 failIfFalse(match(IDENT) && *m_token.m_data.ident == m_vm->propertyNames->of, "Expected either 'in' or 'of' in enumeration syntax");
780 isOfEnumeration = true;
781 failIfTrue(forInInitializer, "Cannot use initialiser syntax in a for-of enumeration");
784 TreeExpression expr = parseExpression(context);
785 failIfFalse(expr, "Expected expression to enumerate");
786 JSTextPosition exprEnd = lastTokenEndPosition();
788 int endLine = tokenLine();
790 handleProductionOrFail(CLOSEPAREN, ")", "end", (isOfEnumeration ? "for-of header" : "for-in header"));
792 const Identifier* unused = 0;
794 TreeStatement statement = parseStatement(context, unused);
796 failIfFalse(statement, "Expected statement as body of for-", isOfEnumeration ? "of" : "in", " statement");
798 return context.createForOfLoop(location, forInTarget, expr, statement, declsStart, inLocation, exprEnd, startLine, endLine);
799 return context.createForInLoop(location, forInTarget, expr, statement, declsStart, inLocation, exprEnd, startLine, endLine);
802 if (!match(SEMICOLON)) {
803 if (match(OPENBRACE) || match(OPENBRACKET)) {
804 SavePoint savePoint = createSavePoint();
805 declsStart = tokenStartPosition();
806 pattern = tryParseDeconstructionPatternExpression(context);
807 declsEnd = lastTokenEndPosition();
808 if (pattern && (match(INTOKEN) || (match(IDENT) && *m_token.m_data.ident == m_vm->propertyNames->of)))
809 goto enumerationLoop;
811 restoreSavePoint(savePoint);
814 declsStart = tokenStartPosition();
815 decls = parseExpression(context);
816 declsEnd = lastTokenEndPosition();
818 failIfFalse(decls, "Cannot parse for loop declarations");
821 if (match(SEMICOLON)) {
825 TreeExpression condition = 0;
827 if (!match(SEMICOLON)) {
828 condition = parseExpression(context);
829 failIfFalse(condition, "Cannot parse for loop condition expression");
831 consumeOrFail(SEMICOLON, "Expected a ';' after the for loop condition expression");
833 TreeExpression increment = 0;
834 if (!match(CLOSEPAREN)) {
835 increment = parseExpression(context);
836 failIfFalse(increment, "Cannot parse for loop iteration expression");
838 int endLine = tokenLine();
839 handleProductionOrFail(CLOSEPAREN, ")", "end", "for-loop header");
840 const Identifier* unused = 0;
842 TreeStatement statement = parseStatement(context, unused);
844 failIfFalse(statement, "Expected a statement as the body of a for loop");
845 return context.createForLoop(location, decls, condition, increment, statement, startLine, endLine);
850 failIfFalse(nonLHSCount == m_nonLHSCount, "Expected a reference on the left hand side of an enumeration statement");
851 bool isOfEnumeration = false;
852 if (!consume(INTOKEN)) {
853 failIfFalse(match(IDENT) && *m_token.m_data.ident == m_vm->propertyNames->of, "Expected either 'in' or 'of' in enumeration syntax");
854 isOfEnumeration = true;
857 TreeExpression expr = parseExpression(context);
858 failIfFalse(expr, "Cannot parse subject for-", isOfEnumeration ? "of" : "in", " statement");
859 JSTextPosition exprEnd = lastTokenEndPosition();
860 int endLine = tokenLine();
862 handleProductionOrFail(CLOSEPAREN, ")", "end", (isOfEnumeration ? "for-of header" : "for-in header"));
863 const Identifier* unused = 0;
865 TreeStatement statement = parseStatement(context, unused);
867 failIfFalse(statement, "Expected a statement as the body of a for-", isOfEnumeration ? "of" : "in", "loop");
871 return context.createForOfLoop(location, pattern, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine);
872 return context.createForInLoop(location, pattern, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine);
875 return context.createForOfLoop(location, decls, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine);
876 return context.createForInLoop(location, decls, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine);
879 template <typename LexerType>
880 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBreakStatement(TreeBuilder& context)
882 ASSERT(match(BREAK));
883 JSTokenLocation location(tokenLocation());
884 JSTextPosition start = tokenStartPosition();
885 JSTextPosition end = tokenEndPosition();
888 if (autoSemiColon()) {
889 semanticFailIfFalse(breakIsValid(), "'break' is only valid inside a switch or loop statement");
890 return context.createBreakStatement(location, &m_vm->propertyNames->nullIdentifier, start, end);
892 matchOrFail(IDENT, "Expected an identifier as the target for a break statement");
893 const Identifier* ident = m_token.m_data.ident;
894 semanticFailIfFalse(getLabel(ident), "Cannot use the undeclared label '", ident->impl(), "'");
895 end = tokenEndPosition();
897 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted break statement");
898 return context.createBreakStatement(location, ident, start, end);
901 template <typename LexerType>
902 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseContinueStatement(TreeBuilder& context)
904 ASSERT(match(CONTINUE));
905 JSTokenLocation location(tokenLocation());
906 JSTextPosition start = tokenStartPosition();
907 JSTextPosition end = tokenEndPosition();
910 if (autoSemiColon()) {
911 semanticFailIfFalse(continueIsValid(), "'continue' is only valid inside a loop statement");
912 return context.createContinueStatement(location, &m_vm->propertyNames->nullIdentifier, start, end);
914 matchOrFail(IDENT, "Expected an identifier as the target for a continue statement");
915 const Identifier* ident = m_token.m_data.ident;
916 ScopeLabelInfo* label = getLabel(ident);
917 semanticFailIfFalse(label, "Cannot use the undeclared label '", ident->impl(), "'");
918 semanticFailIfFalse(label->m_isLoop, "Cannot continue to the label '", ident->impl(), "' as it is not targeting a loop");
919 end = tokenEndPosition();
921 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted continue statement");
922 return context.createContinueStatement(location, ident, start, end);
925 template <typename LexerType>
926 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseReturnStatement(TreeBuilder& context)
928 ASSERT(match(RETURN));
929 JSTokenLocation location(tokenLocation());
930 semanticFailIfFalse(currentScope()->isFunction(), "Return statements are only valid inside functions");
931 JSTextPosition start = tokenStartPosition();
932 JSTextPosition end = tokenEndPosition();
934 // We do the auto semicolon check before attempting to parse expression
935 // as we need to ensure the a line break after the return correctly terminates
937 if (match(SEMICOLON))
938 end = tokenEndPosition();
941 return context.createReturnStatement(location, 0, start, end);
942 TreeExpression expr = parseExpression(context);
943 failIfFalse(expr, "Cannot parse the return expression");
944 end = lastTokenEndPosition();
945 if (match(SEMICOLON))
946 end = tokenEndPosition();
947 if (!autoSemiColon())
948 failWithMessage("Expected a ';' following a return statement");
949 return context.createReturnStatement(location, expr, start, end);
952 template <typename LexerType>
953 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseThrowStatement(TreeBuilder& context)
955 ASSERT(match(THROW));
956 JSTokenLocation location(tokenLocation());
957 JSTextPosition start = tokenStartPosition();
959 failIfTrue(match(SEMICOLON), "Expected expression after 'throw'");
960 semanticFailIfTrue(autoSemiColon(), "Cannot have a newline after 'throw'");
962 TreeExpression expr = parseExpression(context);
963 failIfFalse(expr, "Cannot parse expression for throw statement");
964 JSTextPosition end = lastTokenEndPosition();
965 failIfFalse(autoSemiColon(), "Expected a ';' after a throw statement");
967 return context.createThrowStatement(location, expr, start, end);
970 template <typename LexerType>
971 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWithStatement(TreeBuilder& context)
974 JSTokenLocation location(tokenLocation());
975 semanticFailIfTrue(strictMode(), "'with' statements are not valid in strict mode");
976 currentScope()->setNeedsFullActivation();
977 int startLine = tokenLine();
980 handleProductionOrFail(OPENPAREN, "(", "start", "subject of a 'with' statement");
981 int start = tokenStart();
982 TreeExpression expr = parseExpression(context);
983 failIfFalse(expr, "Cannot parse 'with' subject expression");
984 JSTextPosition end = lastTokenEndPosition();
985 int endLine = tokenLine();
986 handleProductionOrFail(CLOSEPAREN, ")", "start", "subject of a 'with' statement");
987 const Identifier* unused = 0;
988 TreeStatement statement = parseStatement(context, unused);
989 failIfFalse(statement, "A 'with' statement must have a body");
991 return context.createWithStatement(location, expr, statement, start, end, startLine, endLine);
994 template <typename LexerType>
995 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseSwitchStatement(TreeBuilder& context)
997 ASSERT(match(SWITCH));
998 JSTokenLocation location(tokenLocation());
999 int startLine = tokenLine();
1001 handleProductionOrFail(OPENPAREN, "(", "start", "subject of a 'switch'");
1002 TreeExpression expr = parseExpression(context);
1003 failIfFalse(expr, "Cannot parse switch subject expression");
1004 int endLine = tokenLine();
1006 handleProductionOrFail(CLOSEPAREN, ")", "end", "subject of a 'switch'");
1007 handleProductionOrFail(OPENBRACE, "{", "start", "body of a 'switch'");
1009 TreeClauseList firstClauses = parseSwitchClauses(context);
1012 TreeClause defaultClause = parseSwitchDefaultClause(context);
1015 TreeClauseList secondClauses = parseSwitchClauses(context);
1018 handleProductionOrFail(CLOSEBRACE, "}", "end", "body of a 'switch'");
1020 return context.createSwitchStatement(location, expr, firstClauses, defaultClause, secondClauses, startLine, endLine);
1024 template <typename LexerType>
1025 template <class TreeBuilder> TreeClauseList Parser<LexerType>::parseSwitchClauses(TreeBuilder& context)
1029 unsigned startOffset = tokenStart();
1031 TreeExpression condition = parseExpression(context);
1032 failIfFalse(condition, "Cannot parse switch clause");
1033 consumeOrFail(COLON, "Expected a ':' after switch clause expression");
1034 TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode);
1035 failIfFalse(statements, "Cannot parse the body of a switch clause");
1036 TreeClause clause = context.createClause(condition, statements);
1037 context.setStartOffset(clause, startOffset);
1038 TreeClauseList clauseList = context.createClauseList(clause);
1039 TreeClauseList tail = clauseList;
1041 while (match(CASE)) {
1042 startOffset = tokenStart();
1044 TreeExpression condition = parseExpression(context);
1045 failIfFalse(condition, "Cannot parse switch case expression");
1046 consumeOrFail(COLON, "Expected a ':' after switch clause expression");
1047 TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode);
1048 failIfFalse(statements, "Cannot parse the body of a switch clause");
1049 clause = context.createClause(condition, statements);
1050 context.setStartOffset(clause, startOffset);
1051 tail = context.createClauseList(tail, clause);
1056 template <typename LexerType>
1057 template <class TreeBuilder> TreeClause Parser<LexerType>::parseSwitchDefaultClause(TreeBuilder& context)
1059 if (!match(DEFAULT))
1061 unsigned startOffset = tokenStart();
1063 consumeOrFail(COLON, "Expected a ':' after switch default clause");
1064 TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode);
1065 failIfFalse(statements, "Cannot parse the body of a switch default clause");
1066 TreeClause result = context.createClause(0, statements);
1067 context.setStartOffset(result, startOffset);
1071 template <typename LexerType>
1072 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseTryStatement(TreeBuilder& context)
1075 JSTokenLocation location(tokenLocation());
1076 TreeStatement tryBlock = 0;
1077 const Identifier* ident = &m_vm->propertyNames->nullIdentifier;
1078 TreeStatement catchBlock = 0;
1079 TreeStatement finallyBlock = 0;
1080 int firstLine = tokenLine();
1082 matchOrFail(OPENBRACE, "Expected a block statement as body of a try statement");
1084 tryBlock = parseBlockStatement(context);
1085 failIfFalse(tryBlock, "Cannot parse the body of try block");
1086 int lastLine = m_lastTokenEndPosition.line;
1089 currentScope()->setNeedsFullActivation();
1092 handleProductionOrFail(OPENPAREN, "(", "start", "'catch' target");
1093 if (!match(IDENT)) {
1094 semanticFailureDueToKeyword("catch variable name");
1095 failWithMessage("Expected identifier name as catch target");
1097 ident = m_token.m_data.ident;
1099 AutoPopScopeRef catchScope(this, pushScope());
1100 failIfFalseIfStrict(declareVariable(ident), "Cannot declare a catch variable named '", ident->impl(), "' in strict mode");
1101 catchScope->preventNewDecls();
1102 handleProductionOrFail(CLOSEPAREN, ")", "end", "'catch' target");
1103 matchOrFail(OPENBRACE, "Expected exception handler to be a block statement");
1104 catchBlock = parseBlockStatement(context);
1105 failIfFalse(catchBlock, "Unable to parse 'catch' block");
1106 failIfFalse(popScope(catchScope, TreeBuilder::NeedsFreeVariableInfo), "Parse error");
1109 if (match(FINALLY)) {
1111 matchOrFail(OPENBRACE, "Expected block statement for finally body");
1112 finallyBlock = parseBlockStatement(context);
1113 failIfFalse(finallyBlock, "Cannot parse finally body");
1115 failIfFalse(catchBlock || finallyBlock, "Try statements must have at least a catch or finally block");
1116 return context.createTryStatement(location, tryBlock, ident, catchBlock, finallyBlock, firstLine, lastLine);
1119 template <typename LexerType>
1120 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseDebuggerStatement(TreeBuilder& context)
1122 ASSERT(match(DEBUGGER));
1123 JSTokenLocation location(tokenLocation());
1124 int startLine = tokenLine();
1125 int endLine = startLine;
1127 if (match(SEMICOLON))
1128 startLine = tokenLine();
1129 failIfFalse(autoSemiColon(), "Debugger keyword must be followed by a ';'");
1130 return context.createDebugger(location, startLine, endLine);
1133 template <typename LexerType>
1134 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBlockStatement(TreeBuilder& context)
1136 ASSERT(match(OPENBRACE));
1137 JSTokenLocation location(tokenLocation());
1138 int startOffset = m_token.m_data.offset;
1139 int start = tokenLine();
1141 if (match(CLOSEBRACE)) {
1142 int endOffset = m_token.m_data.offset;
1144 TreeStatement result = context.createBlockStatement(location, 0, start, m_lastTokenEndPosition.line);
1145 context.setStartOffset(result, startOffset);
1146 context.setEndOffset(result, endOffset);
1149 TreeSourceElements subtree = parseSourceElements(context, DontCheckForStrictMode);
1150 failIfFalse(subtree, "Cannot parse the body of the block statement");
1151 matchOrFail(CLOSEBRACE, "Expected a closing '}' at the end of a block statement");
1152 int endOffset = m_token.m_data.offset;
1154 TreeStatement result = context.createBlockStatement(location, subtree, start, m_lastTokenEndPosition.line);
1155 context.setStartOffset(result, startOffset);
1156 context.setEndOffset(result, endOffset);
1160 template <typename LexerType>
1161 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseStatement(TreeBuilder& context, const Identifier*& directive, unsigned* directiveLiteralLength)
1163 DepthManager statementDepth(&m_statementDepth);
1166 int nonTrivialExpressionCount = 0;
1167 failIfStackOverflow();
1168 TreeStatement result = 0;
1169 bool shouldSetEndOffset = true;
1170 switch (m_token.m_type) {
1172 result = parseBlockStatement(context);
1173 shouldSetEndOffset = false;
1176 result = parseVarDeclaration(context);
1179 result = parseConstDeclaration(context);
1181 #if ENABLE(ES6_CLASS_SYNTAX)
1183 failIfFalse(m_statementDepth == 1, "Class declaration is not allowed in a lexically nested statement");
1184 result = parseClassDeclaration(context);
1188 failIfFalseIfStrict(m_statementDepth == 1, "Strict mode does not allow function declarations in a lexically nested statement");
1189 result = parseFunctionDeclaration(context);
1192 JSTokenLocation location(tokenLocation());
1194 result = context.createEmptyStatement(location);
1198 result = parseIfStatement(context);
1201 result = parseDoWhileStatement(context);
1204 result = parseWhileStatement(context);
1207 result = parseForStatement(context);
1210 result = parseContinueStatement(context);
1213 result = parseBreakStatement(context);
1216 result = parseReturnStatement(context);
1219 result = parseWithStatement(context);
1222 result = parseSwitchStatement(context);
1225 result = parseThrowStatement(context);
1228 result = parseTryStatement(context);
1231 result = parseDebuggerStatement(context);
1237 // These tokens imply the end of a set of source elements
1240 result = parseExpressionOrLabelStatement(context);
1243 directive = m_token.m_data.ident;
1244 if (directiveLiteralLength)
1245 *directiveLiteralLength = m_token.m_location.endOffset - m_token.m_location.startOffset;
1246 nonTrivialExpressionCount = m_nonTrivialExpressionCount;
1249 TreeStatement exprStatement = parseExpressionStatement(context);
1250 if (directive && nonTrivialExpressionCount != m_nonTrivialExpressionCount)
1252 result = exprStatement;
1256 if (result && shouldSetEndOffset)
1257 context.setEndOffset(result, m_lastTokenEndPosition.offset);
1261 template <typename LexerType>
1262 template <class TreeBuilder> TreeFormalParameterList Parser<LexerType>::parseFormalParameters(TreeBuilder& context)
1264 auto parameter = parseDeconstructionPattern(context, DeconstructToParameters);
1265 failIfFalse(parameter, "Cannot parse parameter pattern");
1266 TreeFormalParameterList list = context.createFormalParameterList(parameter);
1267 TreeFormalParameterList tail = list;
1268 while (consume(COMMA)) {
1269 parameter = parseDeconstructionPattern(context, DeconstructToParameters);
1270 failIfFalse(parameter, "Cannot parse parameter pattern");
1271 tail = context.createFormalParameterList(tail, parameter);
1276 template <typename LexerType>
1277 template <class TreeBuilder> TreeFunctionBody Parser<LexerType>::parseFunctionBody(
1278 TreeBuilder& context, int functionKeywordStart, int functionNameStart,
1279 int parametersStart, ConstructorKind constructorKind)
1281 JSTokenLocation startLocation(tokenLocation());
1282 unsigned startColumn = tokenColumn();
1285 if (match(CLOSEBRACE)) {
1286 unsigned endColumn = tokenColumn();
1287 return context.createFunctionBody(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind);
1289 DepthManager statementDepth(&m_statementDepth);
1290 m_statementDepth = 0;
1291 typename TreeBuilder::FunctionBodyBuilder bodyBuilder(const_cast<VM*>(m_vm), m_lexer.get());
1292 failIfFalse(parseSourceElements(bodyBuilder, CheckForStrictMode), "Cannot parse body of this function");
1293 unsigned endColumn = tokenColumn();
1294 return context.createFunctionBody(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind);
1297 static const char* stringForFunctionMode(FunctionParseMode mode)
1309 RELEASE_ASSERT_NOT_REACHED();
1313 template <typename LexerType> template <class TreeBuilder> int Parser<LexerType>::parseFunctionParameters(TreeBuilder& context, FunctionRequirements requirements, FunctionParseMode mode, bool nameIsInContainingScope, AutoPopScopeRef& functionScope, ParserFunctionInfo<TreeBuilder>& info)
1316 info.name = m_token.m_data.ident;
1317 m_lastFunctionName = info.name;
1319 if (!nameIsInContainingScope)
1320 failIfFalseIfStrict(functionScope->declareVariable(info.name), "'", info.name->impl(), "' is not a valid ", stringForFunctionMode(mode), " name in strict mode");
1321 } else if (requirements == FunctionNeedsName) {
1322 if (match(OPENPAREN) && mode == FunctionMode)
1323 semanticFail("Function statements must have a name");
1324 semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
1325 failDueToUnexpectedToken();
1328 int parametersStart = m_token.m_location.startOffset;
1329 if (!consume(OPENPAREN)) {
1330 semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
1331 failWithMessage("Expected an opening '(' before a ", stringForFunctionMode(mode), "'s parameter list");
1334 if (mode == GetterMode)
1335 consumeOrFail(CLOSEPAREN, "getter functions must have no parameters");
1336 else if (mode == SetterMode) {
1337 failIfTrue(match(CLOSEPAREN), "setter functions must have one parameter");
1338 auto parameter = parseDeconstructionPattern(context, DeconstructToParameters);
1339 failIfFalse(parameter, "setter functions must have one parameter");
1340 info.parameters = context.createFormalParameterList(parameter);
1341 failIfTrue(match(COMMA), "setter functions must have one parameter");
1342 consumeOrFail(CLOSEPAREN, "Expected a ')' after a parameter declaration");
1344 if (!match(CLOSEPAREN)) {
1345 info.parameters = parseFormalParameters(context);
1346 failIfFalse(info.parameters, "Cannot parse parameters for this ", stringForFunctionMode(mode));
1348 consumeOrFail(CLOSEPAREN, "Expected a ')' or a ',' after a parameter declaration");
1351 return parametersStart;
1354 template <typename LexerType>
1355 template <class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuilder& context, FunctionRequirements requirements, FunctionParseMode mode, bool nameIsInContainingScope, ConstructorKind constructorKind, SuperBinding expectedSuperBinding, int functionKeywordStart, ParserFunctionInfo<TreeBuilder>& info)
1357 AutoPopScopeRef functionScope(this, pushScope());
1358 functionScope->setIsFunction();
1359 int functionNameStart = m_token.m_location.startOffset;
1360 const Identifier* lastFunctionName = m_lastFunctionName;
1361 m_lastFunctionName = nullptr;
1363 int parametersStart = parseFunctionParameters(context, requirements, mode, nameIsInContainingScope, functionScope, info);
1366 matchOrFail(OPENBRACE, "Expected an opening '{' at the start of a ", stringForFunctionMode(mode), " body");
1368 // BytecodeGenerator emits code to throw TypeError when a class constructor is "call"ed.
1369 // Set ConstructorKind to None for non-constructor methods of classes.
1370 if (m_defaultConstructorKind != ConstructorKind::None) {
1371 constructorKind = m_defaultConstructorKind;
1372 expectedSuperBinding = m_defaultConstructorKind == ConstructorKind::Derived ? SuperBinding::Needed : SuperBinding::NotNeeded;
1374 bool isClassConstructor = constructorKind != ConstructorKind::None;
1376 info.openBraceOffset = m_token.m_data.offset;
1377 info.bodyStartLine = tokenLine();
1378 info.bodyStartColumn = m_token.m_data.offset - m_token.m_data.lineStartOffset;
1379 JSTokenLocation startLocation(tokenLocation());
1381 // If we know about this function already, we can use the cached info and skip the parser to the end of the function.
1382 if (const SourceProviderCacheItem* cachedInfo = TreeBuilder::CanUseFunctionCache ? findCachedFunctionInfo(info.openBraceOffset) : 0) {
1383 // If we're in a strict context, the cached function info must say it was strict too.
1384 ASSERT(!strictMode() || cachedInfo->strictMode);
1385 JSTokenLocation endLocation;
1387 endLocation.line = cachedInfo->closeBraceLine;
1388 endLocation.startOffset = cachedInfo->closeBraceOffset;
1389 endLocation.lineStartOffset = cachedInfo->closeBraceLineStartOffset;
1391 bool endColumnIsOnStartLine = (endLocation.line == info.bodyStartLine);
1392 ASSERT(endLocation.startOffset >= endLocation.lineStartOffset);
1393 unsigned bodyEndColumn = endColumnIsOnStartLine ?
1394 endLocation.startOffset - m_token.m_data.lineStartOffset :
1395 endLocation.startOffset - endLocation.lineStartOffset;
1396 unsigned currentLineStartOffset = m_token.m_location.lineStartOffset;
1398 info.body = context.createFunctionBody(
1399 startLocation, endLocation, info.bodyStartColumn, bodyEndColumn,
1400 functionKeywordStart, functionNameStart, parametersStart,
1401 cachedInfo->strictMode, constructorKind);
1403 functionScope->restoreFromSourceProviderCache(cachedInfo);
1404 failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo), "Parser error");
1406 info.closeBraceOffset = cachedInfo->closeBraceOffset;
1408 m_token = cachedInfo->closeBraceToken();
1409 if (endColumnIsOnStartLine)
1410 m_token.m_location.lineStartOffset = currentLineStartOffset;
1412 m_lexer->setOffset(m_token.m_location.endOffset, m_token.m_location.lineStartOffset);
1413 m_lexer->setLineNumber(m_token.m_location.line);
1415 context.setEndOffset(info.body, m_lexer->currentOffset());
1418 info.bodyEndLine = m_lastTokenEndPosition.line;
1421 m_lastFunctionName = lastFunctionName;
1422 ParserState oldState = saveState();
1423 info.body = parseFunctionBody(context, functionKeywordStart, functionNameStart, parametersStart, constructorKind);
1424 restoreState(oldState);
1425 failIfFalse(info.body, "Cannot parse the body of this ", stringForFunctionMode(mode));
1426 context.setEndOffset(info.body, m_lexer->currentOffset());
1427 if (functionScope->strictMode() && info.name) {
1428 RELEASE_ASSERT(mode == FunctionMode || mode == MethodMode);
1429 semanticFailIfTrue(m_vm->propertyNames->arguments == *info.name, "'", info.name->impl(), "' is not a valid function name in strict mode");
1430 semanticFailIfTrue(m_vm->propertyNames->eval == *info.name, "'", info.name->impl(), "' is not a valid function name in strict mode");
1432 if (functionScope->hasDirectSuper()) {
1433 semanticFailIfTrue(!isClassConstructor, "Cannot call super() outside of a class constructor");
1434 semanticFailIfTrue(constructorKind != ConstructorKind::Derived, "Cannot call super() in a base class constructor");
1436 if (functionScope->needsSuperBinding())
1437 semanticFailIfTrue(expectedSuperBinding == SuperBinding::NotNeeded, "super can only be used in a method of a derived class");
1439 info.closeBraceOffset = m_token.m_data.offset;
1440 unsigned closeBraceLine = m_token.m_data.line;
1441 unsigned closeBraceLineStartOffset = m_token.m_data.lineStartOffset;
1443 // Cache the tokenizer state and the function scope the first time the function is parsed.
1444 // Any future reparsing can then skip the function.
1445 static const int minimumFunctionLengthToCache = 16;
1446 std::unique_ptr<SourceProviderCacheItem> newInfo;
1447 int functionLength = info.closeBraceOffset - info.openBraceOffset;
1448 if (TreeBuilder::CanUseFunctionCache && m_functionCache && functionLength > minimumFunctionLengthToCache) {
1449 SourceProviderCacheItemCreationParameters parameters;
1450 parameters.functionNameStart = functionNameStart;
1451 parameters.closeBraceLine = closeBraceLine;
1452 parameters.closeBraceOffset = info.closeBraceOffset;
1453 parameters.closeBraceLineStartOffset = closeBraceLineStartOffset;
1454 functionScope->fillParametersForSourceProviderCache(parameters);
1455 newInfo = SourceProviderCacheItem::create(parameters);
1459 failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo), "Parser error");
1460 matchOrFail(CLOSEBRACE, "Expected a closing '}' after a ", stringForFunctionMode(mode), " body");
1463 m_functionCache->add(info.openBraceOffset, WTF::move(newInfo));
1466 info.bodyEndLine = m_lastTokenEndPosition.line;
1470 template <typename LexerType>
1471 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDeclaration(TreeBuilder& context)
1473 ASSERT(match(FUNCTION));
1474 JSTokenLocation location(tokenLocation());
1475 unsigned functionKeywordStart = tokenStart();
1477 ParserFunctionInfo<TreeBuilder> info;
1478 failIfFalse((parseFunctionInfo(context, FunctionNeedsName, FunctionMode, true, ConstructorKind::None, SuperBinding::NotNeeded,
1479 functionKeywordStart, info)), "Cannot parse this function");
1480 failIfFalse(info.name, "Function statements must have a name");
1481 failIfFalseIfStrict(declareVariable(info.name), "Cannot declare a function named '", info.name->impl(), "' in strict mode");
1482 return context.createFuncDeclStatement(location, info);
1485 #if ENABLE(ES6_CLASS_SYNTAX)
1486 template <typename LexerType>
1487 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseClassDeclaration(TreeBuilder& context)
1489 ASSERT(match(CLASSTOKEN));
1490 JSTokenLocation location(tokenLocation());
1491 JSTextPosition classStart = tokenStartPosition();
1492 unsigned classStartLine = tokenLine();
1494 ParserClassInfo<TreeBuilder> info;
1495 TreeClassExpression classExpr = parseClass(context, FunctionNeedsName, info);
1496 failIfFalse(classExpr, "Failed to parse class");
1497 declareVariable(info.className);
1499 // FIXME: This should be like `let`, not `var`.
1500 context.addVar(info.className, DeclarationStacks::HasInitializer);
1502 JSTextPosition classEnd = lastTokenEndPosition();
1503 unsigned classEndLine = tokenLine();
1505 return context.createClassDeclStatement(location, classExpr, classStart, classEnd, classStartLine, classEndLine);
1508 template <typename LexerType>
1509 template <class TreeBuilder> TreeClassExpression Parser<LexerType>::parseClass(TreeBuilder& context, FunctionRequirements requirements, ParserClassInfo<TreeBuilder>& info)
1511 ASSERT(match(CLASSTOKEN));
1512 JSTokenLocation location(tokenLocation());
1515 AutoPopScopeRef classScope(this, pushScope());
1516 classScope->setStrictMode();
1518 const Identifier* className = nullptr;
1520 className = m_token.m_data.ident;
1521 info.className = className;
1523 failIfFalse(classScope->declareVariable(className), "'", className->impl(), "' is not a valid class name");
1524 } else if (requirements == FunctionNeedsName) {
1525 if (match(OPENBRACE))
1526 semanticFail("Class statements must have a name");
1527 semanticFailureDueToKeyword("class name");
1528 failDueToUnexpectedToken();
1530 className = &m_vm->propertyNames->nullIdentifier;
1533 TreeExpression parentClass = 0;
1534 if (consume(EXTENDS)) {
1535 parentClass = parseMemberExpression(context);
1536 failIfFalse(parentClass, "Cannot parse the parent class name");
1538 const ConstructorKind constructorKind = parentClass ? ConstructorKind::Derived : ConstructorKind::Base;
1540 consumeOrFail(OPENBRACE, "Expected opening '{' at the start of a class body");
1542 TreeExpression constructor = 0;
1543 TreePropertyList staticMethods = 0;
1544 TreePropertyList instanceMethods = 0;
1545 TreePropertyList instanceMethodsTail = 0;
1546 TreePropertyList staticMethodsTail = 0;
1547 while (!match(CLOSEBRACE)) {
1548 if (match(SEMICOLON)) {
1553 JSTokenLocation methodLocation(tokenLocation());
1554 unsigned methodStart = tokenStart();
1556 // For backwards compatibility, "static" is a non-reserved keyword in non-strict mode.
1557 bool isStaticMethod = match(RESERVED_IF_STRICT) && *m_token.m_data.ident == m_vm->propertyNames->staticKeyword;
1561 // FIXME: Figure out a way to share more code with parseProperty.
1562 const CommonIdentifiers& propertyNames = *m_vm->propertyNames;
1563 const Identifier* ident = nullptr;
1564 bool isGetter = false;
1565 bool isSetter = false;
1566 switch (m_token.m_type) {
1568 ident = m_token.m_data.ident;
1573 ident = m_token.m_data.ident;
1574 isGetter = *ident == propertyNames.get;
1575 isSetter = *ident == propertyNames.set;
1580 ident = &m_parserArena.identifierArena().makeNumericIdentifier(const_cast<VM*>(m_vm), m_token.m_data.doubleValue);
1585 failDueToUnexpectedToken();
1588 TreeProperty property;
1589 const bool alwaysStrictInsideClass = true;
1590 if (isGetter || isSetter) {
1591 nextExpectIdentifier(LexerFlagsIgnoreReservedWords);
1592 property = parseGetterSetter(context, alwaysStrictInsideClass, isGetter ? PropertyNode::Getter : PropertyNode::Setter, methodStart,
1593 ConstructorKind::None, SuperBinding::Needed);
1594 failIfFalse(property, "Cannot parse this method");
1596 ParserFunctionInfo<TreeBuilder> methodInfo;
1597 bool isConstructor = !isStaticMethod && *ident == propertyNames.constructor;
1598 failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, isStaticMethod ? FunctionMode : MethodMode, false,
1599 isConstructor ? constructorKind : ConstructorKind::None, SuperBinding::Needed, methodStart, methodInfo)), "Cannot parse this method");
1600 failIfFalse(ident && declareVariable(ident), "Cannot declare a method named '", methodInfo.name->impl(), "'");
1601 methodInfo.name = isConstructor ? className : ident;
1603 TreeExpression method = context.createFunctionExpr(methodLocation, methodInfo);
1604 if (isConstructor) {
1605 semanticFailIfTrue(constructor, "Cannot declare multiple constructors in a single class");
1606 constructor = method;
1610 // FIXME: Syntax error when super() is called
1611 semanticFailIfTrue(isStaticMethod && methodInfo.name && *methodInfo.name == propertyNames.prototype,
1612 "Cannot declare a static method named 'prototype'");
1613 property = context.createProperty(methodInfo.name, method, PropertyNode::Constant, PropertyNode::Unknown, alwaysStrictInsideClass, SuperBinding::Needed);
1616 TreePropertyList& tail = isStaticMethod ? staticMethodsTail : instanceMethodsTail;
1618 tail = context.createPropertyList(methodLocation, property, tail);
1620 tail = context.createPropertyList(methodLocation, property);
1622 staticMethods = tail;
1624 instanceMethods = tail;
1628 failIfFalse(popScope(classScope, TreeBuilder::NeedsFreeVariableInfo), "Parser error");
1629 consumeOrFail(CLOSEBRACE, "Expected a closing '}' after a class body");
1631 return context.createClassExpr(location, *className, constructor, parentClass, instanceMethods, staticMethods);
1636 LabelInfo(const Identifier* ident, const JSTextPosition& start, const JSTextPosition& end)
1643 const Identifier* m_ident;
1644 JSTextPosition m_start;
1645 JSTextPosition m_end;
1648 template <typename LexerType>
1649 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionOrLabelStatement(TreeBuilder& context)
1652 /* Expression and Label statements are ambiguous at LL(1), so we have a
1653 * special case that looks for a colon as the next character in the input.
1655 Vector<LabelInfo> labels;
1656 JSTokenLocation location;
1658 JSTextPosition start = tokenStartPosition();
1659 location = tokenLocation();
1660 if (!nextTokenIsColon()) {
1661 // If we hit this path we're making a expression statement, which
1662 // by definition can't make use of continue/break so we can just
1663 // ignore any labels we might have accumulated.
1664 TreeExpression expression = parseExpression(context);
1665 failIfFalse(expression, "Cannot parse expression statement");
1666 if (!autoSemiColon())
1667 failDueToUnexpectedToken();
1668 return context.createExprStatement(location, expression, start, m_lastTokenEndPosition.line);
1670 const Identifier* ident = m_token.m_data.ident;
1671 JSTextPosition end = tokenEndPosition();
1673 consumeOrFail(COLON, "Labels must be followed by a ':'");
1674 if (!m_syntaxAlreadyValidated) {
1675 // This is O(N^2) over the current list of consecutive labels, but I
1676 // have never seen more than one label in a row in the real world.
1677 for (size_t i = 0; i < labels.size(); i++)
1678 failIfTrue(ident->impl() == labels[i].m_ident->impl(), "Attempted to redeclare the label '", ident->impl(), "'");
1679 failIfTrue(getLabel(ident), "Cannot find scope for the label '", ident->impl(), "'");
1680 labels.append(LabelInfo(ident, start, end));
1682 } while (match(IDENT));
1683 bool isLoop = false;
1684 switch (m_token.m_type) {
1694 const Identifier* unused = 0;
1695 if (!m_syntaxAlreadyValidated) {
1696 for (size_t i = 0; i < labels.size(); i++)
1697 pushLabel(labels[i].m_ident, isLoop);
1699 TreeStatement statement = parseStatement(context, unused);
1700 if (!m_syntaxAlreadyValidated) {
1701 for (size_t i = 0; i < labels.size(); i++)
1704 failIfFalse(statement, "Cannot parse statement");
1705 for (size_t i = 0; i < labels.size(); i++) {
1706 const LabelInfo& info = labels[labels.size() - i - 1];
1707 statement = context.createLabelStatement(location, info.m_ident, statement, info.m_start, info.m_end);
1712 template <typename LexerType>
1713 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionStatement(TreeBuilder& context)
1715 JSTextPosition start = tokenStartPosition();
1716 JSTokenLocation location(tokenLocation());
1717 TreeExpression expression = parseExpression(context);
1718 failIfFalse(expression, "Cannot parse expression statement");
1719 failIfFalse(autoSemiColon(), "Parse error");
1720 return context.createExprStatement(location, expression, start, m_lastTokenEndPosition.line);
1723 template <typename LexerType>
1724 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseIfStatement(TreeBuilder& context)
1727 JSTokenLocation ifLocation(tokenLocation());
1728 int start = tokenLine();
1730 handleProductionOrFail(OPENPAREN, "(", "start", "'if' condition");
1732 TreeExpression condition = parseExpression(context);
1733 failIfFalse(condition, "Expected a expression as the condition for an if statement");
1734 int end = tokenLine();
1735 handleProductionOrFail(CLOSEPAREN, ")", "end", "'if' condition");
1737 const Identifier* unused = 0;
1738 TreeStatement trueBlock = parseStatement(context, unused);
1739 failIfFalse(trueBlock, "Expected a statement as the body of an if block");
1742 return context.createIfStatement(ifLocation, condition, trueBlock, 0, start, end);
1744 Vector<TreeExpression> exprStack;
1745 Vector<std::pair<int, int>> posStack;
1746 Vector<JSTokenLocation> tokenLocationStack;
1747 Vector<TreeStatement> statementStack;
1748 bool trailingElse = false;
1750 JSTokenLocation tempLocation = tokenLocation();
1753 const Identifier* unused = 0;
1754 TreeStatement block = parseStatement(context, unused);
1755 failIfFalse(block, "Expected a statement as the body of an else block");
1756 statementStack.append(block);
1757 trailingElse = true;
1760 int innerStart = tokenLine();
1763 handleProductionOrFail(OPENPAREN, "(", "start", "'if' condition");
1765 TreeExpression innerCondition = parseExpression(context);
1766 failIfFalse(innerCondition, "Expected a expression as the condition for an if statement");
1767 int innerEnd = tokenLine();
1768 handleProductionOrFail(CLOSEPAREN, ")", "end", "'if' condition");
1769 const Identifier* unused = 0;
1770 TreeStatement innerTrueBlock = parseStatement(context, unused);
1771 failIfFalse(innerTrueBlock, "Expected a statement as the body of an if block");
1772 tokenLocationStack.append(tempLocation);
1773 exprStack.append(innerCondition);
1774 posStack.append(std::make_pair(innerStart, innerEnd));
1775 statementStack.append(innerTrueBlock);
1776 } while (match(ELSE));
1778 if (!trailingElse) {
1779 TreeExpression condition = exprStack.last();
1780 exprStack.removeLast();
1781 TreeStatement trueBlock = statementStack.last();
1782 statementStack.removeLast();
1783 std::pair<int, int> pos = posStack.last();
1784 posStack.removeLast();
1785 JSTokenLocation elseLocation = tokenLocationStack.last();
1786 tokenLocationStack.removeLast();
1787 TreeStatement ifStatement = context.createIfStatement(elseLocation, condition, trueBlock, 0, pos.first, pos.second);
1788 context.setEndOffset(ifStatement, context.endOffset(trueBlock));
1789 statementStack.append(ifStatement);
1792 while (!exprStack.isEmpty()) {
1793 TreeExpression condition = exprStack.last();
1794 exprStack.removeLast();
1795 TreeStatement falseBlock = statementStack.last();
1796 statementStack.removeLast();
1797 TreeStatement trueBlock = statementStack.last();
1798 statementStack.removeLast();
1799 std::pair<int, int> pos = posStack.last();
1800 posStack.removeLast();
1801 JSTokenLocation elseLocation = tokenLocationStack.last();
1802 tokenLocationStack.removeLast();
1803 TreeStatement ifStatement = context.createIfStatement(elseLocation, condition, trueBlock, falseBlock, pos.first, pos.second);
1804 context.setEndOffset(ifStatement, context.endOffset(falseBlock));
1805 statementStack.append(ifStatement);
1808 return context.createIfStatement(ifLocation, condition, trueBlock, statementStack.last(), start, end);
1811 template <typename LexerType>
1812 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseExpression(TreeBuilder& context)
1814 failIfStackOverflow();
1815 JSTokenLocation location(tokenLocation());
1816 TreeExpression node = parseAssignmentExpression(context);
1817 failIfFalse(node, "Cannot parse expression");
1818 context.setEndOffset(node, m_lastTokenEndPosition.offset);
1822 m_nonTrivialExpressionCount++;
1824 TreeExpression right = parseAssignmentExpression(context);
1825 failIfFalse(right, "Cannot parse expression in a comma expression");
1826 context.setEndOffset(right, m_lastTokenEndPosition.offset);
1827 typename TreeBuilder::Comma head = context.createCommaExpr(location, node);
1828 typename TreeBuilder::Comma tail = context.appendToCommaExpr(location, head, head, right);
1829 while (match(COMMA)) {
1830 next(TreeBuilder::DontBuildStrings);
1831 right = parseAssignmentExpression(context);
1832 failIfFalse(right, "Cannot parse expression in a comma expression");
1833 context.setEndOffset(right, m_lastTokenEndPosition.offset);
1834 tail = context.appendToCommaExpr(location, head, tail, right);
1836 context.setEndOffset(head, m_lastTokenEndPosition.offset);
1840 template <typename LexerType>
1841 template <typename TreeBuilder> TreeExpression Parser<LexerType>::parseAssignmentExpression(TreeBuilder& context)
1843 failIfStackOverflow();
1844 JSTextPosition start = tokenStartPosition();
1845 JSTokenLocation location(tokenLocation());
1846 int initialAssignmentCount = m_assignmentCount;
1847 int initialNonLHSCount = m_nonLHSCount;
1848 if (match(OPENBRACE) || match(OPENBRACKET)) {
1849 SavePoint savePoint = createSavePoint();
1850 auto pattern = tryParseDeconstructionPatternExpression(context);
1851 if (pattern && consume(EQUAL)) {
1852 auto rhs = parseAssignmentExpression(context);
1854 return context.createDeconstructingAssignment(location, pattern, rhs);
1856 restoreSavePoint(savePoint);
1858 TreeExpression lhs = parseConditionalExpression(context);
1859 failIfFalse(lhs, "Cannot parse expression");
1860 if (initialNonLHSCount != m_nonLHSCount) {
1861 if (m_token.m_type >= EQUAL && m_token.m_type <= OREQUAL)
1862 semanticFail("Left hand side of operator '", getToken(), "' must be a reference");
1867 int assignmentStack = 0;
1869 bool hadAssignment = false;
1871 switch (m_token.m_type) {
1872 case EQUAL: op = OpEqual; break;
1873 case PLUSEQUAL: op = OpPlusEq; break;
1874 case MINUSEQUAL: op = OpMinusEq; break;
1875 case MULTEQUAL: op = OpMultEq; break;
1876 case DIVEQUAL: op = OpDivEq; break;
1877 case LSHIFTEQUAL: op = OpLShift; break;
1878 case RSHIFTEQUAL: op = OpRShift; break;
1879 case URSHIFTEQUAL: op = OpURShift; break;
1880 case ANDEQUAL: op = OpAndEq; break;
1881 case XOREQUAL: op = OpXOrEq; break;
1882 case OREQUAL: op = OpOrEq; break;
1883 case MODEQUAL: op = OpModEq; break;
1887 m_nonTrivialExpressionCount++;
1888 hadAssignment = true;
1889 context.assignmentStackAppend(assignmentStack, lhs, start, tokenStartPosition(), m_assignmentCount, op);
1890 start = tokenStartPosition();
1891 m_assignmentCount++;
1892 next(TreeBuilder::DontBuildStrings);
1893 if (strictMode() && m_lastIdentifier && context.isResolve(lhs)) {
1894 failIfTrueIfStrict(m_vm->propertyNames->eval == *m_lastIdentifier, "Cannot modify 'eval' in strict mode");
1895 failIfTrueIfStrict(m_vm->propertyNames->arguments == *m_lastIdentifier, "Cannot modify 'arguments' in strict mode");
1896 declareWrite(m_lastIdentifier);
1897 m_lastIdentifier = 0;
1899 lhs = parseAssignmentExpression(context);
1900 failIfFalse(lhs, "Cannot parse the right hand side of an assignment expression");
1901 if (initialNonLHSCount != m_nonLHSCount) {
1902 if (m_token.m_type >= EQUAL && m_token.m_type <= OREQUAL)
1903 semanticFail("Left hand side of operator '", getToken(), "' must be a reference");
1911 if (!TreeBuilder::CreatesAST)
1914 while (assignmentStack)
1915 lhs = context.createAssignment(location, assignmentStack, lhs, initialAssignmentCount, m_assignmentCount, lastTokenEndPosition());
1920 template <typename LexerType>
1921 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseConditionalExpression(TreeBuilder& context)
1923 JSTokenLocation location(tokenLocation());
1924 TreeExpression cond = parseBinaryExpression(context);
1925 failIfFalse(cond, "Cannot parse expression");
1926 if (!match(QUESTION))
1928 m_nonTrivialExpressionCount++;
1930 next(TreeBuilder::DontBuildStrings);
1931 TreeExpression lhs = parseAssignmentExpression(context);
1932 failIfFalse(lhs, "Cannot parse left hand side of ternary operator");
1933 context.setEndOffset(lhs, m_lastTokenEndPosition.offset);
1934 consumeOrFailWithFlags(COLON, TreeBuilder::DontBuildStrings, "Expected ':' in ternary operator");
1936 TreeExpression rhs = parseAssignmentExpression(context);
1937 failIfFalse(rhs, "Cannot parse right hand side of ternary operator");
1938 context.setEndOffset(rhs, m_lastTokenEndPosition.offset);
1939 return context.createConditionalExpr(location, cond, lhs, rhs);
1942 ALWAYS_INLINE static bool isUnaryOp(JSTokenType token)
1944 return token & UnaryOpTokenFlag;
1947 template <typename LexerType>
1948 int Parser<LexerType>::isBinaryOperator(JSTokenType token)
1951 return token & (BinaryOpTokenPrecedenceMask << BinaryOpTokenAllowsInPrecedenceAdditionalShift);
1952 return token & BinaryOpTokenPrecedenceMask;
1955 template <typename LexerType>
1956 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseBinaryExpression(TreeBuilder& context)
1958 int operandStackDepth = 0;
1959 int operatorStackDepth = 0;
1960 typename TreeBuilder::BinaryExprContext binaryExprContext(context);
1961 JSTokenLocation location(tokenLocation());
1963 JSTextPosition exprStart = tokenStartPosition();
1964 int initialAssignments = m_assignmentCount;
1965 TreeExpression current = parseUnaryExpression(context);
1966 failIfFalse(current, "Cannot parse expression");
1968 context.appendBinaryExpressionInfo(operandStackDepth, current, exprStart, lastTokenEndPosition(), lastTokenEndPosition(), initialAssignments != m_assignmentCount);
1969 int precedence = isBinaryOperator(m_token.m_type);
1972 m_nonTrivialExpressionCount++;
1974 int operatorToken = m_token.m_type;
1975 next(TreeBuilder::DontBuildStrings);
1977 while (operatorStackDepth && context.operatorStackHasHigherPrecedence(operatorStackDepth, precedence)) {
1978 ASSERT(operandStackDepth > 1);
1980 typename TreeBuilder::BinaryOperand rhs = context.getFromOperandStack(-1);
1981 typename TreeBuilder::BinaryOperand lhs = context.getFromOperandStack(-2);
1982 context.shrinkOperandStackBy(operandStackDepth, 2);
1983 context.appendBinaryOperation(location, operandStackDepth, operatorStackDepth, lhs, rhs);
1984 context.operatorStackPop(operatorStackDepth);
1986 context.operatorStackAppend(operatorStackDepth, operatorToken, precedence);
1988 while (operatorStackDepth) {
1989 ASSERT(operandStackDepth > 1);
1991 typename TreeBuilder::BinaryOperand rhs = context.getFromOperandStack(-1);
1992 typename TreeBuilder::BinaryOperand lhs = context.getFromOperandStack(-2);
1993 context.shrinkOperandStackBy(operandStackDepth, 2);
1994 context.appendBinaryOperation(location, operandStackDepth, operatorStackDepth, lhs, rhs);
1995 context.operatorStackPop(operatorStackDepth);
1997 return context.popOperandStack(operandStackDepth);
2000 template <typename LexerType>
2001 template <class TreeBuilder> TreeProperty Parser<LexerType>::parseProperty(TreeBuilder& context, bool complete)
2003 bool wasIdent = false;
2004 switch (m_token.m_type) {
2010 const Identifier* ident = m_token.m_data.ident;
2011 unsigned getterOrSetterStartOffset = tokenStart();
2012 if (complete || (wasIdent && (*ident == m_vm->propertyNames->get || *ident == m_vm->propertyNames->set)))
2013 nextExpectIdentifier(LexerFlagsIgnoreReservedWords);
2015 nextExpectIdentifier(LexerFlagsIgnoreReservedWords | TreeBuilder::DontBuildKeywords);
2019 TreeExpression node = parseAssignmentExpression(context);
2020 failIfFalse(node, "Cannot parse expression for property declaration");
2021 context.setEndOffset(node, m_lexer->currentOffset());
2022 return context.createProperty(ident, node, PropertyNode::Constant, PropertyNode::Unknown, complete);
2025 if (match(OPENPAREN)) {
2026 auto method = parsePropertyMethod(context, ident);
2028 return context.createProperty(ident, method, PropertyNode::Constant, PropertyNode::KnownDirect, complete);
2031 failIfFalse(wasIdent, "Expected an identifier as property name");
2033 if (match(COMMA) || match(CLOSEBRACE)) {
2034 JSTextPosition start = tokenStartPosition();
2035 JSTokenLocation location(tokenLocation());
2036 currentScope()->useVariable(ident, m_vm->propertyNames->eval == *ident);
2037 TreeExpression node = context.createResolve(location, ident, start);
2038 return context.createProperty(ident, node, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Shorthand), PropertyNode::KnownDirect, complete);
2041 PropertyNode::Type type;
2042 if (*ident == m_vm->propertyNames->get)
2043 type = PropertyNode::Getter;
2044 else if (*ident == m_vm->propertyNames->set)
2045 type = PropertyNode::Setter;
2047 failWithMessage("Expected a ':' following the property name '", ident->impl(), "'");
2048 return parseGetterSetter(context, complete, type, getterOrSetterStartOffset);
2052 double propertyName = m_token.m_data.doubleValue;
2055 if (match(OPENPAREN)) {
2056 const Identifier& ident = m_parserArena.identifierArena().makeNumericIdentifier(const_cast<VM*>(m_vm), propertyName);
2057 auto method = parsePropertyMethod(context, &ident);
2059 return context.createProperty(&ident, method, PropertyNode::Constant, PropertyNode::Unknown, complete);
2062 consumeOrFail(COLON, "Expected ':' after property name");
2063 TreeExpression node = parseAssignmentExpression(context);
2064 failIfFalse(node, "Cannot parse expression for property declaration");
2065 context.setEndOffset(node, m_lexer->currentOffset());
2066 return context.createProperty(const_cast<VM*>(m_vm), m_parserArena, propertyName, node, PropertyNode::Constant, PropertyNode::Unknown, complete);
2070 auto propertyName = parseAssignmentExpression(context);
2071 failIfFalse(propertyName, "Cannot parse computed property name");
2072 handleProductionOrFail(CLOSEBRACKET, "]", "end", "computed property name");
2074 if (match(OPENPAREN)) {
2075 auto method = parsePropertyMethod(context, &m_vm->propertyNames->nullIdentifier);
2077 return context.createProperty(propertyName, method, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Computed), PropertyNode::KnownDirect, complete);
2080 consumeOrFail(COLON, "Expected ':' after property name");
2081 TreeExpression node = parseAssignmentExpression(context);
2082 failIfFalse(node, "Cannot parse expression for property declaration");
2083 context.setEndOffset(node, m_lexer->currentOffset());
2084 return context.createProperty(propertyName, node, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Computed), PropertyNode::Unknown, complete);
2087 failIfFalse(m_token.m_type & KeywordTokenFlag, "Expected a property name");
2092 template <typename LexerType>
2093 template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePropertyMethod(TreeBuilder& context, const Identifier* methodName)
2095 JSTokenLocation methodLocation(tokenLocation());
2096 unsigned methodStart = tokenStart();
2097 ParserFunctionInfo<TreeBuilder> methodInfo;
2098 failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, MethodMode, false, ConstructorKind::None, SuperBinding::NotNeeded,
2099 methodStart, methodInfo)), "Cannot parse this method");
2100 methodInfo.name = methodName;
2101 return context.createFunctionExpr(methodLocation, methodInfo);
2104 template <typename LexerType>
2105 template <class TreeBuilder> TreeProperty Parser<LexerType>::parseGetterSetter(TreeBuilder& context, bool strict, PropertyNode::Type type, unsigned getterOrSetterStartOffset,
2106 ConstructorKind constructorKind, SuperBinding superBinding)
2108 const Identifier* stringPropertyName = 0;
2109 double numericPropertyName = 0;
2110 if (m_token.m_type == IDENT || m_token.m_type == STRING) {
2111 stringPropertyName = m_token.m_data.ident;
2112 semanticFailIfTrue(superBinding == SuperBinding::Needed && *stringPropertyName == m_vm->propertyNames->prototype,
2113 "Cannot declare a static method named 'prototype'");
2114 semanticFailIfTrue(superBinding == SuperBinding::Needed && *stringPropertyName == m_vm->propertyNames->constructor,
2115 "Cannot declare a getter or setter named 'constructor'");
2116 } else if (m_token.m_type == DOUBLE || m_token.m_type == INTEGER)
2117 numericPropertyName = m_token.m_data.doubleValue;
2119 failDueToUnexpectedToken();
2120 JSTokenLocation location(tokenLocation());
2122 ParserFunctionInfo<TreeBuilder> info;
2123 if (type & PropertyNode::Getter) {
2124 failIfFalse(match(OPENPAREN), "Expected a parameter list for getter definition");
2125 failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, GetterMode, false, constructorKind, superBinding,
2126 getterOrSetterStartOffset, info)), "Cannot parse getter definition");
2128 failIfFalse(match(OPENPAREN), "Expected a parameter list for setter definition");
2129 failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, SetterMode, false, constructorKind, superBinding,
2130 getterOrSetterStartOffset, info)), "Cannot parse setter definition");
2132 if (stringPropertyName)
2133 return context.createGetterOrSetterProperty(location, type, strict, stringPropertyName, info, superBinding);
2134 return context.createGetterOrSetterProperty(const_cast<VM*>(m_vm), m_parserArena, location, type, strict, numericPropertyName, info, superBinding);
2137 template <typename LexerType>
2138 template <class TreeBuilder> bool Parser<LexerType>::shouldCheckPropertyForUnderscoreProtoDuplicate(TreeBuilder& context, const TreeProperty& property)
2140 if (m_syntaxAlreadyValidated)
2143 if (!context.getName(property))
2146 // A Constant property that is not a Computed or Shorthand Constant property.
2147 return context.getType(property) == PropertyNode::Constant;
2150 template <typename LexerType>
2151 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseObjectLiteral(TreeBuilder& context)
2153 auto savePoint = createSavePoint();
2154 consumeOrFailWithFlags(OPENBRACE, TreeBuilder::DontBuildStrings, "Expected opening '{' at the start of an object literal");
2156 int oldNonLHSCount = m_nonLHSCount;
2158 JSTokenLocation location(tokenLocation());
2159 if (match(CLOSEBRACE)) {
2161 return context.createObjectLiteral(location);
2164 TreeProperty property = parseProperty(context, false);
2165 failIfFalse(property, "Cannot parse object literal property");
2167 if (!m_syntaxAlreadyValidated && context.getType(property) & (PropertyNode::Getter | PropertyNode::Setter)) {
2168 restoreSavePoint(savePoint);
2169 return parseStrictObjectLiteral(context);
2172 bool seenUnderscoreProto = false;
2173 if (shouldCheckPropertyForUnderscoreProtoDuplicate(context, property))
2174 seenUnderscoreProto = *context.getName(property) == m_vm->propertyNames->underscoreProto;
2176 TreePropertyList propertyList = context.createPropertyList(location, property);
2177 TreePropertyList tail = propertyList;
2178 while (match(COMMA)) {
2179 next(TreeBuilder::DontBuildStrings);
2180 if (match(CLOSEBRACE))
2182 JSTokenLocation propertyLocation(tokenLocation());
2183 property = parseProperty(context, false);
2184 failIfFalse(property, "Cannot parse object literal property");
2185 if (!m_syntaxAlreadyValidated && context.getType(property) & (PropertyNode::Getter | PropertyNode::Setter)) {
2186 restoreSavePoint(savePoint);
2187 return parseStrictObjectLiteral(context);
2189 if (shouldCheckPropertyForUnderscoreProtoDuplicate(context, property)) {
2190 if (*context.getName(property) == m_vm->propertyNames->underscoreProto) {
2191 semanticFailIfTrue(seenUnderscoreProto, "Attempted to redefine __proto__ property");
2192 seenUnderscoreProto = true;
2195 tail = context.createPropertyList(propertyLocation, property, tail);
2198 location = tokenLocation();
2199 handleProductionOrFail(CLOSEBRACE, "}", "end", "object literal");
2201 m_nonLHSCount = oldNonLHSCount;
2203 return context.createObjectLiteral(location, propertyList);
2206 template <typename LexerType>
2207 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseStrictObjectLiteral(TreeBuilder& context)
2209 consumeOrFail(OPENBRACE, "Expected opening '{' at the start of an object literal");
2211 int oldNonLHSCount = m_nonLHSCount;
2213 JSTokenLocation location(tokenLocation());
2214 if (match(CLOSEBRACE)) {
2216 return context.createObjectLiteral(location);
2219 TreeProperty property = parseProperty(context, true);
2220 failIfFalse(property, "Cannot parse object literal property");
2222 bool seenUnderscoreProto = false;
2223 if (shouldCheckPropertyForUnderscoreProtoDuplicate(context, property))
2224 seenUnderscoreProto = *context.getName(property) == m_vm->propertyNames->underscoreProto;
2226 TreePropertyList propertyList = context.createPropertyList(location, property);
2227 TreePropertyList tail = propertyList;
2228 while (match(COMMA)) {
2230 if (match(CLOSEBRACE))
2232 JSTokenLocation propertyLocation(tokenLocation());
2233 property = parseProperty(context, true);
2234 failIfFalse(property, "Cannot parse object literal property");
2235 if (shouldCheckPropertyForUnderscoreProtoDuplicate(context, property)) {
2236 if (*context.getName(property) == m_vm->propertyNames->underscoreProto) {
2237 semanticFailIfTrue(seenUnderscoreProto, "Attempted to redefine __proto__ property");
2238 seenUnderscoreProto = true;
2241 tail = context.createPropertyList(propertyLocation, property, tail);
2244 location = tokenLocation();
2245 handleProductionOrFail(CLOSEBRACE, "}", "end", "object literal");
2247 m_nonLHSCount = oldNonLHSCount;
2249 return context.createObjectLiteral(location, propertyList);
2252 template <typename LexerType>
2253 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseArrayLiteral(TreeBuilder& context)
2255 consumeOrFailWithFlags(OPENBRACKET, TreeBuilder::DontBuildStrings, "Expected an opening '[' at the beginning of an array literal");
2257 int oldNonLHSCount = m_nonLHSCount;
2260 while (match(COMMA)) {
2261 next(TreeBuilder::DontBuildStrings);
2264 if (match(CLOSEBRACKET)) {
2265 JSTokenLocation location(tokenLocation());
2266 next(TreeBuilder::DontBuildStrings);
2267 return context.createArray(location, elisions);
2270 TreeExpression elem;
2271 if (UNLIKELY(match(DOTDOTDOT))) {
2272 auto spreadLocation = m_token.m_location;
2273 auto start = m_token.m_startPosition;
2274 auto divot = m_token.m_endPosition;
2276 auto spreadExpr = parseAssignmentExpression(context);
2277 failIfFalse(spreadExpr, "Cannot parse subject of a spread operation");
2278 elem = context.createSpreadExpression(spreadLocation, spreadExpr, start, divot, m_lastTokenEndPosition);
2280 elem = parseAssignmentExpression(context);
2281 failIfFalse(elem, "Cannot parse array literal element");
2282 typename TreeBuilder::ElementList elementList = context.createElementList(elisions, elem);
2283 typename TreeBuilder::ElementList tail = elementList;
2285 while (match(COMMA)) {
2286 next(TreeBuilder::DontBuildStrings);
2289 while (match(COMMA)) {
2294 if (match(CLOSEBRACKET)) {
2295 JSTokenLocation location(tokenLocation());
2296 next(TreeBuilder::DontBuildStrings);
2297 return context.createArray(location, elisions, elementList);
2299 if (UNLIKELY(match(DOTDOTDOT))) {
2300 auto spreadLocation = m_token.m_location;
2301 auto start = m_token.m_startPosition;
2302 auto divot = m_token.m_endPosition;
2304 TreeExpression elem = parseAssignmentExpression(context);
2305 failIfFalse(elem, "Cannot parse subject of a spread operation");
2306 auto spread = context.createSpreadExpression(spreadLocation, elem, start, divot, m_lastTokenEndPosition);
2307 tail = context.createElementList(tail, elisions, spread);
2310 TreeExpression elem = parseAssignmentExpression(context);
2311 failIfFalse(elem, "Cannot parse array literal element");
2312 tail = context.createElementList(tail, elisions, elem);
2315 JSTokenLocation location(tokenLocation());
2316 if (!consume(CLOSEBRACKET)) {
2317 failIfFalse(match(DOTDOTDOT), "Expected either a closing ']' or a ',' following an array element");
2318 semanticFail("The '...' operator should come before a target expression");
2321 m_nonLHSCount = oldNonLHSCount;
2323 return context.createArray(location, elementList);
2326 #if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
2327 template <typename LexerType>
2328 template <class TreeBuilder> typename TreeBuilder::TemplateString Parser<LexerType>::parseTemplateString(TreeBuilder& context, bool isTemplateHead, typename LexerType::RawStringsBuildMode rawStringsBuildMode, bool& elementIsTail)
2330 if (!isTemplateHead) {
2331 matchOrFail(CLOSEBRACE, "Expected a closing '}' following an expression in template literal");
2332 // Re-scan the token to recognize it as Template Element.
2333 m_token.m_type = m_lexer->scanTrailingTemplateString(&m_token, rawStringsBuildMode);
2335 matchOrFail(TEMPLATE, "Expected an template element");
2336 const Identifier* cooked = m_token.m_data.cooked;
2337 const Identifier* raw = m_token.m_data.raw;
2338 elementIsTail = m_token.m_data.isTail;
2339 JSTokenLocation location(tokenLocation());
2341 return context.createTemplateString(location, *cooked, *raw);
2344 template <typename LexerType>
2345 template <class TreeBuilder> typename TreeBuilder::TemplateLiteral Parser<LexerType>::parseTemplateLiteral(TreeBuilder& context, typename LexerType::RawStringsBuildMode rawStringsBuildMode)
2347 JSTokenLocation location(tokenLocation());
2348 bool elementIsTail = false;
2350 auto headTemplateString = parseTemplateString(context, true, rawStringsBuildMode, elementIsTail);
2351 failIfFalse(headTemplateString, "Cannot parse head template element");
2353 typename TreeBuilder::TemplateStringList templateStringList = context.createTemplateStringList(headTemplateString);
2354 typename TreeBuilder::TemplateStringList templateStringTail = templateStringList;
2357 return context.createTemplateLiteral(location, templateStringList);
2359 failIfTrue(match(CLOSEBRACE), "Template literal expression cannot be empty");
2360 TreeExpression expression = parseExpression(context);
2361 failIfFalse(expression, "Cannot parse expression in template literal");
2363 typename TreeBuilder::TemplateExpressionList templateExpressionList = context.createTemplateExpressionList(expression);
2364 typename TreeBuilder::TemplateExpressionList templateExpressionTail = templateExpressionList;
2366 auto templateString = parseTemplateString(context, false, rawStringsBuildMode, elementIsTail);
2367 failIfFalse(templateString, "Cannot parse template element");
2368 templateStringTail = context.createTemplateStringList(templateStringTail, templateString);
2370 while (!elementIsTail) {
2371 failIfTrue(match(CLOSEBRACE), "Template literal expression cannot be empty");
2372 TreeExpression expression = parseExpression(context);
2373 failIfFalse(expression, "Cannot parse expression in template literal");
2375 templateExpressionTail = context.createTemplateExpressionList(templateExpressionTail, expression);
2377 auto templateString = parseTemplateString(context, false, rawStringsBuildMode, elementIsTail);
2378 failIfFalse(templateString, "Cannot parse template element");
2379 templateStringTail = context.createTemplateStringList(templateStringTail, templateString);
2382 return context.createTemplateLiteral(location, templateStringList, templateExpressionList);
2386 template <typename LexerType>
2387 template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePrimaryExpression(TreeBuilder& context)
2389 failIfStackOverflow();
2390 switch (m_token.m_type) {
2392 JSTokenLocation location(tokenLocation());
2393 unsigned functionKeywordStart = tokenStart();
2395 ParserFunctionInfo<TreeBuilder> info;
2396 info.name = &m_vm->propertyNames->nullIdentifier;
2397 failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, FunctionMode, false, ConstructorKind::None, SuperBinding::NotNeeded,
2398 functionKeywordStart, info)), "Cannot parse function expression");
2399 return context.createFunctionExpr(location, info);
2401 #if ENABLE(ES6_CLASS_SYNTAX)
2403 ParserClassInfo<TreeBuilder> info;
2404 return parseClass(context, FunctionNoRequirements, info);
2409 return parseStrictObjectLiteral(context);
2410 return parseObjectLiteral(context);
2412 return parseArrayLiteral(context);
2415 int oldNonLHSCount = m_nonLHSCount;
2416 TreeExpression result = parseExpression(context);
2417 m_nonLHSCount = oldNonLHSCount;
2418 handleProductionOrFail(CLOSEPAREN, ")", "end", "compound expression");
2422 JSTokenLocation location(tokenLocation());
2424 return context.thisExpr(location, m_thisTDZMode);
2427 JSTextPosition start = tokenStartPosition();
2428 const Identifier* ident = m_token.m_data.ident;
2429 JSTokenLocation location(tokenLocation());
2431 currentScope()->useVariable(ident, m_vm->propertyNames->eval == *ident);
2432 m_lastIdentifier = ident;
2433 return context.createResolve(location, ident, start);
2436 const Identifier* ident = m_token.m_data.ident;
2437 JSTokenLocation location(tokenLocation());
2439 return context.createString(location, ident);
2442 double d = m_token.m_data.doubleValue;
2443 JSTokenLocation location(tokenLocation());
2445 return context.createDoubleExpr(location, d);
2448 double d = m_token.m_data.doubleValue;
2449 JSTokenLocation location(tokenLocation());
2451 return context.createIntegerExpr(location, d);
2454 JSTokenLocation location(tokenLocation());
2456 return context.createNull(location);
2459 JSTokenLocation location(tokenLocation());
2461 return context.createBoolean(location, true);
2464 JSTokenLocation location(tokenLocation());
2466 return context.createBoolean(location, false);
2471 const Identifier* pattern;
2472 const Identifier* flags;
2473 if (match(DIVEQUAL))
2474 failIfFalse(m_lexer->scanRegExp(pattern, flags, '='), "Invalid regular expression");
2476 failIfFalse(m_lexer->scanRegExp(pattern, flags), "Invalid regular expression");
2478 JSTextPosition start = tokenStartPosition();
2479 JSTokenLocation location(tokenLocation());
2481 TreeExpression re = context.createRegExp(location, *pattern, *flags, start);
2483 const char* yarrErrorMsg = Yarr::checkSyntax(pattern->string());
2484 regexFail(yarrErrorMsg);
2488 #if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
2490 return parseTemplateLiteral(context, LexerType::RawStringsBuildMode::DontBuildRawStrings);
2493 failDueToUnexpectedToken();
2497 template <typename LexerType>
2498 template <class TreeBuilder> TreeArguments Parser<LexerType>::parseArguments(TreeBuilder& context, SpreadMode mode)
2500 consumeOrFailWithFlags(OPENPAREN, TreeBuilder::DontBuildStrings, "Expected opening '(' at start of argument list");
2501 JSTokenLocation location(tokenLocation());
2502 if (match(CLOSEPAREN)) {
2503 next(TreeBuilder::DontBuildStrings);
2504 return context.createArguments();
2506 if (match(DOTDOTDOT) && mode == AllowSpread) {
2507 JSTokenLocation spreadLocation(tokenLocation());
2508 auto start = m_token.m_startPosition;
2509 auto divot = m_token.m_endPosition;
2511 auto spreadExpr = parseAssignmentExpression(context);
2512 auto end = m_lastTokenEndPosition;
2514 failWithMessage("Cannot parse spread expression");
2515 if (!consume(CLOSEPAREN)) {
2517 semanticFail("Spread operator may only be applied to the last argument passed to a function");
2518 handleProductionOrFail(CLOSEPAREN, ")", "end", "argument list");
2520 auto spread = context.createSpreadExpression(spreadLocation, spreadExpr, start, divot, end);
2521 TreeArgumentsList argList = context.createArgumentsList(location, spread);
2522 return context.createArguments(argList);
2524 TreeExpression firstArg = parseAssignmentExpression(context);
2525 failIfFalse(firstArg, "Cannot parse function argument");
2527 TreeArgumentsList argList = context.createArgumentsList(location, firstArg);
2528 TreeArgumentsList tail = argList;
2529 while (match(COMMA)) {
2530 JSTokenLocation argumentLocation(tokenLocation());
2531 next(TreeBuilder::DontBuildStrings);
2532 TreeExpression arg = parseAssignmentExpression(context);
2533 failIfFalse(arg, "Cannot parse function argument");
2534 tail = context.createArgumentsList(argumentLocation, tail, arg);
2536 semanticFailIfTrue(match(DOTDOTDOT), "The '...' operator should come before the target expression");
2537 handleProductionOrFail(CLOSEPAREN, ")", "end", "argument list");
2538 return context.createArguments(argList);
2541 template <typename LexerType>
2542 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseMemberExpression(TreeBuilder& context)
2544 TreeExpression base = 0;
2545 JSTextPosition expressionStart = tokenStartPosition();
2547 JSTokenLocation startLocation = tokenLocation();
2548 JSTokenLocation location;
2549 while (match(NEW)) {
2554 #if ENABLE(ES6_CLASS_SYNTAX)
2555 bool baseIsSuper = match(SUPER);
2556 semanticFailIfTrue(baseIsSuper && newCount, "Cannot use new with super");
2558 bool baseIsSuper = false;
2562 base = context.superExpr(location);
2564 currentScope()->setNeedsSuperBinding();
2566 base = parsePrimaryExpression(context);
2568 failIfFalse(base, "Cannot parse base expression");
2570 location = tokenLocation();
2571 switch (m_token.m_type) {
2573 m_nonTrivialExpressionCount++;
2574 JSTextPosition expressionEnd = lastTokenEndPosition();
2576 int nonLHSCount = m_nonLHSCount;
2577 int initialAssignments = m_assignmentCount;
2578 TreeExpression property = parseExpression(context);
2579 failIfFalse(property, "Cannot parse subscript expression");
2580 base = context.createBracketAccess(location, base, property, initialAssignments != m_assignmentCount, expressionStart, expressionEnd, tokenEndPosition());
2581 handleProductionOrFail(CLOSEBRACKET, "]", "end", "subscript expression");
2582 m_nonLHSCount = nonLHSCount;
2586 m_nonTrivialExpressionCount++;
2587 int nonLHSCount = m_nonLHSCount;
2590 JSTextPosition expressionEnd = lastTokenEndPosition();
2591 TreeArguments arguments = parseArguments(context, AllowSpread);
2592 failIfFalse(arguments, "Cannot parse call arguments");
2593 base = context.createNewExpr(location, base, arguments, expressionStart, expressionEnd, lastTokenEndPosition());
2595 JSTextPosition expressionEnd = lastTokenEndPosition();
2596 TreeArguments arguments = parseArguments(context, AllowSpread);
2597 failIfFalse(arguments, "Cannot parse call arguments");
2599 currentScope()->setHasDirectSuper();
2600 base = context.makeFunctionCallNode(startLocation, base, arguments, expressionStart, expressionEnd, lastTokenEndPosition());
2602 m_nonLHSCount = nonLHSCount;
2606 m_nonTrivialExpressionCount++;
2607 JSTextPosition expressionEnd = lastTokenEndPosition();
2608 nextExpectIdentifier(LexerFlagsIgnoreReservedWords | TreeBuilder::DontBuildKeywords);
2609 matchOrFail(IDENT, "Expected a property name after '.'");
2610 base = context.createDotAccess(location, base, m_token.m_data.ident, expressionStart, expressionEnd, tokenEndPosition());
2614 #if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
2616 semanticFailIfTrue(baseIsSuper, "Cannot use super as tag for tagged templates");
2617 JSTextPosition expressionEnd = lastTokenEndPosition();
2618 int nonLHSCount = m_nonLHSCount;
2619 typename TreeBuilder::TemplateLiteral templateLiteral = parseTemplateLiteral(context, LexerType::RawStringsBuildMode::BuildRawStrings);
2620 failIfFalse(templateLiteral, "Cannot parse template literal");
2621 base = context.createTaggedTemplate(location, base, templateLiteral, expressionStart, expressionEnd, lastTokenEndPosition());
2622 m_nonLHSCount = nonLHSCount;
2627 goto endMemberExpression;
2629 baseIsSuper = false;
2631 endMemberExpression:
2632 semanticFailIfTrue(baseIsSuper, "Cannot reference super");
2634 base = context.createNewExpr(location, base, expressionStart, lastTokenEndPosition());
2638 static const char* operatorString(bool prefix, unsigned tok)
2642 case AUTOMINUSMINUS:
2643 return prefix ? "prefix-decrement" : "decrement";
2647 return prefix ? "prefix-increment" : "increment";
2650 return "logical-not";
2653 return "bitwise-not";
2664 RELEASE_ASSERT_NOT_REACHED();
2668 template <typename LexerType>
2669 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseUnaryExpression(TreeBuilder& context)
2671 typename TreeBuilder::UnaryExprContext unaryExprContext(context);
2672 AllowInOverride allowInOverride(this);
2673 int tokenStackDepth = 0;
2674 bool modifiesExpr = false;
2675 bool requiresLExpr = false;
2676 unsigned lastOperator = 0;
2677 while (isUnaryOp(m_token.m_type)) {
2679 switch (m_token.m_type) {
2683 case AUTOMINUSMINUS:
2684 semanticFailIfTrue(requiresLExpr, "The ", operatorString(true, lastOperator), " operator requires a reference expression");
2685 modifiesExpr = true;
2686 requiresLExpr = true;
2689 semanticFailIfTrue(requiresLExpr, "The ", operatorString(true, lastOperator), " operator requires a reference expression");
2690 requiresLExpr = true;
2693 semanticFailIfTrue(requiresLExpr, "The ", operatorString(true, lastOperator), " operator requires a reference expression");
2697 lastOperator = m_token.m_type;
2699 context.appendUnaryToken(tokenStackDepth, m_token.m_type, tokenStartPosition());
2701 m_nonTrivialExpressionCount++;
2703 JSTextPosition subExprStart = tokenStartPosition();
2704 ASSERT(subExprStart.offset >= subExprStart.lineStartOffset);
2705 JSTokenLocation location(tokenLocation());
2706 TreeExpression expr = parseMemberExpression(context);
2709 failWithMessage("Cannot parse subexpression of ", operatorString(true, lastOperator), "operator");
2710 failWithMessage("Cannot parse member expression");
2712 bool isEvalOrArguments = false;
2713 if (strictMode() && !m_syntaxAlreadyValidated) {
2714 if (context.isResolve(expr))
2715 isEvalOrArguments = *m_lastIdentifier == m_vm->propertyNames->eval || *m_lastIdentifier == m_vm->propertyNames->arguments;
2717 failIfTrueIfStrict(isEvalOrArguments && modifiesExpr, "Cannot modify '", m_lastIdentifier->impl(), "' in strict mode");
2718 switch (m_token.m_type) {
2720 m_nonTrivialExpressionCount++;
2722 expr = context.makePostfixNode(location, expr, OpPlusPlus, subExprStart, lastTokenEndPosition(), tokenEndPosition());
2723 m_assignmentCount++;
2724 failIfTrueIfStrict(isEvalOrArguments, "Cannot modify '", m_lastIdentifier->impl(), "' in strict mode");
2725 semanticFailIfTrue(requiresLExpr, "The ", operatorString(false, lastOperator), " operator requires a reference expression");
2726 lastOperator = PLUSPLUS;
2730 m_nonTrivialExpressionCount++;
2732 expr = context.makePostfixNode(location, expr, OpMinusMinus, subExprStart, lastTokenEndPosition(), tokenEndPosition());
2733 m_assignmentCount++;
2734 failIfTrueIfStrict(isEvalOrArguments, "'", m_lastIdentifier->impl(), "' cannot be modified in strict mode");
2735 semanticFailIfTrue(requiresLExpr, "The ", operatorString(false, lastOperator), " operator requires a reference expression");
2736 lastOperator = PLUSPLUS;
2743 JSTextPosition end = lastTokenEndPosition();
2745 if (!TreeBuilder::CreatesAST && (m_syntaxAlreadyValidated || !strictMode()))
2748 location = tokenLocation();
2749 location.line = m_lexer->lastLineNumber();
2750 while (tokenStackDepth) {
2751 switch (context.unaryTokenStackLastType(tokenStackDepth)) {
2753 expr = context.createLogicalNot(location, expr);
2756 expr = context.makeBitwiseNotNode(location, expr);
2759 expr = context.makeNegateNode(location, expr);
2762 expr = context.createUnaryPlus(location, expr);
2766 expr = context.makePrefixNode(location, expr, OpPlusPlus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end);
2767 m_assignmentCount++;
2770 case AUTOMINUSMINUS:
2771 expr = context.makePrefixNode(location, expr, OpMinusMinus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end);
2772 m_assignmentCount++;
2775 expr = context.makeTypeOfNode(location, expr);
2778 expr = context.createVoid(location, expr);
2781 failIfTrueIfStrict(context.isResolve(expr), "Cannot delete unqualified property '", m_lastIdentifier->impl(), "' in strict mode");
2782 expr = context.makeDeleteNode(location, expr, context.unaryTokenStackLastStart(tokenStackDepth), end, end);
2785 // If we get here something has gone horribly horribly wrong
2788 subExprStart = context.unaryTokenStackLastStart(tokenStackDepth);
2789 context.unaryTokenStackRemoveLast(tokenStackDepth);
2795 template <typename LexerType> void Parser<LexerType>::printUnexpectedTokenText(WTF::PrintStream& out)
2797 switch (m_token.m_type) {
2799 out.print("Unexpected end of script");
2801 case UNTERMINATED_IDENTIFIER_ESCAPE_ERRORTOK:
2802 case UNTERMINATED_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK:
2803 out.print("Incomplete unicode escape in identifier: '", getToken(), "'");
2805 case UNTERMINATED_MULTILINE_COMMENT_ERRORTOK:
2806 out.print("Unterminated multiline comment");
2808 case UNTERMINATED_NUMERIC_LITERAL_ERRORTOK:
2809 out.print("Unterminated numeric literal '", getToken(), "'");
2811 case UNTERMINATED_STRING_LITERAL_ERRORTOK:
2812 out.print("Unterminated string literal '", getToken(), "'");
2814 case INVALID_IDENTIFIER_ESCAPE_ERRORTOK:
2815 out.print("Invalid escape in identifier: '", getToken(), "'");
2817 case INVALID_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK:
2818 out.print("Invalid unicode escape in identifier: '", getToken(), "'");
2820 case INVALID_NUMERIC_LITERAL_ERRORTOK:
2821 out.print("Invalid numeric literal: '", getToken(), "'");
2823 case INVALID_OCTAL_NUMBER_ERRORTOK:
2824 out.print("Invalid use of octal: '", getToken(), "'");
2826 case INVALID_STRING_LITERAL_ERRORTOK:
2827 out.print("Invalid string literal: '", getToken(), "'");
2830 out.print("Unrecognized token '", getToken(), "'");
2833 out.print("Unexpected string literal ", getToken());
2837 out.print("Unexpected number '", getToken(), "'");
2840 case RESERVED_IF_STRICT:
2841 out.print("Unexpected use of reserved word '", getToken(), "' in strict mode");
2845 out.print("Unexpected use of reserved word '", getToken(), "'");
2848 case INVALID_PRIVATE_NAME_ERRORTOK:
2849 out.print("Invalid private name '", getToken(), "'");
2853 out.print("Unexpected identifier '", getToken(), "'");
2860 if (m_token.m_type & KeywordTokenFlag) {
2861 out.print("Unexpected keyword '", getToken(), "'");
2865 out.print("Unexpected token '", getToken(), "'");
2868 // Instantiate the two flavors of Parser we need instead of putting most of this file in Parser.h
2869 template class Parser<Lexer<LChar>>;
2870 template class Parser<Lexer<UChar>>;