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
>>;