2 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
3 * Copyright (C) 2001 Peter Kelly (pmk@post.com)
4 * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc. All rights reserved.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
26 #include "ASTBuilder.h"
27 #include "CodeBlock.h"
29 #include "JSCJSValueInlines.h"
31 #include "JSCInlines.h"
32 #include "SourceProvider.h"
35 #include <wtf/HashFunctions.h>
36 #include <wtf/StringPrintStream.h>
37 #include <wtf/WTFThreadData.h>
40 #define updateErrorMessage(shouldPrintToken, ...) do {\
42 logError(shouldPrintToken, __VA_ARGS__); \
45 #define propagateError() do { if (hasError()) return 0; } while (0)
46 #define internalFailWithMessage(shouldPrintToken, ...) do { updateErrorMessage(shouldPrintToken, __VA_ARGS__); return 0; } while (0)
47 #define handleErrorToken() do { if (m_token.m_type == EOFTOK || m_token.m_type & ErrorTokenFlag) { failDueToUnexpectedToken(); } } while (0)
48 #define failWithMessage(...) do { { handleErrorToken(); updateErrorMessage(true, __VA_ARGS__); } return 0; } while (0)
49 #define failWithStackOverflow() do { updateErrorMessage(false, "Stack exhausted"); m_hasStackOverflow = true; return 0; } while (0)
50 #define failIfFalse(cond, ...) do { if (!(cond)) { handleErrorToken(); internalFailWithMessage(true, __VA_ARGS__); } } while (0)
51 #define failIfTrue(cond, ...) do { if (cond) { handleErrorToken(); internalFailWithMessage(true, __VA_ARGS__); } } while (0)
52 #define failIfTrueIfStrict(cond, ...) do { if ((cond) && strictMode()) internalFailWithMessage(false, __VA_ARGS__); } while (0)
53 #define failIfFalseIfStrict(cond, ...) do { if ((!(cond)) && strictMode()) internalFailWithMessage(false, __VA_ARGS__); } while (0)
54 #define consumeOrFail(tokenType, ...) do { if (!consume(tokenType)) { handleErrorToken(); internalFailWithMessage(true, __VA_ARGS__); } } while (0)
55 #define consumeOrFailWithFlags(tokenType, flags, ...) do { if (!consume(tokenType, flags)) { handleErrorToken(); internalFailWithMessage(true, __VA_ARGS__); } } while (0)
56 #define matchOrFail(tokenType, ...) do { if (!match(tokenType)) { handleErrorToken(); internalFailWithMessage(true, __VA_ARGS__); } } while (0)
57 #define failIfStackOverflow() do { if (!canRecurse()) failWithStackOverflow(); } while (0)
58 #define semanticFail(...) do { internalFailWithMessage(false, __VA_ARGS__); } while (0)
59 #define semanticFailIfTrue(cond, ...) do { if (cond) internalFailWithMessage(false, __VA_ARGS__); } while (0)
60 #define semanticFailIfFalse(cond, ...) do { if (!(cond)) internalFailWithMessage(false, __VA_ARGS__); } while (0)
61 #define regexFail(failure) do { setErrorMessage(failure); return 0; } while (0)
62 #define failDueToUnexpectedToken() do {\
67 #define handleProductionOrFail(token, tokenString, operation, production) do {\
68 consumeOrFail(token, "Expected '", tokenString, "' to ", operation, " a ", production);\
71 #define semanticFailureDueToKeyword(...) do { \
72 if (strictMode() && m_token.m_type == RESERVED_IF_STRICT) \
73 semanticFail("Cannot use the reserved word '", getToken(), "' as a ", __VA_ARGS__, " in strict mode"); \
74 if (m_token.m_type == RESERVED || m_token.m_type == RESERVED_IF_STRICT) \
75 semanticFail("Cannot use the reserved word '", getToken(), "' as a ", __VA_ARGS__); \
76 if (m_token.m_type & KeywordTokenFlag) \
77 semanticFail("Cannot use the keyword '", getToken(), "' as a ", __VA_ARGS__); \
84 template <typename LexerType>
85 void Parser<LexerType>::logError(bool)
89 StringPrintStream stream;
90 printUnexpectedTokenText(stream);
91 setErrorMessage(stream.toString());
94 template <typename LexerType> template <typename A>
95 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1)
99 StringPrintStream stream;
100 if (shouldPrintToken) {
101 printUnexpectedTokenText(stream);
104 stream.print(value1, ".");
105 setErrorMessage(stream.toString());
108 template <typename LexerType> template <typename A, typename B>
109 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2)
113 StringPrintStream stream;
114 if (shouldPrintToken) {
115 printUnexpectedTokenText(stream);
118 stream.print(value1, value2, ".");
119 setErrorMessage(stream.toString());
122 template <typename LexerType> template <typename A, typename B, typename C>
123 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2, const C& value3)
127 StringPrintStream stream;
128 if (shouldPrintToken) {
129 printUnexpectedTokenText(stream);
132 stream.print(value1, value2, value3, ".");
133 setErrorMessage(stream.toString());
136 template <typename LexerType> template <typename A, typename B, typename C, typename D>
137 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2, const C& value3, const D& value4)
141 StringPrintStream stream;
142 if (shouldPrintToken) {
143 printUnexpectedTokenText(stream);
146 stream.print(value1, value2, value3, value4, ".");
147 setErrorMessage(stream.toString());
150 template <typename LexerType> template <typename A, typename B, typename C, typename D, typename E>
151 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2, const C& value3, const D& value4, const E& value5)
155 StringPrintStream stream;
156 if (shouldPrintToken) {
157 printUnexpectedTokenText(stream);
160 stream.print(value1, value2, value3, value4, value5, ".");
161 setErrorMessage(stream.toString());
164 template <typename LexerType> template <typename A, typename B, typename C, typename D, typename E, typename F>
165 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2, const C& value3, const D& value4, const E& value5, const F& value6)
169 StringPrintStream stream;
170 if (shouldPrintToken) {
171 printUnexpectedTokenText(stream);
174 stream.print(value1, value2, value3, value4, value5, value6, ".");
175 setErrorMessage(stream.toString());
178 template <typename LexerType> template <typename A, typename B, typename C, typename D, typename E, typename F, typename G>
179 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2, const C& value3, const D& value4, const E& value5, const F& value6, const G& value7)
183 StringPrintStream stream;
184 if (shouldPrintToken) {
185 printUnexpectedTokenText(stream);
188 stream.print(value1, value2, value3, value4, value5, value6, value7, ".");
189 setErrorMessage(stream.toString());
192 template <typename LexerType>
193 Parser<LexerType>::Parser(
194 VM* vm, const SourceCode& source, FunctionParameters* parameters,
195 const Identifier& name, JSParserBuiltinMode builtinMode,
196 JSParserStrictMode strictMode, JSParserCodeType codeType,
197 ConstructorKind defaultConstructorKind, ThisTDZMode thisTDZMode)
200 , m_hasStackOverflow(false)
202 , m_assignmentCount(0)
204 , m_syntaxAlreadyValidated(source.provider()->isValid())
205 , m_statementDepth(0)
206 , m_nonTrivialExpressionCount(0)
207 , m_lastIdentifier(0)
208 , m_lastFunctionName(nullptr)
209 , m_sourceElements(0)
210 , m_parsingBuiltin(builtinMode == JSParserBuiltinMode::Builtin)
211 , m_defaultConstructorKind(defaultConstructorKind)
212 , m_thisTDZMode(thisTDZMode)
214 m_lexer = std::make_unique<LexerType>(vm, builtinMode);
215 m_lexer->setCode(source, &m_parserArena);
216 m_token.m_location.line = source.firstLine();
217 m_token.m_location.startOffset = source.startOffset();
218 m_token.m_location.endOffset = source.startOffset();
219 m_token.m_location.lineStartOffset = source.startOffset();
220 m_functionCache = vm->addSourceProviderCache(source.provider());
221 ScopeRef scope = pushScope();
222 if (codeType == JSParserCodeType::Function)
223 scope->setIsFunction();
224 if (strictMode == JSParserStrictMode::Strict)
225 scope->setStrictMode();
227 bool hadBindingParameters = false;
228 for (unsigned i = 0; i < parameters->size(); i++) {
229 auto parameter = parameters->at(i);
230 if (!parameter->isBindingNode()) {
231 hadBindingParameters = true;
234 scope->declareParameter(&static_cast<BindingNode*>(parameter)->boundProperty());
236 if (hadBindingParameters) {
237 Vector<Identifier> boundParameterNames;
238 for (unsigned i = 0; i < parameters->size(); i++) {
239 auto parameter = parameters->at(i);
240 if (parameter->isBindingNode())
242 parameter->collectBoundIdentifiers(boundParameterNames);
244 for (auto& boundParameterName : boundParameterNames)
245 scope->declareVariable(&boundParameterName);
249 scope->declareCallee(&name);
253 template <typename LexerType>
254 Parser<LexerType>::~Parser()
258 template <typename LexerType>
259 String Parser<LexerType>::parseInner()
261 String parseError = String();
263 ASTBuilder context(const_cast<VM*>(m_vm), m_parserArena, const_cast<SourceCode*>(m_source));
264 if (m_lexer->isReparsing())
266 ScopeRef scope = currentScope();
267 SourceElements* sourceElements = parseSourceElements(context, CheckForStrictMode, StandardFunctionParseType);
268 if (!sourceElements || !consume(EOFTOK)) {
270 parseError = m_errorMessage;
272 parseError = ASCIILiteral("Parser error");
275 IdentifierSet capturedVariables;
276 bool modifiedParameter = false;
277 bool modifiedArguments = false;
278 scope->getCapturedVariables(capturedVariables, modifiedParameter, modifiedArguments);
280 CodeFeatures features = context.features();
281 if (scope->strictMode())
282 features |= StrictModeFeature;
283 if (scope->shadowsArguments())
284 features |= ShadowsArgumentsFeature;
285 if (modifiedParameter)
286 features |= ModifiedParameterFeature;
287 if (modifiedArguments)
288 features |= ModifiedArgumentsFeature;
289 Vector<RefPtr<UniquedStringImpl>> closedVariables;
290 if (m_parsingBuiltin) {
291 IdentifierSet usedVariables;
292 scope->getUsedVariables(usedVariables);
293 for (const auto& variable : usedVariables) {
294 Identifier identifier = Identifier::fromUid(m_vm, variable.get());
295 if (scope->hasDeclaredVariable(identifier))
298 if (scope->hasDeclaredParameter(identifier))
301 if (variable == m_vm->propertyNames->arguments.impl())
304 closedVariables.append(variable);
307 if (!capturedVariables.isEmpty()) {
308 for (const auto& capturedVariable : capturedVariables) {
309 Identifier identifier = Identifier::fromUid(m_vm, capturedVariable.get());
310 if (scope->hasDeclaredVariable(identifier))
313 if (scope->hasDeclaredParameter(identifier))
316 RELEASE_ASSERT_NOT_REACHED();
320 didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), features,
321 context.numConstants(), capturedVariables, WTF::move(closedVariables));
326 template <typename LexerType>
327 void Parser<LexerType>::didFinishParsing(SourceElements* sourceElements, DeclarationStacks::VarStack& varStack,
328 DeclarationStacks::FunctionStack& funcStack, CodeFeatures features, int numConstants, IdentifierSet& capturedVars, const Vector<RefPtr<UniquedStringImpl>>&& closedVariables)
330 m_sourceElements = sourceElements;
331 m_varDeclarations.swap(varStack);
332 m_funcDeclarations.swap(funcStack);
333 m_capturedVariables.swap(capturedVars);
334 m_closedVariables = closedVariables;
335 m_features = features;
336 m_numConstants = numConstants;
339 template <typename LexerType>
340 bool Parser<LexerType>::allowAutomaticSemicolon()
342 return match(CLOSEBRACE) || match(EOFTOK) || m_lexer->prevTerminator();
345 template <typename LexerType>
346 template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseSourceElements(TreeBuilder& context, SourceElementsMode mode, FunctionParseType functionParseType)
348 const unsigned lengthOfUseStrictLiteral = 12; // "use strict".length
349 TreeSourceElements sourceElements = context.createSourceElements();
350 bool seenNonDirective = false;
351 const Identifier* directive = 0;
352 unsigned directiveLiteralLength = 0;
353 auto savePoint = createSavePoint();
354 bool hasSetStrict = false;
356 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
357 if (match(ARROWFUNCTION)) {
358 TreeStatement arrowfunctionStatement = parseArrowFunctionSingleExpressionBody(context, functionParseType);
360 if (arrowfunctionStatement) {
361 context.setEndOffset(arrowfunctionStatement, m_lastTokenEndPosition.offset);
362 context.appendStatement(sourceElements, arrowfunctionStatement);
366 return sourceElements;
369 UNUSED_PARAM(functionParseType);
372 while (TreeStatement statement = parseStatementListItem(context, directive, &directiveLiteralLength)) {
373 if (mode == CheckForStrictMode && !seenNonDirective) {
375 // "use strict" must be the exact literal without escape sequences or line continuation.
376 if (!hasSetStrict && directiveLiteralLength == lengthOfUseStrictLiteral && m_vm->propertyNames->useStrictIdentifier == *directive) {
379 if (!isValidStrictMode()) {
380 if (m_lastFunctionName) {
381 if (m_vm->propertyNames->arguments == *m_lastFunctionName)
382 semanticFail("Cannot name a function 'arguments' in strict mode");
383 if (m_vm->propertyNames->eval == *m_lastFunctionName)
384 semanticFail("Cannot name a function 'eval' in strict mode");
386 if (hasDeclaredVariable(m_vm->propertyNames->arguments))
387 semanticFail("Cannot declare a variable named 'arguments' in strict mode");
388 if (hasDeclaredVariable(m_vm->propertyNames->eval))
389 semanticFail("Cannot declare a variable named 'eval' in strict mode");
390 semanticFailIfFalse(isValidStrictMode(), "Invalid parameters or function name in strict mode");
392 restoreSavePoint(savePoint);
397 seenNonDirective = true;
399 context.appendStatement(sourceElements, statement);
403 return sourceElements;
405 template <typename LexerType>
406 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseStatementListItem(TreeBuilder& context, const Identifier*& directive, unsigned* directiveLiteralLength)
408 // The grammar is documented here:
409 // http://www.ecma-international.org/ecma-262/6.0/index.html#sec-statements
410 TreeStatement result = 0;
411 switch (m_token.m_type) {
413 result = parseConstDeclaration(context);
415 #if ENABLE(ES6_CLASS_SYNTAX)
417 result = parseClassDeclaration(context);
421 // FIXME: This needs to consider 'let' in bug:
422 // https://bugs.webkit.org/show_bug.cgi?id=142944
423 result = parseStatement(context, directive, directiveLiteralLength);
430 template <typename LexerType>
431 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseVarDeclaration(TreeBuilder& context)
434 JSTokenLocation location(tokenLocation());
435 int start = tokenLine();
438 TreeDestructuringPattern scratch1 = 0;
439 TreeExpression scratch2 = 0;
440 JSTextPosition scratch3;
441 TreeExpression varDecls = parseVarDeclarationList(context, scratch, scratch1, scratch2, scratch3, scratch3, scratch3, VarDeclarationContext);
443 failIfFalse(autoSemiColon(), "Expected ';' after var declaration");
445 return context.createVarStatement(location, varDecls, start, end);
448 template <typename LexerType>
449 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseConstDeclaration(TreeBuilder& context)
451 ASSERT(match(CONSTTOKEN));
452 JSTokenLocation location(tokenLocation());
453 int start = tokenLine();
455 TreeConstDeclList constDecls = parseConstDeclarationList(context);
457 failIfFalse(autoSemiColon(), "Expected ';' after const declaration");
459 return context.createConstStatement(location, constDecls, start, end);
462 template <typename LexerType>
463 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseDoWhileStatement(TreeBuilder& context)
466 int startLine = tokenLine();
468 const Identifier* unused = 0;
470 TreeStatement statement = parseStatement(context, unused);
472 failIfFalse(statement, "Expected a statement following 'do'");
473 int endLine = tokenLine();
474 JSTokenLocation location(tokenLocation());
475 handleProductionOrFail(WHILE, "while", "end", "do-while loop");
476 handleProductionOrFail(OPENPAREN, "(", "start", "do-while loop condition");
477 semanticFailIfTrue(match(CLOSEPAREN), "Must provide an expression as a do-while loop condition");
478 TreeExpression expr = parseExpression(context);
479 failIfFalse(expr, "Unable to parse do-while loop condition");
480 handleProductionOrFail(CLOSEPAREN, ")", "end", "do-while loop condition");
481 if (match(SEMICOLON))
482 next(); // Always performs automatic semicolon insertion.
483 return context.createDoWhileStatement(location, statement, expr, startLine, endLine);
486 template <typename LexerType>
487 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWhileStatement(TreeBuilder& context)
489 ASSERT(match(WHILE));
490 JSTokenLocation location(tokenLocation());
491 int startLine = tokenLine();
494 handleProductionOrFail(OPENPAREN, "(", "start", "while loop condition");
495 semanticFailIfTrue(match(CLOSEPAREN), "Must provide an expression as a while loop condition");
496 TreeExpression expr = parseExpression(context);
497 failIfFalse(expr, "Unable to parse while loop condition");
498 int endLine = tokenLine();
499 handleProductionOrFail(CLOSEPAREN, ")", "end", "while loop condition");
501 const Identifier* unused = 0;
503 TreeStatement statement = parseStatement(context, unused);
505 failIfFalse(statement, "Expected a statement as the body of a while loop");
506 return context.createWhileStatement(location, expr, statement, startLine, endLine);
509 template <typename LexerType>
510 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseVarDeclarationList(TreeBuilder& context, int& declarations, TreeDestructuringPattern& lastPattern, TreeExpression& lastInitializer, JSTextPosition& identStart, JSTextPosition& initStart, JSTextPosition& initEnd, VarDeclarationListContext declarationListContext)
512 TreeExpression head = 0;
513 TreeExpression tail = 0;
514 const Identifier* lastIdent;
515 JSToken lastIdentToken;
518 lastPattern = TreeDestructuringPattern(0);
519 JSTokenLocation location(tokenLocation());
521 TreeExpression node = 0;
523 bool hasInitializer = false;
525 JSTextPosition varStart = tokenStartPosition();
526 JSTokenLocation varStartLocation(tokenLocation());
527 identStart = varStart;
528 const Identifier* name = m_token.m_data.ident;
530 lastIdentToken = m_token;
532 hasInitializer = match(EQUAL);
533 failIfFalseIfStrict(declareVariable(name), "Cannot declare a variable named ", name->impl(), " in strict mode");
534 context.addVar(name, (hasInitializer || (!m_allowsIn && (match(INTOKEN) || isofToken()))) ? DeclarationStacks::HasInitializer : 0);
535 if (hasInitializer) {
536 JSTextPosition varDivot = tokenStartPosition() + 1;
537 initStart = tokenStartPosition();
538 next(TreeBuilder::DontBuildStrings); // consume '='
539 TreeExpression initializer = parseAssignmentExpression(context);
540 initEnd = lastTokenEndPosition();
541 lastInitializer = initializer;
542 failIfFalse(initializer, "Expected expression as the intializer for the variable '", name->impl(), "'");
544 node = context.createAssignResolve(location, *name, initializer, varStart, varDivot, lastTokenEndPosition());
546 node = context.createEmptyVarExpression(varStartLocation, *name);
549 auto pattern = parseDestructuringPattern(context, DestructureToVariables);
550 failIfFalse(pattern, "Cannot parse this destructuring pattern");
551 hasInitializer = match(EQUAL);
552 failIfTrue(declarationListContext == VarDeclarationContext && !hasInitializer, "Expected an initializer in destructuring variable declaration");
553 lastPattern = pattern;
554 if (hasInitializer) {
555 next(TreeBuilder::DontBuildStrings); // consume '='
556 TreeExpression rhs = parseAssignmentExpression(context);
557 node = context.createDestructuringAssignment(location, pattern, rhs);
558 lastInitializer = rhs;
565 head = context.createCommaExpr(location, head);
566 tail = context.appendToCommaExpr(location, head, head, node);
568 tail = context.appendToCommaExpr(location, head, tail, node);
569 } while (match(COMMA));
571 lastPattern = createBindingPattern(context, DestructureToVariables, *lastIdent, 0, lastIdentToken);
575 template <typename LexerType>
576 template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::createBindingPattern(TreeBuilder& context, DestructuringKind kind, const Identifier& name, int depth, JSToken token)
578 ASSERT(!name.isNull());
580 ASSERT(name.impl()->isAtomic() || name.impl()->isSymbol());
582 if (kind == DestructureToVariables)
583 failIfFalseIfStrict(declareVariable(&name), "Cannot destructure to a variable named '", name.impl(), "' in strict mode");
584 if (kind == DestructureToParameters) {
585 auto bindingResult = declareBoundParameter(&name);
586 if (bindingResult == Scope::StrictBindingFailed && strictMode()) {
587 semanticFailIfTrue(m_vm->propertyNames->arguments == name || m_vm->propertyNames->eval == name, "Cannot destructure to a parameter name '", name.impl(), "' in strict mode");
588 if (m_lastFunctionName && name == *m_lastFunctionName)
589 semanticFail("Cannot destructure to '", name.impl(), "' as it shadows the name of a strict mode function");
590 semanticFailureDueToKeyword("bound parameter name");
591 if (hasDeclaredParameter(name))
592 semanticFail("Cannot destructure to '", name.impl(), "' as it has already been declared");
593 semanticFail("Cannot bind to a parameter named '", name.impl(), "' in strict mode");
595 if (bindingResult == Scope::BindingFailed) {
596 semanticFailureDueToKeyword("bound parameter name");
597 if (hasDeclaredParameter(name))
598 semanticFail("Cannot destructure to '", name.impl(), "' as it has already been declared");
599 semanticFail("Cannot destructure to a parameter named '", name.impl(), "'");
602 if (kind != DestructureToExpressions)
603 context.addVar(&name, DeclarationStacks::HasInitializer);
606 if (kind == DestructureToVariables) {
607 failIfFalseIfStrict(declareVariable(&name), "Cannot declare a variable named '", name.impl(), "' in strict mode");
608 context.addVar(&name, DeclarationStacks::HasInitializer);
611 if (kind == DestructureToParameters) {
612 bool declarationResult = declareParameter(&name);
613 if (!declarationResult && strictMode()) {
614 semanticFailIfTrue(m_vm->propertyNames->arguments == name || m_vm->propertyNames->eval == name, "Cannot destructure to a parameter name '", name.impl(), "' in strict mode");
615 if (m_lastFunctionName && name == *m_lastFunctionName)
616 semanticFail("Cannot declare a parameter named '", name.impl(), "' as it shadows the name of a strict mode function");
617 semanticFailureDueToKeyword("parameter name");
618 if (hasDeclaredParameter(name))
619 semanticFail("Cannot declare a parameter named '", name.impl(), "' in strict mode as it has already been declared");
620 semanticFail("Cannot declare a parameter named '", name.impl(), "' in strict mode");
624 return context.createBindingLocation(token.m_location, name, token.m_startPosition, token.m_endPosition);
627 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
628 template <typename LexerType>
629 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseArrowFunctionSingleExpressionBody(TreeBuilder& context, FunctionParseType parseType)
631 ASSERT(match(ARROWFUNCTION));
633 // When reparsing phase, parseType becomes StandardFunctionParseType even if the function is arrow function.
634 // This condition considers the following situations.
635 // (1): If we are in the reparsing phase, this arrow function is already parsed once, so there is no syntax error.
636 // (2): But if we are not in the reparsing phase, we should check this function is called in the context of the arrow function.
637 if (!m_lexer->isReparsing() && parseType != ArrowFunctionParseType)
638 failDueToUnexpectedToken();
640 JSTokenLocation location(tokenLocation());
641 JSTextPosition start = tokenStartPosition();
642 JSTextPosition end = tokenEndPosition();
646 failIfStackOverflow();
647 TreeExpression expr = parseAssignmentExpression(context);
648 failIfFalse(expr, "Cannot parse the arrow function expression");
650 context.setEndOffset(expr, m_lastTokenEndPosition.offset);
652 failIfFalse(isEndOfArrowFunction(), "Expected a ';', ']', '}', ')', ',', line terminator or EOF following a arrow function statement");
654 end = tokenEndPosition();
656 if (!m_lexer->prevTerminator())
659 return context.createReturnStatement(location, expr, start, end);
663 template <typename LexerType>
664 template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::tryParseDestructuringPatternExpression(TreeBuilder& context)
666 return parseDestructuringPattern(context, DestructureToExpressions);
669 template <typename LexerType>
670 template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseDestructuringPattern(TreeBuilder& context, DestructuringKind kind, int depth)
672 failIfStackOverflow();
673 int nonLHSCount = m_nonLHSCount;
674 TreeDestructuringPattern pattern;
675 switch (m_token.m_type) {
677 JSTextPosition divotStart = tokenStartPosition();
678 auto arrayPattern = context.createArrayPattern(m_token.m_location);
681 bool restElementWasFound = false;
684 while (match(COMMA)) {
685 context.appendArrayPatternSkipEntry(arrayPattern, m_token.m_location);
690 if (match(CLOSEBRACKET))
693 if (UNLIKELY(match(DOTDOTDOT))) {
694 JSTokenLocation location = m_token.m_location;
696 auto innerPattern = parseDestructuringPattern(context, kind, depth + 1);
697 if (kind == DestructureToExpressions && !innerPattern)
699 failIfFalse(innerPattern, "Cannot parse this destructuring pattern");
701 failIfTrue(kind != DestructureToExpressions && !context.isBindingNode(innerPattern), "Expected identifier for a rest element destructuring pattern");
703 context.appendArrayPatternRestEntry(arrayPattern, location, innerPattern);
704 restElementWasFound = true;
708 JSTokenLocation location = m_token.m_location;
709 auto innerPattern = parseDestructuringPattern(context, kind, depth + 1);
710 if (kind == DestructureToExpressions && !innerPattern)
712 failIfFalse(innerPattern, "Cannot parse this destructuring pattern");
713 TreeExpression defaultValue = parseDefaultValueForDestructuringPattern(context);
714 failIfTrue(kind == DestructureToParameters && defaultValue, "Default values in destructuring parameters are currently not supported");
715 context.appendArrayPatternEntry(arrayPattern, location, innerPattern, defaultValue);
716 } while (consume(COMMA));
718 if (kind == DestructureToExpressions && !match(CLOSEBRACKET))
720 consumeOrFail(CLOSEBRACKET, restElementWasFound ? "Expected a closing ']' following a rest element destructuring pattern" : "Expected either a closing ']' or a ',' following an element destructuring pattern");
721 context.finishArrayPattern(arrayPattern, divotStart, divotStart, lastTokenEndPosition());
722 pattern = arrayPattern;
726 auto objectPattern = context.createObjectPattern(m_token.m_location);
730 bool wasString = false;
732 if (match(CLOSEBRACE))
735 Identifier propertyName;
736 TreeDestructuringPattern innerPattern = 0;
737 JSTokenLocation location = m_token.m_location;
739 propertyName = *m_token.m_data.ident;
740 JSToken identifierToken = m_token;
743 innerPattern = parseDestructuringPattern(context, kind, depth + 1);
745 innerPattern = createBindingPattern(context, kind, propertyName, depth, identifierToken);
747 JSTokenType tokenType = m_token.m_type;
748 switch (m_token.m_type) {
751 propertyName = Identifier::from(m_vm, m_token.m_data.doubleValue);
754 propertyName = *m_token.m_data.ident;
758 if (m_token.m_type != RESERVED && m_token.m_type != RESERVED_IF_STRICT && !(m_token.m_type & KeywordTokenFlag)) {
759 if (kind == DestructureToExpressions)
761 failWithMessage("Expected a property name");
763 propertyName = *m_token.m_data.ident;
767 if (!consume(COLON)) {
768 if (kind == DestructureToExpressions)
770 semanticFailIfTrue(tokenType == RESERVED, "Cannot use abbreviated destructuring syntax for reserved name '", propertyName.impl(), "'");
771 semanticFailIfTrue(tokenType == RESERVED_IF_STRICT, "Cannot use abbreviated destructuring syntax for reserved name '", propertyName.impl(), "' in strict mode");
772 semanticFailIfTrue(tokenType & KeywordTokenFlag, "Cannot use abbreviated destructuring syntax for keyword '", propertyName.impl(), "'");
774 failWithMessage("Expected a ':' prior to a named destructuring property");
776 innerPattern = parseDestructuringPattern(context, kind, depth + 1);
778 if (kind == DestructureToExpressions && !innerPattern)
780 failIfFalse(innerPattern, "Cannot parse this destructuring pattern");
781 TreeExpression defaultValue = parseDefaultValueForDestructuringPattern(context);
782 failIfTrue(kind == DestructureToParameters && defaultValue, "Default values in destructuring parameters are currently not supported");
783 context.appendObjectPatternEntry(objectPattern, location, wasString, propertyName, innerPattern, defaultValue);
784 } while (consume(COMMA));
786 if (kind == DestructureToExpressions && !match(CLOSEBRACE))
788 consumeOrFail(CLOSEBRACE, "Expected either a closing '}' or an ',' after a property destructuring pattern");
789 pattern = objectPattern;
795 if (kind == DestructureToExpressions)
797 semanticFailureDueToKeyword("variable name");
798 failWithMessage("Expected a parameter pattern or a ')' in parameter list");
800 pattern = createBindingPattern(context, kind, *m_token.m_data.ident, depth, m_token);
805 m_nonLHSCount = nonLHSCount;
809 template <typename LexerType>
810 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseDefaultValueForDestructuringPattern(TreeBuilder& context)
815 next(TreeBuilder::DontBuildStrings); // consume '='
816 return parseAssignmentExpression(context);
819 template <typename LexerType>
820 template <class TreeBuilder> TreeConstDeclList Parser<LexerType>::parseConstDeclarationList(TreeBuilder& context)
822 failIfTrue(strictMode(), "Const declarations are not supported in strict mode");
823 TreeConstDeclList constDecls = 0;
824 TreeConstDeclList tail = 0;
826 JSTokenLocation location(tokenLocation());
828 matchOrFail(IDENT, "Expected an identifier name in const declaration");
829 const Identifier* name = m_token.m_data.ident;
831 bool hasInitializer = match(EQUAL);
832 declareVariable(name);
833 context.addVar(name, DeclarationStacks::IsConstant | (hasInitializer ? DeclarationStacks::HasInitializer : 0));
835 TreeExpression initializer = 0;
836 if (hasInitializer) {
837 next(TreeBuilder::DontBuildStrings); // consume '='
838 initializer = parseAssignmentExpression(context);
839 failIfFalse(!!initializer, "Unable to parse initializer");
841 tail = context.appendConstDecl(location, tail, name, initializer);
844 } while (match(COMMA));
848 template <typename LexerType>
849 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseForStatement(TreeBuilder& context)
852 JSTokenLocation location(tokenLocation());
853 int startLine = tokenLine();
855 handleProductionOrFail(OPENPAREN, "(", "start", "for-loop header");
856 int nonLHSCount = m_nonLHSCount;
857 int declarations = 0;
858 JSTextPosition declsStart;
859 JSTextPosition declsEnd;
860 TreeExpression decls = 0;
861 TreeDestructuringPattern pattern = 0;
864 for (var IDENT in expression) statement
865 for (var varDeclarationList; expressionOpt; expressionOpt)
867 TreeDestructuringPattern forInTarget = 0;
868 TreeExpression forInInitializer = 0;
870 JSTextPosition initStart;
871 JSTextPosition initEnd;
872 decls = parseVarDeclarationList(context, declarations, forInTarget, forInInitializer, declsStart, initStart, initEnd, ForLoopContext);
876 // Remainder of a standard for loop is handled identically
877 if (match(SEMICOLON))
878 goto standardForLoop;
880 failIfFalse(declarations == 1, "can only declare a single variable in an enumeration");
881 failIfTrueIfStrict(forInInitializer, "Cannot use initialiser syntax in a strict mode enumeration");
883 if (forInInitializer)
884 failIfFalse(context.isBindingNode(forInTarget), "Cannot use initialiser syntax when binding to a pattern during enumeration");
886 // Handle for-in with var declaration
887 JSTextPosition inLocation = tokenStartPosition();
888 bool isOfEnumeration = false;
889 if (!consume(INTOKEN)) {
890 failIfFalse(match(IDENT) && *m_token.m_data.ident == m_vm->propertyNames->of, "Expected either 'in' or 'of' in enumeration syntax");
891 isOfEnumeration = true;
892 failIfTrue(forInInitializer, "Cannot use initialiser syntax in a for-of enumeration");
895 TreeExpression expr = parseExpression(context);
896 failIfFalse(expr, "Expected expression to enumerate");
897 JSTextPosition exprEnd = lastTokenEndPosition();
899 int endLine = tokenLine();
901 handleProductionOrFail(CLOSEPAREN, ")", "end", (isOfEnumeration ? "for-of header" : "for-in header"));
903 const Identifier* unused = 0;
905 TreeStatement statement = parseStatement(context, unused);
907 failIfFalse(statement, "Expected statement as body of for-", isOfEnumeration ? "of" : "in", " statement");
909 return context.createForOfLoop(location, forInTarget, expr, statement, declsStart, inLocation, exprEnd, startLine, endLine);
910 return context.createForInLoop(location, forInTarget, expr, statement, declsStart, inLocation, exprEnd, startLine, endLine);
913 if (!match(SEMICOLON)) {
914 if (match(OPENBRACE) || match(OPENBRACKET)) {
915 SavePoint savePoint = createSavePoint();
916 declsStart = tokenStartPosition();
917 pattern = tryParseDestructuringPatternExpression(context);
918 declsEnd = lastTokenEndPosition();
919 if (pattern && (match(INTOKEN) || (match(IDENT) && *m_token.m_data.ident == m_vm->propertyNames->of)))
920 goto enumerationLoop;
921 pattern = TreeDestructuringPattern(0);
922 restoreSavePoint(savePoint);
925 declsStart = tokenStartPosition();
926 decls = parseExpression(context);
927 declsEnd = lastTokenEndPosition();
929 failIfFalse(decls, "Cannot parse for loop declarations");
932 if (match(SEMICOLON)) {
936 TreeExpression condition = 0;
938 if (!match(SEMICOLON)) {
939 condition = parseExpression(context);
940 failIfFalse(condition, "Cannot parse for loop condition expression");
942 consumeOrFail(SEMICOLON, "Expected a ';' after the for loop condition expression");
944 TreeExpression increment = 0;
945 if (!match(CLOSEPAREN)) {
946 increment = parseExpression(context);
947 failIfFalse(increment, "Cannot parse for loop iteration expression");
949 int endLine = tokenLine();
950 handleProductionOrFail(CLOSEPAREN, ")", "end", "for-loop header");
951 const Identifier* unused = 0;
953 TreeStatement statement = parseStatement(context, unused);
955 failIfFalse(statement, "Expected a statement as the body of a for loop");
956 return context.createForLoop(location, decls, condition, increment, statement, startLine, endLine);
961 failIfFalse(nonLHSCount == m_nonLHSCount, "Expected a reference on the left hand side of an enumeration statement");
962 bool isOfEnumeration = false;
963 if (!consume(INTOKEN)) {
964 failIfFalse(match(IDENT) && *m_token.m_data.ident == m_vm->propertyNames->of, "Expected either 'in' or 'of' in enumeration syntax");
965 isOfEnumeration = true;
968 TreeExpression expr = parseExpression(context);
969 failIfFalse(expr, "Cannot parse subject for-", isOfEnumeration ? "of" : "in", " statement");
970 JSTextPosition exprEnd = lastTokenEndPosition();
971 int endLine = tokenLine();
973 handleProductionOrFail(CLOSEPAREN, ")", "end", (isOfEnumeration ? "for-of header" : "for-in header"));
974 const Identifier* unused = 0;
976 TreeStatement statement = parseStatement(context, unused);
978 failIfFalse(statement, "Expected a statement as the body of a for-", isOfEnumeration ? "of" : "in", "loop");
982 return context.createForOfLoop(location, pattern, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine);
983 return context.createForInLoop(location, pattern, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine);
986 return context.createForOfLoop(location, decls, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine);
987 return context.createForInLoop(location, decls, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine);
990 template <typename LexerType>
991 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBreakStatement(TreeBuilder& context)
993 ASSERT(match(BREAK));
994 JSTokenLocation location(tokenLocation());
995 JSTextPosition start = tokenStartPosition();
996 JSTextPosition end = tokenEndPosition();
999 if (autoSemiColon()) {
1000 semanticFailIfFalse(breakIsValid(), "'break' is only valid inside a switch or loop statement");
1001 return context.createBreakStatement(location, &m_vm->propertyNames->nullIdentifier, start, end);
1003 matchOrFail(IDENT, "Expected an identifier as the target for a break statement");
1004 const Identifier* ident = m_token.m_data.ident;
1005 semanticFailIfFalse(getLabel(ident), "Cannot use the undeclared label '", ident->impl(), "'");
1006 end = tokenEndPosition();
1008 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted break statement");
1009 return context.createBreakStatement(location, ident, start, end);
1012 template <typename LexerType>
1013 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseContinueStatement(TreeBuilder& context)
1015 ASSERT(match(CONTINUE));
1016 JSTokenLocation location(tokenLocation());
1017 JSTextPosition start = tokenStartPosition();
1018 JSTextPosition end = tokenEndPosition();
1021 if (autoSemiColon()) {
1022 semanticFailIfFalse(continueIsValid(), "'continue' is only valid inside a loop statement");
1023 return context.createContinueStatement(location, &m_vm->propertyNames->nullIdentifier, start, end);
1025 matchOrFail(IDENT, "Expected an identifier as the target for a continue statement");
1026 const Identifier* ident = m_token.m_data.ident;
1027 ScopeLabelInfo* label = getLabel(ident);
1028 semanticFailIfFalse(label, "Cannot use the undeclared label '", ident->impl(), "'");
1029 semanticFailIfFalse(label->isLoop, "Cannot continue to the label '", ident->impl(), "' as it is not targeting a loop");
1030 end = tokenEndPosition();
1032 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted continue statement");
1033 return context.createContinueStatement(location, ident, start, end);
1036 template <typename LexerType>
1037 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseReturnStatement(TreeBuilder& context)
1039 ASSERT(match(RETURN));
1040 JSTokenLocation location(tokenLocation());
1041 semanticFailIfFalse(currentScope()->isFunction(), "Return statements are only valid inside functions");
1042 JSTextPosition start = tokenStartPosition();
1043 JSTextPosition end = tokenEndPosition();
1045 // We do the auto semicolon check before attempting to parse expression
1046 // as we need to ensure the a line break after the return correctly terminates
1048 if (match(SEMICOLON))
1049 end = tokenEndPosition();
1051 if (autoSemiColon())
1052 return context.createReturnStatement(location, 0, start, end);
1053 TreeExpression expr = parseExpression(context);
1054 failIfFalse(expr, "Cannot parse the return expression");
1055 end = lastTokenEndPosition();
1056 if (match(SEMICOLON))
1057 end = tokenEndPosition();
1058 if (!autoSemiColon())
1059 failWithMessage("Expected a ';' following a return statement");
1060 return context.createReturnStatement(location, expr, start, end);
1063 template <typename LexerType>
1064 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseThrowStatement(TreeBuilder& context)
1066 ASSERT(match(THROW));
1067 JSTokenLocation location(tokenLocation());
1068 JSTextPosition start = tokenStartPosition();
1070 failIfTrue(match(SEMICOLON), "Expected expression after 'throw'");
1071 semanticFailIfTrue(autoSemiColon(), "Cannot have a newline after 'throw'");
1073 TreeExpression expr = parseExpression(context);
1074 failIfFalse(expr, "Cannot parse expression for throw statement");
1075 JSTextPosition end = lastTokenEndPosition();
1076 failIfFalse(autoSemiColon(), "Expected a ';' after a throw statement");
1078 return context.createThrowStatement(location, expr, start, end);
1081 template <typename LexerType>
1082 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWithStatement(TreeBuilder& context)
1084 ASSERT(match(WITH));
1085 JSTokenLocation location(tokenLocation());
1086 semanticFailIfTrue(strictMode(), "'with' statements are not valid in strict mode");
1087 currentScope()->setNeedsFullActivation();
1088 int startLine = tokenLine();
1091 handleProductionOrFail(OPENPAREN, "(", "start", "subject of a 'with' statement");
1092 int start = tokenStart();
1093 TreeExpression expr = parseExpression(context);
1094 failIfFalse(expr, "Cannot parse 'with' subject expression");
1095 JSTextPosition end = lastTokenEndPosition();
1096 int endLine = tokenLine();
1097 handleProductionOrFail(CLOSEPAREN, ")", "start", "subject of a 'with' statement");
1098 const Identifier* unused = 0;
1099 TreeStatement statement = parseStatement(context, unused);
1100 failIfFalse(statement, "A 'with' statement must have a body");
1102 return context.createWithStatement(location, expr, statement, start, end, startLine, endLine);
1105 template <typename LexerType>
1106 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseSwitchStatement(TreeBuilder& context)
1108 ASSERT(match(SWITCH));
1109 JSTokenLocation location(tokenLocation());
1110 int startLine = tokenLine();
1112 handleProductionOrFail(OPENPAREN, "(", "start", "subject of a 'switch'");
1113 TreeExpression expr = parseExpression(context);
1114 failIfFalse(expr, "Cannot parse switch subject expression");
1115 int endLine = tokenLine();
1117 handleProductionOrFail(CLOSEPAREN, ")", "end", "subject of a 'switch'");
1118 handleProductionOrFail(OPENBRACE, "{", "start", "body of a 'switch'");
1120 TreeClauseList firstClauses = parseSwitchClauses(context);
1123 TreeClause defaultClause = parseSwitchDefaultClause(context);
1126 TreeClauseList secondClauses = parseSwitchClauses(context);
1129 handleProductionOrFail(CLOSEBRACE, "}", "end", "body of a 'switch'");
1131 return context.createSwitchStatement(location, expr, firstClauses, defaultClause, secondClauses, startLine, endLine);
1135 template <typename LexerType>
1136 template <class TreeBuilder> TreeClauseList Parser<LexerType>::parseSwitchClauses(TreeBuilder& context)
1140 unsigned startOffset = tokenStart();
1142 TreeExpression condition = parseExpression(context);
1143 failIfFalse(condition, "Cannot parse switch clause");
1144 consumeOrFail(COLON, "Expected a ':' after switch clause expression");
1145 TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode, StandardFunctionParseType);
1146 failIfFalse(statements, "Cannot parse the body of a switch clause");
1147 TreeClause clause = context.createClause(condition, statements);
1148 context.setStartOffset(clause, startOffset);
1149 TreeClauseList clauseList = context.createClauseList(clause);
1150 TreeClauseList tail = clauseList;
1152 while (match(CASE)) {
1153 startOffset = tokenStart();
1155 TreeExpression condition = parseExpression(context);
1156 failIfFalse(condition, "Cannot parse switch case expression");
1157 consumeOrFail(COLON, "Expected a ':' after switch clause expression");
1158 TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode, StandardFunctionParseType);
1159 failIfFalse(statements, "Cannot parse the body of a switch clause");
1160 clause = context.createClause(condition, statements);
1161 context.setStartOffset(clause, startOffset);
1162 tail = context.createClauseList(tail, clause);
1167 template <typename LexerType>
1168 template <class TreeBuilder> TreeClause Parser<LexerType>::parseSwitchDefaultClause(TreeBuilder& context)
1170 if (!match(DEFAULT))
1172 unsigned startOffset = tokenStart();
1174 consumeOrFail(COLON, "Expected a ':' after switch default clause");
1175 TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode, StandardFunctionParseType);
1176 failIfFalse(statements, "Cannot parse the body of a switch default clause");
1177 TreeClause result = context.createClause(0, statements);
1178 context.setStartOffset(result, startOffset);
1182 template <typename LexerType>
1183 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseTryStatement(TreeBuilder& context)
1186 JSTokenLocation location(tokenLocation());
1187 TreeStatement tryBlock = 0;
1188 const Identifier* ident = &m_vm->propertyNames->nullIdentifier;
1189 TreeStatement catchBlock = 0;
1190 TreeStatement finallyBlock = 0;
1191 int firstLine = tokenLine();
1193 matchOrFail(OPENBRACE, "Expected a block statement as body of a try statement");
1195 tryBlock = parseBlockStatement(context);
1196 failIfFalse(tryBlock, "Cannot parse the body of try block");
1197 int lastLine = m_lastTokenEndPosition.line;
1200 currentScope()->setNeedsFullActivation();
1203 handleProductionOrFail(OPENPAREN, "(", "start", "'catch' target");
1204 if (!match(IDENT)) {
1205 semanticFailureDueToKeyword("catch variable name");
1206 failWithMessage("Expected identifier name as catch target");
1208 ident = m_token.m_data.ident;
1210 AutoPopScopeRef catchScope(this, pushScope());
1211 failIfFalseIfStrict(declareVariable(ident), "Cannot declare a catch variable named '", ident->impl(), "' in strict mode");
1212 catchScope->preventNewDecls();
1213 handleProductionOrFail(CLOSEPAREN, ")", "end", "'catch' target");
1214 matchOrFail(OPENBRACE, "Expected exception handler to be a block statement");
1215 catchBlock = parseBlockStatement(context);
1216 failIfFalse(catchBlock, "Unable to parse 'catch' block");
1217 failIfFalse(popScope(catchScope, TreeBuilder::NeedsFreeVariableInfo), "Parse error");
1220 if (match(FINALLY)) {
1222 matchOrFail(OPENBRACE, "Expected block statement for finally body");
1223 finallyBlock = parseBlockStatement(context);
1224 failIfFalse(finallyBlock, "Cannot parse finally body");
1226 failIfFalse(catchBlock || finallyBlock, "Try statements must have at least a catch or finally block");
1227 return context.createTryStatement(location, tryBlock, ident, catchBlock, finallyBlock, firstLine, lastLine);
1230 template <typename LexerType>
1231 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseDebuggerStatement(TreeBuilder& context)
1233 ASSERT(match(DEBUGGER));
1234 JSTokenLocation location(tokenLocation());
1235 int startLine = tokenLine();
1236 int endLine = startLine;
1238 if (match(SEMICOLON))
1239 startLine = tokenLine();
1240 failIfFalse(autoSemiColon(), "Debugger keyword must be followed by a ';'");
1241 return context.createDebugger(location, startLine, endLine);
1244 template <typename LexerType>
1245 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBlockStatement(TreeBuilder& context)
1247 ASSERT(match(OPENBRACE));
1248 JSTokenLocation location(tokenLocation());
1249 int startOffset = m_token.m_data.offset;
1250 int start = tokenLine();
1252 if (match(CLOSEBRACE)) {
1253 int endOffset = m_token.m_data.offset;
1255 TreeStatement result = context.createBlockStatement(location, 0, start, m_lastTokenEndPosition.line);
1256 context.setStartOffset(result, startOffset);
1257 context.setEndOffset(result, endOffset);
1260 TreeSourceElements subtree = parseSourceElements(context, DontCheckForStrictMode, StandardFunctionParseType);
1261 failIfFalse(subtree, "Cannot parse the body of the block statement");
1262 matchOrFail(CLOSEBRACE, "Expected a closing '}' at the end of a block statement");
1263 int endOffset = m_token.m_data.offset;
1265 TreeStatement result = context.createBlockStatement(location, subtree, start, m_lastTokenEndPosition.line);
1266 context.setStartOffset(result, startOffset);
1267 context.setEndOffset(result, endOffset);
1271 template <typename LexerType>
1272 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseStatement(TreeBuilder& context, const Identifier*& directive, unsigned* directiveLiteralLength)
1274 DepthManager statementDepth(&m_statementDepth);
1277 int nonTrivialExpressionCount = 0;
1278 failIfStackOverflow();
1279 TreeStatement result = 0;
1280 bool shouldSetEndOffset = true;
1282 switch (m_token.m_type) {
1284 result = parseBlockStatement(context);
1285 shouldSetEndOffset = false;
1288 result = parseVarDeclaration(context);
1291 failIfFalseIfStrict(m_statementDepth == 1, "Strict mode does not allow function declarations in a lexically nested statement");
1292 result = parseFunctionDeclaration(context);
1295 JSTokenLocation location(tokenLocation());
1297 result = context.createEmptyStatement(location);
1301 result = parseIfStatement(context);
1304 result = parseDoWhileStatement(context);
1307 result = parseWhileStatement(context);
1310 result = parseForStatement(context);
1313 result = parseContinueStatement(context);
1316 result = parseBreakStatement(context);
1319 result = parseReturnStatement(context);
1322 result = parseWithStatement(context);
1325 result = parseSwitchStatement(context);
1328 result = parseThrowStatement(context);
1331 result = parseTryStatement(context);
1334 result = parseDebuggerStatement(context);
1340 // These tokens imply the end of a set of source elements
1343 result = parseExpressionOrLabelStatement(context);
1346 directive = m_token.m_data.ident;
1347 if (directiveLiteralLength)
1348 *directiveLiteralLength = m_token.m_location.endOffset - m_token.m_location.startOffset;
1349 nonTrivialExpressionCount = m_nonTrivialExpressionCount;
1352 TreeStatement exprStatement = parseExpressionStatement(context);
1353 if (directive && nonTrivialExpressionCount != m_nonTrivialExpressionCount)
1355 result = exprStatement;
1359 if (result && shouldSetEndOffset)
1360 context.setEndOffset(result, m_lastTokenEndPosition.offset);
1364 template <typename LexerType>
1365 template <class TreeBuilder> TreeFormalParameterList Parser<LexerType>::parseFormalParameters(TreeBuilder& context)
1367 auto parameter = parseDestructuringPattern(context, DestructureToParameters);
1368 failIfFalse(parameter, "Cannot parse parameter pattern");
1369 TreeFormalParameterList list = context.createFormalParameterList(parameter);
1370 TreeFormalParameterList tail = list;
1371 while (consume(COMMA)) {
1372 parameter = parseDestructuringPattern(context, DestructureToParameters);
1373 failIfFalse(parameter, "Cannot parse parameter pattern");
1374 tail = context.createFormalParameterList(tail, parameter);
1379 template <typename LexerType>
1380 template <class TreeBuilder> TreeFunctionBody Parser<LexerType>::parseFunctionBody(
1381 TreeBuilder& context, int functionKeywordStart, int functionNameStart,
1382 int parametersStart, ConstructorKind constructorKind, FunctionParseType parseType)
1384 JSTokenLocation startLocation(tokenLocation());
1385 unsigned startColumn = tokenColumn();
1387 if (parseType == StandardFunctionParseType) {
1389 if (match(CLOSEBRACE)) {
1390 unsigned endColumn = tokenColumn();
1391 return context.createFunctionBody(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind);
1395 DepthManager statementDepth(&m_statementDepth);
1396 m_statementDepth = 0;
1397 typename TreeBuilder::FunctionBodyBuilder bodyBuilder(const_cast<VM*>(m_vm), m_lexer.get());
1398 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
1399 failIfFalse(parseSourceElements(bodyBuilder, CheckForStrictMode, parseType), parseType == StandardFunctionParseType ? "Cannot parse body of this function" : "Cannot parse body of this arrow function");
1401 failIfFalse(parseSourceElements(bodyBuilder, CheckForStrictMode, StandardFunctionParseType), "Cannot parse body of this function");
1403 unsigned endColumn = tokenColumn();
1404 return context.createFunctionBody(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind);
1407 static const char* stringForFunctionMode(FunctionParseMode mode)
1418 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
1419 case ArrowFunctionMode:
1420 return "arrow function";
1423 RELEASE_ASSERT_NOT_REACHED();
1427 template <typename LexerType> template <class TreeBuilder> int Parser<LexerType>::parseFunctionParameters(TreeBuilder& context, FunctionParseMode mode, ParserFunctionInfo<TreeBuilder>& info)
1429 int parametersStart = m_token.m_location.startOffset;
1431 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
1432 if (mode == ArrowFunctionMode) {
1433 if (!match(IDENT) && !match(OPENPAREN)) {
1434 semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
1435 failWithMessage("Expected an arrow function input parameter");
1437 if (match(OPENPAREN)) {
1440 if (!match(CLOSEPAREN)) {
1441 info.parameters = parseFormalParameters(context);
1442 failIfFalse(info.parameters, "Cannot parse parameters for this ", stringForFunctionMode(mode));
1445 consumeOrFail(CLOSEPAREN, "Expected a ')' or a ',' after a parameter declaration");
1447 auto parameter = parseDestructuringPattern(context, DestructureToParameters);
1448 failIfFalse(parameter, "Cannot parse parameter pattern");
1449 info.parameters = context.createFormalParameterList(parameter);
1450 failIfFalse(info.parameters, "Cannot parse parameters for this ", stringForFunctionMode(mode));
1454 return parametersStart;
1458 if (!consume(OPENPAREN)) {
1459 semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
1460 failWithMessage("Expected an opening '(' before a ", stringForFunctionMode(mode), "'s parameter list");
1463 if (mode == GetterMode)
1464 consumeOrFail(CLOSEPAREN, "getter functions must have no parameters");
1465 else if (mode == SetterMode) {
1466 failIfTrue(match(CLOSEPAREN), "setter functions must have one parameter");
1467 auto parameter = parseDestructuringPattern(context, DestructureToParameters);
1468 failIfFalse(parameter, "setter functions must have one parameter");
1469 info.parameters = context.createFormalParameterList(parameter);
1470 failIfTrue(match(COMMA), "setter functions must have one parameter");
1471 consumeOrFail(CLOSEPAREN, "Expected a ')' after a parameter declaration");
1473 if (!match(CLOSEPAREN)) {
1474 info.parameters = parseFormalParameters(context);
1475 failIfFalse(info.parameters, "Cannot parse parameters for this ", stringForFunctionMode(mode));
1477 consumeOrFail(CLOSEPAREN, "Expected a ')' or a ',' after a parameter declaration");
1480 return parametersStart;
1483 template <typename LexerType>
1484 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)
1486 AutoPopScopeRef functionScope(this, pushScope());
1487 functionScope->setIsFunction();
1488 int functionNameStart = m_token.m_location.startOffset;
1489 const Identifier* lastFunctionName = m_lastFunctionName;
1490 m_lastFunctionName = nullptr;
1491 int parametersStart;
1493 switch (parseType) {
1494 case StandardFunctionParseType: {
1496 info.name = m_token.m_data.ident;
1497 m_lastFunctionName = info.name;
1499 if (!nameIsInContainingScope)
1500 failIfFalseIfStrict(functionScope->declareVariable(info.name), "'", info.name->impl(), "' is not a valid ", stringForFunctionMode(mode), " name in strict mode");
1501 } else if (requirements == FunctionNeedsName) {
1502 if (match(OPENPAREN) && mode == FunctionMode)
1503 semanticFail("Function statements must have a name");
1504 semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
1505 failDueToUnexpectedToken();
1509 parametersStart = parseFunctionParameters(context, mode, info);
1512 matchOrFail(OPENBRACE, "Expected an opening '{' at the start of a ", stringForFunctionMode(mode), " body");
1514 // BytecodeGenerator emits code to throw TypeError when a class constructor is "call"ed.
1515 // Set ConstructorKind to None for non-constructor methods of classes.
1517 if (m_defaultConstructorKind != ConstructorKind::None) {
1518 constructorKind = m_defaultConstructorKind;
1519 expectedSuperBinding = m_defaultConstructorKind == ConstructorKind::Derived ? SuperBinding::Needed : SuperBinding::NotNeeded;
1522 info.startFunctionOffset = m_token.m_data.offset;
1526 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
1527 case ArrowFunctionParseType: {
1528 parametersStart = parseFunctionParameters(context, ArrowFunctionMode, info);
1531 matchOrFail(ARROWFUNCTION, "Expected a '=>' after arrow function parameter declaration");
1533 if (m_lexer->prevTerminator())
1534 failDueToUnexpectedToken();
1536 ASSERT(constructorKind == ConstructorKind::None);
1538 info.arrowFunctionOffset = m_token.m_data.offset;
1539 // Check if arrow body start with {. If it true it mean that arrow function is Fat arrow function
1540 // and we need use common approach to parse function body
1541 SavePoint savePoint = createSavePoint();
1544 info.functionBodyType = match(OPENBRACE) ? ArrowFunctionBodyBlock : ArrowFunctionBodyExpression;
1545 info.startFunctionOffset = (info.functionBodyType == ArrowFunctionBodyBlock) ? m_token.m_data.offset : info.arrowFunctionOffset;
1547 restoreSavePoint(savePoint);
1554 bool isClassConstructor = constructorKind != ConstructorKind::None;
1556 info.bodyStartLine = tokenLine();
1557 info.bodyStartColumn = m_token.m_data.offset - m_token.m_data.lineStartOffset;
1558 JSTokenLocation startLocation(tokenLocation());
1560 // If we know about this function already, we can use the cached info and skip the parser to the end of the function.
1561 if (const SourceProviderCacheItem* cachedInfo = TreeBuilder::CanUseFunctionCache ? findCachedFunctionInfo(info.startFunctionOffset) : 0) {
1562 // If we're in a strict context, the cached function info must say it was strict too.
1563 ASSERT(!strictMode() || cachedInfo->strictMode);
1564 JSTokenLocation endLocation;
1566 endLocation.line = cachedInfo->lastTockenLine;
1567 endLocation.startOffset = cachedInfo->lastTockenStartOffset;
1568 endLocation.lineStartOffset = cachedInfo->lastTockenLineStartOffset;
1570 bool endColumnIsOnStartLine = (endLocation.line == info.bodyStartLine);
1571 ASSERT(endLocation.startOffset >= endLocation.lineStartOffset);
1572 unsigned bodyEndColumn = endColumnIsOnStartLine ?
1573 endLocation.startOffset - m_token.m_data.lineStartOffset :
1574 endLocation.startOffset - endLocation.lineStartOffset;
1575 unsigned currentLineStartOffset = m_token.m_location.lineStartOffset;
1577 info.body = context.createFunctionBody(
1578 startLocation, endLocation, info.bodyStartColumn, bodyEndColumn,
1579 functionKeywordStart, functionNameStart, parametersStart,
1580 cachedInfo->strictMode, constructorKind);
1582 functionScope->restoreFromSourceProviderCache(cachedInfo);
1583 failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo), "Parser error");
1585 m_token = cachedInfo->endFunctionToken();
1587 if (endColumnIsOnStartLine)
1588 m_token.m_location.lineStartOffset = currentLineStartOffset;
1590 m_lexer->setOffset(m_token.m_location.endOffset, m_token.m_location.lineStartOffset);
1591 m_lexer->setLineNumber(m_token.m_location.line);
1592 info.endFunctionOffset = cachedInfo->endFunctionOffset;
1593 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
1594 if (parseType == ArrowFunctionParseType)
1595 info.functionBodyType = cachedInfo->isBodyArrowExpression ? ArrowFunctionBodyExpression : ArrowFunctionBodyBlock;
1597 info.functionBodyType = StandardFunctionBodyBlock;
1599 switch (info.functionBodyType) {
1600 case ArrowFunctionBodyExpression:
1602 context.setEndOffset(info.body, m_lexer->currentOffset());
1604 case ArrowFunctionBodyBlock:
1605 case StandardFunctionBodyBlock:
1606 context.setEndOffset(info.body, m_lexer->currentOffset());
1611 context.setEndOffset(info.body, m_lexer->currentOffset());
1614 info.bodyEndLine = m_lastTokenEndPosition.line;
1618 m_lastFunctionName = lastFunctionName;
1619 ParserState oldState = saveState();
1621 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
1622 switch (info.functionBodyType) {
1623 case ArrowFunctionBodyBlock: {
1624 // Consume => in case of arrow function block e.g. x => { return x; }
1627 info.bodyStartLine = tokenLine();
1628 info.bodyStartColumn = m_token.m_data.offset - m_token.m_data.lineStartOffset;
1630 info.body = parseFunctionBody(context, functionKeywordStart, functionNameStart, parametersStart, constructorKind, StandardFunctionParseType);
1633 case StandardFunctionBodyBlock:
1634 case ArrowFunctionBodyExpression : {
1635 info.body = parseFunctionBody(context, functionKeywordStart, functionNameStart, parametersStart, constructorKind, parseType);
1640 info.body = parseFunctionBody(context, functionKeywordStart, functionNameStart, parametersStart, constructorKind, StandardFunctionParseType);
1643 restoreState(oldState);
1644 failIfFalse(info.body, "Cannot parse the body of this ", stringForFunctionMode(mode));
1645 context.setEndOffset(info.body, m_lexer->currentOffset());
1646 if (functionScope->strictMode() && info.name) {
1647 RELEASE_ASSERT(mode == FunctionMode || mode == MethodMode);
1648 semanticFailIfTrue(m_vm->propertyNames->arguments == *info.name, "'", info.name->impl(), "' is not a valid function name in strict mode");
1649 semanticFailIfTrue(m_vm->propertyNames->eval == *info.name, "'", info.name->impl(), "' is not a valid function name in strict mode");
1651 if (functionScope->hasDirectSuper()) {
1652 semanticFailIfTrue(!isClassConstructor, "Cannot call super() outside of a class constructor");
1653 semanticFailIfTrue(constructorKind != ConstructorKind::Derived, "Cannot call super() in a base class constructor");
1655 if (functionScope->needsSuperBinding())
1656 semanticFailIfTrue(expectedSuperBinding == SuperBinding::NotNeeded, "super can only be used in a method of a derived class");
1658 JSTokenLocation location = JSTokenLocation(m_token.m_location);
1659 info.endFunctionOffset = m_token.m_data.offset;
1661 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
1662 if (info.functionBodyType == ArrowFunctionBodyExpression) {
1663 location = locationBeforeLastToken();
1664 info.endFunctionOffset = location.endOffset;
1668 // Cache the tokenizer state and the function scope the first time the function is parsed.
1669 // Any future reparsing can then skip the function.
1670 static const int minimumFunctionLengthToCache = 16;
1671 std::unique_ptr<SourceProviderCacheItem> newInfo;
1672 int functionLength = info.endFunctionOffset - info.startFunctionOffset;
1673 if (TreeBuilder::CanUseFunctionCache && m_functionCache && functionLength > minimumFunctionLengthToCache) {
1674 SourceProviderCacheItemCreationParameters parameters;
1675 parameters.endFunctionOffset = info.endFunctionOffset;
1676 parameters.functionNameStart = functionNameStart;
1677 parameters.lastTockenLine = location.line;
1678 parameters.lastTockenStartOffset = location.startOffset;
1679 parameters.lastTockenEndOffset = location.endOffset;
1680 parameters.lastTockenLineStartOffset = location.lineStartOffset;
1681 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
1682 if (info.functionBodyType == ArrowFunctionBodyExpression) {
1683 parameters.isBodyArrowExpression = true;
1684 parameters.tokenType = m_token.m_type;
1687 functionScope->fillParametersForSourceProviderCache(parameters);
1688 newInfo = SourceProviderCacheItem::create(parameters);
1691 failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo), "Parser error");
1693 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
1694 if (info.functionBodyType == ArrowFunctionBodyExpression)
1695 failIfFalse(isEndOfArrowFunction(), "Expected the closing ';' ',' ']' ')' '}', line terminator or EOF after arrow function");
1697 matchOrFail(CLOSEBRACE, "Expected a closing '}' after a ", stringForFunctionMode(mode), " body");
1701 matchOrFail(CLOSEBRACE, "Expected a closing '}' after a ", stringForFunctionMode(mode), " body");
1706 m_functionCache->add(info.startFunctionOffset, WTF::move(newInfo));
1708 info.bodyEndLine = m_lastTokenEndPosition.line;
1712 template <typename LexerType>
1713 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDeclaration(TreeBuilder& context)
1715 ASSERT(match(FUNCTION));
1716 JSTokenLocation location(tokenLocation());
1717 unsigned functionKeywordStart = tokenStart();
1719 ParserFunctionInfo<TreeBuilder> info;
1720 failIfFalse((parseFunctionInfo(context, FunctionNeedsName, FunctionMode, true, ConstructorKind::None, SuperBinding::NotNeeded,
1721 functionKeywordStart, info, StandardFunctionParseType)), "Cannot parse this function");
1722 failIfFalse(info.name, "Function statements must have a name");
1723 failIfFalseIfStrict(declareVariable(info.name), "Cannot declare a function named '", info.name->impl(), "' in strict mode");
1724 return context.createFuncDeclStatement(location, info);
1727 #if ENABLE(ES6_CLASS_SYNTAX)
1728 template <typename LexerType>
1729 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseClassDeclaration(TreeBuilder& context)
1731 ASSERT(match(CLASSTOKEN));
1732 JSTokenLocation location(tokenLocation());
1733 JSTextPosition classStart = tokenStartPosition();
1734 unsigned classStartLine = tokenLine();
1736 ParserClassInfo<TreeBuilder> info;
1737 TreeClassExpression classExpr = parseClass(context, FunctionNeedsName, info);
1738 failIfFalse(classExpr, "Failed to parse class");
1739 declareVariable(info.className);
1741 // FIXME: This should be like `let`, not `var`.
1742 context.addVar(info.className, DeclarationStacks::HasInitializer);
1744 JSTextPosition classEnd = lastTokenEndPosition();
1745 unsigned classEndLine = tokenLine();
1747 return context.createClassDeclStatement(location, classExpr, classStart, classEnd, classStartLine, classEndLine);
1750 template <typename LexerType>
1751 template <class TreeBuilder> TreeClassExpression Parser<LexerType>::parseClass(TreeBuilder& context, FunctionRequirements requirements, ParserClassInfo<TreeBuilder>& info)
1753 ASSERT(match(CLASSTOKEN));
1754 JSTokenLocation location(tokenLocation());
1757 AutoPopScopeRef classScope(this, pushScope());
1758 classScope->setStrictMode();
1760 const Identifier* className = nullptr;
1762 className = m_token.m_data.ident;
1763 info.className = className;
1765 failIfFalse(classScope->declareVariable(className), "'", className->impl(), "' is not a valid class name");
1766 } else if (requirements == FunctionNeedsName) {
1767 if (match(OPENBRACE))
1768 semanticFail("Class statements must have a name");
1769 semanticFailureDueToKeyword("class name");
1770 failDueToUnexpectedToken();
1772 className = &m_vm->propertyNames->nullIdentifier;
1775 TreeExpression parentClass = 0;
1776 if (consume(EXTENDS)) {
1777 parentClass = parseMemberExpression(context);
1778 failIfFalse(parentClass, "Cannot parse the parent class name");
1780 const ConstructorKind constructorKind = parentClass ? ConstructorKind::Derived : ConstructorKind::Base;
1782 consumeOrFail(OPENBRACE, "Expected opening '{' at the start of a class body");
1784 TreeExpression constructor = 0;
1785 TreePropertyList staticMethods = 0;
1786 TreePropertyList instanceMethods = 0;
1787 TreePropertyList instanceMethodsTail = 0;
1788 TreePropertyList staticMethodsTail = 0;
1789 while (!match(CLOSEBRACE)) {
1790 if (match(SEMICOLON)) {
1795 JSTokenLocation methodLocation(tokenLocation());
1796 unsigned methodStart = tokenStart();
1798 // For backwards compatibility, "static" is a non-reserved keyword in non-strict mode.
1799 bool isStaticMethod = match(RESERVED_IF_STRICT) && *m_token.m_data.ident == m_vm->propertyNames->staticKeyword;
1803 // FIXME: Figure out a way to share more code with parseProperty.
1804 const CommonIdentifiers& propertyNames = *m_vm->propertyNames;
1805 const Identifier* ident = nullptr;
1806 bool isGetter = false;
1807 bool isSetter = false;
1808 switch (m_token.m_type) {
1810 ident = m_token.m_data.ident;
1815 ident = m_token.m_data.ident;
1816 isGetter = *ident == propertyNames.get;
1817 isSetter = *ident == propertyNames.set;
1822 ident = &m_parserArena.identifierArena().makeNumericIdentifier(const_cast<VM*>(m_vm), m_token.m_data.doubleValue);
1827 failDueToUnexpectedToken();
1830 TreeProperty property;
1831 const bool alwaysStrictInsideClass = true;
1832 if (isGetter || isSetter) {
1833 nextExpectIdentifier(LexerFlagsIgnoreReservedWords);
1834 property = parseGetterSetter(context, alwaysStrictInsideClass, isGetter ? PropertyNode::Getter : PropertyNode::Setter, methodStart,
1835 ConstructorKind::None, SuperBinding::Needed);
1836 failIfFalse(property, "Cannot parse this method");
1838 ParserFunctionInfo<TreeBuilder> methodInfo;
1839 bool isConstructor = !isStaticMethod && *ident == propertyNames.constructor;
1840 failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, isStaticMethod ? FunctionMode : MethodMode, false, isConstructor ? constructorKind : ConstructorKind::None, SuperBinding::Needed, methodStart, methodInfo, StandardFunctionParseType)), "Cannot parse this method");
1841 failIfFalse(ident && declareVariable(ident), "Cannot declare a method named '", methodInfo.name->impl(), "'");
1842 methodInfo.name = isConstructor ? className : ident;
1844 TreeExpression method = context.createFunctionExpr(methodLocation, methodInfo);
1845 if (isConstructor) {
1846 semanticFailIfTrue(constructor, "Cannot declare multiple constructors in a single class");
1847 constructor = method;
1851 // FIXME: Syntax error when super() is called
1852 semanticFailIfTrue(isStaticMethod && methodInfo.name && *methodInfo.name == propertyNames.prototype,
1853 "Cannot declare a static method named 'prototype'");
1854 property = context.createProperty(methodInfo.name, method, PropertyNode::Constant, PropertyNode::Unknown, alwaysStrictInsideClass, SuperBinding::Needed);
1857 TreePropertyList& tail = isStaticMethod ? staticMethodsTail : instanceMethodsTail;
1859 tail = context.createPropertyList(methodLocation, property, tail);
1861 tail = context.createPropertyList(methodLocation, property);
1863 staticMethods = tail;
1865 instanceMethods = tail;
1869 failIfFalse(popScope(classScope, TreeBuilder::NeedsFreeVariableInfo), "Parser error");
1870 consumeOrFail(CLOSEBRACE, "Expected a closing '}' after a class body");
1872 return context.createClassExpr(location, *className, constructor, parentClass, instanceMethods, staticMethods);
1877 LabelInfo(const Identifier* ident, const JSTextPosition& start, const JSTextPosition& end)
1884 const Identifier* m_ident;
1885 JSTextPosition m_start;
1886 JSTextPosition m_end;
1889 template <typename LexerType>
1890 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionOrLabelStatement(TreeBuilder& context)
1893 /* Expression and Label statements are ambiguous at LL(1), so we have a
1894 * special case that looks for a colon as the next character in the input.
1896 Vector<LabelInfo> labels;
1897 JSTokenLocation location;
1899 JSTextPosition start = tokenStartPosition();
1900 location = tokenLocation();
1901 if (!nextTokenIsColon()) {
1902 // If we hit this path we're making a expression statement, which
1903 // by definition can't make use of continue/break so we can just
1904 // ignore any labels we might have accumulated.
1905 TreeExpression expression = parseExpression(context);
1906 failIfFalse(expression, "Cannot parse expression statement");
1907 if (!autoSemiColon())
1908 failDueToUnexpectedToken();
1909 return context.createExprStatement(location, expression, start, m_lastTokenEndPosition.line);
1911 const Identifier* ident = m_token.m_data.ident;
1912 JSTextPosition end = tokenEndPosition();
1914 consumeOrFail(COLON, "Labels must be followed by a ':'");
1915 if (!m_syntaxAlreadyValidated) {
1916 // This is O(N^2) over the current list of consecutive labels, but I
1917 // have never seen more than one label in a row in the real world.
1918 for (size_t i = 0; i < labels.size(); i++)
1919 failIfTrue(ident->impl() == labels[i].m_ident->impl(), "Attempted to redeclare the label '", ident->impl(), "'");
1920 failIfTrue(getLabel(ident), "Cannot find scope for the label '", ident->impl(), "'");
1921 labels.append(LabelInfo(ident, start, end));
1923 } while (match(IDENT));
1924 bool isLoop = false;
1925 switch (m_token.m_type) {
1935 const Identifier* unused = 0;
1936 if (!m_syntaxAlreadyValidated) {
1937 for (size_t i = 0; i < labels.size(); i++)
1938 pushLabel(labels[i].m_ident, isLoop);
1940 TreeStatement statement = parseStatement(context, unused);
1941 if (!m_syntaxAlreadyValidated) {
1942 for (size_t i = 0; i < labels.size(); i++)
1945 failIfFalse(statement, "Cannot parse statement");
1946 for (size_t i = 0; i < labels.size(); i++) {
1947 const LabelInfo& info = labels[labels.size() - i - 1];
1948 statement = context.createLabelStatement(location, info.m_ident, statement, info.m_start, info.m_end);
1953 template <typename LexerType>
1954 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionStatement(TreeBuilder& context)
1956 switch (m_token.m_type) {
1957 // Consult: http://www.ecma-international.org/ecma-262/6.0/index.html#sec-expression-statement
1958 // The ES6 spec mandates that we should fail from FUNCTION token here. We handle this case
1959 // in parseStatement() which is the only caller of parseExpressionStatement().
1960 // We actually allow FUNCTION in situations where it should not be allowed unless we're in strict mode.
1962 failWithMessage("'class' declaration is not directly within a block statement");
1965 // FIXME: when implementing 'let' we should fail when we see the token sequence "let [".
1966 // https://bugs.webkit.org/show_bug.cgi?id=142944
1969 JSTextPosition start = tokenStartPosition();
1970 JSTokenLocation location(tokenLocation());
1971 TreeExpression expression = parseExpression(context);
1972 failIfFalse(expression, "Cannot parse expression statement");
1973 failIfFalse(autoSemiColon(), "Parse error");
1974 return context.createExprStatement(location, expression, start, m_lastTokenEndPosition.line);
1977 template <typename LexerType>
1978 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseIfStatement(TreeBuilder& context)
1981 JSTokenLocation ifLocation(tokenLocation());
1982 int start = tokenLine();
1984 handleProductionOrFail(OPENPAREN, "(", "start", "'if' condition");
1986 TreeExpression condition = parseExpression(context);
1987 failIfFalse(condition, "Expected a expression as the condition for an if statement");
1988 int end = tokenLine();
1989 handleProductionOrFail(CLOSEPAREN, ")", "end", "'if' condition");
1991 const Identifier* unused = 0;
1992 TreeStatement trueBlock = parseStatement(context, unused);
1993 failIfFalse(trueBlock, "Expected a statement as the body of an if block");
1996 return context.createIfStatement(ifLocation, condition, trueBlock, 0, start, end);
1998 Vector<TreeExpression> exprStack;
1999 Vector<std::pair<int, int>> posStack;
2000 Vector<JSTokenLocation> tokenLocationStack;
2001 Vector<TreeStatement> statementStack;
2002 bool trailingElse = false;
2004 JSTokenLocation tempLocation = tokenLocation();
2007 const Identifier* unused = 0;
2008 TreeStatement block = parseStatement(context, unused);
2009 failIfFalse(block, "Expected a statement as the body of an else block");
2010 statementStack.append(block);
2011 trailingElse = true;
2014 int innerStart = tokenLine();
2017 handleProductionOrFail(OPENPAREN, "(", "start", "'if' condition");
2019 TreeExpression innerCondition = parseExpression(context);
2020 failIfFalse(innerCondition, "Expected a expression as the condition for an if statement");
2021 int innerEnd = tokenLine();
2022 handleProductionOrFail(CLOSEPAREN, ")", "end", "'if' condition");
2023 const Identifier* unused = 0;
2024 TreeStatement innerTrueBlock = parseStatement(context, unused);
2025 failIfFalse(innerTrueBlock, "Expected a statement as the body of an if block");
2026 tokenLocationStack.append(tempLocation);
2027 exprStack.append(innerCondition);
2028 posStack.append(std::make_pair(innerStart, innerEnd));
2029 statementStack.append(innerTrueBlock);
2030 } while (match(ELSE));
2032 if (!trailingElse) {
2033 TreeExpression condition = exprStack.last();
2034 exprStack.removeLast();
2035 TreeStatement trueBlock = statementStack.last();
2036 statementStack.removeLast();
2037 std::pair<int, int> pos = posStack.last();
2038 posStack.removeLast();
2039 JSTokenLocation elseLocation = tokenLocationStack.last();
2040 tokenLocationStack.removeLast();
2041 TreeStatement ifStatement = context.createIfStatement(elseLocation, condition, trueBlock, 0, pos.first, pos.second);
2042 context.setEndOffset(ifStatement, context.endOffset(trueBlock));
2043 statementStack.append(ifStatement);
2046 while (!exprStack.isEmpty()) {
2047 TreeExpression condition = exprStack.last();
2048 exprStack.removeLast();
2049 TreeStatement falseBlock = statementStack.last();
2050 statementStack.removeLast();
2051 TreeStatement trueBlock = statementStack.last();
2052 statementStack.removeLast();
2053 std::pair<int, int> pos = posStack.last();
2054 posStack.removeLast();
2055 JSTokenLocation elseLocation = tokenLocationStack.last();
2056 tokenLocationStack.removeLast();
2057 TreeStatement ifStatement = context.createIfStatement(elseLocation, condition, trueBlock, falseBlock, pos.first, pos.second);
2058 context.setEndOffset(ifStatement, context.endOffset(falseBlock));
2059 statementStack.append(ifStatement);
2062 return context.createIfStatement(ifLocation, condition, trueBlock, statementStack.last(), start, end);
2065 template <typename LexerType>
2066 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseExpression(TreeBuilder& context)
2068 failIfStackOverflow();
2069 JSTokenLocation location(tokenLocation());
2070 TreeExpression node = parseAssignmentExpression(context);
2071 failIfFalse(node, "Cannot parse expression");
2072 context.setEndOffset(node, m_lastTokenEndPosition.offset);
2076 m_nonTrivialExpressionCount++;
2078 TreeExpression right = parseAssignmentExpression(context);
2079 failIfFalse(right, "Cannot parse expression in a comma expression");
2080 context.setEndOffset(right, m_lastTokenEndPosition.offset);
2081 typename TreeBuilder::Comma head = context.createCommaExpr(location, node);
2082 typename TreeBuilder::Comma tail = context.appendToCommaExpr(location, head, head, right);
2083 while (match(COMMA)) {
2084 next(TreeBuilder::DontBuildStrings);
2085 right = parseAssignmentExpression(context);
2086 failIfFalse(right, "Cannot parse expression in a comma expression");
2087 context.setEndOffset(right, m_lastTokenEndPosition.offset);
2088 tail = context.appendToCommaExpr(location, head, tail, right);
2090 context.setEndOffset(head, m_lastTokenEndPosition.offset);
2095 template <typename LexerType>
2096 template <typename TreeBuilder> TreeExpression Parser<LexerType>::parseAssignmentExpression(TreeBuilder& context)
2098 failIfStackOverflow();
2099 JSTextPosition start = tokenStartPosition();
2100 JSTokenLocation location(tokenLocation());
2101 int initialAssignmentCount = m_assignmentCount;
2102 int initialNonLHSCount = m_nonLHSCount;
2103 if (match(OPENBRACE) || match(OPENBRACKET)) {
2104 SavePoint savePoint = createSavePoint();
2105 auto pattern = tryParseDestructuringPatternExpression(context);
2106 if (pattern && consume(EQUAL)) {
2107 auto rhs = parseAssignmentExpression(context);
2109 return context.createDestructuringAssignment(location, pattern, rhs);
2111 restoreSavePoint(savePoint);
2114 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
2115 if (isArrowFunctionParamters())
2116 return parseArrowFunctionExpression(context);
2119 TreeExpression lhs = parseConditionalExpression(context);
2120 failIfFalse(lhs, "Cannot parse expression");
2121 if (initialNonLHSCount != m_nonLHSCount) {
2122 if (m_token.m_type >= EQUAL && m_token.m_type <= OREQUAL)
2123 semanticFail("Left hand side of operator '", getToken(), "' must be a reference");
2128 int assignmentStack = 0;
2130 bool hadAssignment = false;
2132 switch (m_token.m_type) {
2133 case EQUAL: op = OpEqual; break;
2134 case PLUSEQUAL: op = OpPlusEq; break;
2135 case MINUSEQUAL: op = OpMinusEq; break;
2136 case MULTEQUAL: op = OpMultEq; break;
2137 case DIVEQUAL: op = OpDivEq; break;
2138 case LSHIFTEQUAL: op = OpLShift; break;
2139 case RSHIFTEQUAL: op = OpRShift; break;
2140 case URSHIFTEQUAL: op = OpURShift; break;
2141 case ANDEQUAL: op = OpAndEq; break;
2142 case XOREQUAL: op = OpXOrEq; break;
2143 case OREQUAL: op = OpOrEq; break;
2144 case MODEQUAL: op = OpModEq; break;
2148 m_nonTrivialExpressionCount++;
2149 hadAssignment = true;
2150 context.assignmentStackAppend(assignmentStack, lhs, start, tokenStartPosition(), m_assignmentCount, op);
2151 start = tokenStartPosition();
2152 m_assignmentCount++;
2153 next(TreeBuilder::DontBuildStrings);
2154 if (strictMode() && m_lastIdentifier && context.isResolve(lhs)) {
2155 failIfTrueIfStrict(m_vm->propertyNames->eval == *m_lastIdentifier, "Cannot modify 'eval' in strict mode");
2156 failIfTrueIfStrict(m_vm->propertyNames->arguments == *m_lastIdentifier, "Cannot modify 'arguments' in strict mode");
2157 declareWrite(m_lastIdentifier);
2158 m_lastIdentifier = 0;
2160 lhs = parseAssignmentExpression(context);
2161 failIfFalse(lhs, "Cannot parse the right hand side of an assignment expression");
2162 if (initialNonLHSCount != m_nonLHSCount) {
2163 if (m_token.m_type >= EQUAL && m_token.m_type <= OREQUAL)
2164 semanticFail("Left hand side of operator '", getToken(), "' must be a reference");
2172 if (!TreeBuilder::CreatesAST)
2175 while (assignmentStack)
2176 lhs = context.createAssignment(location, assignmentStack, lhs, initialAssignmentCount, m_assignmentCount, lastTokenEndPosition());
2181 template <typename LexerType>
2182 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseConditionalExpression(TreeBuilder& context)
2184 JSTokenLocation location(tokenLocation());
2185 TreeExpression cond = parseBinaryExpression(context);
2186 failIfFalse(cond, "Cannot parse expression");
2187 if (!match(QUESTION))
2189 m_nonTrivialExpressionCount++;
2191 next(TreeBuilder::DontBuildStrings);
2192 TreeExpression lhs = parseAssignmentExpression(context);
2193 failIfFalse(lhs, "Cannot parse left hand side of ternary operator");
2194 context.setEndOffset(lhs, m_lastTokenEndPosition.offset);
2195 consumeOrFailWithFlags(COLON, TreeBuilder::DontBuildStrings, "Expected ':' in ternary operator");
2197 TreeExpression rhs = parseAssignmentExpression(context);
2198 failIfFalse(rhs, "Cannot parse right hand side of ternary operator");
2199 context.setEndOffset(rhs, m_lastTokenEndPosition.offset);
2200 return context.createConditionalExpr(location, cond, lhs, rhs);
2203 ALWAYS_INLINE static bool isUnaryOp(JSTokenType token)
2205 return token & UnaryOpTokenFlag;
2208 template <typename LexerType>
2209 int Parser<LexerType>::isBinaryOperator(JSTokenType token)
2212 return token & (BinaryOpTokenPrecedenceMask << BinaryOpTokenAllowsInPrecedenceAdditionalShift);
2213 return token & BinaryOpTokenPrecedenceMask;
2216 template <typename LexerType>
2217 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseBinaryExpression(TreeBuilder& context)
2219 int operandStackDepth = 0;
2220 int operatorStackDepth = 0;
2221 typename TreeBuilder::BinaryExprContext binaryExprContext(context);
2222 JSTokenLocation location(tokenLocation());
2224 JSTextPosition exprStart = tokenStartPosition();
2225 int initialAssignments = m_assignmentCount;
2226 TreeExpression current = parseUnaryExpression(context);
2227 failIfFalse(current, "Cannot parse expression");
2229 context.appendBinaryExpressionInfo(operandStackDepth, current, exprStart, lastTokenEndPosition(), lastTokenEndPosition(), initialAssignments != m_assignmentCount);
2230 int precedence = isBinaryOperator(m_token.m_type);
2233 m_nonTrivialExpressionCount++;
2235 int operatorToken = m_token.m_type;
2236 next(TreeBuilder::DontBuildStrings);
2238 while (operatorStackDepth && context.operatorStackHasHigherPrecedence(operatorStackDepth, precedence)) {
2239 ASSERT(operandStackDepth > 1);
2241 typename TreeBuilder::BinaryOperand rhs = context.getFromOperandStack(-1);
2242 typename TreeBuilder::BinaryOperand lhs = context.getFromOperandStack(-2);
2243 context.shrinkOperandStackBy(operandStackDepth, 2);
2244 context.appendBinaryOperation(location, operandStackDepth, operatorStackDepth, lhs, rhs);
2245 context.operatorStackPop(operatorStackDepth);
2247 context.operatorStackAppend(operatorStackDepth, operatorToken, precedence);
2249 while (operatorStackDepth) {
2250 ASSERT(operandStackDepth > 1);
2252 typename TreeBuilder::BinaryOperand rhs = context.getFromOperandStack(-1);
2253 typename TreeBuilder::BinaryOperand lhs = context.getFromOperandStack(-2);
2254 context.shrinkOperandStackBy(operandStackDepth, 2);
2255 context.appendBinaryOperation(location, operandStackDepth, operatorStackDepth, lhs, rhs);
2256 context.operatorStackPop(operatorStackDepth);
2258 return context.popOperandStack(operandStackDepth);
2261 template <typename LexerType>
2262 template <class TreeBuilder> TreeProperty Parser<LexerType>::parseProperty(TreeBuilder& context, bool complete)
2264 bool wasIdent = false;
2265 switch (m_token.m_type) {
2271 const Identifier* ident = m_token.m_data.ident;
2272 unsigned getterOrSetterStartOffset = tokenStart();
2273 if (complete || (wasIdent && (*ident == m_vm->propertyNames->get || *ident == m_vm->propertyNames->set)))
2274 nextExpectIdentifier(LexerFlagsIgnoreReservedWords);
2276 nextExpectIdentifier(LexerFlagsIgnoreReservedWords | TreeBuilder::DontBuildKeywords);
2280 TreeExpression node = parseAssignmentExpression(context);
2281 failIfFalse(node, "Cannot parse expression for property declaration");
2282 context.setEndOffset(node, m_lexer->currentOffset());
2283 return context.createProperty(ident, node, PropertyNode::Constant, PropertyNode::Unknown, complete);
2286 if (match(OPENPAREN)) {
2287 auto method = parsePropertyMethod(context, ident);
2289 return context.createProperty(ident, method, PropertyNode::Constant, PropertyNode::KnownDirect, complete);
2292 failIfFalse(wasIdent, "Expected an identifier as property name");
2294 if (match(COMMA) || match(CLOSEBRACE)) {
2295 JSTextPosition start = tokenStartPosition();
2296 JSTokenLocation location(tokenLocation());
2297 currentScope()->useVariable(ident, m_vm->propertyNames->eval == *ident);
2298 TreeExpression node = context.createResolve(location, ident, start);
2299 return context.createProperty(ident, node, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Shorthand), PropertyNode::KnownDirect, complete);
2302 PropertyNode::Type type;
2303 if (*ident == m_vm->propertyNames->get)
2304 type = PropertyNode::Getter;
2305 else if (*ident == m_vm->propertyNames->set)
2306 type = PropertyNode::Setter;
2308 failWithMessage("Expected a ':' following the property name '", ident->impl(), "'");
2309 return parseGetterSetter(context, complete, type, getterOrSetterStartOffset);
2313 double propertyName = m_token.m_data.doubleValue;
2316 if (match(OPENPAREN)) {
2317 const Identifier& ident = m_parserArena.identifierArena().makeNumericIdentifier(const_cast<VM*>(m_vm), propertyName);
2318 auto method = parsePropertyMethod(context, &ident);
2320 return context.createProperty(&ident, method, PropertyNode::Constant, PropertyNode::Unknown, complete);
2323 consumeOrFail(COLON, "Expected ':' after property name");
2324 TreeExpression node = parseAssignmentExpression(context);
2325 failIfFalse(node, "Cannot parse expression for property declaration");
2326 context.setEndOffset(node, m_lexer->currentOffset());
2327 return context.createProperty(const_cast<VM*>(m_vm), m_parserArena, propertyName, node, PropertyNode::Constant, PropertyNode::Unknown, complete);
2331 auto propertyName = parseAssignmentExpression(context);
2332 failIfFalse(propertyName, "Cannot parse computed property name");
2333 handleProductionOrFail(CLOSEBRACKET, "]", "end", "computed property name");
2335 if (match(OPENPAREN)) {
2336 auto method = parsePropertyMethod(context, &m_vm->propertyNames->nullIdentifier);
2338 return context.createProperty(propertyName, method, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Computed), PropertyNode::KnownDirect, complete);
2341 consumeOrFail(COLON, "Expected ':' after property name");
2342 TreeExpression node = parseAssignmentExpression(context);
2343 failIfFalse(node, "Cannot parse expression for property declaration");
2344 context.setEndOffset(node, m_lexer->currentOffset());
2345 return context.createProperty(propertyName, node, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Computed), PropertyNode::Unknown, complete);
2348 failIfFalse(m_token.m_type & KeywordTokenFlag, "Expected a property name");
2353 template <typename LexerType>
2354 template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePropertyMethod(TreeBuilder& context, const Identifier* methodName)
2356 JSTokenLocation methodLocation(tokenLocation());
2357 unsigned methodStart = tokenStart();
2358 ParserFunctionInfo<TreeBuilder> methodInfo;
2359 failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, MethodMode, false, ConstructorKind::None, SuperBinding::NotNeeded, methodStart, methodInfo, StandardFunctionParseType)), "Cannot parse this method");
2360 methodInfo.name = methodName;
2361 return context.createFunctionExpr(methodLocation, methodInfo);
2364 template <typename LexerType>
2365 template <class TreeBuilder> TreeProperty Parser<LexerType>::parseGetterSetter(TreeBuilder& context, bool strict, PropertyNode::Type type, unsigned getterOrSetterStartOffset,
2366 ConstructorKind constructorKind, SuperBinding superBinding)
2368 const Identifier* stringPropertyName = 0;
2369 double numericPropertyName = 0;
2370 if (m_token.m_type == IDENT || m_token.m_type == STRING) {
2371 stringPropertyName = m_token.m_data.ident;
2372 semanticFailIfTrue(superBinding == SuperBinding::Needed && *stringPropertyName == m_vm->propertyNames->prototype,
2373 "Cannot declare a static method named 'prototype'");
2374 semanticFailIfTrue(superBinding == SuperBinding::Needed && *stringPropertyName == m_vm->propertyNames->constructor,
2375 "Cannot declare a getter or setter named 'constructor'");
2376 } else if (m_token.m_type == DOUBLE || m_token.m_type == INTEGER)
2377 numericPropertyName = m_token.m_data.doubleValue;
2379 failDueToUnexpectedToken();
2380 JSTokenLocation location(tokenLocation());
2382 ParserFunctionInfo<TreeBuilder> info;
2383 if (type & PropertyNode::Getter) {
2384 failIfFalse(match(OPENPAREN), "Expected a parameter list for getter definition");
2385 failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, GetterMode, false, constructorKind, superBinding,
2386 getterOrSetterStartOffset, info, StandardFunctionParseType)), "Cannot parse getter definition");
2388 failIfFalse(match(OPENPAREN), "Expected a parameter list for setter definition");
2389 failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, SetterMode, false, constructorKind, superBinding,
2390 getterOrSetterStartOffset, info, StandardFunctionParseType)), "Cannot parse setter definition");
2392 if (stringPropertyName)
2393 return context.createGetterOrSetterProperty(location, type, strict, stringPropertyName, info, superBinding);
2394 return context.createGetterOrSetterProperty(const_cast<VM*>(m_vm), m_parserArena, location, type, strict, numericPropertyName, info, superBinding);
2397 template <typename LexerType>
2398 template <class TreeBuilder> bool Parser<LexerType>::shouldCheckPropertyForUnderscoreProtoDuplicate(TreeBuilder& context, const TreeProperty& property)
2400 if (m_syntaxAlreadyValidated)
2403 if (!context.getName(property))
2406 // A Constant property that is not a Computed or Shorthand Constant property.
2407 return context.getType(property) == PropertyNode::Constant;
2410 template <typename LexerType>
2411 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseObjectLiteral(TreeBuilder& context)
2413 auto savePoint = createSavePoint();
2414 consumeOrFailWithFlags(OPENBRACE, TreeBuilder::DontBuildStrings, "Expected opening '{' at the start of an object literal");
2416 int oldNonLHSCount = m_nonLHSCount;
2418 JSTokenLocation location(tokenLocation());
2419 if (match(CLOSEBRACE)) {
2421 return context.createObjectLiteral(location);
2424 TreeProperty property = parseProperty(context, false);
2425 failIfFalse(property, "Cannot parse object literal property");
2427 if (!m_syntaxAlreadyValidated && context.getType(property) & (PropertyNode::Getter | PropertyNode::Setter)) {
2428 restoreSavePoint(savePoint);
2429 return parseStrictObjectLiteral(context);
2432 bool seenUnderscoreProto = false;
2433 if (shouldCheckPropertyForUnderscoreProtoDuplicate(context, property))
2434 seenUnderscoreProto = *context.getName(property) == m_vm->propertyNames->underscoreProto;
2436 TreePropertyList propertyList = context.createPropertyList(location, property);
2437 TreePropertyList tail = propertyList;
2438 while (match(COMMA)) {
2439 next(TreeBuilder::DontBuildStrings);
2440 if (match(CLOSEBRACE))
2442 JSTokenLocation propertyLocation(tokenLocation());
2443 property = parseProperty(context, false);
2444 failIfFalse(property, "Cannot parse object literal property");
2445 if (!m_syntaxAlreadyValidated && context.getType(property) & (PropertyNode::Getter | PropertyNode::Setter)) {
2446 restoreSavePoint(savePoint);
2447 return parseStrictObjectLiteral(context);
2449 if (shouldCheckPropertyForUnderscoreProtoDuplicate(context, property)) {
2450 if (*context.getName(property) == m_vm->propertyNames->underscoreProto) {
2451 semanticFailIfTrue(seenUnderscoreProto, "Attempted to redefine __proto__ property");
2452 seenUnderscoreProto = true;
2455 tail = context.createPropertyList(propertyLocation, property, tail);
2458 location = tokenLocation();
2459 handleProductionOrFail(CLOSEBRACE, "}", "end", "object literal");
2461 m_nonLHSCount = oldNonLHSCount;
2463 return context.createObjectLiteral(location, propertyList);
2466 template <typename LexerType>
2467 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseStrictObjectLiteral(TreeBuilder& context)
2469 consumeOrFail(OPENBRACE, "Expected opening '{' at the start of an object literal");
2471 int oldNonLHSCount = m_nonLHSCount;
2473 JSTokenLocation location(tokenLocation());
2474 if (match(CLOSEBRACE)) {
2476 return context.createObjectLiteral(location);
2479 TreeProperty property = parseProperty(context, true);
2480 failIfFalse(property, "Cannot parse object literal property");
2482 bool seenUnderscoreProto = false;
2483 if (shouldCheckPropertyForUnderscoreProtoDuplicate(context, property))
2484 seenUnderscoreProto = *context.getName(property) == m_vm->propertyNames->underscoreProto;
2486 TreePropertyList propertyList = context.createPropertyList(location, property);
2487 TreePropertyList tail = propertyList;
2488 while (match(COMMA)) {
2490 if (match(CLOSEBRACE))
2492 JSTokenLocation propertyLocation(tokenLocation());
2493 property = parseProperty(context, true);
2494 failIfFalse(property, "Cannot parse object literal property");
2495 if (shouldCheckPropertyForUnderscoreProtoDuplicate(context, property)) {
2496 if (*context.getName(property) == m_vm->propertyNames->underscoreProto) {
2497 semanticFailIfTrue(seenUnderscoreProto, "Attempted to redefine __proto__ property");
2498 seenUnderscoreProto = true;
2501 tail = context.createPropertyList(propertyLocation, property, tail);
2504 location = tokenLocation();
2505 handleProductionOrFail(CLOSEBRACE, "}", "end", "object literal");
2507 m_nonLHSCount = oldNonLHSCount;
2509 return context.createObjectLiteral(location, propertyList);
2512 template <typename LexerType>
2513 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseArrayLiteral(TreeBuilder& context)
2515 consumeOrFailWithFlags(OPENBRACKET, TreeBuilder::DontBuildStrings, "Expected an opening '[' at the beginning of an array literal");
2517 int oldNonLHSCount = m_nonLHSCount;
2520 while (match(COMMA)) {
2521 next(TreeBuilder::DontBuildStrings);
2524 if (match(CLOSEBRACKET)) {
2525 JSTokenLocation location(tokenLocation());
2526 next(TreeBuilder::DontBuildStrings);
2527 return context.createArray(location, elisions);
2530 TreeExpression elem;
2531 if (UNLIKELY(match(DOTDOTDOT))) {
2532 auto spreadLocation = m_token.m_location;
2533 auto start = m_token.m_startPosition;
2534 auto divot = m_token.m_endPosition;
2536 auto spreadExpr = parseAssignmentExpression(context);
2537 failIfFalse(spreadExpr, "Cannot parse subject of a spread operation");
2538 elem = context.createSpreadExpression(spreadLocation, spreadExpr, start, divot, m_lastTokenEndPosition);
2540 elem = parseAssignmentExpression(context);
2541 failIfFalse(elem, "Cannot parse array literal element");
2542 typename TreeBuilder::ElementList elementList = context.createElementList(elisions, elem);
2543 typename TreeBuilder::ElementList tail = elementList;
2545 while (match(COMMA)) {
2546 next(TreeBuilder::DontBuildStrings);
2549 while (match(COMMA)) {
2554 if (match(CLOSEBRACKET)) {
2555 JSTokenLocation location(tokenLocation());
2556 next(TreeBuilder::DontBuildStrings);
2557 return context.createArray(location, elisions, elementList);
2559 if (UNLIKELY(match(DOTDOTDOT))) {
2560 auto spreadLocation = m_token.m_location;
2561 auto start = m_token.m_startPosition;
2562 auto divot = m_token.m_endPosition;
2564 TreeExpression elem = parseAssignmentExpression(context);
2565 failIfFalse(elem, "Cannot parse subject of a spread operation");
2566 auto spread = context.createSpreadExpression(spreadLocation, elem, start, divot, m_lastTokenEndPosition);
2567 tail = context.createElementList(tail, elisions, spread);
2570 TreeExpression elem = parseAssignmentExpression(context);
2571 failIfFalse(elem, "Cannot parse array literal element");
2572 tail = context.createElementList(tail, elisions, elem);
2575 JSTokenLocation location(tokenLocation());
2576 if (!consume(CLOSEBRACKET)) {
2577 failIfFalse(match(DOTDOTDOT), "Expected either a closing ']' or a ',' following an array element");
2578 semanticFail("The '...' operator should come before a target expression");
2581 m_nonLHSCount = oldNonLHSCount;
2583 return context.createArray(location, elementList);
2586 #if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
2587 template <typename LexerType>
2588 template <class TreeBuilder> typename TreeBuilder::TemplateString Parser<LexerType>::parseTemplateString(TreeBuilder& context, bool isTemplateHead, typename LexerType::RawStringsBuildMode rawStringsBuildMode, bool& elementIsTail)
2590 if (!isTemplateHead) {
2591 matchOrFail(CLOSEBRACE, "Expected a closing '}' following an expression in template literal");
2592 // Re-scan the token to recognize it as Template Element.
2593 m_token.m_type = m_lexer->scanTrailingTemplateString(&m_token, rawStringsBuildMode);
2595 matchOrFail(TEMPLATE, "Expected an template element");
2596 const Identifier* cooked = m_token.m_data.cooked;
2597 const Identifier* raw = m_token.m_data.raw;
2598 elementIsTail = m_token.m_data.isTail;
2599 JSTokenLocation location(tokenLocation());
2601 return context.createTemplateString(location, *cooked, *raw);
2604 template <typename LexerType>
2605 template <class TreeBuilder> typename TreeBuilder::TemplateLiteral Parser<LexerType>::parseTemplateLiteral(TreeBuilder& context, typename LexerType::RawStringsBuildMode rawStringsBuildMode)
2607 JSTokenLocation location(tokenLocation());
2608 bool elementIsTail = false;
2610 auto headTemplateString = parseTemplateString(context, true, rawStringsBuildMode, elementIsTail);
2611 failIfFalse(headTemplateString, "Cannot parse head template element");
2613 typename TreeBuilder::TemplateStringList templateStringList = context.createTemplateStringList(headTemplateString);
2614 typename TreeBuilder::TemplateStringList templateStringTail = templateStringList;
2617 return context.createTemplateLiteral(location, templateStringList);
2619 failIfTrue(match(CLOSEBRACE), "Template literal expression cannot be empty");
2620 TreeExpression expression = parseExpression(context);
2621 failIfFalse(expression, "Cannot parse expression in template literal");
2623 typename TreeBuilder::TemplateExpressionList templateExpressionList = context.createTemplateExpressionList(expression);
2624 typename TreeBuilder::TemplateExpressionList templateExpressionTail = templateExpressionList;
2626 auto templateString = parseTemplateString(context, false, rawStringsBuildMode, elementIsTail);
2627 failIfFalse(templateString, "Cannot parse template element");
2628 templateStringTail = context.createTemplateStringList(templateStringTail, templateString);
2630 while (!elementIsTail) {
2631 failIfTrue(match(CLOSEBRACE), "Template literal expression cannot be empty");
2632 TreeExpression expression = parseExpression(context);
2633 failIfFalse(expression, "Cannot parse expression in template literal");
2635 templateExpressionTail = context.createTemplateExpressionList(templateExpressionTail, expression);
2637 auto templateString = parseTemplateString(context, false, rawStringsBuildMode, elementIsTail);
2638 failIfFalse(templateString, "Cannot parse template element");
2639 templateStringTail = context.createTemplateStringList(templateStringTail, templateString);
2642 return context.createTemplateLiteral(location, templateStringList, templateExpressionList);
2646 template <typename LexerType>
2647 template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePrimaryExpression(TreeBuilder& context)
2649 failIfStackOverflow();
2650 switch (m_token.m_type) {
2652 JSTokenLocation location(tokenLocation());
2653 unsigned functionKeywordStart = tokenStart();
2655 ParserFunctionInfo<TreeBuilder> info;
2656 info.name = &m_vm->propertyNames->nullIdentifier;
2657 failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, FunctionMode, false, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, info, StandardFunctionParseType)), "Cannot parse function expression");
2658 return context.createFunctionExpr(location, info);
2660 #if ENABLE(ES6_CLASS_SYNTAX)
2662 ParserClassInfo<TreeBuilder> info;
2663 return parseClass(context, FunctionNoRequirements, info);
2668 return parseStrictObjectLiteral(context);
2669 return parseObjectLiteral(context);
2671 return parseArrayLiteral(context);
2674 int oldNonLHSCount = m_nonLHSCount;
2675 TreeExpression result = parseExpression(context);
2676 m_nonLHSCount = oldNonLHSCount;
2677 handleProductionOrFail(CLOSEPAREN, ")", "end", "compound expression");
2681 JSTokenLocation location(tokenLocation());
2683 return context.thisExpr(location, m_thisTDZMode);
2686 JSTextPosition start = tokenStartPosition();
2687 const Identifier* ident = m_token.m_data.ident;
2688 JSTokenLocation location(tokenLocation());
2690 currentScope()->useVariable(ident, m_vm->propertyNames->eval == *ident);
2691 m_lastIdentifier = ident;
2692 return context.createResolve(location, ident, start);
2695 const Identifier* ident = m_token.m_data.ident;
2696 JSTokenLocation location(tokenLocation());
2698 return context.createString(location, ident);
2701 double d = m_token.m_data.doubleValue;
2702 JSTokenLocation location(tokenLocation());
2704 return context.createDoubleExpr(location, d);
2707 double d = m_token.m_data.doubleValue;
2708 JSTokenLocation location(tokenLocation());
2710 return context.createIntegerExpr(location, d);
2713 JSTokenLocation location(tokenLocation());
2715 return context.createNull(location);
2718 JSTokenLocation location(tokenLocation());
2720 return context.createBoolean(location, true);
2723 JSTokenLocation location(tokenLocation());
2725 return context.createBoolean(location, false);
2730 const Identifier* pattern;
2731 const Identifier* flags;
2732 if (match(DIVEQUAL))
2733 failIfFalse(m_lexer->scanRegExp(pattern, flags, '='), "Invalid regular expression");
2735 failIfFalse(m_lexer->scanRegExp(pattern, flags), "Invalid regular expression");
2737 JSTextPosition start = tokenStartPosition();
2738 JSTokenLocation location(tokenLocation());
2740 TreeExpression re = context.createRegExp(location, *pattern, *flags, start);
2742 const char* yarrErrorMsg = Yarr::checkSyntax(pattern->string());
2743 regexFail(yarrErrorMsg);
2747 #if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
2749 return parseTemplateLiteral(context, LexerType::RawStringsBuildMode::DontBuildRawStrings);
2752 failDueToUnexpectedToken();
2756 template <typename LexerType>
2757 template <class TreeBuilder> TreeArguments Parser<LexerType>::parseArguments(TreeBuilder& context, SpreadMode mode)
2759 consumeOrFailWithFlags(OPENPAREN, TreeBuilder::DontBuildStrings, "Expected opening '(' at start of argument list");
2760 JSTokenLocation location(tokenLocation());
2761 if (match(CLOSEPAREN)) {
2762 next(TreeBuilder::DontBuildStrings);
2763 return context.createArguments();
2765 if (match(DOTDOTDOT) && mode == AllowSpread) {
2766 JSTokenLocation spreadLocation(tokenLocation());
2767 auto start = m_token.m_startPosition;
2768 auto divot = m_token.m_endPosition;
2770 auto spreadExpr = parseAssignmentExpression(context);
2771 auto end = m_lastTokenEndPosition;
2773 failWithMessage("Cannot parse spread expression");
2774 if (!consume(CLOSEPAREN)) {
2776 semanticFail("Spread operator may only be applied to the last argument passed to a function");
2777 handleProductionOrFail(CLOSEPAREN, ")", "end", "argument list");
2779 auto spread = context.createSpreadExpression(spreadLocation, spreadExpr, start, divot, end);
2780 TreeArgumentsList argList = context.createArgumentsList(location, spread);
2781 return context.createArguments(argList);
2783 TreeExpression firstArg = parseAssignmentExpression(context);
2784 failIfFalse(firstArg, "Cannot parse function argument");
2786 TreeArgumentsList argList = context.createArgumentsList(location, firstArg);
2787 TreeArgumentsList tail = argList;
2788 while (match(COMMA)) {
2789 JSTokenLocation argumentLocation(tokenLocation());
2790 next(TreeBuilder::DontBuildStrings);
2791 TreeExpression arg = parseAssignmentExpression(context);
2792 failIfFalse(arg, "Cannot parse function argument");
2793 tail = context.createArgumentsList(argumentLocation, tail, arg);
2795 semanticFailIfTrue(match(DOTDOTDOT), "The '...' operator should come before the target expression");
2796 handleProductionOrFail(CLOSEPAREN, ")", "end", "argument list");
2797 return context.createArguments(argList);
2800 template <typename LexerType>
2801 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseMemberExpression(TreeBuilder& context)
2803 TreeExpression base = 0;
2804 JSTextPosition expressionStart = tokenStartPosition();
2806 JSTokenLocation startLocation = tokenLocation();
2807 JSTokenLocation location;
2808 while (match(NEW)) {
2813 #if ENABLE(ES6_CLASS_SYNTAX)
2814 bool baseIsSuper = match(SUPER);
2815 semanticFailIfTrue(baseIsSuper && newCount, "Cannot use new with super");
2817 bool baseIsSuper = false;
2821 base = context.superExpr(location);
2823 currentScope()->setNeedsSuperBinding();
2825 base = parsePrimaryExpression(context);
2827 failIfFalse(base, "Cannot parse base expression");
2829 location = tokenLocation();
2830 switch (m_token.m_type) {
2832 m_nonTrivialExpressionCount++;
2833 JSTextPosition expressionEnd = lastTokenEndPosition();
2835 int nonLHSCount = m_nonLHSCount;
2836 int initialAssignments = m_assignmentCount;
2837 TreeExpression property = parseExpression(context);
2838 failIfFalse(property, "Cannot parse subscript expression");
2839 base = context.createBracketAccess(location, base, property, initialAssignments != m_assignmentCount, expressionStart, expressionEnd, tokenEndPosition());
2840 handleProductionOrFail(CLOSEBRACKET, "]", "end", "subscript expression");
2841 m_nonLHSCount = nonLHSCount;
2845 m_nonTrivialExpressionCount++;
2846 int nonLHSCount = m_nonLHSCount;
2849 JSTextPosition expressionEnd = lastTokenEndPosition();
2850 TreeArguments arguments = parseArguments(context, AllowSpread);
2851 failIfFalse(arguments, "Cannot parse call arguments");
2852 base = context.createNewExpr(location, base, arguments, expressionStart, expressionEnd, lastTokenEndPosition());
2854 JSTextPosition expressionEnd = lastTokenEndPosition();
2855 TreeArguments arguments = parseArguments(context, AllowSpread);
2856 failIfFalse(arguments, "Cannot parse call arguments");
2858 currentScope()->setHasDirectSuper();
2859 base = context.makeFunctionCallNode(startLocation, base, arguments, expressionStart, expressionEnd, lastTokenEndPosition());
2861 m_nonLHSCount = nonLHSCount;
2865 m_nonTrivialExpressionCount++;
2866 JSTextPosition expressionEnd = lastTokenEndPosition();
2867 nextExpectIdentifier(LexerFlagsIgnoreReservedWords | TreeBuilder::DontBuildKeywords);
2868 matchOrFail(IDENT, "Expected a property name after '.'");
2869 base = context.createDotAccess(location, base, m_token.m_data.ident, expressionStart, expressionEnd, tokenEndPosition());
2873 #if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
2875 semanticFailIfTrue(baseIsSuper, "Cannot use super as tag for tagged templates");
2876 JSTextPosition expressionEnd = lastTokenEndPosition();
2877 int nonLHSCount = m_nonLHSCount;
2878 typename TreeBuilder::TemplateLiteral templateLiteral = parseTemplateLiteral(context, LexerType::RawStringsBuildMode::BuildRawStrings);
2879 failIfFalse(templateLiteral, "Cannot parse template literal");
2880 base = context.createTaggedTemplate(location, base, templateLiteral, expressionStart, expressionEnd, lastTokenEndPosition());
2881 m_nonLHSCount = nonLHSCount;
2886 goto endMemberExpression;
2888 baseIsSuper = false;
2890 endMemberExpression:
2891 semanticFailIfTrue(baseIsSuper, "Cannot reference super");
2893 base = context.createNewExpr(location, base, expressionStart, lastTokenEndPosition());
2897 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
2898 template <typename LexerType>
2899 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseArrowFunctionExpression(TreeBuilder& context)
2901 JSTokenLocation location;
2903 unsigned functionKeywordStart = tokenStart();
2904 location = tokenLocation();
2905 ParserFunctionInfo<TreeBuilder> info;
2906 info.name = &m_vm->propertyNames->nullIdentifier;
2907 failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, FunctionMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, info, ArrowFunctionParseType)), "Cannot parse arrow function expression");
2909 return context.createArrowFunctionExpr(location, info);
2913 static const char* operatorString(bool prefix, unsigned tok)
2917 case AUTOMINUSMINUS:
2918 return prefix ? "prefix-decrement" : "decrement";
2922 return prefix ? "prefix-increment" : "increment";
2925 return "logical-not";
2928 return "bitwise-not";
2939 RELEASE_ASSERT_NOT_REACHED();
2943 template <typename LexerType>
2944 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseUnaryExpression(TreeBuilder& context)
2946 typename TreeBuilder::UnaryExprContext unaryExprContext(context);
2947 AllowInOverride allowInOverride(this);
2948 int tokenStackDepth = 0;
2949 bool modifiesExpr = false;
2950 bool requiresLExpr = false;
2951 unsigned lastOperator = 0;
2952 while (isUnaryOp(m_token.m_type)) {
2954 switch (m_token.m_type) {
2958 case AUTOMINUSMINUS:
2959 semanticFailIfTrue(requiresLExpr, "The ", operatorString(true, lastOperator), " operator requires a reference expression");
2960 modifiesExpr = true;
2961 requiresLExpr = true;
2964 semanticFailIfTrue(requiresLExpr, "The ", operatorString(true, lastOperator), " operator requires a reference expression");
2965 requiresLExpr = true;
2968 semanticFailIfTrue(requiresLExpr, "The ", operatorString(true, lastOperator), " operator requires a reference expression");
2972 lastOperator = m_token.m_type;
2974 context.appendUnaryToken(tokenStackDepth, m_token.m_type, tokenStartPosition());
2976 m_nonTrivialExpressionCount++;
2978 JSTextPosition subExprStart = tokenStartPosition();
2979 ASSERT(subExprStart.offset >= subExprStart.lineStartOffset);
2980 JSTokenLocation location(tokenLocation());
2981 TreeExpression expr = parseMemberExpression(context);
2984 failWithMessage("Cannot parse subexpression of ", operatorString(true, lastOperator), "operator");
2985 failWithMessage("Cannot parse member expression");
2987 bool isEvalOrArguments = false;
2988 if (strictMode() && !m_syntaxAlreadyValidated) {
2989 if (context.isResolve(expr))
2990 isEvalOrArguments = *m_lastIdentifier == m_vm->propertyNames->eval || *m_lastIdentifier == m_vm->propertyNames->arguments;
2992 failIfTrueIfStrict(isEvalOrArguments && modifiesExpr, "Cannot modify '", m_lastIdentifier->impl(), "' in strict mode");
2993 switch (m_token.m_type) {
2995 m_nonTrivialExpressionCount++;
2997 expr = context.makePostfixNode(location, expr, OpPlusPlus, subExprStart, lastTokenEndPosition(), tokenEndPosition());
2998 m_assignmentCount++;
2999 failIfTrueIfStrict(isEvalOrArguments, "Cannot modify '", m_lastIdentifier->impl(), "' in strict mode");
3000 semanticFailIfTrue(requiresLExpr, "The ", operatorString(false, lastOperator), " operator requires a reference expression");
3001 lastOperator = PLUSPLUS;
3005 m_nonTrivialExpressionCount++;
3007 expr = context.makePostfixNode(location, expr, OpMinusMinus, subExprStart, lastTokenEndPosition(), tokenEndPosition());
3008 m_assignmentCount++;
3009 failIfTrueIfStrict(isEvalOrArguments, "'", m_lastIdentifier->impl(), "' cannot be modified in strict mode");
3010 semanticFailIfTrue(requiresLExpr, "The ", operatorString(false, lastOperator), " operator requires a reference expression");
3011 lastOperator = PLUSPLUS;
3018 JSTextPosition end = lastTokenEndPosition();
3020 if (!TreeBuilder::CreatesAST && (m_syntaxAlreadyValidated || !strictMode()))
3023 location = tokenLocation();
3024 location.line = m_lexer->lastLineNumber();
3025 while (tokenStackDepth) {
3026 switch (context.unaryTokenStackLastType(tokenStackDepth)) {
3028 expr = context.createLogicalNot(location, expr);
3031 expr = context.makeBitwiseNotNode(location, expr);
3034 expr = context.makeNegateNode(location, expr);
3037 expr = context.createUnaryPlus(location, expr);
3041 expr = context.makePrefixNode(location, expr, OpPlusPlus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end);
3042 m_assignmentCount++;
3045 case AUTOMINUSMINUS:
3046 expr = context.makePrefixNode(location, expr, OpMinusMinus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end);
3047 m_assignmentCount++;
3050 expr = context.makeTypeOfNode(location, expr);
3053 expr = context.createVoid(location, expr);
3056 failIfTrueIfStrict(context.isResolve(expr), "Cannot delete unqualified property '", m_lastIdentifier->impl(), "' in strict mode");
3057 expr = context.makeDeleteNode(location, expr, context.unaryTokenStackLastStart(tokenStackDepth), end, end);
3060 // If we get here something has gone horribly horribly wrong
3063 subExprStart = context.unaryTokenStackLastStart(tokenStackDepth);
3064 context.unaryTokenStackRemoveLast(tokenStackDepth);
3070 template <typename LexerType> void Parser<LexerType>::printUnexpectedTokenText(WTF::PrintStream& out)
3072 switch (m_token.m_type) {
3074 out.print("Unexpected end of script");
3076 case UNTERMINATED_IDENTIFIER_ESCAPE_ERRORTOK:
3077 case UNTERMINATED_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK:
3078 out.print("Incomplete unicode escape in identifier: '", getToken(), "'");
3080 case UNTERMINATED_MULTILINE_COMMENT_ERRORTOK:
3081 out.print("Unterminated multiline comment");
3083 case UNTERMINATED_NUMERIC_LITERAL_ERRORTOK:
3084 out.print("Unterminated numeric literal '", getToken(), "'");
3086 case UNTERMINATED_STRING_LITERAL_ERRORTOK:
3087 out.print("Unterminated string literal '", getToken(), "'");
3089 case INVALID_IDENTIFIER_ESCAPE_ERRORTOK:
3090 out.print("Invalid escape in identifier: '", getToken(), "'");
3092 case INVALID_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK:
3093 out.print("Invalid unicode escape in identifier: '", getToken(), "'");
3095 case INVALID_NUMERIC_LITERAL_ERRORTOK:
3096 out.print("Invalid numeric literal: '", getToken(), "'");
3098 case INVALID_OCTAL_NUMBER_ERRORTOK:
3099 out.print("Invalid use of octal: '", getToken(), "'");
3101 case INVALID_STRING_LITERAL_ERRORTOK:
3102 out.print("Invalid string literal: '", getToken(), "'");
3105 out.print("Unrecognized token '", getToken(), "'");
3108 out.print("Unexpected string literal ", getToken());
3112 out.print("Unexpected number '", getToken(), "'");
3115 case RESERVED_IF_STRICT:
3116 out.print("Unexpected use of reserved word '", getToken(), "' in strict mode");
3120 out.print("Unexpected use of reserved word '", getToken(), "'");
3123 case INVALID_PRIVATE_NAME_ERRORTOK:
3124 out.print("Invalid private name '", getToken(), "'");
3128 out.print("Unexpected identifier '", getToken(), "'");
3135 if (m_token.m_type & KeywordTokenFlag) {
3136 out.print("Unexpected keyword '", getToken(), "'");
3140 out.print("Unexpected token '", getToken(), "'");
3143 // Instantiate the two flavors of Parser we need instead of putting most of this file in Parser.h
3144 template class Parser<Lexer<LChar>>;
3145 template class Parser<Lexer<UChar>>;