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 scope->setIsLexicalScope();
269 SourceElements* sourceElements = parseSourceElements(context, CheckForStrictMode, StandardFunctionParseType);
270 if (!sourceElements || !consume(EOFTOK)) {
272 parseError = m_errorMessage;
274 parseError = ASCIILiteral("Parser error");
277 IdentifierSet capturedVariables;
278 bool modifiedParameter = false;
279 bool modifiedArguments = false;
280 scope->getCapturedVars(capturedVariables, modifiedParameter, modifiedArguments);
281 VariableEnvironment& varDeclarations = scope->declaredVariables();
282 for (auto& entry : capturedVariables)
283 varDeclarations.markVariableAsCaptured(entry);
285 CodeFeatures features = context.features();
286 if (scope->strictMode())
287 features |= StrictModeFeature;
288 if (scope->shadowsArguments())
289 features |= ShadowsArgumentsFeature;
290 if (modifiedParameter)
291 features |= ModifiedParameterFeature;
292 if (modifiedArguments)
293 features |= ModifiedArgumentsFeature;
294 Vector<RefPtr<UniquedStringImpl>> closedVariables;
295 if (m_parsingBuiltin) {
296 IdentifierSet usedVariables;
297 scope->getUsedVariables(usedVariables);
298 // FIXME: This needs to be changed if we want to allow builtins to use lexical declarations.
299 for (const auto& variable : usedVariables) {
300 Identifier identifier = Identifier::fromUid(m_vm, variable.get());
301 if (scope->hasDeclaredVariable(identifier))
304 if (scope->hasDeclaredParameter(identifier))
307 if (variable == m_vm->propertyNames->arguments.impl())
310 closedVariables.append(variable);
313 if (!capturedVariables.isEmpty()) {
314 for (const auto& capturedVariable : capturedVariables) {
315 if (scope->hasDeclaredVariable(capturedVariable))
318 if (scope->hasDeclaredParameter(capturedVariable))
321 RELEASE_ASSERT_NOT_REACHED();
325 didFinishParsing(sourceElements, context.funcDeclarations(), varDeclarations, features, context.numConstants(), WTF::move(closedVariables));
330 template <typename LexerType>
331 void Parser<LexerType>::didFinishParsing(SourceElements* sourceElements, DeclarationStacks::FunctionStack& funcStack,
332 VariableEnvironment& varDeclarations, CodeFeatures features, int numConstants, const Vector<RefPtr<UniquedStringImpl>>&& closedVariables)
334 m_sourceElements = sourceElements;
335 m_funcDeclarations.swap(funcStack);
336 m_varDeclarations.swap(varDeclarations);
337 m_closedVariables = closedVariables;
338 m_features = features;
339 m_numConstants = numConstants;
342 template <typename LexerType>
343 bool Parser<LexerType>::allowAutomaticSemicolon()
345 return match(CLOSEBRACE) || match(EOFTOK) || m_lexer->prevTerminator();
348 template <typename LexerType>
349 template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseSourceElements(TreeBuilder& context, SourceElementsMode mode, FunctionParseType functionParseType)
351 const unsigned lengthOfUseStrictLiteral = 12; // "use strict".length
352 TreeSourceElements sourceElements = context.createSourceElements();
353 bool seenNonDirective = false;
354 const Identifier* directive = 0;
355 unsigned directiveLiteralLength = 0;
356 auto savePoint = createSavePoint();
357 bool hasSetStrict = false;
359 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
360 if (match(ARROWFUNCTION)) {
361 TreeStatement arrowfunctionStatement = parseArrowFunctionSingleExpressionBody(context, functionParseType);
363 if (arrowfunctionStatement) {
364 context.setEndOffset(arrowfunctionStatement, m_lastTokenEndPosition.offset);
365 context.appendStatement(sourceElements, arrowfunctionStatement);
369 return sourceElements;
372 UNUSED_PARAM(functionParseType);
375 while (TreeStatement statement = parseStatementListItem(context, directive, &directiveLiteralLength)) {
376 if (mode == CheckForStrictMode && !seenNonDirective) {
378 // "use strict" must be the exact literal without escape sequences or line continuation.
379 if (!hasSetStrict && directiveLiteralLength == lengthOfUseStrictLiteral && m_vm->propertyNames->useStrictIdentifier == *directive) {
382 if (!isValidStrictMode()) {
383 if (m_lastFunctionName) {
384 if (m_vm->propertyNames->arguments == *m_lastFunctionName)
385 semanticFail("Cannot name a function 'arguments' in strict mode");
386 if (m_vm->propertyNames->eval == *m_lastFunctionName)
387 semanticFail("Cannot name a function 'eval' in strict mode");
389 if (hasDeclaredVariable(m_vm->propertyNames->arguments))
390 semanticFail("Cannot declare a variable named 'arguments' in strict mode");
391 if (hasDeclaredVariable(m_vm->propertyNames->eval))
392 semanticFail("Cannot declare a variable named 'eval' in strict mode");
393 semanticFailIfFalse(isValidStrictMode(), "Invalid parameters or function name in strict mode");
395 restoreSavePoint(savePoint);
400 seenNonDirective = true;
402 context.appendStatement(sourceElements, statement);
406 return sourceElements;
408 template <typename LexerType>
409 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseStatementListItem(TreeBuilder& context, const Identifier*& directive, unsigned* directiveLiteralLength)
411 // The grammar is documented here:
412 // http://www.ecma-international.org/ecma-262/6.0/index.html#sec-statements
413 DepthManager statementDepth(&m_statementDepth);
415 TreeStatement result = 0;
416 bool shouldSetEndOffset = true;
417 switch (m_token.m_type) {
419 result = parseConstDeclaration(context);
422 bool shouldParseVariableDeclaration = true;
424 SavePoint savePoint = createSavePoint();
426 if (!match(IDENT) && !match(OPENBRACE) && !match(OPENBRACKET))
427 shouldParseVariableDeclaration = false;
428 restoreSavePoint(savePoint);
430 if (shouldParseVariableDeclaration)
431 result = parseVariableDeclaration(context, DeclarationType::LexicalDeclaration);
433 result = parseExpressionOrLabelStatement(context); // Treat this as an IDENT. This is how ::parseStatement() handles IDENT.
437 #if ENABLE(ES6_CLASS_SYNTAX)
439 result = parseClassDeclaration(context);
443 m_statementDepth--; // parseStatement() increments the depth.
444 result = parseStatement(context, directive, directiveLiteralLength);
445 shouldSetEndOffset = false;
449 if (result && shouldSetEndOffset)
450 context.setEndOffset(result, m_lastTokenEndPosition.offset);
455 template <typename LexerType>
456 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseVariableDeclaration(TreeBuilder& context, DeclarationType declarationType)
458 ASSERT(match(VAR) || match(LET));
459 JSTokenLocation location(tokenLocation());
460 int start = tokenLine();
463 TreeDestructuringPattern scratch1 = 0;
464 TreeExpression scratch2 = 0;
465 JSTextPosition scratch3;
466 TreeExpression variableDecls = parseVariableDeclarationList(context, scratch, scratch1, scratch2, scratch3, scratch3, scratch3, VarDeclarationContext, declarationType);
468 failIfFalse(autoSemiColon(), "Expected ';' after var declaration");
470 if (declarationType == DeclarationType::VarDeclaration)
471 return context.createVarStatement(location, variableDecls, start, end);
472 ASSERT(declarationType == DeclarationType::LexicalDeclaration);
473 return context.createLetStatement(location, variableDecls, start, end);
476 template <typename LexerType>
477 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseConstDeclaration(TreeBuilder& context)
479 ASSERT(match(CONSTTOKEN));
480 JSTokenLocation location(tokenLocation());
481 int start = tokenLine();
483 TreeConstDeclList constDecls = parseConstDeclarationList(context);
485 failIfFalse(autoSemiColon(), "Expected ';' after const declaration");
487 return context.createConstStatement(location, constDecls, start, end);
490 template <typename LexerType>
491 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseDoWhileStatement(TreeBuilder& context)
494 int startLine = tokenLine();
496 const Identifier* unused = 0;
498 TreeStatement statement = parseStatement(context, unused);
500 failIfFalse(statement, "Expected a statement following 'do'");
501 int endLine = tokenLine();
502 JSTokenLocation location(tokenLocation());
503 handleProductionOrFail(WHILE, "while", "end", "do-while loop");
504 handleProductionOrFail(OPENPAREN, "(", "start", "do-while loop condition");
505 semanticFailIfTrue(match(CLOSEPAREN), "Must provide an expression as a do-while loop condition");
506 TreeExpression expr = parseExpression(context);
507 failIfFalse(expr, "Unable to parse do-while loop condition");
508 handleProductionOrFail(CLOSEPAREN, ")", "end", "do-while loop condition");
509 if (match(SEMICOLON))
510 next(); // Always performs automatic semicolon insertion.
511 return context.createDoWhileStatement(location, statement, expr, startLine, endLine);
514 template <typename LexerType>
515 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWhileStatement(TreeBuilder& context)
517 ASSERT(match(WHILE));
518 JSTokenLocation location(tokenLocation());
519 int startLine = tokenLine();
522 handleProductionOrFail(OPENPAREN, "(", "start", "while loop condition");
523 semanticFailIfTrue(match(CLOSEPAREN), "Must provide an expression as a while loop condition");
524 TreeExpression expr = parseExpression(context);
525 failIfFalse(expr, "Unable to parse while loop condition");
526 int endLine = tokenLine();
527 handleProductionOrFail(CLOSEPAREN, ")", "end", "while loop condition");
529 const Identifier* unused = 0;
531 TreeStatement statement = parseStatement(context, unused);
533 failIfFalse(statement, "Expected a statement as the body of a while loop");
534 return context.createWhileStatement(location, expr, statement, startLine, endLine);
537 template <typename LexerType>
538 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseVariableDeclarationList(TreeBuilder& context, int& declarations, TreeDestructuringPattern& lastPattern, TreeExpression& lastInitializer, JSTextPosition& identStart, JSTextPosition& initStart, JSTextPosition& initEnd, VarDeclarationListContext declarationListContext, DeclarationType declarationType)
540 ASSERT(declarationType == DeclarationType::LexicalDeclaration || declarationType == DeclarationType::VarDeclaration);
541 TreeExpression head = 0;
542 TreeExpression tail = 0;
543 const Identifier* lastIdent;
544 JSToken lastIdentToken;
547 lastPattern = TreeDestructuringPattern(0);
548 JSTokenLocation location(tokenLocation());
550 TreeExpression node = 0;
552 bool hasInitializer = false;
553 if (match(IDENT) || isLETMaskedAsIDENT()) {
554 failIfTrue(isLETMaskedAsIDENT() && declarationType == DeclarationType::LexicalDeclaration, "Can't use 'let' as an identifier name for a LexicalDeclaration");
555 JSTextPosition varStart = tokenStartPosition();
556 JSTokenLocation varStartLocation(tokenLocation());
557 identStart = varStart;
558 const Identifier* name = m_token.m_data.ident;
560 lastIdentToken = m_token;
562 hasInitializer = match(EQUAL);
563 if (!declareVariable(name, declarationType)) {
564 if (declarationType == DeclarationType::LexicalDeclaration)
565 internalFailWithMessage(false, "Cannot declare a lexical variable twice: '", name->impl(), "'");
566 else if (strictMode())
567 internalFailWithMessage(false, "Cannot declare a variable named ", name->impl(), " in strict mode");
569 if (hasInitializer) {
570 JSTextPosition varDivot = tokenStartPosition() + 1;
571 initStart = tokenStartPosition();
572 next(TreeBuilder::DontBuildStrings); // consume '='
573 TreeExpression initializer = parseAssignmentExpression(context);
574 initEnd = lastTokenEndPosition();
575 lastInitializer = initializer;
576 failIfFalse(initializer, "Expected expression as the intializer for the variable '", name->impl(), "'");
578 node = context.createAssignResolve(location, *name, initializer, varStart, varDivot, lastTokenEndPosition(), AssignmentContext::DeclarationStatement);
580 if (declarationType == DeclarationType::VarDeclaration)
581 node = context.createEmptyVarExpression(varStartLocation, *name);
583 node = context.createEmptyLetExpression(varStartLocation, *name);
587 auto pattern = parseDestructuringPattern(context, declarationType == DeclarationType::VarDeclaration ? DestructureToVariables : DestructureToLexicalVariables, AssignmentContext::DeclarationStatement);
588 failIfFalse(pattern, "Cannot parse this destructuring pattern");
589 hasInitializer = match(EQUAL);
590 failIfTrue(declarationListContext == VarDeclarationContext && !hasInitializer, "Expected an initializer in destructuring variable declaration");
591 lastPattern = pattern;
592 if (hasInitializer) {
593 next(TreeBuilder::DontBuildStrings); // consume '='
594 TreeExpression rhs = parseAssignmentExpression(context);
595 node = context.createDestructuringAssignment(location, pattern, rhs);
596 lastInitializer = rhs;
603 head = context.createCommaExpr(location, head);
604 tail = context.appendToCommaExpr(location, head, head, node);
606 tail = context.appendToCommaExpr(location, head, tail, node);
607 } while (match(COMMA));
609 lastPattern = context.createBindingLocation(lastIdentToken.m_location, *lastIdent, lastIdentToken.m_startPosition, lastIdentToken.m_endPosition, AssignmentContext::DeclarationStatement);
614 template <typename LexerType>
615 template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::createBindingPattern(TreeBuilder& context, DestructuringKind kind, const Identifier& name, int depth, JSToken token, AssignmentContext bindingContext)
617 ASSERT(!name.isNull());
619 ASSERT(name.impl()->isAtomic() || name.impl()->isSymbol());
621 if (kind == DestructureToVariables)
622 failIfFalseIfStrict(declareVariable(&name), "Cannot deconstruct to a variable named '", name.impl(), "' in strict mode");
623 else if (kind == DestructureToLexicalVariables)
624 semanticFailIfFalse(declareVariable(&name, DeclarationType::LexicalDeclaration), "Cannot declare a lexical variable twice: '", name.impl(), "'");
625 else if (kind == DestructureToParameters) {
626 auto bindingResult = declareBoundParameter(&name);
627 if (bindingResult == Scope::StrictBindingFailed && strictMode()) {
628 semanticFailIfTrue(m_vm->propertyNames->arguments == name || m_vm->propertyNames->eval == name, "Cannot destructure to a parameter name '", name.impl(), "' in strict mode");
629 if (m_lastFunctionName && name == *m_lastFunctionName)
630 semanticFail("Cannot destructure to '", name.impl(), "' as it shadows the name of a strict mode function");
631 semanticFailureDueToKeyword("bound parameter name");
632 if (hasDeclaredParameter(name))
633 semanticFail("Cannot destructure to '", name.impl(), "' as it has already been declared");
634 semanticFail("Cannot bind to a parameter named '", name.impl(), "' in strict mode");
636 if (bindingResult == Scope::BindingFailed) {
637 semanticFailureDueToKeyword("bound parameter name");
638 if (hasDeclaredParameter(name))
639 semanticFail("Cannot destructure to '", name.impl(), "' as it has already been declared");
640 semanticFail("Cannot destructure to a parameter named '", name.impl(), "'");
645 if (kind == DestructureToVariables)
646 failIfFalseIfStrict(declareVariable(&name), "Cannot declare a variable named '", name.impl(), "' in strict mode");
647 else if (kind == DestructureToLexicalVariables)
648 semanticFailIfFalse(declareVariable(&name, DeclarationType::LexicalDeclaration), "Cannot declare a lexical variable twice: '", name.impl(), "'");
649 else if (kind == DestructureToParameters) {
650 bool declarationResult = declareParameter(&name);
651 if (!declarationResult && strictMode()) {
652 semanticFailIfTrue(m_vm->propertyNames->arguments == name || m_vm->propertyNames->eval == name, "Cannot destructure to a parameter name '", name.impl(), "' in strict mode");
653 if (m_lastFunctionName && name == *m_lastFunctionName)
654 semanticFail("Cannot declare a parameter named '", name.impl(), "' as it shadows the name of a strict mode function");
655 semanticFailureDueToKeyword("parameter name");
656 if (hasDeclaredParameter(name))
657 semanticFail("Cannot declare a parameter named '", name.impl(), "' in strict mode as it has already been declared");
658 semanticFail("Cannot declare a parameter named '", name.impl(), "' in strict mode");
662 return context.createBindingLocation(token.m_location, name, token.m_startPosition, token.m_endPosition, bindingContext);
665 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
666 template <typename LexerType>
667 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseArrowFunctionSingleExpressionBody(TreeBuilder& context, FunctionParseType parseType)
669 ASSERT(match(ARROWFUNCTION));
671 // When reparsing phase, parseType becomes StandardFunctionParseType even if the function is arrow function.
672 // This condition considers the following situations.
673 // (1): If we are in the reparsing phase, this arrow function is already parsed once, so there is no syntax error.
674 // (2): But if we are not in the reparsing phase, we should check this function is called in the context of the arrow function.
675 if (!m_lexer->isReparsing() && parseType != ArrowFunctionParseType)
676 failDueToUnexpectedToken();
678 JSTokenLocation location(tokenLocation());
679 JSTextPosition start = tokenStartPosition();
680 JSTextPosition end = tokenEndPosition();
684 failIfStackOverflow();
685 TreeExpression expr = parseAssignmentExpression(context);
686 failIfFalse(expr, "Cannot parse the arrow function expression");
688 context.setEndOffset(expr, m_lastTokenEndPosition.offset);
690 failIfFalse(isEndOfArrowFunction(), "Expected a ';', ']', '}', ')', ',', line terminator or EOF following a arrow function statement");
692 end = tokenEndPosition();
694 if (!m_lexer->prevTerminator())
697 return context.createReturnStatement(location, expr, start, end);
701 template <typename LexerType>
702 template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::tryParseDestructuringPatternExpression(TreeBuilder& context, AssignmentContext bindingContext)
704 return parseDestructuringPattern(context, DestructureToExpressions, bindingContext);
707 template <typename LexerType>
708 template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseDestructuringPattern(TreeBuilder& context, DestructuringKind kind, AssignmentContext bindingContext, int depth)
710 failIfStackOverflow();
711 int nonLHSCount = m_nonLHSCount;
712 TreeDestructuringPattern pattern;
713 switch (m_token.m_type) {
715 JSTextPosition divotStart = tokenStartPosition();
716 auto arrayPattern = context.createArrayPattern(m_token.m_location);
719 bool restElementWasFound = false;
722 while (match(COMMA)) {
723 context.appendArrayPatternSkipEntry(arrayPattern, m_token.m_location);
728 if (match(CLOSEBRACKET))
731 if (UNLIKELY(match(DOTDOTDOT))) {
732 JSTokenLocation location = m_token.m_location;
734 auto innerPattern = parseDestructuringPattern(context, kind, bindingContext, depth + 1);
735 if (kind == DestructureToExpressions && !innerPattern)
737 failIfFalse(innerPattern, "Cannot parse this destructuring pattern");
739 failIfTrue(kind != DestructureToExpressions && !context.isBindingNode(innerPattern), "Expected identifier for a rest element destructuring pattern");
741 context.appendArrayPatternRestEntry(arrayPattern, location, innerPattern);
742 restElementWasFound = true;
746 JSTokenLocation location = m_token.m_location;
747 auto innerPattern = parseDestructuringPattern(context, kind, bindingContext, depth + 1);
748 if (kind == DestructureToExpressions && !innerPattern)
750 failIfFalse(innerPattern, "Cannot parse this destructuring pattern");
751 TreeExpression defaultValue = parseDefaultValueForDestructuringPattern(context);
752 failIfTrue(kind == DestructureToParameters && defaultValue, "Default values in destructuring parameters are currently not supported");
753 context.appendArrayPatternEntry(arrayPattern, location, innerPattern, defaultValue);
754 } while (consume(COMMA));
756 if (kind == DestructureToExpressions && !match(CLOSEBRACKET))
758 consumeOrFail(CLOSEBRACKET, restElementWasFound ? "Expected a closing ']' following a rest element destructuring pattern" : "Expected either a closing ']' or a ',' following an element destructuring pattern");
759 context.finishArrayPattern(arrayPattern, divotStart, divotStart, lastTokenEndPosition());
760 pattern = arrayPattern;
764 auto objectPattern = context.createObjectPattern(m_token.m_location);
768 bool wasString = false;
770 if (match(CLOSEBRACE))
773 Identifier propertyName;
774 TreeDestructuringPattern innerPattern = 0;
775 JSTokenLocation location = m_token.m_location;
776 if (match(IDENT) || isLETMaskedAsIDENT()) {
777 failIfTrue(isLETMaskedAsIDENT() && kind == DestructureToLexicalVariables, "Can't use 'let' as an identifier name for a LexicalDeclaration");
778 propertyName = *m_token.m_data.ident;
779 JSToken identifierToken = m_token;
782 innerPattern = parseDestructuringPattern(context, kind, bindingContext, depth + 1);
784 innerPattern = createBindingPattern(context, kind, propertyName, depth, identifierToken, bindingContext);
786 JSTokenType tokenType = m_token.m_type;
787 switch (m_token.m_type) {
790 propertyName = Identifier::from(m_vm, m_token.m_data.doubleValue);
793 propertyName = *m_token.m_data.ident;
797 if (m_token.m_type != RESERVED && m_token.m_type != RESERVED_IF_STRICT && !(m_token.m_type & KeywordTokenFlag)) {
798 if (kind == DestructureToExpressions)
800 failWithMessage("Expected a property name");
802 propertyName = *m_token.m_data.ident;
806 if (!consume(COLON)) {
807 if (kind == DestructureToExpressions)
809 semanticFailIfTrue(tokenType == RESERVED, "Cannot use abbreviated destructuring syntax for reserved name '", propertyName.impl(), "'");
810 semanticFailIfTrue(tokenType == RESERVED_IF_STRICT, "Cannot use abbreviated destructuring syntax for reserved name '", propertyName.impl(), "' in strict mode");
811 semanticFailIfTrue(tokenType & KeywordTokenFlag, "Cannot use abbreviated destructuring syntax for keyword '", propertyName.impl(), "'");
813 failWithMessage("Expected a ':' prior to a named destructuring property");
815 innerPattern = parseDestructuringPattern(context, kind, bindingContext, depth + 1);
817 if (kind == DestructureToExpressions && !innerPattern)
819 failIfFalse(innerPattern, "Cannot parse this destructuring pattern");
820 TreeExpression defaultValue = parseDefaultValueForDestructuringPattern(context);
821 failIfTrue(kind == DestructureToParameters && defaultValue, "Default values in destructuring parameters are currently not supported");
822 context.appendObjectPatternEntry(objectPattern, location, wasString, propertyName, innerPattern, defaultValue);
823 } while (consume(COMMA));
825 if (kind == DestructureToExpressions && !match(CLOSEBRACE))
827 consumeOrFail(CLOSEBRACE, "Expected either a closing '}' or an ',' after a property destructuring pattern");
828 pattern = objectPattern;
833 if (!match(IDENT) && !isLETMaskedAsIDENT()) {
834 if (kind == DestructureToExpressions)
836 semanticFailureDueToKeyword("variable name");
837 failWithMessage("Expected a parameter pattern or a ')' in parameter list");
839 failIfTrue(isLETMaskedAsIDENT() && kind == DestructureToLexicalVariables, "Can't use 'let' as an identifier name for a LexicalDeclaration");
840 pattern = createBindingPattern(context, kind, *m_token.m_data.ident, depth, m_token, bindingContext);
845 m_nonLHSCount = nonLHSCount;
849 template <typename LexerType>
850 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseDefaultValueForDestructuringPattern(TreeBuilder& context)
855 next(TreeBuilder::DontBuildStrings); // consume '='
856 return parseAssignmentExpression(context);
859 template <typename LexerType>
860 template <class TreeBuilder> TreeConstDeclList Parser<LexerType>::parseConstDeclarationList(TreeBuilder& context)
862 failIfTrue(strictMode(), "Const declarations are not supported in strict mode");
863 TreeConstDeclList constDecls = 0;
864 TreeConstDeclList tail = 0;
866 JSTokenLocation location(tokenLocation());
868 failIfFalse(match(IDENT), "Expected an identifier name in const declaration");
869 const Identifier* name = m_token.m_data.ident;
871 bool hasInitializer = match(EQUAL);
872 // FIXME: This should be LexicalVariable when we support proper ES6 const semantics.
873 declareVariable(name, DeclarationType::VarDeclaration, true);
874 TreeExpression initializer = 0;
875 if (hasInitializer) {
876 next(TreeBuilder::DontBuildStrings); // consume '='
877 initializer = parseAssignmentExpression(context);
878 failIfFalse(!!initializer, "Unable to parse initializer");
880 tail = context.appendConstDecl(location, tail, name, initializer);
883 } while (match(COMMA));
887 template <typename LexerType>
888 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseForStatement(TreeBuilder& context)
891 JSTokenLocation location(tokenLocation());
892 int startLine = tokenLine();
894 handleProductionOrFail(OPENPAREN, "(", "start", "for-loop header");
895 int nonLHSCount = m_nonLHSCount;
896 int declarations = 0;
897 JSTextPosition declsStart;
898 JSTextPosition declsEnd;
899 TreeExpression decls = 0;
900 TreeDestructuringPattern pattern = 0;
901 bool isVarDeclaraton = match(VAR);
902 bool isLetDeclaration = match(LET);
904 VariableEnvironment dummySet;
905 VariableEnvironment* lexicalVariables = nullptr;
906 AutoCleanupLexicalScope lexicalScope;
908 auto gatherLexicalVariablesIfNecessary = [&] {
909 if (isLetDeclaration) {
910 ScopeRef scope = lexicalScope.scope();
911 lexicalVariables = &scope->finalizeLexicalEnvironment();
913 lexicalVariables = &dummySet;
916 auto popLexicalScopeIfNecessary = [&] {
917 if (isLetDeclaration)
918 popScope(lexicalScope, TreeBuilder::NeedsFreeVariableInfo);
921 if (isVarDeclaraton || isLetDeclaration) {
923 for (var/let IDENT in expression) statement
924 for (var/let varDeclarationList; expressionOpt; expressionOpt)
926 if (isLetDeclaration) {
927 ScopeRef newScope = pushScope();
928 newScope->setIsLexicalScope();
929 newScope->preventVarDeclarations();
930 lexicalScope.setIsValid(newScope, this);
933 TreeDestructuringPattern forInTarget = 0;
934 TreeExpression forInInitializer = 0;
936 JSTextPosition initStart;
937 JSTextPosition initEnd;
938 decls = parseVariableDeclarationList(context, declarations, forInTarget, forInInitializer, declsStart, initStart, initEnd, ForLoopContext, isVarDeclaraton ? DeclarationType::VarDeclaration : DeclarationType::LexicalDeclaration);
942 // Remainder of a standard for loop is handled identically
943 if (match(SEMICOLON))
944 goto standardForLoop;
946 failIfFalse(declarations == 1, "can only declare a single variable in an enumeration");
947 failIfTrueIfStrict(forInInitializer, "Cannot use initialiser syntax in a strict mode enumeration");
949 if (forInInitializer)
950 failIfFalse(context.isBindingNode(forInTarget), "Cannot use initialiser syntax when binding to a pattern during enumeration");
952 // Handle for-in with var declaration
953 JSTextPosition inLocation = tokenStartPosition();
954 bool isOfEnumeration = false;
955 if (!consume(INTOKEN)) {
956 failIfFalse(match(IDENT) && *m_token.m_data.ident == m_vm->propertyNames->of, "Expected either 'in' or 'of' in enumeration syntax");
957 isOfEnumeration = true;
958 failIfTrue(forInInitializer, "Cannot use initialiser syntax in a for-of enumeration");
961 TreeExpression expr = parseExpression(context);
962 failIfFalse(expr, "Expected expression to enumerate");
963 JSTextPosition exprEnd = lastTokenEndPosition();
965 int endLine = tokenLine();
967 handleProductionOrFail(CLOSEPAREN, ")", "end", (isOfEnumeration ? "for-of header" : "for-in header"));
969 const Identifier* unused = 0;
971 TreeStatement statement = parseStatement(context, unused);
973 failIfFalse(statement, "Expected statement as body of for-", isOfEnumeration ? "of" : "in", " statement");
974 gatherLexicalVariablesIfNecessary();
975 TreeStatement result;
977 result = context.createForOfLoop(location, forInTarget, expr, statement, declsStart, inLocation, exprEnd, startLine, endLine, *lexicalVariables);
979 result = context.createForInLoop(location, forInTarget, expr, statement, declsStart, inLocation, exprEnd, startLine, endLine, *lexicalVariables);
980 popLexicalScopeIfNecessary();
984 if (!match(SEMICOLON)) {
985 if (match(OPENBRACE) || match(OPENBRACKET)) {
986 SavePoint savePoint = createSavePoint();
987 declsStart = tokenStartPosition();
988 pattern = tryParseDestructuringPatternExpression(context, AssignmentContext::DeclarationStatement);
989 declsEnd = lastTokenEndPosition();
990 if (pattern && (match(INTOKEN) || (match(IDENT) && *m_token.m_data.ident == m_vm->propertyNames->of)))
991 goto enumerationLoop;
992 pattern = TreeDestructuringPattern(0);
993 restoreSavePoint(savePoint);
996 declsStart = tokenStartPosition();
997 decls = parseExpression(context);
998 declsEnd = lastTokenEndPosition();
1000 failIfFalse(decls, "Cannot parse for loop declarations");
1003 if (match(SEMICOLON)) {
1005 // Standard for loop
1007 TreeExpression condition = 0;
1009 if (!match(SEMICOLON)) {
1010 condition = parseExpression(context);
1011 failIfFalse(condition, "Cannot parse for loop condition expression");
1013 consumeOrFail(SEMICOLON, "Expected a ';' after the for loop condition expression");
1015 TreeExpression increment = 0;
1016 if (!match(CLOSEPAREN)) {
1017 increment = parseExpression(context);
1018 failIfFalse(increment, "Cannot parse for loop iteration expression");
1020 int endLine = tokenLine();
1021 handleProductionOrFail(CLOSEPAREN, ")", "end", "for-loop header");
1022 const Identifier* unused = 0;
1024 TreeStatement statement = parseStatement(context, unused);
1026 failIfFalse(statement, "Expected a statement as the body of a for loop");
1027 gatherLexicalVariablesIfNecessary();
1028 TreeStatement result = context.createForLoop(location, decls, condition, increment, statement, startLine, endLine, *lexicalVariables);
1029 popLexicalScopeIfNecessary();
1033 // For-in and For-of loop
1035 failIfFalse(nonLHSCount == m_nonLHSCount, "Expected a reference on the left hand side of an enumeration statement");
1036 bool isOfEnumeration = false;
1037 if (!consume(INTOKEN)) {
1038 failIfFalse(match(IDENT) && *m_token.m_data.ident == m_vm->propertyNames->of, "Expected either 'in' or 'of' in enumeration syntax");
1039 isOfEnumeration = true;
1042 TreeExpression expr = parseExpression(context);
1043 failIfFalse(expr, "Cannot parse subject for-", isOfEnumeration ? "of" : "in", " statement");
1044 JSTextPosition exprEnd = lastTokenEndPosition();
1045 int endLine = tokenLine();
1047 handleProductionOrFail(CLOSEPAREN, ")", "end", (isOfEnumeration ? "for-of header" : "for-in header"));
1048 const Identifier* unused = 0;
1050 TreeStatement statement = parseStatement(context, unused);
1052 failIfFalse(statement, "Expected a statement as the body of a for-", isOfEnumeration ? "of" : "in", "loop");
1053 gatherLexicalVariablesIfNecessary();
1054 TreeStatement result;
1057 if (isOfEnumeration)
1058 result = context.createForOfLoop(location, pattern, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
1060 result = context.createForInLoop(location, pattern, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
1062 popLexicalScopeIfNecessary();
1065 if (isOfEnumeration)
1066 result = context.createForOfLoop(location, decls, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
1068 result = context.createForInLoop(location, decls, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
1069 popLexicalScopeIfNecessary();
1073 template <typename LexerType>
1074 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBreakStatement(TreeBuilder& context)
1076 ASSERT(match(BREAK));
1077 JSTokenLocation location(tokenLocation());
1078 JSTextPosition start = tokenStartPosition();
1079 JSTextPosition end = tokenEndPosition();
1082 if (autoSemiColon()) {
1083 semanticFailIfFalse(breakIsValid(), "'break' is only valid inside a switch or loop statement");
1084 return context.createBreakStatement(location, &m_vm->propertyNames->nullIdentifier, start, end);
1086 failIfFalse(match(IDENT) || isLETMaskedAsIDENT(), "Expected an identifier as the target for a break statement");
1087 const Identifier* ident = m_token.m_data.ident;
1088 semanticFailIfFalse(getLabel(ident), "Cannot use the undeclared label '", ident->impl(), "'");
1089 end = tokenEndPosition();
1091 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted break statement");
1092 return context.createBreakStatement(location, ident, start, end);
1095 template <typename LexerType>
1096 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseContinueStatement(TreeBuilder& context)
1098 ASSERT(match(CONTINUE));
1099 JSTokenLocation location(tokenLocation());
1100 JSTextPosition start = tokenStartPosition();
1101 JSTextPosition end = tokenEndPosition();
1104 if (autoSemiColon()) {
1105 semanticFailIfFalse(continueIsValid(), "'continue' is only valid inside a loop statement");
1106 return context.createContinueStatement(location, &m_vm->propertyNames->nullIdentifier, start, end);
1108 failIfFalse(match(IDENT) || isLETMaskedAsIDENT(), "Expected an identifier as the target for a continue statement");
1109 const Identifier* ident = m_token.m_data.ident;
1110 ScopeLabelInfo* label = getLabel(ident);
1111 semanticFailIfFalse(label, "Cannot use the undeclared label '", ident->impl(), "'");
1112 semanticFailIfFalse(label->isLoop, "Cannot continue to the label '", ident->impl(), "' as it is not targeting a loop");
1113 end = tokenEndPosition();
1115 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted continue statement");
1116 return context.createContinueStatement(location, ident, start, end);
1119 template <typename LexerType>
1120 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseReturnStatement(TreeBuilder& context)
1122 ASSERT(match(RETURN));
1123 JSTokenLocation location(tokenLocation());
1124 semanticFailIfFalse(currentScope()->isFunction(), "Return statements are only valid inside functions");
1125 JSTextPosition start = tokenStartPosition();
1126 JSTextPosition end = tokenEndPosition();
1128 // We do the auto semicolon check before attempting to parse expression
1129 // as we need to ensure the a line break after the return correctly terminates
1131 if (match(SEMICOLON))
1132 end = tokenEndPosition();
1134 if (autoSemiColon())
1135 return context.createReturnStatement(location, 0, start, end);
1136 TreeExpression expr = parseExpression(context);
1137 failIfFalse(expr, "Cannot parse the return expression");
1138 end = lastTokenEndPosition();
1139 if (match(SEMICOLON))
1140 end = tokenEndPosition();
1141 if (!autoSemiColon())
1142 failWithMessage("Expected a ';' following a return statement");
1143 return context.createReturnStatement(location, expr, start, end);
1146 template <typename LexerType>
1147 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseThrowStatement(TreeBuilder& context)
1149 ASSERT(match(THROW));
1150 JSTokenLocation location(tokenLocation());
1151 JSTextPosition start = tokenStartPosition();
1153 failIfTrue(match(SEMICOLON), "Expected expression after 'throw'");
1154 semanticFailIfTrue(autoSemiColon(), "Cannot have a newline after 'throw'");
1156 TreeExpression expr = parseExpression(context);
1157 failIfFalse(expr, "Cannot parse expression for throw statement");
1158 JSTextPosition end = lastTokenEndPosition();
1159 failIfFalse(autoSemiColon(), "Expected a ';' after a throw statement");
1161 return context.createThrowStatement(location, expr, start, end);
1164 template <typename LexerType>
1165 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWithStatement(TreeBuilder& context)
1167 ASSERT(match(WITH));
1168 JSTokenLocation location(tokenLocation());
1169 semanticFailIfTrue(strictMode(), "'with' statements are not valid in strict mode");
1170 currentScope()->setNeedsFullActivation();
1171 int startLine = tokenLine();
1174 handleProductionOrFail(OPENPAREN, "(", "start", "subject of a 'with' statement");
1175 int start = tokenStart();
1176 TreeExpression expr = parseExpression(context);
1177 failIfFalse(expr, "Cannot parse 'with' subject expression");
1178 JSTextPosition end = lastTokenEndPosition();
1179 int endLine = tokenLine();
1180 handleProductionOrFail(CLOSEPAREN, ")", "start", "subject of a 'with' statement");
1181 const Identifier* unused = 0;
1182 TreeStatement statement = parseStatement(context, unused);
1183 failIfFalse(statement, "A 'with' statement must have a body");
1185 return context.createWithStatement(location, expr, statement, start, end, startLine, endLine);
1188 template <typename LexerType>
1189 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseSwitchStatement(TreeBuilder& context)
1191 ASSERT(match(SWITCH));
1192 JSTokenLocation location(tokenLocation());
1193 int startLine = tokenLine();
1195 handleProductionOrFail(OPENPAREN, "(", "start", "subject of a 'switch'");
1196 TreeExpression expr = parseExpression(context);
1197 failIfFalse(expr, "Cannot parse switch subject expression");
1198 int endLine = tokenLine();
1200 handleProductionOrFail(CLOSEPAREN, ")", "end", "subject of a 'switch'");
1201 handleProductionOrFail(OPENBRACE, "{", "start", "body of a 'switch'");
1202 AutoPopScopeRef lexicalScope(this, pushScope());
1203 lexicalScope->setIsLexicalScope();
1204 lexicalScope->preventVarDeclarations();
1206 TreeClauseList firstClauses = parseSwitchClauses(context);
1209 TreeClause defaultClause = parseSwitchDefaultClause(context);
1212 TreeClauseList secondClauses = parseSwitchClauses(context);
1215 handleProductionOrFail(CLOSEBRACE, "}", "end", "body of a 'switch'");
1217 TreeStatement result = context.createSwitchStatement(location, expr, firstClauses, defaultClause, secondClauses, startLine, endLine, lexicalScope->finalizeLexicalEnvironment());
1218 popScope(lexicalScope, TreeBuilder::NeedsFreeVariableInfo);
1222 template <typename LexerType>
1223 template <class TreeBuilder> TreeClauseList Parser<LexerType>::parseSwitchClauses(TreeBuilder& context)
1227 unsigned startOffset = tokenStart();
1229 TreeExpression condition = parseExpression(context);
1230 failIfFalse(condition, "Cannot parse switch clause");
1231 consumeOrFail(COLON, "Expected a ':' after switch clause expression");
1232 TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode, StandardFunctionParseType);
1233 failIfFalse(statements, "Cannot parse the body of a switch clause");
1234 TreeClause clause = context.createClause(condition, statements);
1235 context.setStartOffset(clause, startOffset);
1236 TreeClauseList clauseList = context.createClauseList(clause);
1237 TreeClauseList tail = clauseList;
1239 while (match(CASE)) {
1240 startOffset = tokenStart();
1242 TreeExpression condition = parseExpression(context);
1243 failIfFalse(condition, "Cannot parse switch case expression");
1244 consumeOrFail(COLON, "Expected a ':' after switch clause expression");
1245 TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode, StandardFunctionParseType);
1246 failIfFalse(statements, "Cannot parse the body of a switch clause");
1247 clause = context.createClause(condition, statements);
1248 context.setStartOffset(clause, startOffset);
1249 tail = context.createClauseList(tail, clause);
1254 template <typename LexerType>
1255 template <class TreeBuilder> TreeClause Parser<LexerType>::parseSwitchDefaultClause(TreeBuilder& context)
1257 if (!match(DEFAULT))
1259 unsigned startOffset = tokenStart();
1261 consumeOrFail(COLON, "Expected a ':' after switch default clause");
1262 TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode, StandardFunctionParseType);
1263 failIfFalse(statements, "Cannot parse the body of a switch default clause");
1264 TreeClause result = context.createClause(0, statements);
1265 context.setStartOffset(result, startOffset);
1269 template <typename LexerType>
1270 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseTryStatement(TreeBuilder& context)
1273 JSTokenLocation location(tokenLocation());
1274 TreeStatement tryBlock = 0;
1275 const Identifier* ident = &m_vm->propertyNames->nullIdentifier;
1276 TreeStatement catchBlock = 0;
1277 TreeStatement finallyBlock = 0;
1278 int firstLine = tokenLine();
1280 matchOrFail(OPENBRACE, "Expected a block statement as body of a try statement");
1282 tryBlock = parseBlockStatement(context);
1283 failIfFalse(tryBlock, "Cannot parse the body of try block");
1284 int lastLine = m_lastTokenEndPosition.line;
1287 currentScope()->setNeedsFullActivation();
1290 handleProductionOrFail(OPENPAREN, "(", "start", "'catch' target");
1291 if (!(match(IDENT) || isLETMaskedAsIDENT())) {
1292 semanticFailureDueToKeyword("catch variable name");
1293 failWithMessage("Expected identifier name as catch target");
1295 ident = m_token.m_data.ident;
1297 AutoPopScopeRef catchScope(this, pushScope());
1298 failIfFalseIfStrict(declareVariable(ident), "Cannot declare a catch variable named '", ident->impl(), "' in strict mode");
1299 catchScope->preventAllVariableDeclarations();
1300 handleProductionOrFail(CLOSEPAREN, ")", "end", "'catch' target");
1301 matchOrFail(OPENBRACE, "Expected exception handler to be a block statement");
1302 catchBlock = parseBlockStatement(context);
1303 failIfFalse(catchBlock, "Unable to parse 'catch' block");
1304 popScope(catchScope, TreeBuilder::NeedsFreeVariableInfo);
1307 if (match(FINALLY)) {
1309 matchOrFail(OPENBRACE, "Expected block statement for finally body");
1310 finallyBlock = parseBlockStatement(context);
1311 failIfFalse(finallyBlock, "Cannot parse finally body");
1313 failIfFalse(catchBlock || finallyBlock, "Try statements must have at least a catch or finally block");
1314 return context.createTryStatement(location, tryBlock, ident, catchBlock, finallyBlock, firstLine, lastLine);
1317 template <typename LexerType>
1318 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseDebuggerStatement(TreeBuilder& context)
1320 ASSERT(match(DEBUGGER));
1321 JSTokenLocation location(tokenLocation());
1322 int startLine = tokenLine();
1323 int endLine = startLine;
1325 if (match(SEMICOLON))
1326 startLine = tokenLine();
1327 failIfFalse(autoSemiColon(), "Debugger keyword must be followed by a ';'");
1328 return context.createDebugger(location, startLine, endLine);
1331 template <typename LexerType>
1332 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBlockStatement(TreeBuilder& context)
1334 ASSERT(match(OPENBRACE));
1336 // We should treat the first block statement of the function (the body of the function) as the lexical
1337 // scope of the function itself, and not the lexical scope of a 'block' statement within the function.
1338 AutoCleanupLexicalScope lexicalScope;
1339 bool shouldPushLexicalScope = m_statementDepth > 0;
1340 if (shouldPushLexicalScope) {
1341 ScopeRef newScope = pushScope();
1342 newScope->setIsLexicalScope();
1343 newScope->preventVarDeclarations();
1344 lexicalScope.setIsValid(newScope, this);
1346 JSTokenLocation location(tokenLocation());
1347 int startOffset = m_token.m_data.offset;
1348 int start = tokenLine();
1349 VariableEnvironment emptyEnvironment;
1351 if (match(CLOSEBRACE)) {
1352 int endOffset = m_token.m_data.offset;
1354 TreeStatement result = context.createBlockStatement(location, 0, start, m_lastTokenEndPosition.line, shouldPushLexicalScope ? currentScope()->finalizeLexicalEnvironment() : emptyEnvironment);
1355 context.setStartOffset(result, startOffset);
1356 context.setEndOffset(result, endOffset);
1357 if (shouldPushLexicalScope)
1358 popScope(lexicalScope, TreeBuilder::NeedsFreeVariableInfo);
1361 TreeSourceElements subtree = parseSourceElements(context, DontCheckForStrictMode, StandardFunctionParseType);
1362 failIfFalse(subtree, "Cannot parse the body of the block statement");
1363 matchOrFail(CLOSEBRACE, "Expected a closing '}' at the end of a block statement");
1364 int endOffset = m_token.m_data.offset;
1366 TreeStatement result = context.createBlockStatement(location, subtree, start, m_lastTokenEndPosition.line, shouldPushLexicalScope ? currentScope()->finalizeLexicalEnvironment() : emptyEnvironment);
1367 context.setStartOffset(result, startOffset);
1368 context.setEndOffset(result, endOffset);
1369 if (shouldPushLexicalScope)
1370 popScope(lexicalScope, TreeBuilder::NeedsFreeVariableInfo);
1375 template <typename LexerType>
1376 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseStatement(TreeBuilder& context, const Identifier*& directive, unsigned* directiveLiteralLength)
1378 DepthManager statementDepth(&m_statementDepth);
1381 int nonTrivialExpressionCount = 0;
1382 failIfStackOverflow();
1383 TreeStatement result = 0;
1384 bool shouldSetEndOffset = true;
1386 switch (m_token.m_type) {
1388 result = parseBlockStatement(context);
1389 shouldSetEndOffset = false;
1392 result = parseVariableDeclaration(context, DeclarationType::VarDeclaration);
1395 failIfFalseIfStrict(m_statementDepth == 1, "Strict mode does not allow function declarations in a lexically nested statement");
1396 result = parseFunctionDeclaration(context);
1399 JSTokenLocation location(tokenLocation());
1401 result = context.createEmptyStatement(location);
1405 result = parseIfStatement(context);
1408 result = parseDoWhileStatement(context);
1411 result = parseWhileStatement(context);
1414 result = parseForStatement(context);
1417 result = parseContinueStatement(context);
1420 result = parseBreakStatement(context);
1423 result = parseReturnStatement(context);
1426 result = parseWithStatement(context);
1429 result = parseSwitchStatement(context);
1432 result = parseThrowStatement(context);
1435 result = parseTryStatement(context);
1438 result = parseDebuggerStatement(context);
1444 // These tokens imply the end of a set of source elements
1447 result = parseExpressionOrLabelStatement(context);
1450 directive = m_token.m_data.ident;
1451 if (directiveLiteralLength)
1452 *directiveLiteralLength = m_token.m_location.endOffset - m_token.m_location.startOffset;
1453 nonTrivialExpressionCount = m_nonTrivialExpressionCount;
1456 TreeStatement exprStatement = parseExpressionStatement(context);
1457 if (directive && nonTrivialExpressionCount != m_nonTrivialExpressionCount)
1459 result = exprStatement;
1463 if (result && shouldSetEndOffset)
1464 context.setEndOffset(result, m_lastTokenEndPosition.offset);
1468 template <typename LexerType>
1469 template <class TreeBuilder> TreeFormalParameterList Parser<LexerType>::parseFormalParameters(TreeBuilder& context)
1471 auto parameter = parseDestructuringPattern(context, DestructureToParameters);
1472 failIfFalse(parameter, "Cannot parse parameter pattern");
1473 TreeFormalParameterList list = context.createFormalParameterList(parameter);
1474 TreeFormalParameterList tail = list;
1475 while (consume(COMMA)) {
1476 parameter = parseDestructuringPattern(context, DestructureToParameters);
1477 failIfFalse(parameter, "Cannot parse parameter pattern");
1478 tail = context.createFormalParameterList(tail, parameter);
1483 template <typename LexerType>
1484 template <class TreeBuilder> TreeFunctionBody Parser<LexerType>::parseFunctionBody(
1485 TreeBuilder& context, int functionKeywordStart, int functionNameStart,
1486 int parametersStart, ConstructorKind constructorKind, FunctionParseType parseType)
1488 JSTokenLocation startLocation(tokenLocation());
1489 unsigned startColumn = tokenColumn();
1491 if (parseType == StandardFunctionParseType) {
1493 if (match(CLOSEBRACE)) {
1494 unsigned endColumn = tokenColumn();
1495 return context.createFunctionBody(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind);
1499 DepthManager statementDepth(&m_statementDepth);
1500 m_statementDepth = 0;
1501 typename TreeBuilder::FunctionBodyBuilder bodyBuilder(const_cast<VM*>(m_vm), m_lexer.get());
1502 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
1503 failIfFalse(parseSourceElements(bodyBuilder, CheckForStrictMode, parseType), parseType == StandardFunctionParseType ? "Cannot parse body of this function" : "Cannot parse body of this arrow function");
1505 failIfFalse(parseSourceElements(bodyBuilder, CheckForStrictMode, StandardFunctionParseType), "Cannot parse body of this function");
1507 unsigned endColumn = tokenColumn();
1508 return context.createFunctionBody(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind);
1511 static const char* stringForFunctionMode(FunctionParseMode mode)
1522 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
1523 case ArrowFunctionMode:
1524 return "arrow function";
1527 RELEASE_ASSERT_NOT_REACHED();
1531 template <typename LexerType> template <class TreeBuilder> int Parser<LexerType>::parseFunctionParameters(TreeBuilder& context, FunctionParseMode mode, ParserFunctionInfo<TreeBuilder>& info)
1533 int parametersStart = m_token.m_location.startOffset;
1535 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
1536 if (mode == ArrowFunctionMode) {
1537 if (!match(IDENT) && !match(OPENPAREN)) {
1538 semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
1539 failWithMessage("Expected an arrow function input parameter");
1541 if (match(OPENPAREN)) {
1544 if (!match(CLOSEPAREN)) {
1545 info.parameters = parseFormalParameters(context);
1546 failIfFalse(info.parameters, "Cannot parse parameters for this ", stringForFunctionMode(mode));
1549 consumeOrFail(CLOSEPAREN, "Expected a ')' or a ',' after a parameter declaration");
1551 auto parameter = parseDestructuringPattern(context, DestructureToParameters);
1552 failIfFalse(parameter, "Cannot parse parameter pattern");
1553 info.parameters = context.createFormalParameterList(parameter);
1554 failIfFalse(info.parameters, "Cannot parse parameters for this ", stringForFunctionMode(mode));
1558 return parametersStart;
1562 if (!consume(OPENPAREN)) {
1563 semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
1564 failWithMessage("Expected an opening '(' before a ", stringForFunctionMode(mode), "'s parameter list");
1567 if (mode == GetterMode)
1568 consumeOrFail(CLOSEPAREN, "getter functions must have no parameters");
1569 else if (mode == SetterMode) {
1570 failIfTrue(match(CLOSEPAREN), "setter functions must have one parameter");
1571 auto parameter = parseDestructuringPattern(context, DestructureToParameters);
1572 failIfFalse(parameter, "setter functions must have one parameter");
1573 info.parameters = context.createFormalParameterList(parameter);
1574 failIfTrue(match(COMMA), "setter functions must have one parameter");
1575 consumeOrFail(CLOSEPAREN, "Expected a ')' after a parameter declaration");
1577 if (!match(CLOSEPAREN)) {
1578 info.parameters = parseFormalParameters(context);
1579 failIfFalse(info.parameters, "Cannot parse parameters for this ", stringForFunctionMode(mode));
1581 consumeOrFail(CLOSEPAREN, "Expected a ')' or a ',' after a parameter declaration");
1584 return parametersStart;
1587 template <typename LexerType>
1588 template <class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuilder& context, FunctionRequirements requirements, FunctionParseMode mode, bool nameIsInContainingScope, ConstructorKind constructorKind, SuperBinding expectedSuperBinding, int functionKeywordStart, ParserFunctionInfo<TreeBuilder>& info, FunctionParseType parseType)
1590 AutoPopScopeRef functionScope(this, pushScope());
1591 functionScope->setIsFunction();
1592 int functionNameStart = m_token.m_location.startOffset;
1593 const Identifier* lastFunctionName = m_lastFunctionName;
1594 m_lastFunctionName = nullptr;
1595 int parametersStart;
1597 switch (parseType) {
1598 case StandardFunctionParseType: {
1599 if (match(IDENT) || isLETMaskedAsIDENT()) {
1600 info.name = m_token.m_data.ident;
1601 m_lastFunctionName = info.name;
1603 if (!nameIsInContainingScope)
1604 failIfFalseIfStrict(functionScope->declareVariable(info.name), "'", info.name->impl(), "' is not a valid ", stringForFunctionMode(mode), " name in strict mode");
1605 } else if (requirements == FunctionNeedsName) {
1606 if (match(OPENPAREN) && mode == FunctionMode)
1607 semanticFail("Function statements must have a name");
1608 semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
1609 failDueToUnexpectedToken();
1613 parametersStart = parseFunctionParameters(context, mode, info);
1616 matchOrFail(OPENBRACE, "Expected an opening '{' at the start of a ", stringForFunctionMode(mode), " body");
1618 // BytecodeGenerator emits code to throw TypeError when a class constructor is "call"ed.
1619 // Set ConstructorKind to None for non-constructor methods of classes.
1621 if (m_defaultConstructorKind != ConstructorKind::None) {
1622 constructorKind = m_defaultConstructorKind;
1623 expectedSuperBinding = m_defaultConstructorKind == ConstructorKind::Derived ? SuperBinding::Needed : SuperBinding::NotNeeded;
1626 info.startFunctionOffset = m_token.m_data.offset;
1630 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
1631 case ArrowFunctionParseType: {
1632 parametersStart = parseFunctionParameters(context, ArrowFunctionMode, info);
1635 matchOrFail(ARROWFUNCTION, "Expected a '=>' after arrow function parameter declaration");
1637 if (m_lexer->prevTerminator())
1638 failDueToUnexpectedToken();
1640 ASSERT(constructorKind == ConstructorKind::None);
1642 info.arrowFunctionOffset = m_token.m_data.offset;
1643 // Check if arrow body start with {. If it true it mean that arrow function is Fat arrow function
1644 // and we need use common approach to parse function body
1645 SavePoint savePoint = createSavePoint();
1648 info.functionBodyType = match(OPENBRACE) ? ArrowFunctionBodyBlock : ArrowFunctionBodyExpression;
1649 info.startFunctionOffset = (info.functionBodyType == ArrowFunctionBodyBlock) ? m_token.m_data.offset : info.arrowFunctionOffset;
1651 restoreSavePoint(savePoint);
1658 bool isClassConstructor = constructorKind != ConstructorKind::None;
1660 info.bodyStartLine = tokenLine();
1661 info.bodyStartColumn = m_token.m_data.offset - m_token.m_data.lineStartOffset;
1662 JSTokenLocation startLocation(tokenLocation());
1664 // If we know about this function already, we can use the cached info and skip the parser to the end of the function.
1665 if (const SourceProviderCacheItem* cachedInfo = TreeBuilder::CanUseFunctionCache ? findCachedFunctionInfo(info.startFunctionOffset) : 0) {
1666 // If we're in a strict context, the cached function info must say it was strict too.
1667 ASSERT(!strictMode() || cachedInfo->strictMode);
1668 JSTokenLocation endLocation;
1670 endLocation.line = cachedInfo->lastTockenLine;
1671 endLocation.startOffset = cachedInfo->lastTockenStartOffset;
1672 endLocation.lineStartOffset = cachedInfo->lastTockenLineStartOffset;
1674 bool endColumnIsOnStartLine = (endLocation.line == info.bodyStartLine);
1675 ASSERT(endLocation.startOffset >= endLocation.lineStartOffset);
1676 unsigned bodyEndColumn = endColumnIsOnStartLine ?
1677 endLocation.startOffset - m_token.m_data.lineStartOffset :
1678 endLocation.startOffset - endLocation.lineStartOffset;
1679 unsigned currentLineStartOffset = m_token.m_location.lineStartOffset;
1681 info.body = context.createFunctionBody(
1682 startLocation, endLocation, info.bodyStartColumn, bodyEndColumn,
1683 functionKeywordStart, functionNameStart, parametersStart,
1684 cachedInfo->strictMode, constructorKind);
1686 functionScope->restoreFromSourceProviderCache(cachedInfo);
1687 popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo);
1689 m_token = cachedInfo->endFunctionToken();
1691 if (endColumnIsOnStartLine)
1692 m_token.m_location.lineStartOffset = currentLineStartOffset;
1694 m_lexer->setOffset(m_token.m_location.endOffset, m_token.m_location.lineStartOffset);
1695 m_lexer->setLineNumber(m_token.m_location.line);
1696 info.endFunctionOffset = cachedInfo->endFunctionOffset;
1697 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
1698 if (parseType == ArrowFunctionParseType)
1699 info.functionBodyType = cachedInfo->isBodyArrowExpression ? ArrowFunctionBodyExpression : ArrowFunctionBodyBlock;
1701 info.functionBodyType = StandardFunctionBodyBlock;
1703 switch (info.functionBodyType) {
1704 case ArrowFunctionBodyExpression:
1706 context.setEndOffset(info.body, m_lexer->currentOffset());
1708 case ArrowFunctionBodyBlock:
1709 case StandardFunctionBodyBlock:
1710 context.setEndOffset(info.body, m_lexer->currentOffset());
1715 context.setEndOffset(info.body, m_lexer->currentOffset());
1718 info.bodyEndLine = m_lastTokenEndPosition.line;
1722 m_lastFunctionName = lastFunctionName;
1723 ParserState oldState = saveState();
1725 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
1726 switch (info.functionBodyType) {
1727 case ArrowFunctionBodyBlock: {
1728 // Consume => in case of arrow function block e.g. x => { return x; }
1731 info.bodyStartLine = tokenLine();
1732 info.bodyStartColumn = m_token.m_data.offset - m_token.m_data.lineStartOffset;
1734 info.body = parseFunctionBody(context, functionKeywordStart, functionNameStart, parametersStart, constructorKind, StandardFunctionParseType);
1737 case StandardFunctionBodyBlock:
1738 case ArrowFunctionBodyExpression : {
1739 info.body = parseFunctionBody(context, functionKeywordStart, functionNameStart, parametersStart, constructorKind, parseType);
1744 info.body = parseFunctionBody(context, functionKeywordStart, functionNameStart, parametersStart, constructorKind, StandardFunctionParseType);
1747 restoreState(oldState);
1748 failIfFalse(info.body, "Cannot parse the body of this ", stringForFunctionMode(mode));
1749 context.setEndOffset(info.body, m_lexer->currentOffset());
1750 if (functionScope->strictMode() && info.name) {
1751 RELEASE_ASSERT(mode == FunctionMode || mode == MethodMode);
1752 semanticFailIfTrue(m_vm->propertyNames->arguments == *info.name, "'", info.name->impl(), "' is not a valid function name in strict mode");
1753 semanticFailIfTrue(m_vm->propertyNames->eval == *info.name, "'", info.name->impl(), "' is not a valid function name in strict mode");
1755 if (functionScope->hasDirectSuper()) {
1756 semanticFailIfTrue(!isClassConstructor, "Cannot call super() outside of a class constructor");
1757 semanticFailIfTrue(constructorKind != ConstructorKind::Derived, "Cannot call super() in a base class constructor");
1759 if (functionScope->needsSuperBinding())
1760 semanticFailIfTrue(expectedSuperBinding == SuperBinding::NotNeeded, "super can only be used in a method of a derived class");
1762 JSTokenLocation location = JSTokenLocation(m_token.m_location);
1763 info.endFunctionOffset = m_token.m_data.offset;
1765 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
1766 if (info.functionBodyType == ArrowFunctionBodyExpression) {
1767 location = locationBeforeLastToken();
1768 info.endFunctionOffset = location.endOffset;
1772 // Cache the tokenizer state and the function scope the first time the function is parsed.
1773 // Any future reparsing can then skip the function.
1774 static const int minimumFunctionLengthToCache = 16;
1775 std::unique_ptr<SourceProviderCacheItem> newInfo;
1776 int functionLength = info.endFunctionOffset - info.startFunctionOffset;
1777 if (TreeBuilder::CanUseFunctionCache && m_functionCache && functionLength > minimumFunctionLengthToCache) {
1778 SourceProviderCacheItemCreationParameters parameters;
1779 parameters.endFunctionOffset = info.endFunctionOffset;
1780 parameters.functionNameStart = functionNameStart;
1781 parameters.lastTockenLine = location.line;
1782 parameters.lastTockenStartOffset = location.startOffset;
1783 parameters.lastTockenEndOffset = location.endOffset;
1784 parameters.lastTockenLineStartOffset = location.lineStartOffset;
1785 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
1786 if (info.functionBodyType == ArrowFunctionBodyExpression) {
1787 parameters.isBodyArrowExpression = true;
1788 parameters.tokenType = m_token.m_type;
1791 functionScope->fillParametersForSourceProviderCache(parameters);
1792 newInfo = SourceProviderCacheItem::create(parameters);
1795 popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo);
1797 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
1798 if (info.functionBodyType == ArrowFunctionBodyExpression)
1799 failIfFalse(isEndOfArrowFunction(), "Expected the closing ';' ',' ']' ')' '}', line terminator or EOF after arrow function");
1801 matchOrFail(CLOSEBRACE, "Expected a closing '}' after a ", stringForFunctionMode(mode), " body");
1805 matchOrFail(CLOSEBRACE, "Expected a closing '}' after a ", stringForFunctionMode(mode), " body");
1810 m_functionCache->add(info.startFunctionOffset, WTF::move(newInfo));
1812 info.bodyEndLine = m_lastTokenEndPosition.line;
1816 template <typename LexerType>
1817 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDeclaration(TreeBuilder& context)
1819 ASSERT(match(FUNCTION));
1820 JSTokenLocation location(tokenLocation());
1821 unsigned functionKeywordStart = tokenStart();
1823 ParserFunctionInfo<TreeBuilder> info;
1824 failIfFalse((parseFunctionInfo(context, FunctionNeedsName, FunctionMode, true, ConstructorKind::None, SuperBinding::NotNeeded,
1825 functionKeywordStart, info, StandardFunctionParseType)), "Cannot parse this function");
1826 failIfFalse(info.name, "Function statements must have a name");
1827 failIfFalseIfStrict(declareVariable(info.name), "Cannot declare a function named '", info.name->impl(), "' in strict mode");
1828 return context.createFuncDeclStatement(location, info);
1831 #if ENABLE(ES6_CLASS_SYNTAX)
1832 template <typename LexerType>
1833 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseClassDeclaration(TreeBuilder& context)
1835 ASSERT(match(CLASSTOKEN));
1836 JSTokenLocation location(tokenLocation());
1837 JSTextPosition classStart = tokenStartPosition();
1838 unsigned classStartLine = tokenLine();
1840 ParserClassInfo<TreeBuilder> info;
1841 TreeClassExpression classExpr = parseClass(context, FunctionNeedsName, info);
1842 failIfFalse(classExpr, "Failed to parse class");
1843 // FIXME: This should be like `let`, not `var`.
1844 declareVariable(info.className);
1846 JSTextPosition classEnd = lastTokenEndPosition();
1847 unsigned classEndLine = tokenLine();
1849 return context.createClassDeclStatement(location, classExpr, classStart, classEnd, classStartLine, classEndLine);
1852 template <typename LexerType>
1853 template <class TreeBuilder> TreeClassExpression Parser<LexerType>::parseClass(TreeBuilder& context, FunctionRequirements requirements, ParserClassInfo<TreeBuilder>& info)
1855 ASSERT(match(CLASSTOKEN));
1856 JSTokenLocation location(tokenLocation());
1859 AutoPopScopeRef classScope(this, pushScope());
1860 classScope->setStrictMode();
1862 const Identifier* className = nullptr;
1864 className = m_token.m_data.ident;
1865 info.className = className;
1867 failIfFalse(classScope->declareVariable(className), "'", className->impl(), "' is not a valid class name");
1868 } else if (requirements == FunctionNeedsName) {
1869 if (match(OPENBRACE))
1870 semanticFail("Class statements must have a name");
1871 semanticFailureDueToKeyword("class name");
1872 failDueToUnexpectedToken();
1874 className = &m_vm->propertyNames->nullIdentifier;
1877 TreeExpression parentClass = 0;
1878 if (consume(EXTENDS)) {
1879 parentClass = parseMemberExpression(context);
1880 failIfFalse(parentClass, "Cannot parse the parent class name");
1882 const ConstructorKind constructorKind = parentClass ? ConstructorKind::Derived : ConstructorKind::Base;
1884 consumeOrFail(OPENBRACE, "Expected opening '{' at the start of a class body");
1886 TreeExpression constructor = 0;
1887 TreePropertyList staticMethods = 0;
1888 TreePropertyList instanceMethods = 0;
1889 TreePropertyList instanceMethodsTail = 0;
1890 TreePropertyList staticMethodsTail = 0;
1891 while (!match(CLOSEBRACE)) {
1892 if (match(SEMICOLON)) {
1897 JSTokenLocation methodLocation(tokenLocation());
1898 unsigned methodStart = tokenStart();
1900 // For backwards compatibility, "static" is a non-reserved keyword in non-strict mode.
1901 bool isStaticMethod = match(RESERVED_IF_STRICT) && *m_token.m_data.ident == m_vm->propertyNames->staticKeyword;
1905 // FIXME: Figure out a way to share more code with parseProperty.
1906 const CommonIdentifiers& propertyNames = *m_vm->propertyNames;
1907 const Identifier* ident = nullptr;
1908 bool isGetter = false;
1909 bool isSetter = false;
1910 switch (m_token.m_type) {
1912 ident = m_token.m_data.ident;
1917 ident = m_token.m_data.ident;
1918 isGetter = *ident == propertyNames.get;
1919 isSetter = *ident == propertyNames.set;
1924 ident = &m_parserArena.identifierArena().makeNumericIdentifier(const_cast<VM*>(m_vm), m_token.m_data.doubleValue);
1929 failDueToUnexpectedToken();
1932 TreeProperty property;
1933 const bool alwaysStrictInsideClass = true;
1934 if (isGetter || isSetter) {
1935 nextExpectIdentifier(LexerFlagsIgnoreReservedWords);
1936 property = parseGetterSetter(context, alwaysStrictInsideClass, isGetter ? PropertyNode::Getter : PropertyNode::Setter, methodStart,
1937 ConstructorKind::None, SuperBinding::Needed);
1938 failIfFalse(property, "Cannot parse this method");
1940 ParserFunctionInfo<TreeBuilder> methodInfo;
1941 bool isConstructor = !isStaticMethod && *ident == propertyNames.constructor;
1942 failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, isStaticMethod ? FunctionMode : MethodMode, false, isConstructor ? constructorKind : ConstructorKind::None, SuperBinding::Needed, methodStart, methodInfo, StandardFunctionParseType)), "Cannot parse this method");
1943 failIfFalse(ident && declareVariable(ident), "Cannot declare a method named '", methodInfo.name->impl(), "'");
1944 methodInfo.name = isConstructor ? className : ident;
1946 TreeExpression method = context.createFunctionExpr(methodLocation, methodInfo);
1947 if (isConstructor) {
1948 semanticFailIfTrue(constructor, "Cannot declare multiple constructors in a single class");
1949 constructor = method;
1953 // FIXME: Syntax error when super() is called
1954 semanticFailIfTrue(isStaticMethod && methodInfo.name && *methodInfo.name == propertyNames.prototype,
1955 "Cannot declare a static method named 'prototype'");
1956 property = context.createProperty(methodInfo.name, method, PropertyNode::Constant, PropertyNode::Unknown, alwaysStrictInsideClass, SuperBinding::Needed);
1959 TreePropertyList& tail = isStaticMethod ? staticMethodsTail : instanceMethodsTail;
1961 tail = context.createPropertyList(methodLocation, property, tail);
1963 tail = context.createPropertyList(methodLocation, property);
1965 staticMethods = tail;
1967 instanceMethods = tail;
1971 popScope(classScope, TreeBuilder::NeedsFreeVariableInfo);
1972 consumeOrFail(CLOSEBRACE, "Expected a closing '}' after a class body");
1974 return context.createClassExpr(location, *className, constructor, parentClass, instanceMethods, staticMethods);
1979 LabelInfo(const Identifier* ident, const JSTextPosition& start, const JSTextPosition& end)
1986 const Identifier* m_ident;
1987 JSTextPosition m_start;
1988 JSTextPosition m_end;
1991 template <typename LexerType>
1992 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionOrLabelStatement(TreeBuilder& context)
1995 /* Expression and Label statements are ambiguous at LL(1), so we have a
1996 * special case that looks for a colon as the next character in the input.
1998 Vector<LabelInfo> labels;
1999 JSTokenLocation location;
2001 JSTextPosition start = tokenStartPosition();
2002 location = tokenLocation();
2003 if (!nextTokenIsColon()) {
2004 // If we hit this path we're making a expression statement, which
2005 // by definition can't make use of continue/break so we can just
2006 // ignore any labels we might have accumulated.
2007 TreeExpression expression = parseExpression(context);
2008 failIfFalse(expression, "Cannot parse expression statement");
2009 if (!autoSemiColon())
2010 failDueToUnexpectedToken();
2011 return context.createExprStatement(location, expression, start, m_lastTokenEndPosition.line);
2013 const Identifier* ident = m_token.m_data.ident;
2014 JSTextPosition end = tokenEndPosition();
2016 consumeOrFail(COLON, "Labels must be followed by a ':'");
2017 if (!m_syntaxAlreadyValidated) {
2018 // This is O(N^2) over the current list of consecutive labels, but I
2019 // have never seen more than one label in a row in the real world.
2020 for (size_t i = 0; i < labels.size(); i++)
2021 failIfTrue(ident->impl() == labels[i].m_ident->impl(), "Attempted to redeclare the label '", ident->impl(), "'");
2022 failIfTrue(getLabel(ident), "Cannot find scope for the label '", ident->impl(), "'");
2023 labels.append(LabelInfo(ident, start, end));
2025 } while (match(IDENT) || isLETMaskedAsIDENT());
2026 bool isLoop = false;
2027 switch (m_token.m_type) {
2037 const Identifier* unused = 0;
2038 ScopeRef labelScope = currentScope();
2039 if (!m_syntaxAlreadyValidated) {
2040 for (size_t i = 0; i < labels.size(); i++)
2041 pushLabel(labels[i].m_ident, isLoop);
2043 TreeStatement statement = parseStatement(context, unused);
2044 if (!m_syntaxAlreadyValidated) {
2045 for (size_t i = 0; i < labels.size(); i++)
2046 popLabel(labelScope);
2048 failIfFalse(statement, "Cannot parse statement");
2049 for (size_t i = 0; i < labels.size(); i++) {
2050 const LabelInfo& info = labels[labels.size() - i - 1];
2051 statement = context.createLabelStatement(location, info.m_ident, statement, info.m_start, info.m_end);
2056 template <typename LexerType>
2057 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionStatement(TreeBuilder& context)
2059 switch (m_token.m_type) {
2060 // Consult: http://www.ecma-international.org/ecma-262/6.0/index.html#sec-expression-statement
2061 // The ES6 spec mandates that we should fail from FUNCTION token here. We handle this case
2062 // in parseStatement() which is the only caller of parseExpressionStatement().
2063 // We actually allow FUNCTION in situations where it should not be allowed unless we're in strict mode.
2065 failWithMessage("'class' declaration is not directly within a block statement");
2068 // FIXME: when implementing 'let' we should fail when we see the token sequence "let [".
2069 // https://bugs.webkit.org/show_bug.cgi?id=142944
2072 JSTextPosition start = tokenStartPosition();
2073 JSTokenLocation location(tokenLocation());
2074 TreeExpression expression = parseExpression(context);
2075 failIfFalse(expression, "Cannot parse expression statement");
2076 failIfFalse(autoSemiColon(), "Parse error");
2077 return context.createExprStatement(location, expression, start, m_lastTokenEndPosition.line);
2080 template <typename LexerType>
2081 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseIfStatement(TreeBuilder& context)
2084 JSTokenLocation ifLocation(tokenLocation());
2085 int start = tokenLine();
2087 handleProductionOrFail(OPENPAREN, "(", "start", "'if' condition");
2089 TreeExpression condition = parseExpression(context);
2090 failIfFalse(condition, "Expected a expression as the condition for an if statement");
2091 int end = tokenLine();
2092 handleProductionOrFail(CLOSEPAREN, ")", "end", "'if' condition");
2094 const Identifier* unused = 0;
2095 TreeStatement trueBlock = parseStatement(context, unused);
2096 failIfFalse(trueBlock, "Expected a statement as the body of an if block");
2099 return context.createIfStatement(ifLocation, condition, trueBlock, 0, start, end);
2101 Vector<TreeExpression> exprStack;
2102 Vector<std::pair<int, int>> posStack;
2103 Vector<JSTokenLocation> tokenLocationStack;
2104 Vector<TreeStatement> statementStack;
2105 bool trailingElse = false;
2107 JSTokenLocation tempLocation = tokenLocation();
2110 const Identifier* unused = 0;
2111 TreeStatement block = parseStatement(context, unused);
2112 failIfFalse(block, "Expected a statement as the body of an else block");
2113 statementStack.append(block);
2114 trailingElse = true;
2117 int innerStart = tokenLine();
2120 handleProductionOrFail(OPENPAREN, "(", "start", "'if' condition");
2122 TreeExpression innerCondition = parseExpression(context);
2123 failIfFalse(innerCondition, "Expected a expression as the condition for an if statement");
2124 int innerEnd = tokenLine();
2125 handleProductionOrFail(CLOSEPAREN, ")", "end", "'if' condition");
2126 const Identifier* unused = 0;
2127 TreeStatement innerTrueBlock = parseStatement(context, unused);
2128 failIfFalse(innerTrueBlock, "Expected a statement as the body of an if block");
2129 tokenLocationStack.append(tempLocation);
2130 exprStack.append(innerCondition);
2131 posStack.append(std::make_pair(innerStart, innerEnd));
2132 statementStack.append(innerTrueBlock);
2133 } while (match(ELSE));
2135 if (!trailingElse) {
2136 TreeExpression condition = exprStack.last();
2137 exprStack.removeLast();
2138 TreeStatement trueBlock = statementStack.last();
2139 statementStack.removeLast();
2140 std::pair<int, int> pos = posStack.last();
2141 posStack.removeLast();
2142 JSTokenLocation elseLocation = tokenLocationStack.last();
2143 tokenLocationStack.removeLast();
2144 TreeStatement ifStatement = context.createIfStatement(elseLocation, condition, trueBlock, 0, pos.first, pos.second);
2145 context.setEndOffset(ifStatement, context.endOffset(trueBlock));
2146 statementStack.append(ifStatement);
2149 while (!exprStack.isEmpty()) {
2150 TreeExpression condition = exprStack.last();
2151 exprStack.removeLast();
2152 TreeStatement falseBlock = statementStack.last();
2153 statementStack.removeLast();
2154 TreeStatement trueBlock = statementStack.last();
2155 statementStack.removeLast();
2156 std::pair<int, int> pos = posStack.last();
2157 posStack.removeLast();
2158 JSTokenLocation elseLocation = tokenLocationStack.last();
2159 tokenLocationStack.removeLast();
2160 TreeStatement ifStatement = context.createIfStatement(elseLocation, condition, trueBlock, falseBlock, pos.first, pos.second);
2161 context.setEndOffset(ifStatement, context.endOffset(falseBlock));
2162 statementStack.append(ifStatement);
2165 return context.createIfStatement(ifLocation, condition, trueBlock, statementStack.last(), start, end);
2168 template <typename LexerType>
2169 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseExpression(TreeBuilder& context)
2171 failIfStackOverflow();
2172 JSTokenLocation location(tokenLocation());
2173 TreeExpression node = parseAssignmentExpression(context);
2174 failIfFalse(node, "Cannot parse expression");
2175 context.setEndOffset(node, m_lastTokenEndPosition.offset);
2179 m_nonTrivialExpressionCount++;
2181 TreeExpression right = parseAssignmentExpression(context);
2182 failIfFalse(right, "Cannot parse expression in a comma expression");
2183 context.setEndOffset(right, m_lastTokenEndPosition.offset);
2184 typename TreeBuilder::Comma head = context.createCommaExpr(location, node);
2185 typename TreeBuilder::Comma tail = context.appendToCommaExpr(location, head, head, right);
2186 while (match(COMMA)) {
2187 next(TreeBuilder::DontBuildStrings);
2188 right = parseAssignmentExpression(context);
2189 failIfFalse(right, "Cannot parse expression in a comma expression");
2190 context.setEndOffset(right, m_lastTokenEndPosition.offset);
2191 tail = context.appendToCommaExpr(location, head, tail, right);
2193 context.setEndOffset(head, m_lastTokenEndPosition.offset);
2198 template <typename LexerType>
2199 template <typename TreeBuilder> TreeExpression Parser<LexerType>::parseAssignmentExpression(TreeBuilder& context)
2201 failIfStackOverflow();
2202 JSTextPosition start = tokenStartPosition();
2203 JSTokenLocation location(tokenLocation());
2204 int initialAssignmentCount = m_assignmentCount;
2205 int initialNonLHSCount = m_nonLHSCount;
2206 if (match(OPENBRACE) || match(OPENBRACKET)) {
2207 SavePoint savePoint = createSavePoint();
2208 auto pattern = tryParseDestructuringPatternExpression(context, AssignmentContext::AssignmentExpression);
2209 if (pattern && consume(EQUAL)) {
2210 auto rhs = parseAssignmentExpression(context);
2212 return context.createDestructuringAssignment(location, pattern, rhs);
2214 restoreSavePoint(savePoint);
2217 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
2218 if (isArrowFunctionParamters())
2219 return parseArrowFunctionExpression(context);
2222 TreeExpression lhs = parseConditionalExpression(context);
2223 failIfFalse(lhs, "Cannot parse expression");
2224 if (initialNonLHSCount != m_nonLHSCount) {
2225 if (m_token.m_type >= EQUAL && m_token.m_type <= OREQUAL)
2226 semanticFail("Left hand side of operator '", getToken(), "' must be a reference");
2231 int assignmentStack = 0;
2233 bool hadAssignment = false;
2235 switch (m_token.m_type) {
2236 case EQUAL: op = OpEqual; break;
2237 case PLUSEQUAL: op = OpPlusEq; break;
2238 case MINUSEQUAL: op = OpMinusEq; break;
2239 case MULTEQUAL: op = OpMultEq; break;
2240 case DIVEQUAL: op = OpDivEq; break;
2241 case LSHIFTEQUAL: op = OpLShift; break;
2242 case RSHIFTEQUAL: op = OpRShift; break;
2243 case URSHIFTEQUAL: op = OpURShift; break;
2244 case ANDEQUAL: op = OpAndEq; break;
2245 case XOREQUAL: op = OpXOrEq; break;
2246 case OREQUAL: op = OpOrEq; break;
2247 case MODEQUAL: op = OpModEq; break;
2251 m_nonTrivialExpressionCount++;
2252 hadAssignment = true;
2253 context.assignmentStackAppend(assignmentStack, lhs, start, tokenStartPosition(), m_assignmentCount, op);
2254 start = tokenStartPosition();
2255 m_assignmentCount++;
2256 next(TreeBuilder::DontBuildStrings);
2257 if (strictMode() && m_lastIdentifier && context.isResolve(lhs)) {
2258 failIfTrueIfStrict(m_vm->propertyNames->eval == *m_lastIdentifier, "Cannot modify 'eval' in strict mode");
2259 failIfTrueIfStrict(m_vm->propertyNames->arguments == *m_lastIdentifier, "Cannot modify 'arguments' in strict mode");
2260 declareWrite(m_lastIdentifier);
2261 m_lastIdentifier = 0;
2263 lhs = parseAssignmentExpression(context);
2264 failIfFalse(lhs, "Cannot parse the right hand side of an assignment expression");
2265 if (initialNonLHSCount != m_nonLHSCount) {
2266 if (m_token.m_type >= EQUAL && m_token.m_type <= OREQUAL)
2267 semanticFail("Left hand side of operator '", getToken(), "' must be a reference");
2275 if (!TreeBuilder::CreatesAST)
2278 while (assignmentStack)
2279 lhs = context.createAssignment(location, assignmentStack, lhs, initialAssignmentCount, m_assignmentCount, lastTokenEndPosition());
2284 template <typename LexerType>
2285 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseConditionalExpression(TreeBuilder& context)
2287 JSTokenLocation location(tokenLocation());
2288 TreeExpression cond = parseBinaryExpression(context);
2289 failIfFalse(cond, "Cannot parse expression");
2290 if (!match(QUESTION))
2292 m_nonTrivialExpressionCount++;
2294 next(TreeBuilder::DontBuildStrings);
2295 TreeExpression lhs = parseAssignmentExpression(context);
2296 failIfFalse(lhs, "Cannot parse left hand side of ternary operator");
2297 context.setEndOffset(lhs, m_lastTokenEndPosition.offset);
2298 consumeOrFailWithFlags(COLON, TreeBuilder::DontBuildStrings, "Expected ':' in ternary operator");
2300 TreeExpression rhs = parseAssignmentExpression(context);
2301 failIfFalse(rhs, "Cannot parse right hand side of ternary operator");
2302 context.setEndOffset(rhs, m_lastTokenEndPosition.offset);
2303 return context.createConditionalExpr(location, cond, lhs, rhs);
2306 ALWAYS_INLINE static bool isUnaryOp(JSTokenType token)
2308 return token & UnaryOpTokenFlag;
2311 template <typename LexerType>
2312 int Parser<LexerType>::isBinaryOperator(JSTokenType token)
2315 return token & (BinaryOpTokenPrecedenceMask << BinaryOpTokenAllowsInPrecedenceAdditionalShift);
2316 return token & BinaryOpTokenPrecedenceMask;
2319 template <typename LexerType>
2320 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseBinaryExpression(TreeBuilder& context)
2322 int operandStackDepth = 0;
2323 int operatorStackDepth = 0;
2324 typename TreeBuilder::BinaryExprContext binaryExprContext(context);
2325 JSTokenLocation location(tokenLocation());
2327 JSTextPosition exprStart = tokenStartPosition();
2328 int initialAssignments = m_assignmentCount;
2329 TreeExpression current = parseUnaryExpression(context);
2330 failIfFalse(current, "Cannot parse expression");
2332 context.appendBinaryExpressionInfo(operandStackDepth, current, exprStart, lastTokenEndPosition(), lastTokenEndPosition(), initialAssignments != m_assignmentCount);
2333 int precedence = isBinaryOperator(m_token.m_type);
2336 m_nonTrivialExpressionCount++;
2338 int operatorToken = m_token.m_type;
2339 next(TreeBuilder::DontBuildStrings);
2341 while (operatorStackDepth && context.operatorStackHasHigherPrecedence(operatorStackDepth, precedence)) {
2342 ASSERT(operandStackDepth > 1);
2344 typename TreeBuilder::BinaryOperand rhs = context.getFromOperandStack(-1);
2345 typename TreeBuilder::BinaryOperand lhs = context.getFromOperandStack(-2);
2346 context.shrinkOperandStackBy(operandStackDepth, 2);
2347 context.appendBinaryOperation(location, operandStackDepth, operatorStackDepth, lhs, rhs);
2348 context.operatorStackPop(operatorStackDepth);
2350 context.operatorStackAppend(operatorStackDepth, operatorToken, precedence);
2352 while (operatorStackDepth) {
2353 ASSERT(operandStackDepth > 1);
2355 typename TreeBuilder::BinaryOperand rhs = context.getFromOperandStack(-1);
2356 typename TreeBuilder::BinaryOperand lhs = context.getFromOperandStack(-2);
2357 context.shrinkOperandStackBy(operandStackDepth, 2);
2358 context.appendBinaryOperation(location, operandStackDepth, operatorStackDepth, lhs, rhs);
2359 context.operatorStackPop(operatorStackDepth);
2361 return context.popOperandStack(operandStackDepth);
2364 template <typename LexerType>
2365 template <class TreeBuilder> TreeProperty Parser<LexerType>::parseProperty(TreeBuilder& context, bool complete)
2367 bool wasIdent = false;
2368 switch (m_token.m_type) {
2374 const Identifier* ident = m_token.m_data.ident;
2375 unsigned getterOrSetterStartOffset = tokenStart();
2376 if (complete || (wasIdent && (*ident == m_vm->propertyNames->get || *ident == m_vm->propertyNames->set)))
2377 nextExpectIdentifier(LexerFlagsIgnoreReservedWords);
2379 nextExpectIdentifier(LexerFlagsIgnoreReservedWords | TreeBuilder::DontBuildKeywords);
2383 TreeExpression node = parseAssignmentExpression(context);
2384 failIfFalse(node, "Cannot parse expression for property declaration");
2385 context.setEndOffset(node, m_lexer->currentOffset());
2386 return context.createProperty(ident, node, PropertyNode::Constant, PropertyNode::Unknown, complete);
2389 if (match(OPENPAREN)) {
2390 auto method = parsePropertyMethod(context, ident);
2392 return context.createProperty(ident, method, PropertyNode::Constant, PropertyNode::KnownDirect, complete);
2395 failIfFalse(wasIdent, "Expected an identifier as property name");
2397 if (match(COMMA) || match(CLOSEBRACE)) {
2398 JSTextPosition start = tokenStartPosition();
2399 JSTokenLocation location(tokenLocation());
2400 currentScope()->useVariable(ident, m_vm->propertyNames->eval == *ident);
2401 TreeExpression node = context.createResolve(location, ident, start);
2402 return context.createProperty(ident, node, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Shorthand), PropertyNode::KnownDirect, complete);
2405 PropertyNode::Type type;
2406 if (*ident == m_vm->propertyNames->get)
2407 type = PropertyNode::Getter;
2408 else if (*ident == m_vm->propertyNames->set)
2409 type = PropertyNode::Setter;
2411 failWithMessage("Expected a ':' following the property name '", ident->impl(), "'");
2412 return parseGetterSetter(context, complete, type, getterOrSetterStartOffset);
2416 double propertyName = m_token.m_data.doubleValue;
2419 if (match(OPENPAREN)) {
2420 const Identifier& ident = m_parserArena.identifierArena().makeNumericIdentifier(const_cast<VM*>(m_vm), propertyName);
2421 auto method = parsePropertyMethod(context, &ident);
2423 return context.createProperty(&ident, method, PropertyNode::Constant, PropertyNode::Unknown, complete);
2426 consumeOrFail(COLON, "Expected ':' after property name");
2427 TreeExpression node = parseAssignmentExpression(context);
2428 failIfFalse(node, "Cannot parse expression for property declaration");
2429 context.setEndOffset(node, m_lexer->currentOffset());
2430 return context.createProperty(const_cast<VM*>(m_vm), m_parserArena, propertyName, node, PropertyNode::Constant, PropertyNode::Unknown, complete);
2434 auto propertyName = parseAssignmentExpression(context);
2435 failIfFalse(propertyName, "Cannot parse computed property name");
2436 handleProductionOrFail(CLOSEBRACKET, "]", "end", "computed property name");
2438 if (match(OPENPAREN)) {
2439 auto method = parsePropertyMethod(context, &m_vm->propertyNames->nullIdentifier);
2441 return context.createProperty(propertyName, method, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Computed), PropertyNode::KnownDirect, complete);
2444 consumeOrFail(COLON, "Expected ':' after property name");
2445 TreeExpression node = parseAssignmentExpression(context);
2446 failIfFalse(node, "Cannot parse expression for property declaration");
2447 context.setEndOffset(node, m_lexer->currentOffset());
2448 return context.createProperty(propertyName, node, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Computed), PropertyNode::Unknown, complete);
2451 failIfFalse(m_token.m_type & KeywordTokenFlag, "Expected a property name");
2456 template <typename LexerType>
2457 template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePropertyMethod(TreeBuilder& context, const Identifier* methodName)
2459 JSTokenLocation methodLocation(tokenLocation());
2460 unsigned methodStart = tokenStart();
2461 ParserFunctionInfo<TreeBuilder> methodInfo;
2462 failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, MethodMode, false, ConstructorKind::None, SuperBinding::NotNeeded, methodStart, methodInfo, StandardFunctionParseType)), "Cannot parse this method");
2463 methodInfo.name = methodName;
2464 return context.createFunctionExpr(methodLocation, methodInfo);
2467 template <typename LexerType>
2468 template <class TreeBuilder> TreeProperty Parser<LexerType>::parseGetterSetter(TreeBuilder& context, bool strict, PropertyNode::Type type, unsigned getterOrSetterStartOffset,
2469 ConstructorKind constructorKind, SuperBinding superBinding)
2471 const Identifier* stringPropertyName = 0;
2472 double numericPropertyName = 0;
2473 if (m_token.m_type == IDENT || m_token.m_type == STRING || isLETMaskedAsIDENT()) {
2474 stringPropertyName = m_token.m_data.ident;
2475 semanticFailIfTrue(superBinding == SuperBinding::Needed && *stringPropertyName == m_vm->propertyNames->prototype,
2476 "Cannot declare a static method named 'prototype'");
2477 semanticFailIfTrue(superBinding == SuperBinding::Needed && *stringPropertyName == m_vm->propertyNames->constructor,
2478 "Cannot declare a getter or setter named 'constructor'");
2479 } else if (m_token.m_type == DOUBLE || m_token.m_type == INTEGER)
2480 numericPropertyName = m_token.m_data.doubleValue;
2482 failDueToUnexpectedToken();
2483 JSTokenLocation location(tokenLocation());
2485 ParserFunctionInfo<TreeBuilder> info;
2486 if (type & PropertyNode::Getter) {
2487 failIfFalse(match(OPENPAREN), "Expected a parameter list for getter definition");
2488 failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, GetterMode, false, constructorKind, superBinding,
2489 getterOrSetterStartOffset, info, StandardFunctionParseType)), "Cannot parse getter definition");
2491 failIfFalse(match(OPENPAREN), "Expected a parameter list for setter definition");
2492 failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, SetterMode, false, constructorKind, superBinding,
2493 getterOrSetterStartOffset, info, StandardFunctionParseType)), "Cannot parse setter definition");
2495 if (stringPropertyName)
2496 return context.createGetterOrSetterProperty(location, type, strict, stringPropertyName, info, superBinding);
2497 return context.createGetterOrSetterProperty(const_cast<VM*>(m_vm), m_parserArena, location, type, strict, numericPropertyName, info, superBinding);
2500 template <typename LexerType>
2501 template <class TreeBuilder> bool Parser<LexerType>::shouldCheckPropertyForUnderscoreProtoDuplicate(TreeBuilder& context, const TreeProperty& property)
2503 if (m_syntaxAlreadyValidated)
2506 if (!context.getName(property))
2509 // A Constant property that is not a Computed or Shorthand Constant property.
2510 return context.getType(property) == PropertyNode::Constant;
2513 template <typename LexerType>
2514 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseObjectLiteral(TreeBuilder& context)
2516 auto savePoint = createSavePoint();
2517 consumeOrFailWithFlags(OPENBRACE, TreeBuilder::DontBuildStrings, "Expected opening '{' at the start of an object literal");
2519 int oldNonLHSCount = m_nonLHSCount;
2521 JSTokenLocation location(tokenLocation());
2522 if (match(CLOSEBRACE)) {
2524 return context.createObjectLiteral(location);
2527 TreeProperty property = parseProperty(context, false);
2528 failIfFalse(property, "Cannot parse object literal property");
2530 if (!m_syntaxAlreadyValidated && context.getType(property) & (PropertyNode::Getter | PropertyNode::Setter)) {
2531 restoreSavePoint(savePoint);
2532 return parseStrictObjectLiteral(context);
2535 bool seenUnderscoreProto = false;
2536 if (shouldCheckPropertyForUnderscoreProtoDuplicate(context, property))
2537 seenUnderscoreProto = *context.getName(property) == m_vm->propertyNames->underscoreProto;
2539 TreePropertyList propertyList = context.createPropertyList(location, property);
2540 TreePropertyList tail = propertyList;
2541 while (match(COMMA)) {
2542 next(TreeBuilder::DontBuildStrings);
2543 if (match(CLOSEBRACE))
2545 JSTokenLocation propertyLocation(tokenLocation());
2546 property = parseProperty(context, false);
2547 failIfFalse(property, "Cannot parse object literal property");
2548 if (!m_syntaxAlreadyValidated && context.getType(property) & (PropertyNode::Getter | PropertyNode::Setter)) {
2549 restoreSavePoint(savePoint);
2550 return parseStrictObjectLiteral(context);
2552 if (shouldCheckPropertyForUnderscoreProtoDuplicate(context, property)) {
2553 if (*context.getName(property) == m_vm->propertyNames->underscoreProto) {
2554 semanticFailIfTrue(seenUnderscoreProto, "Attempted to redefine __proto__ property");
2555 seenUnderscoreProto = true;
2558 tail = context.createPropertyList(propertyLocation, property, tail);
2561 location = tokenLocation();
2562 handleProductionOrFail(CLOSEBRACE, "}", "end", "object literal");
2564 m_nonLHSCount = oldNonLHSCount;
2566 return context.createObjectLiteral(location, propertyList);
2569 template <typename LexerType>
2570 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseStrictObjectLiteral(TreeBuilder& context)
2572 consumeOrFail(OPENBRACE, "Expected opening '{' at the start of an object literal");
2574 int oldNonLHSCount = m_nonLHSCount;
2576 JSTokenLocation location(tokenLocation());
2577 if (match(CLOSEBRACE)) {
2579 return context.createObjectLiteral(location);
2582 TreeProperty property = parseProperty(context, true);
2583 failIfFalse(property, "Cannot parse object literal property");
2585 bool seenUnderscoreProto = false;
2586 if (shouldCheckPropertyForUnderscoreProtoDuplicate(context, property))
2587 seenUnderscoreProto = *context.getName(property) == m_vm->propertyNames->underscoreProto;
2589 TreePropertyList propertyList = context.createPropertyList(location, property);
2590 TreePropertyList tail = propertyList;
2591 while (match(COMMA)) {
2593 if (match(CLOSEBRACE))
2595 JSTokenLocation propertyLocation(tokenLocation());
2596 property = parseProperty(context, true);
2597 failIfFalse(property, "Cannot parse object literal property");
2598 if (shouldCheckPropertyForUnderscoreProtoDuplicate(context, property)) {
2599 if (*context.getName(property) == m_vm->propertyNames->underscoreProto) {
2600 semanticFailIfTrue(seenUnderscoreProto, "Attempted to redefine __proto__ property");
2601 seenUnderscoreProto = true;
2604 tail = context.createPropertyList(propertyLocation, property, tail);
2607 location = tokenLocation();
2608 handleProductionOrFail(CLOSEBRACE, "}", "end", "object literal");
2610 m_nonLHSCount = oldNonLHSCount;
2612 return context.createObjectLiteral(location, propertyList);
2615 template <typename LexerType>
2616 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseArrayLiteral(TreeBuilder& context)
2618 consumeOrFailWithFlags(OPENBRACKET, TreeBuilder::DontBuildStrings, "Expected an opening '[' at the beginning of an array literal");
2620 int oldNonLHSCount = m_nonLHSCount;
2623 while (match(COMMA)) {
2624 next(TreeBuilder::DontBuildStrings);
2627 if (match(CLOSEBRACKET)) {
2628 JSTokenLocation location(tokenLocation());
2629 next(TreeBuilder::DontBuildStrings);
2630 return context.createArray(location, elisions);
2633 TreeExpression elem;
2634 if (UNLIKELY(match(DOTDOTDOT))) {
2635 auto spreadLocation = m_token.m_location;
2636 auto start = m_token.m_startPosition;
2637 auto divot = m_token.m_endPosition;
2639 auto spreadExpr = parseAssignmentExpression(context);
2640 failIfFalse(spreadExpr, "Cannot parse subject of a spread operation");
2641 elem = context.createSpreadExpression(spreadLocation, spreadExpr, start, divot, m_lastTokenEndPosition);
2643 elem = parseAssignmentExpression(context);
2644 failIfFalse(elem, "Cannot parse array literal element");
2645 typename TreeBuilder::ElementList elementList = context.createElementList(elisions, elem);
2646 typename TreeBuilder::ElementList tail = elementList;
2648 while (match(COMMA)) {
2649 next(TreeBuilder::DontBuildStrings);
2652 while (match(COMMA)) {
2657 if (match(CLOSEBRACKET)) {
2658 JSTokenLocation location(tokenLocation());
2659 next(TreeBuilder::DontBuildStrings);
2660 return context.createArray(location, elisions, elementList);
2662 if (UNLIKELY(match(DOTDOTDOT))) {
2663 auto spreadLocation = m_token.m_location;
2664 auto start = m_token.m_startPosition;
2665 auto divot = m_token.m_endPosition;
2667 TreeExpression elem = parseAssignmentExpression(context);
2668 failIfFalse(elem, "Cannot parse subject of a spread operation");
2669 auto spread = context.createSpreadExpression(spreadLocation, elem, start, divot, m_lastTokenEndPosition);
2670 tail = context.createElementList(tail, elisions, spread);
2673 TreeExpression elem = parseAssignmentExpression(context);
2674 failIfFalse(elem, "Cannot parse array literal element");
2675 tail = context.createElementList(tail, elisions, elem);
2678 JSTokenLocation location(tokenLocation());
2679 if (!consume(CLOSEBRACKET)) {
2680 failIfFalse(match(DOTDOTDOT), "Expected either a closing ']' or a ',' following an array element");
2681 semanticFail("The '...' operator should come before a target expression");
2684 m_nonLHSCount = oldNonLHSCount;
2686 return context.createArray(location, elementList);
2689 #if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
2690 template <typename LexerType>
2691 template <class TreeBuilder> typename TreeBuilder::TemplateString Parser<LexerType>::parseTemplateString(TreeBuilder& context, bool isTemplateHead, typename LexerType::RawStringsBuildMode rawStringsBuildMode, bool& elementIsTail)
2693 if (!isTemplateHead) {
2694 matchOrFail(CLOSEBRACE, "Expected a closing '}' following an expression in template literal");
2695 // Re-scan the token to recognize it as Template Element.
2696 m_token.m_type = m_lexer->scanTrailingTemplateString(&m_token, rawStringsBuildMode);
2698 matchOrFail(TEMPLATE, "Expected an template element");
2699 const Identifier* cooked = m_token.m_data.cooked;
2700 const Identifier* raw = m_token.m_data.raw;
2701 elementIsTail = m_token.m_data.isTail;
2702 JSTokenLocation location(tokenLocation());
2704 return context.createTemplateString(location, *cooked, *raw);
2707 template <typename LexerType>
2708 template <class TreeBuilder> typename TreeBuilder::TemplateLiteral Parser<LexerType>::parseTemplateLiteral(TreeBuilder& context, typename LexerType::RawStringsBuildMode rawStringsBuildMode)
2710 JSTokenLocation location(tokenLocation());
2711 bool elementIsTail = false;
2713 auto headTemplateString = parseTemplateString(context, true, rawStringsBuildMode, elementIsTail);
2714 failIfFalse(headTemplateString, "Cannot parse head template element");
2716 typename TreeBuilder::TemplateStringList templateStringList = context.createTemplateStringList(headTemplateString);
2717 typename TreeBuilder::TemplateStringList templateStringTail = templateStringList;
2720 return context.createTemplateLiteral(location, templateStringList);
2722 failIfTrue(match(CLOSEBRACE), "Template literal expression cannot be empty");
2723 TreeExpression expression = parseExpression(context);
2724 failIfFalse(expression, "Cannot parse expression in template literal");
2726 typename TreeBuilder::TemplateExpressionList templateExpressionList = context.createTemplateExpressionList(expression);
2727 typename TreeBuilder::TemplateExpressionList templateExpressionTail = templateExpressionList;
2729 auto templateString = parseTemplateString(context, false, rawStringsBuildMode, elementIsTail);
2730 failIfFalse(templateString, "Cannot parse template element");
2731 templateStringTail = context.createTemplateStringList(templateStringTail, templateString);
2733 while (!elementIsTail) {
2734 failIfTrue(match(CLOSEBRACE), "Template literal expression cannot be empty");
2735 TreeExpression expression = parseExpression(context);
2736 failIfFalse(expression, "Cannot parse expression in template literal");
2738 templateExpressionTail = context.createTemplateExpressionList(templateExpressionTail, expression);
2740 auto templateString = parseTemplateString(context, false, rawStringsBuildMode, elementIsTail);
2741 failIfFalse(templateString, "Cannot parse template element");
2742 templateStringTail = context.createTemplateStringList(templateStringTail, templateString);
2745 return context.createTemplateLiteral(location, templateStringList, templateExpressionList);
2749 template <typename LexerType>
2750 template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePrimaryExpression(TreeBuilder& context)
2752 failIfStackOverflow();
2753 switch (m_token.m_type) {
2755 JSTokenLocation location(tokenLocation());
2756 unsigned functionKeywordStart = tokenStart();
2758 ParserFunctionInfo<TreeBuilder> info;
2759 info.name = &m_vm->propertyNames->nullIdentifier;
2760 failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, FunctionMode, false, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, info, StandardFunctionParseType)), "Cannot parse function expression");
2761 return context.createFunctionExpr(location, info);
2763 #if ENABLE(ES6_CLASS_SYNTAX)
2765 ParserClassInfo<TreeBuilder> info;
2766 return parseClass(context, FunctionNoRequirements, info);
2771 return parseStrictObjectLiteral(context);
2772 return parseObjectLiteral(context);
2774 return parseArrayLiteral(context);
2777 int oldNonLHSCount = m_nonLHSCount;
2778 TreeExpression result = parseExpression(context);
2779 m_nonLHSCount = oldNonLHSCount;
2780 handleProductionOrFail(CLOSEPAREN, ")", "end", "compound expression");
2784 JSTokenLocation location(tokenLocation());
2786 return context.thisExpr(location, m_thisTDZMode);
2789 identifierExpression:
2790 JSTextPosition start = tokenStartPosition();
2791 const Identifier* ident = m_token.m_data.ident;
2792 JSTokenLocation location(tokenLocation());
2794 currentScope()->useVariable(ident, m_vm->propertyNames->eval == *ident);
2795 m_lastIdentifier = ident;
2796 return context.createResolve(location, ident, start);
2799 const Identifier* ident = m_token.m_data.ident;
2800 JSTokenLocation location(tokenLocation());
2802 return context.createString(location, ident);
2805 double d = m_token.m_data.doubleValue;
2806 JSTokenLocation location(tokenLocation());
2808 return context.createDoubleExpr(location, d);
2811 double d = m_token.m_data.doubleValue;
2812 JSTokenLocation location(tokenLocation());
2814 return context.createIntegerExpr(location, d);
2817 JSTokenLocation location(tokenLocation());
2819 return context.createNull(location);
2822 JSTokenLocation location(tokenLocation());
2824 return context.createBoolean(location, true);
2827 JSTokenLocation location(tokenLocation());
2829 return context.createBoolean(location, false);
2834 const Identifier* pattern;
2835 const Identifier* flags;
2836 if (match(DIVEQUAL))
2837 failIfFalse(m_lexer->scanRegExp(pattern, flags, '='), "Invalid regular expression");
2839 failIfFalse(m_lexer->scanRegExp(pattern, flags), "Invalid regular expression");
2841 JSTextPosition start = tokenStartPosition();
2842 JSTokenLocation location(tokenLocation());
2844 TreeExpression re = context.createRegExp(location, *pattern, *flags, start);
2846 const char* yarrErrorMsg = Yarr::checkSyntax(pattern->string());
2847 regexFail(yarrErrorMsg);
2851 #if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
2853 return parseTemplateLiteral(context, LexerType::RawStringsBuildMode::DontBuildRawStrings);
2857 goto identifierExpression;
2860 failDueToUnexpectedToken();
2864 template <typename LexerType>
2865 template <class TreeBuilder> TreeArguments Parser<LexerType>::parseArguments(TreeBuilder& context, SpreadMode mode)
2867 consumeOrFailWithFlags(OPENPAREN, TreeBuilder::DontBuildStrings, "Expected opening '(' at start of argument list");
2868 JSTokenLocation location(tokenLocation());
2869 if (match(CLOSEPAREN)) {
2870 next(TreeBuilder::DontBuildStrings);
2871 return context.createArguments();
2873 if (match(DOTDOTDOT) && mode == AllowSpread) {
2874 JSTokenLocation spreadLocation(tokenLocation());
2875 auto start = m_token.m_startPosition;
2876 auto divot = m_token.m_endPosition;
2878 auto spreadExpr = parseAssignmentExpression(context);
2879 auto end = m_lastTokenEndPosition;
2881 failWithMessage("Cannot parse spread expression");
2882 if (!consume(CLOSEPAREN)) {
2884 semanticFail("Spread operator may only be applied to the last argument passed to a function");
2885 handleProductionOrFail(CLOSEPAREN, ")", "end", "argument list");
2887 auto spread = context.createSpreadExpression(spreadLocation, spreadExpr, start, divot, end);
2888 TreeArgumentsList argList = context.createArgumentsList(location, spread);
2889 return context.createArguments(argList);
2891 TreeExpression firstArg = parseAssignmentExpression(context);
2892 failIfFalse(firstArg, "Cannot parse function argument");
2894 TreeArgumentsList argList = context.createArgumentsList(location, firstArg);
2895 TreeArgumentsList tail = argList;
2896 while (match(COMMA)) {
2897 JSTokenLocation argumentLocation(tokenLocation());
2898 next(TreeBuilder::DontBuildStrings);
2899 TreeExpression arg = parseAssignmentExpression(context);
2900 failIfFalse(arg, "Cannot parse function argument");
2901 tail = context.createArgumentsList(argumentLocation, tail, arg);
2903 semanticFailIfTrue(match(DOTDOTDOT), "The '...' operator should come before the target expression");
2904 handleProductionOrFail(CLOSEPAREN, ")", "end", "argument list");
2905 return context.createArguments(argList);
2908 template <typename LexerType>
2909 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseMemberExpression(TreeBuilder& context)
2911 TreeExpression base = 0;
2912 JSTextPosition expressionStart = tokenStartPosition();
2914 JSTokenLocation startLocation = tokenLocation();
2915 JSTokenLocation location;
2916 while (match(NEW)) {
2921 #if ENABLE(ES6_CLASS_SYNTAX)
2922 bool baseIsSuper = match(SUPER);
2923 semanticFailIfTrue(baseIsSuper && newCount, "Cannot use new with super");
2925 bool baseIsSuper = false;
2929 base = context.superExpr(location);
2931 currentScope()->setNeedsSuperBinding();
2933 base = parsePrimaryExpression(context);
2935 failIfFalse(base, "Cannot parse base expression");
2937 location = tokenLocation();
2938 switch (m_token.m_type) {
2940 m_nonTrivialExpressionCount++;
2941 JSTextPosition expressionEnd = lastTokenEndPosition();
2943 int nonLHSCount = m_nonLHSCount;
2944 int initialAssignments = m_assignmentCount;
2945 TreeExpression property = parseExpression(context);
2946 failIfFalse(property, "Cannot parse subscript expression");
2947 base = context.createBracketAccess(location, base, property, initialAssignments != m_assignmentCount, expressionStart, expressionEnd, tokenEndPosition());
2948 handleProductionOrFail(CLOSEBRACKET, "]", "end", "subscript expression");
2949 m_nonLHSCount = nonLHSCount;
2953 m_nonTrivialExpressionCount++;
2954 int nonLHSCount = m_nonLHSCount;
2957 JSTextPosition expressionEnd = lastTokenEndPosition();
2958 TreeArguments arguments = parseArguments(context, AllowSpread);
2959 failIfFalse(arguments, "Cannot parse call arguments");
2960 base = context.createNewExpr(location, base, arguments, expressionStart, expressionEnd, lastTokenEndPosition());
2962 JSTextPosition expressionEnd = lastTokenEndPosition();
2963 TreeArguments arguments = parseArguments(context, AllowSpread);
2964 failIfFalse(arguments, "Cannot parse call arguments");
2966 currentScope()->setHasDirectSuper();
2967 base = context.makeFunctionCallNode(startLocation, base, arguments, expressionStart, expressionEnd, lastTokenEndPosition());
2969 m_nonLHSCount = nonLHSCount;
2973 m_nonTrivialExpressionCount++;
2974 JSTextPosition expressionEnd = lastTokenEndPosition();
2975 nextExpectIdentifier(LexerFlagsIgnoreReservedWords | TreeBuilder::DontBuildKeywords);
2976 matchOrFail(IDENT, "Expected a property name after '.'");
2977 base = context.createDotAccess(location, base, m_token.m_data.ident, expressionStart, expressionEnd, tokenEndPosition());
2981 #if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
2983 semanticFailIfTrue(baseIsSuper, "Cannot use super as tag for tagged templates");
2984 JSTextPosition expressionEnd = lastTokenEndPosition();
2985 int nonLHSCount = m_nonLHSCount;
2986 typename TreeBuilder::TemplateLiteral templateLiteral = parseTemplateLiteral(context, LexerType::RawStringsBuildMode::BuildRawStrings);
2987 failIfFalse(templateLiteral, "Cannot parse template literal");
2988 base = context.createTaggedTemplate(location, base, templateLiteral, expressionStart, expressionEnd, lastTokenEndPosition());
2989 m_nonLHSCount = nonLHSCount;
2994 goto endMemberExpression;
2996 baseIsSuper = false;
2998 endMemberExpression:
2999 semanticFailIfTrue(baseIsSuper, "Cannot reference super");
3001 base = context.createNewExpr(location, base, expressionStart, lastTokenEndPosition());
3005 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
3006 template <typename LexerType>
3007 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseArrowFunctionExpression(TreeBuilder& context)
3009 JSTokenLocation location;
3011 unsigned functionKeywordStart = tokenStart();
3012 location = tokenLocation();
3013 ParserFunctionInfo<TreeBuilder> info;
3014 info.name = &m_vm->propertyNames->nullIdentifier;
3015 failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, FunctionMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, info, ArrowFunctionParseType)), "Cannot parse arrow function expression");
3017 return context.createArrowFunctionExpr(location, info);
3021 static const char* operatorString(bool prefix, unsigned tok)
3025 case AUTOMINUSMINUS:
3026 return prefix ? "prefix-decrement" : "decrement";
3030 return prefix ? "prefix-increment" : "increment";
3033 return "logical-not";
3036 return "bitwise-not";
3047 RELEASE_ASSERT_NOT_REACHED();
3051 template <typename LexerType>
3052 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseUnaryExpression(TreeBuilder& context)
3054 typename TreeBuilder::UnaryExprContext unaryExprContext(context);
3055 AllowInOverride allowInOverride(this);
3056 int tokenStackDepth = 0;
3057 bool modifiesExpr = false;
3058 bool requiresLExpr = false;
3059 unsigned lastOperator = 0;
3060 while (isUnaryOp(m_token.m_type)) {
3062 switch (m_token.m_type) {
3066 case AUTOMINUSMINUS:
3067 semanticFailIfTrue(requiresLExpr, "The ", operatorString(true, lastOperator), " operator requires a reference expression");
3068 modifiesExpr = true;
3069 requiresLExpr = true;
3072 semanticFailIfTrue(requiresLExpr, "The ", operatorString(true, lastOperator), " operator requires a reference expression");
3073 requiresLExpr = true;
3076 semanticFailIfTrue(requiresLExpr, "The ", operatorString(true, lastOperator), " operator requires a reference expression");
3080 lastOperator = m_token.m_type;
3082 context.appendUnaryToken(tokenStackDepth, m_token.m_type, tokenStartPosition());
3084 m_nonTrivialExpressionCount++;
3086 JSTextPosition subExprStart = tokenStartPosition();
3087 ASSERT(subExprStart.offset >= subExprStart.lineStartOffset);
3088 JSTokenLocation location(tokenLocation());
3089 TreeExpression expr = parseMemberExpression(context);
3092 failWithMessage("Cannot parse subexpression of ", operatorString(true, lastOperator), "operator");
3093 failWithMessage("Cannot parse member expression");
3095 bool isEvalOrArguments = false;
3096 if (strictMode() && !m_syntaxAlreadyValidated) {
3097 if (context.isResolve(expr))
3098 isEvalOrArguments = *m_lastIdentifier == m_vm->propertyNames->eval || *m_lastIdentifier == m_vm->propertyNames->arguments;
3100 failIfTrueIfStrict(isEvalOrArguments && modifiesExpr, "Cannot modify '", m_lastIdentifier->impl(), "' in strict mode");
3101 switch (m_token.m_type) {
3103 m_nonTrivialExpressionCount++;
3105 expr = context.makePostfixNode(location, expr, OpPlusPlus, subExprStart, lastTokenEndPosition(), tokenEndPosition());
3106 m_assignmentCount++;
3107 failIfTrueIfStrict(isEvalOrArguments, "Cannot modify '", m_lastIdentifier->impl(), "' in strict mode");
3108 semanticFailIfTrue(requiresLExpr, "The ", operatorString(false, lastOperator), " operator requires a reference expression");
3109 lastOperator = PLUSPLUS;
3113 m_nonTrivialExpressionCount++;
3115 expr = context.makePostfixNode(location, expr, OpMinusMinus, subExprStart, lastTokenEndPosition(), tokenEndPosition());
3116 m_assignmentCount++;
3117 failIfTrueIfStrict(isEvalOrArguments, "'", m_lastIdentifier->impl(), "' cannot be modified in strict mode");
3118 semanticFailIfTrue(requiresLExpr, "The ", operatorString(false, lastOperator), " operator requires a reference expression");
3119 lastOperator = PLUSPLUS;
3126 JSTextPosition end = lastTokenEndPosition();
3128 if (!TreeBuilder::CreatesAST && (m_syntaxAlreadyValidated || !strictMode()))
3131 location = tokenLocation();
3132 location.line = m_lexer->lastLineNumber();
3133 while (tokenStackDepth) {
3134 switch (context.unaryTokenStackLastType(tokenStackDepth)) {
3136 expr = context.createLogicalNot(location, expr);
3139 expr = context.makeBitwiseNotNode(location, expr);
3142 expr = context.makeNegateNode(location, expr);
3145 expr = context.createUnaryPlus(location, expr);
3149 expr = context.makePrefixNode(location, expr, OpPlusPlus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end);
3150 m_assignmentCount++;
3153 case AUTOMINUSMINUS:
3154 expr = context.makePrefixNode(location, expr, OpMinusMinus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end);
3155 m_assignmentCount++;
3158 expr = context.makeTypeOfNode(location, expr);
3161 expr = context.createVoid(location, expr);
3164 failIfTrueIfStrict(context.isResolve(expr), "Cannot delete unqualified property '", m_lastIdentifier->impl(), "' in strict mode");
3165 expr = context.makeDeleteNode(location, expr, context.unaryTokenStackLastStart(tokenStackDepth), end, end);
3168 // If we get here something has gone horribly horribly wrong
3171 subExprStart = context.unaryTokenStackLastStart(tokenStackDepth);
3172 context.unaryTokenStackRemoveLast(tokenStackDepth);
3178 template <typename LexerType> void Parser<LexerType>::printUnexpectedTokenText(WTF::PrintStream& out)
3180 switch (m_token.m_type) {
3182 out.print("Unexpected end of script");
3184 case UNTERMINATED_IDENTIFIER_ESCAPE_ERRORTOK:
3185 case UNTERMINATED_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK:
3186 out.print("Incomplete unicode escape in identifier: '", getToken(), "'");
3188 case UNTERMINATED_MULTILINE_COMMENT_ERRORTOK:
3189 out.print("Unterminated multiline comment");
3191 case UNTERMINATED_NUMERIC_LITERAL_ERRORTOK:
3192 out.print("Unterminated numeric literal '", getToken(), "'");
3194 case UNTERMINATED_STRING_LITERAL_ERRORTOK:
3195 out.print("Unterminated string literal '", getToken(), "'");
3197 case INVALID_IDENTIFIER_ESCAPE_ERRORTOK:
3198 out.print("Invalid escape in identifier: '", getToken(), "'");
3200 case INVALID_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK:
3201 out.print("Invalid unicode escape in identifier: '", getToken(), "'");
3203 case INVALID_NUMERIC_LITERAL_ERRORTOK:
3204 out.print("Invalid numeric literal: '", getToken(), "'");
3206 case INVALID_OCTAL_NUMBER_ERRORTOK:
3207 out.print("Invalid use of octal: '", getToken(), "'");
3209 case INVALID_STRING_LITERAL_ERRORTOK:
3210 out.print("Invalid string literal: '", getToken(), "'");
3213 out.print("Unrecognized token '", getToken(), "'");
3216 out.print("Unexpected string literal ", getToken());
3220 out.print("Unexpected number '", getToken(), "'");
3223 case RESERVED_IF_STRICT:
3224 out.print("Unexpected use of reserved word '", getToken(), "' in strict mode");
3228 out.print("Unexpected use of reserved word '", getToken(), "'");
3231 case INVALID_PRIVATE_NAME_ERRORTOK:
3232 out.print("Invalid private name '", getToken(), "'");
3236 out.print("Unexpected identifier '", getToken(), "'");
3243 if (m_token.m_type & KeywordTokenFlag) {
3244 out.print("Unexpected keyword '", getToken(), "'");
3248 out.print("Unexpected token '", getToken(), "'");
3251 // Instantiate the two flavors of Parser we need instead of putting most of this file in Parser.h
3252 template class Parser<Lexer<LChar>>;
3253 template class Parser<Lexer<UChar>>;