]> git.saurik.com Git - apple/javascriptcore.git/blob - parser/Parser.cpp
be88dd2556764ce7ea136febb38165d91a3e5d7a
[apple/javascriptcore.git] / parser / Parser.cpp
1 /*
2 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
3 * Copyright (C) 2001 Peter Kelly (pmk@post.com)
4 * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc. All rights reserved.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "config.h"
24 #include "Parser.h"
25
26 #include "ASTBuilder.h"
27 #include "CodeBlock.h"
28 #include "Debugger.h"
29 #include "JSCJSValueInlines.h"
30 #include "Lexer.h"
31 #include "JSCInlines.h"
32 #include "SourceProvider.h"
33 #include "VM.h"
34 #include <utility>
35 #include <wtf/HashFunctions.h>
36 #include <wtf/StringPrintStream.h>
37 #include <wtf/WTFThreadData.h>
38
39
40 #define updateErrorMessage(shouldPrintToken, ...) do {\
41 propagateError(); \
42 logError(shouldPrintToken, __VA_ARGS__); \
43 } while (0)
44
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 {\
63 logError(true);\
64 return 0;\
65 } while (0)
66
67 #define handleProductionOrFail(token, tokenString, operation, production) do {\
68 consumeOrFail(token, "Expected '", tokenString, "' to ", operation, " a ", production);\
69 } while (0)
70
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__); \
78 } while (0)
79
80 using namespace std;
81
82 namespace JSC {
83
84 template <typename LexerType>
85 void Parser<LexerType>::logError(bool)
86 {
87 if (hasError())
88 return;
89 StringPrintStream stream;
90 printUnexpectedTokenText(stream);
91 setErrorMessage(stream.toString());
92 }
93
94 template <typename LexerType> template <typename A>
95 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1)
96 {
97 if (hasError())
98 return;
99 StringPrintStream stream;
100 if (shouldPrintToken) {
101 printUnexpectedTokenText(stream);
102 stream.print(". ");
103 }
104 stream.print(value1, ".");
105 setErrorMessage(stream.toString());
106 }
107
108 template <typename LexerType> template <typename A, typename B>
109 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2)
110 {
111 if (hasError())
112 return;
113 StringPrintStream stream;
114 if (shouldPrintToken) {
115 printUnexpectedTokenText(stream);
116 stream.print(". ");
117 }
118 stream.print(value1, value2, ".");
119 setErrorMessage(stream.toString());
120 }
121
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)
124 {
125 if (hasError())
126 return;
127 StringPrintStream stream;
128 if (shouldPrintToken) {
129 printUnexpectedTokenText(stream);
130 stream.print(". ");
131 }
132 stream.print(value1, value2, value3, ".");
133 setErrorMessage(stream.toString());
134 }
135
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)
138 {
139 if (hasError())
140 return;
141 StringPrintStream stream;
142 if (shouldPrintToken) {
143 printUnexpectedTokenText(stream);
144 stream.print(". ");
145 }
146 stream.print(value1, value2, value3, value4, ".");
147 setErrorMessage(stream.toString());
148 }
149
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)
152 {
153 if (hasError())
154 return;
155 StringPrintStream stream;
156 if (shouldPrintToken) {
157 printUnexpectedTokenText(stream);
158 stream.print(". ");
159 }
160 stream.print(value1, value2, value3, value4, value5, ".");
161 setErrorMessage(stream.toString());
162 }
163
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)
166 {
167 if (hasError())
168 return;
169 StringPrintStream stream;
170 if (shouldPrintToken) {
171 printUnexpectedTokenText(stream);
172 stream.print(". ");
173 }
174 stream.print(value1, value2, value3, value4, value5, value6, ".");
175 setErrorMessage(stream.toString());
176 }
177
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)
180 {
181 if (hasError())
182 return;
183 StringPrintStream stream;
184 if (shouldPrintToken) {
185 printUnexpectedTokenText(stream);
186 stream.print(". ");
187 }
188 stream.print(value1, value2, value3, value4, value5, value6, value7, ".");
189 setErrorMessage(stream.toString());
190 }
191
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)
198 : m_vm(vm)
199 , m_source(&source)
200 , m_hasStackOverflow(false)
201 , m_allowsIn(true)
202 , m_assignmentCount(0)
203 , m_nonLHSCount(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)
213 {
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();
226 if (parameters) {
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;
232 continue;
233 }
234 scope->declareParameter(&static_cast<BindingNode*>(parameter)->boundProperty());
235 }
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())
241 continue;
242 parameter->collectBoundIdentifiers(boundParameterNames);
243 }
244 for (auto& boundParameterName : boundParameterNames)
245 scope->declareVariable(&boundParameterName);
246 }
247 }
248 if (!name.isNull())
249 scope->declareCallee(&name);
250 next();
251 }
252
253 template <typename LexerType>
254 Parser<LexerType>::~Parser()
255 {
256 }
257
258 template <typename LexerType>
259 String Parser<LexerType>::parseInner()
260 {
261 String parseError = String();
262
263 ASTBuilder context(const_cast<VM*>(m_vm), m_parserArena, const_cast<SourceCode*>(m_source));
264 if (m_lexer->isReparsing())
265 m_statementDepth--;
266 ScopeRef scope = currentScope();
267 SourceElements* sourceElements = parseSourceElements(context, CheckForStrictMode, StandardFunctionParseType);
268 if (!sourceElements || !consume(EOFTOK)) {
269 if (hasError())
270 parseError = m_errorMessage;
271 else
272 parseError = ASCIILiteral("Parser error");
273 }
274
275 IdentifierSet capturedVariables;
276 bool modifiedParameter = false;
277 bool modifiedArguments = false;
278 scope->getCapturedVariables(capturedVariables, modifiedParameter, modifiedArguments);
279
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))
296 continue;
297
298 if (scope->hasDeclaredParameter(identifier))
299 continue;
300
301 if (variable == m_vm->propertyNames->arguments.impl())
302 continue;
303
304 closedVariables.append(variable);
305 }
306
307 if (!capturedVariables.isEmpty()) {
308 for (const auto& capturedVariable : capturedVariables) {
309 Identifier identifier = Identifier::fromUid(m_vm, capturedVariable.get());
310 if (scope->hasDeclaredVariable(identifier))
311 continue;
312
313 if (scope->hasDeclaredParameter(identifier))
314 continue;
315
316 RELEASE_ASSERT_NOT_REACHED();
317 }
318 }
319 }
320 didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), features,
321 context.numConstants(), capturedVariables, WTF::move(closedVariables));
322
323 return parseError;
324 }
325
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)
329 {
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;
337 }
338
339 template <typename LexerType>
340 bool Parser<LexerType>::allowAutomaticSemicolon()
341 {
342 return match(CLOSEBRACE) || match(EOFTOK) || m_lexer->prevTerminator();
343 }
344
345 template <typename LexerType>
346 template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseSourceElements(TreeBuilder& context, SourceElementsMode mode, FunctionParseType functionParseType)
347 {
348 const unsigned lengthOfUseStrictLiteral = 12; // "use strict".length
349 TreeSourceElements sourceElements = context.createSourceElements();
350 bool seenNonDirective = false;
351 const Identifier* directive = 0;
352 unsigned directiveLiteralLength = 0;
353 auto savePoint = createSavePoint();
354 bool hasSetStrict = false;
355
356 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
357 if (match(ARROWFUNCTION)) {
358 TreeStatement arrowfunctionStatement = parseArrowFunctionSingleExpressionBody(context, functionParseType);
359
360 if (arrowfunctionStatement) {
361 context.setEndOffset(arrowfunctionStatement, m_lastTokenEndPosition.offset);
362 context.appendStatement(sourceElements, arrowfunctionStatement);
363 }
364
365 propagateError();
366 return sourceElements;
367 }
368 #else
369 UNUSED_PARAM(functionParseType);
370 #endif
371
372 while (TreeStatement statement = parseStatementListItem(context, directive, &directiveLiteralLength)) {
373 if (mode == CheckForStrictMode && !seenNonDirective) {
374 if (directive) {
375 // "use strict" must be the exact literal without escape sequences or line continuation.
376 if (!hasSetStrict && directiveLiteralLength == lengthOfUseStrictLiteral && m_vm->propertyNames->useStrictIdentifier == *directive) {
377 setStrictMode();
378 hasSetStrict = true;
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");
385 }
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");
391 }
392 restoreSavePoint(savePoint);
393 propagateError();
394 continue;
395 }
396 } else
397 seenNonDirective = true;
398 }
399 context.appendStatement(sourceElements, statement);
400 }
401
402 propagateError();
403 return sourceElements;
404 }
405 template <typename LexerType>
406 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseStatementListItem(TreeBuilder& context, const Identifier*& directive, unsigned* directiveLiteralLength)
407 {
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) {
412 case CONSTTOKEN:
413 result = parseConstDeclaration(context);
414 break;
415 #if ENABLE(ES6_CLASS_SYNTAX)
416 case CLASSTOKEN:
417 result = parseClassDeclaration(context);
418 break;
419 #endif
420 default:
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);
424 break;
425 }
426
427 return result;
428 }
429
430 template <typename LexerType>
431 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseVarDeclaration(TreeBuilder& context)
432 {
433 ASSERT(match(VAR));
434 JSTokenLocation location(tokenLocation());
435 int start = tokenLine();
436 int end = 0;
437 int scratch;
438 TreeDestructuringPattern scratch1 = 0;
439 TreeExpression scratch2 = 0;
440 JSTextPosition scratch3;
441 TreeExpression varDecls = parseVarDeclarationList(context, scratch, scratch1, scratch2, scratch3, scratch3, scratch3, VarDeclarationContext);
442 propagateError();
443 failIfFalse(autoSemiColon(), "Expected ';' after var declaration");
444
445 return context.createVarStatement(location, varDecls, start, end);
446 }
447
448 template <typename LexerType>
449 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseConstDeclaration(TreeBuilder& context)
450 {
451 ASSERT(match(CONSTTOKEN));
452 JSTokenLocation location(tokenLocation());
453 int start = tokenLine();
454 int end = 0;
455 TreeConstDeclList constDecls = parseConstDeclarationList(context);
456 propagateError();
457 failIfFalse(autoSemiColon(), "Expected ';' after const declaration");
458
459 return context.createConstStatement(location, constDecls, start, end);
460 }
461
462 template <typename LexerType>
463 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseDoWhileStatement(TreeBuilder& context)
464 {
465 ASSERT(match(DO));
466 int startLine = tokenLine();
467 next();
468 const Identifier* unused = 0;
469 startLoop();
470 TreeStatement statement = parseStatement(context, unused);
471 endLoop();
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);
484 }
485
486 template <typename LexerType>
487 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWhileStatement(TreeBuilder& context)
488 {
489 ASSERT(match(WHILE));
490 JSTokenLocation location(tokenLocation());
491 int startLine = tokenLine();
492 next();
493
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");
500
501 const Identifier* unused = 0;
502 startLoop();
503 TreeStatement statement = parseStatement(context, unused);
504 endLoop();
505 failIfFalse(statement, "Expected a statement as the body of a while loop");
506 return context.createWhileStatement(location, expr, statement, startLine, endLine);
507 }
508
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)
511 {
512 TreeExpression head = 0;
513 TreeExpression tail = 0;
514 const Identifier* lastIdent;
515 JSToken lastIdentToken;
516 do {
517 lastIdent = 0;
518 lastPattern = TreeDestructuringPattern(0);
519 JSTokenLocation location(tokenLocation());
520 next();
521 TreeExpression node = 0;
522 declarations++;
523 bool hasInitializer = false;
524 if (match(IDENT)) {
525 JSTextPosition varStart = tokenStartPosition();
526 JSTokenLocation varStartLocation(tokenLocation());
527 identStart = varStart;
528 const Identifier* name = m_token.m_data.ident;
529 lastIdent = name;
530 lastIdentToken = m_token;
531 next();
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(), "'");
543
544 node = context.createAssignResolve(location, *name, initializer, varStart, varDivot, lastTokenEndPosition());
545 } else
546 node = context.createEmptyVarExpression(varStartLocation, *name);
547 } else {
548 lastIdent = 0;
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;
559 }
560 }
561
562 if (!head)
563 head = node;
564 else if (!tail) {
565 head = context.createCommaExpr(location, head);
566 tail = context.appendToCommaExpr(location, head, head, node);
567 } else
568 tail = context.appendToCommaExpr(location, head, tail, node);
569 } while (match(COMMA));
570 if (lastIdent)
571 lastPattern = createBindingPattern(context, DestructureToVariables, *lastIdent, 0, lastIdentToken);
572 return head;
573 }
574
575 template <typename LexerType>
576 template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::createBindingPattern(TreeBuilder& context, DestructuringKind kind, const Identifier& name, int depth, JSToken token)
577 {
578 ASSERT(!name.isNull());
579
580 ASSERT(name.impl()->isAtomic() || name.impl()->isSymbol());
581 if (depth) {
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");
594 }
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(), "'");
600 }
601 }
602 if (kind != DestructureToExpressions)
603 context.addVar(&name, DeclarationStacks::HasInitializer);
604
605 } else {
606 if (kind == DestructureToVariables) {
607 failIfFalseIfStrict(declareVariable(&name), "Cannot declare a variable named '", name.impl(), "' in strict mode");
608 context.addVar(&name, DeclarationStacks::HasInitializer);
609 }
610
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");
621 }
622 }
623 }
624 return context.createBindingLocation(token.m_location, name, token.m_startPosition, token.m_endPosition);
625 }
626
627 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
628 template <typename LexerType>
629 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseArrowFunctionSingleExpressionBody(TreeBuilder& context, FunctionParseType parseType)
630 {
631 ASSERT(match(ARROWFUNCTION));
632
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();
639
640 JSTokenLocation location(tokenLocation());
641 JSTextPosition start = tokenStartPosition();
642 JSTextPosition end = tokenEndPosition();
643
644 next();
645
646 failIfStackOverflow();
647 TreeExpression expr = parseAssignmentExpression(context);
648 failIfFalse(expr, "Cannot parse the arrow function expression");
649
650 context.setEndOffset(expr, m_lastTokenEndPosition.offset);
651
652 failIfFalse(isEndOfArrowFunction(), "Expected a ';', ']', '}', ')', ',', line terminator or EOF following a arrow function statement");
653
654 end = tokenEndPosition();
655
656 if (!m_lexer->prevTerminator())
657 setEndOfStatement();
658
659 return context.createReturnStatement(location, expr, start, end);
660 }
661 #endif
662
663 template <typename LexerType>
664 template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::tryParseDestructuringPatternExpression(TreeBuilder& context)
665 {
666 return parseDestructuringPattern(context, DestructureToExpressions);
667 }
668
669 template <typename LexerType>
670 template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseDestructuringPattern(TreeBuilder& context, DestructuringKind kind, int depth)
671 {
672 failIfStackOverflow();
673 int nonLHSCount = m_nonLHSCount;
674 TreeDestructuringPattern pattern;
675 switch (m_token.m_type) {
676 case OPENBRACKET: {
677 JSTextPosition divotStart = tokenStartPosition();
678 auto arrayPattern = context.createArrayPattern(m_token.m_location);
679 next();
680
681 bool restElementWasFound = false;
682
683 do {
684 while (match(COMMA)) {
685 context.appendArrayPatternSkipEntry(arrayPattern, m_token.m_location);
686 next();
687 }
688 propagateError();
689
690 if (match(CLOSEBRACKET))
691 break;
692
693 if (UNLIKELY(match(DOTDOTDOT))) {
694 JSTokenLocation location = m_token.m_location;
695 next();
696 auto innerPattern = parseDestructuringPattern(context, kind, depth + 1);
697 if (kind == DestructureToExpressions && !innerPattern)
698 return 0;
699 failIfFalse(innerPattern, "Cannot parse this destructuring pattern");
700
701 failIfTrue(kind != DestructureToExpressions && !context.isBindingNode(innerPattern), "Expected identifier for a rest element destructuring pattern");
702
703 context.appendArrayPatternRestEntry(arrayPattern, location, innerPattern);
704 restElementWasFound = true;
705 break;
706 }
707
708 JSTokenLocation location = m_token.m_location;
709 auto innerPattern = parseDestructuringPattern(context, kind, depth + 1);
710 if (kind == DestructureToExpressions && !innerPattern)
711 return 0;
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));
717
718 if (kind == DestructureToExpressions && !match(CLOSEBRACKET))
719 return 0;
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;
723 break;
724 }
725 case OPENBRACE: {
726 auto objectPattern = context.createObjectPattern(m_token.m_location);
727 next();
728
729 do {
730 bool wasString = false;
731
732 if (match(CLOSEBRACE))
733 break;
734
735 Identifier propertyName;
736 TreeDestructuringPattern innerPattern = 0;
737 JSTokenLocation location = m_token.m_location;
738 if (match(IDENT)) {
739 propertyName = *m_token.m_data.ident;
740 JSToken identifierToken = m_token;
741 next();
742 if (consume(COLON))
743 innerPattern = parseDestructuringPattern(context, kind, depth + 1);
744 else
745 innerPattern = createBindingPattern(context, kind, propertyName, depth, identifierToken);
746 } else {
747 JSTokenType tokenType = m_token.m_type;
748 switch (m_token.m_type) {
749 case DOUBLE:
750 case INTEGER:
751 propertyName = Identifier::from(m_vm, m_token.m_data.doubleValue);
752 break;
753 case STRING:
754 propertyName = *m_token.m_data.ident;
755 wasString = true;
756 break;
757 default:
758 if (m_token.m_type != RESERVED && m_token.m_type != RESERVED_IF_STRICT && !(m_token.m_type & KeywordTokenFlag)) {
759 if (kind == DestructureToExpressions)
760 return 0;
761 failWithMessage("Expected a property name");
762 }
763 propertyName = *m_token.m_data.ident;
764 break;
765 }
766 next();
767 if (!consume(COLON)) {
768 if (kind == DestructureToExpressions)
769 return 0;
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(), "'");
773
774 failWithMessage("Expected a ':' prior to a named destructuring property");
775 }
776 innerPattern = parseDestructuringPattern(context, kind, depth + 1);
777 }
778 if (kind == DestructureToExpressions && !innerPattern)
779 return 0;
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));
785
786 if (kind == DestructureToExpressions && !match(CLOSEBRACE))
787 return 0;
788 consumeOrFail(CLOSEBRACE, "Expected either a closing '}' or an ',' after a property destructuring pattern");
789 pattern = objectPattern;
790 break;
791 }
792
793 default: {
794 if (!match(IDENT)) {
795 if (kind == DestructureToExpressions)
796 return 0;
797 semanticFailureDueToKeyword("variable name");
798 failWithMessage("Expected a parameter pattern or a ')' in parameter list");
799 }
800 pattern = createBindingPattern(context, kind, *m_token.m_data.ident, depth, m_token);
801 next();
802 break;
803 }
804 }
805 m_nonLHSCount = nonLHSCount;
806 return pattern;
807 }
808
809 template <typename LexerType>
810 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseDefaultValueForDestructuringPattern(TreeBuilder& context)
811 {
812 if (!match(EQUAL))
813 return 0;
814
815 next(TreeBuilder::DontBuildStrings); // consume '='
816 return parseAssignmentExpression(context);
817 }
818
819 template <typename LexerType>
820 template <class TreeBuilder> TreeConstDeclList Parser<LexerType>::parseConstDeclarationList(TreeBuilder& context)
821 {
822 failIfTrue(strictMode(), "Const declarations are not supported in strict mode");
823 TreeConstDeclList constDecls = 0;
824 TreeConstDeclList tail = 0;
825 do {
826 JSTokenLocation location(tokenLocation());
827 next();
828 matchOrFail(IDENT, "Expected an identifier name in const declaration");
829 const Identifier* name = m_token.m_data.ident;
830 next();
831 bool hasInitializer = match(EQUAL);
832 declareVariable(name);
833 context.addVar(name, DeclarationStacks::IsConstant | (hasInitializer ? DeclarationStacks::HasInitializer : 0));
834
835 TreeExpression initializer = 0;
836 if (hasInitializer) {
837 next(TreeBuilder::DontBuildStrings); // consume '='
838 initializer = parseAssignmentExpression(context);
839 failIfFalse(!!initializer, "Unable to parse initializer");
840 }
841 tail = context.appendConstDecl(location, tail, name, initializer);
842 if (!constDecls)
843 constDecls = tail;
844 } while (match(COMMA));
845 return constDecls;
846 }
847
848 template <typename LexerType>
849 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseForStatement(TreeBuilder& context)
850 {
851 ASSERT(match(FOR));
852 JSTokenLocation location(tokenLocation());
853 int startLine = tokenLine();
854 next();
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;
862 if (match(VAR)) {
863 /*
864 for (var IDENT in expression) statement
865 for (var varDeclarationList; expressionOpt; expressionOpt)
866 */
867 TreeDestructuringPattern forInTarget = 0;
868 TreeExpression forInInitializer = 0;
869 m_allowsIn = false;
870 JSTextPosition initStart;
871 JSTextPosition initEnd;
872 decls = parseVarDeclarationList(context, declarations, forInTarget, forInInitializer, declsStart, initStart, initEnd, ForLoopContext);
873 m_allowsIn = true;
874 propagateError();
875
876 // Remainder of a standard for loop is handled identically
877 if (match(SEMICOLON))
878 goto standardForLoop;
879
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");
882
883 if (forInInitializer)
884 failIfFalse(context.isBindingNode(forInTarget), "Cannot use initialiser syntax when binding to a pattern during enumeration");
885
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");
893 next();
894 }
895 TreeExpression expr = parseExpression(context);
896 failIfFalse(expr, "Expected expression to enumerate");
897 JSTextPosition exprEnd = lastTokenEndPosition();
898
899 int endLine = tokenLine();
900
901 handleProductionOrFail(CLOSEPAREN, ")", "end", (isOfEnumeration ? "for-of header" : "for-in header"));
902
903 const Identifier* unused = 0;
904 startLoop();
905 TreeStatement statement = parseStatement(context, unused);
906 endLoop();
907 failIfFalse(statement, "Expected statement as body of for-", isOfEnumeration ? "of" : "in", " statement");
908 if (isOfEnumeration)
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);
911 }
912
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);
923 }
924 m_allowsIn = false;
925 declsStart = tokenStartPosition();
926 decls = parseExpression(context);
927 declsEnd = lastTokenEndPosition();
928 m_allowsIn = true;
929 failIfFalse(decls, "Cannot parse for loop declarations");
930 }
931
932 if (match(SEMICOLON)) {
933 standardForLoop:
934 // Standard for loop
935 next();
936 TreeExpression condition = 0;
937
938 if (!match(SEMICOLON)) {
939 condition = parseExpression(context);
940 failIfFalse(condition, "Cannot parse for loop condition expression");
941 }
942 consumeOrFail(SEMICOLON, "Expected a ';' after the for loop condition expression");
943
944 TreeExpression increment = 0;
945 if (!match(CLOSEPAREN)) {
946 increment = parseExpression(context);
947 failIfFalse(increment, "Cannot parse for loop iteration expression");
948 }
949 int endLine = tokenLine();
950 handleProductionOrFail(CLOSEPAREN, ")", "end", "for-loop header");
951 const Identifier* unused = 0;
952 startLoop();
953 TreeStatement statement = parseStatement(context, unused);
954 endLoop();
955 failIfFalse(statement, "Expected a statement as the body of a for loop");
956 return context.createForLoop(location, decls, condition, increment, statement, startLine, endLine);
957 }
958
959 // For-in loop
960 enumerationLoop:
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;
966 next();
967 }
968 TreeExpression expr = parseExpression(context);
969 failIfFalse(expr, "Cannot parse subject for-", isOfEnumeration ? "of" : "in", " statement");
970 JSTextPosition exprEnd = lastTokenEndPosition();
971 int endLine = tokenLine();
972
973 handleProductionOrFail(CLOSEPAREN, ")", "end", (isOfEnumeration ? "for-of header" : "for-in header"));
974 const Identifier* unused = 0;
975 startLoop();
976 TreeStatement statement = parseStatement(context, unused);
977 endLoop();
978 failIfFalse(statement, "Expected a statement as the body of a for-", isOfEnumeration ? "of" : "in", "loop");
979 if (pattern) {
980 ASSERT(!decls);
981 if (isOfEnumeration)
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);
984 }
985 if (isOfEnumeration)
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);
988 }
989
990 template <typename LexerType>
991 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBreakStatement(TreeBuilder& context)
992 {
993 ASSERT(match(BREAK));
994 JSTokenLocation location(tokenLocation());
995 JSTextPosition start = tokenStartPosition();
996 JSTextPosition end = tokenEndPosition();
997 next();
998
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);
1002 }
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();
1007 next();
1008 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted break statement");
1009 return context.createBreakStatement(location, ident, start, end);
1010 }
1011
1012 template <typename LexerType>
1013 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseContinueStatement(TreeBuilder& context)
1014 {
1015 ASSERT(match(CONTINUE));
1016 JSTokenLocation location(tokenLocation());
1017 JSTextPosition start = tokenStartPosition();
1018 JSTextPosition end = tokenEndPosition();
1019 next();
1020
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);
1024 }
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();
1031 next();
1032 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted continue statement");
1033 return context.createContinueStatement(location, ident, start, end);
1034 }
1035
1036 template <typename LexerType>
1037 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseReturnStatement(TreeBuilder& context)
1038 {
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();
1044 next();
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
1047 // the statement
1048 if (match(SEMICOLON))
1049 end = tokenEndPosition();
1050
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);
1061 }
1062
1063 template <typename LexerType>
1064 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseThrowStatement(TreeBuilder& context)
1065 {
1066 ASSERT(match(THROW));
1067 JSTokenLocation location(tokenLocation());
1068 JSTextPosition start = tokenStartPosition();
1069 next();
1070 failIfTrue(match(SEMICOLON), "Expected expression after 'throw'");
1071 semanticFailIfTrue(autoSemiColon(), "Cannot have a newline after 'throw'");
1072
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");
1077
1078 return context.createThrowStatement(location, expr, start, end);
1079 }
1080
1081 template <typename LexerType>
1082 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWithStatement(TreeBuilder& context)
1083 {
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();
1089 next();
1090
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");
1101
1102 return context.createWithStatement(location, expr, statement, start, end, startLine, endLine);
1103 }
1104
1105 template <typename LexerType>
1106 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseSwitchStatement(TreeBuilder& context)
1107 {
1108 ASSERT(match(SWITCH));
1109 JSTokenLocation location(tokenLocation());
1110 int startLine = tokenLine();
1111 next();
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();
1116
1117 handleProductionOrFail(CLOSEPAREN, ")", "end", "subject of a 'switch'");
1118 handleProductionOrFail(OPENBRACE, "{", "start", "body of a 'switch'");
1119 startSwitch();
1120 TreeClauseList firstClauses = parseSwitchClauses(context);
1121 propagateError();
1122
1123 TreeClause defaultClause = parseSwitchDefaultClause(context);
1124 propagateError();
1125
1126 TreeClauseList secondClauses = parseSwitchClauses(context);
1127 propagateError();
1128 endSwitch();
1129 handleProductionOrFail(CLOSEBRACE, "}", "end", "body of a 'switch'");
1130
1131 return context.createSwitchStatement(location, expr, firstClauses, defaultClause, secondClauses, startLine, endLine);
1132
1133 }
1134
1135 template <typename LexerType>
1136 template <class TreeBuilder> TreeClauseList Parser<LexerType>::parseSwitchClauses(TreeBuilder& context)
1137 {
1138 if (!match(CASE))
1139 return 0;
1140 unsigned startOffset = tokenStart();
1141 next();
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;
1151
1152 while (match(CASE)) {
1153 startOffset = tokenStart();
1154 next();
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);
1163 }
1164 return clauseList;
1165 }
1166
1167 template <typename LexerType>
1168 template <class TreeBuilder> TreeClause Parser<LexerType>::parseSwitchDefaultClause(TreeBuilder& context)
1169 {
1170 if (!match(DEFAULT))
1171 return 0;
1172 unsigned startOffset = tokenStart();
1173 next();
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);
1179 return result;
1180 }
1181
1182 template <typename LexerType>
1183 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseTryStatement(TreeBuilder& context)
1184 {
1185 ASSERT(match(TRY));
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();
1192 next();
1193 matchOrFail(OPENBRACE, "Expected a block statement as body of a try statement");
1194
1195 tryBlock = parseBlockStatement(context);
1196 failIfFalse(tryBlock, "Cannot parse the body of try block");
1197 int lastLine = m_lastTokenEndPosition.line;
1198
1199 if (match(CATCH)) {
1200 currentScope()->setNeedsFullActivation();
1201 next();
1202
1203 handleProductionOrFail(OPENPAREN, "(", "start", "'catch' target");
1204 if (!match(IDENT)) {
1205 semanticFailureDueToKeyword("catch variable name");
1206 failWithMessage("Expected identifier name as catch target");
1207 }
1208 ident = m_token.m_data.ident;
1209 next();
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");
1218 }
1219
1220 if (match(FINALLY)) {
1221 next();
1222 matchOrFail(OPENBRACE, "Expected block statement for finally body");
1223 finallyBlock = parseBlockStatement(context);
1224 failIfFalse(finallyBlock, "Cannot parse finally body");
1225 }
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);
1228 }
1229
1230 template <typename LexerType>
1231 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseDebuggerStatement(TreeBuilder& context)
1232 {
1233 ASSERT(match(DEBUGGER));
1234 JSTokenLocation location(tokenLocation());
1235 int startLine = tokenLine();
1236 int endLine = startLine;
1237 next();
1238 if (match(SEMICOLON))
1239 startLine = tokenLine();
1240 failIfFalse(autoSemiColon(), "Debugger keyword must be followed by a ';'");
1241 return context.createDebugger(location, startLine, endLine);
1242 }
1243
1244 template <typename LexerType>
1245 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBlockStatement(TreeBuilder& context)
1246 {
1247 ASSERT(match(OPENBRACE));
1248 JSTokenLocation location(tokenLocation());
1249 int startOffset = m_token.m_data.offset;
1250 int start = tokenLine();
1251 next();
1252 if (match(CLOSEBRACE)) {
1253 int endOffset = m_token.m_data.offset;
1254 next();
1255 TreeStatement result = context.createBlockStatement(location, 0, start, m_lastTokenEndPosition.line);
1256 context.setStartOffset(result, startOffset);
1257 context.setEndOffset(result, endOffset);
1258 return result;
1259 }
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;
1264 next();
1265 TreeStatement result = context.createBlockStatement(location, subtree, start, m_lastTokenEndPosition.line);
1266 context.setStartOffset(result, startOffset);
1267 context.setEndOffset(result, endOffset);
1268 return result;
1269 }
1270
1271 template <typename LexerType>
1272 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseStatement(TreeBuilder& context, const Identifier*& directive, unsigned* directiveLiteralLength)
1273 {
1274 DepthManager statementDepth(&m_statementDepth);
1275 m_statementDepth++;
1276 directive = 0;
1277 int nonTrivialExpressionCount = 0;
1278 failIfStackOverflow();
1279 TreeStatement result = 0;
1280 bool shouldSetEndOffset = true;
1281
1282 switch (m_token.m_type) {
1283 case OPENBRACE:
1284 result = parseBlockStatement(context);
1285 shouldSetEndOffset = false;
1286 break;
1287 case VAR:
1288 result = parseVarDeclaration(context);
1289 break;
1290 case FUNCTION:
1291 failIfFalseIfStrict(m_statementDepth == 1, "Strict mode does not allow function declarations in a lexically nested statement");
1292 result = parseFunctionDeclaration(context);
1293 break;
1294 case SEMICOLON: {
1295 JSTokenLocation location(tokenLocation());
1296 next();
1297 result = context.createEmptyStatement(location);
1298 break;
1299 }
1300 case IF:
1301 result = parseIfStatement(context);
1302 break;
1303 case DO:
1304 result = parseDoWhileStatement(context);
1305 break;
1306 case WHILE:
1307 result = parseWhileStatement(context);
1308 break;
1309 case FOR:
1310 result = parseForStatement(context);
1311 break;
1312 case CONTINUE:
1313 result = parseContinueStatement(context);
1314 break;
1315 case BREAK:
1316 result = parseBreakStatement(context);
1317 break;
1318 case RETURN:
1319 result = parseReturnStatement(context);
1320 break;
1321 case WITH:
1322 result = parseWithStatement(context);
1323 break;
1324 case SWITCH:
1325 result = parseSwitchStatement(context);
1326 break;
1327 case THROW:
1328 result = parseThrowStatement(context);
1329 break;
1330 case TRY:
1331 result = parseTryStatement(context);
1332 break;
1333 case DEBUGGER:
1334 result = parseDebuggerStatement(context);
1335 break;
1336 case EOFTOK:
1337 case CASE:
1338 case CLOSEBRACE:
1339 case DEFAULT:
1340 // These tokens imply the end of a set of source elements
1341 return 0;
1342 case IDENT:
1343 result = parseExpressionOrLabelStatement(context);
1344 break;
1345 case STRING:
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;
1350 FALLTHROUGH;
1351 default:
1352 TreeStatement exprStatement = parseExpressionStatement(context);
1353 if (directive && nonTrivialExpressionCount != m_nonTrivialExpressionCount)
1354 directive = 0;
1355 result = exprStatement;
1356 break;
1357 }
1358
1359 if (result && shouldSetEndOffset)
1360 context.setEndOffset(result, m_lastTokenEndPosition.offset);
1361 return result;
1362 }
1363
1364 template <typename LexerType>
1365 template <class TreeBuilder> TreeFormalParameterList Parser<LexerType>::parseFormalParameters(TreeBuilder& context)
1366 {
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);
1375 }
1376 return list;
1377 }
1378
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)
1383 {
1384 JSTokenLocation startLocation(tokenLocation());
1385 unsigned startColumn = tokenColumn();
1386
1387 if (parseType == StandardFunctionParseType) {
1388 next();
1389 if (match(CLOSEBRACE)) {
1390 unsigned endColumn = tokenColumn();
1391 return context.createFunctionBody(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind);
1392 }
1393 }
1394
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");
1400 #else
1401 failIfFalse(parseSourceElements(bodyBuilder, CheckForStrictMode, StandardFunctionParseType), "Cannot parse body of this function");
1402 #endif
1403 unsigned endColumn = tokenColumn();
1404 return context.createFunctionBody(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind);
1405 }
1406
1407 static const char* stringForFunctionMode(FunctionParseMode mode)
1408 {
1409 switch (mode) {
1410 case GetterMode:
1411 return "getter";
1412 case SetterMode:
1413 return "setter";
1414 case FunctionMode:
1415 return "function";
1416 case MethodMode:
1417 return "method";
1418 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
1419 case ArrowFunctionMode:
1420 return "arrow function";
1421 #endif
1422 }
1423 RELEASE_ASSERT_NOT_REACHED();
1424 return nullptr;
1425 }
1426
1427 template <typename LexerType> template <class TreeBuilder> int Parser<LexerType>::parseFunctionParameters(TreeBuilder& context, FunctionParseMode mode, ParserFunctionInfo<TreeBuilder>& info)
1428 {
1429 int parametersStart = m_token.m_location.startOffset;
1430
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");
1436 } else {
1437 if (match(OPENPAREN)) {
1438 next();
1439
1440 if (!match(CLOSEPAREN)) {
1441 info.parameters = parseFormalParameters(context);
1442 failIfFalse(info.parameters, "Cannot parse parameters for this ", stringForFunctionMode(mode));
1443 }
1444
1445 consumeOrFail(CLOSEPAREN, "Expected a ')' or a ',' after a parameter declaration");
1446 } else {
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));
1451 }
1452 }
1453
1454 return parametersStart;
1455 }
1456 #endif
1457
1458 if (!consume(OPENPAREN)) {
1459 semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
1460 failWithMessage("Expected an opening '(' before a ", stringForFunctionMode(mode), "'s parameter list");
1461 }
1462
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");
1472 } else {
1473 if (!match(CLOSEPAREN)) {
1474 info.parameters = parseFormalParameters(context);
1475 failIfFalse(info.parameters, "Cannot parse parameters for this ", stringForFunctionMode(mode));
1476 }
1477 consumeOrFail(CLOSEPAREN, "Expected a ')' or a ',' after a parameter declaration");
1478 }
1479
1480 return parametersStart;
1481 }
1482
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)
1485 {
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;
1492
1493 switch (parseType) {
1494 case StandardFunctionParseType: {
1495 if (match(IDENT)) {
1496 info.name = m_token.m_data.ident;
1497 m_lastFunctionName = info.name;
1498 next();
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();
1506 return false;
1507 }
1508
1509 parametersStart = parseFunctionParameters(context, mode, info);
1510 propagateError();
1511
1512 matchOrFail(OPENBRACE, "Expected an opening '{' at the start of a ", stringForFunctionMode(mode), " body");
1513
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.
1516
1517 if (m_defaultConstructorKind != ConstructorKind::None) {
1518 constructorKind = m_defaultConstructorKind;
1519 expectedSuperBinding = m_defaultConstructorKind == ConstructorKind::Derived ? SuperBinding::Needed : SuperBinding::NotNeeded;
1520 }
1521
1522 info.startFunctionOffset = m_token.m_data.offset;
1523
1524 break;
1525 }
1526 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
1527 case ArrowFunctionParseType: {
1528 parametersStart = parseFunctionParameters(context, ArrowFunctionMode, info);
1529 propagateError();
1530
1531 matchOrFail(ARROWFUNCTION, "Expected a '=>' after arrow function parameter declaration");
1532
1533 if (m_lexer->prevTerminator())
1534 failDueToUnexpectedToken();
1535
1536 ASSERT(constructorKind == ConstructorKind::None);
1537
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();
1542
1543 next();
1544 info.functionBodyType = match(OPENBRACE) ? ArrowFunctionBodyBlock : ArrowFunctionBodyExpression;
1545 info.startFunctionOffset = (info.functionBodyType == ArrowFunctionBodyBlock) ? m_token.m_data.offset : info.arrowFunctionOffset;
1546
1547 restoreSavePoint(savePoint);
1548
1549 break;
1550 }
1551 #endif
1552 }
1553
1554 bool isClassConstructor = constructorKind != ConstructorKind::None;
1555
1556 info.bodyStartLine = tokenLine();
1557 info.bodyStartColumn = m_token.m_data.offset - m_token.m_data.lineStartOffset;
1558 JSTokenLocation startLocation(tokenLocation());
1559
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;
1565
1566 endLocation.line = cachedInfo->lastTockenLine;
1567 endLocation.startOffset = cachedInfo->lastTockenStartOffset;
1568 endLocation.lineStartOffset = cachedInfo->lastTockenLineStartOffset;
1569
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;
1576
1577 info.body = context.createFunctionBody(
1578 startLocation, endLocation, info.bodyStartColumn, bodyEndColumn,
1579 functionKeywordStart, functionNameStart, parametersStart,
1580 cachedInfo->strictMode, constructorKind);
1581
1582 functionScope->restoreFromSourceProviderCache(cachedInfo);
1583 failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo), "Parser error");
1584
1585 m_token = cachedInfo->endFunctionToken();
1586
1587 if (endColumnIsOnStartLine)
1588 m_token.m_location.lineStartOffset = currentLineStartOffset;
1589
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;
1596 else
1597 info.functionBodyType = StandardFunctionBodyBlock;
1598
1599 switch (info.functionBodyType) {
1600 case ArrowFunctionBodyExpression:
1601 next();
1602 context.setEndOffset(info.body, m_lexer->currentOffset());
1603 break;
1604 case ArrowFunctionBodyBlock:
1605 case StandardFunctionBodyBlock:
1606 context.setEndOffset(info.body, m_lexer->currentOffset());
1607 next();
1608 break;
1609 }
1610 #else
1611 context.setEndOffset(info.body, m_lexer->currentOffset());
1612 next();
1613 #endif
1614 info.bodyEndLine = m_lastTokenEndPosition.line;
1615 return true;
1616 }
1617
1618 m_lastFunctionName = lastFunctionName;
1619 ParserState oldState = saveState();
1620
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; }
1625 next();
1626
1627 info.bodyStartLine = tokenLine();
1628 info.bodyStartColumn = m_token.m_data.offset - m_token.m_data.lineStartOffset;
1629
1630 info.body = parseFunctionBody(context, functionKeywordStart, functionNameStart, parametersStart, constructorKind, StandardFunctionParseType);
1631 break;
1632 }
1633 case StandardFunctionBodyBlock:
1634 case ArrowFunctionBodyExpression : {
1635 info.body = parseFunctionBody(context, functionKeywordStart, functionNameStart, parametersStart, constructorKind, parseType);
1636 break;
1637 }
1638 }
1639 #else
1640 info.body = parseFunctionBody(context, functionKeywordStart, functionNameStart, parametersStart, constructorKind, StandardFunctionParseType);
1641 #endif
1642
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");
1650 }
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");
1654 }
1655 if (functionScope->needsSuperBinding())
1656 semanticFailIfTrue(expectedSuperBinding == SuperBinding::NotNeeded, "super can only be used in a method of a derived class");
1657
1658 JSTokenLocation location = JSTokenLocation(m_token.m_location);
1659 info.endFunctionOffset = m_token.m_data.offset;
1660
1661 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
1662 if (info.functionBodyType == ArrowFunctionBodyExpression) {
1663 location = locationBeforeLastToken();
1664 info.endFunctionOffset = location.endOffset;
1665 }
1666 #endif
1667
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;
1685 }
1686 #endif
1687 functionScope->fillParametersForSourceProviderCache(parameters);
1688 newInfo = SourceProviderCacheItem::create(parameters);
1689 }
1690
1691 failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo), "Parser error");
1692
1693 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
1694 if (info.functionBodyType == ArrowFunctionBodyExpression)
1695 failIfFalse(isEndOfArrowFunction(), "Expected the closing ';' ',' ']' ')' '}', line terminator or EOF after arrow function");
1696 else {
1697 matchOrFail(CLOSEBRACE, "Expected a closing '}' after a ", stringForFunctionMode(mode), " body");
1698 next();
1699 }
1700 #else
1701 matchOrFail(CLOSEBRACE, "Expected a closing '}' after a ", stringForFunctionMode(mode), " body");
1702 next();
1703 #endif
1704
1705 if (newInfo)
1706 m_functionCache->add(info.startFunctionOffset, WTF::move(newInfo));
1707
1708 info.bodyEndLine = m_lastTokenEndPosition.line;
1709 return true;
1710 }
1711
1712 template <typename LexerType>
1713 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDeclaration(TreeBuilder& context)
1714 {
1715 ASSERT(match(FUNCTION));
1716 JSTokenLocation location(tokenLocation());
1717 unsigned functionKeywordStart = tokenStart();
1718 next();
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);
1725 }
1726
1727 #if ENABLE(ES6_CLASS_SYNTAX)
1728 template <typename LexerType>
1729 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseClassDeclaration(TreeBuilder& context)
1730 {
1731 ASSERT(match(CLASSTOKEN));
1732 JSTokenLocation location(tokenLocation());
1733 JSTextPosition classStart = tokenStartPosition();
1734 unsigned classStartLine = tokenLine();
1735
1736 ParserClassInfo<TreeBuilder> info;
1737 TreeClassExpression classExpr = parseClass(context, FunctionNeedsName, info);
1738 failIfFalse(classExpr, "Failed to parse class");
1739 declareVariable(info.className);
1740
1741 // FIXME: This should be like `let`, not `var`.
1742 context.addVar(info.className, DeclarationStacks::HasInitializer);
1743
1744 JSTextPosition classEnd = lastTokenEndPosition();
1745 unsigned classEndLine = tokenLine();
1746
1747 return context.createClassDeclStatement(location, classExpr, classStart, classEnd, classStartLine, classEndLine);
1748 }
1749
1750 template <typename LexerType>
1751 template <class TreeBuilder> TreeClassExpression Parser<LexerType>::parseClass(TreeBuilder& context, FunctionRequirements requirements, ParserClassInfo<TreeBuilder>& info)
1752 {
1753 ASSERT(match(CLASSTOKEN));
1754 JSTokenLocation location(tokenLocation());
1755 next();
1756
1757 AutoPopScopeRef classScope(this, pushScope());
1758 classScope->setStrictMode();
1759
1760 const Identifier* className = nullptr;
1761 if (match(IDENT)) {
1762 className = m_token.m_data.ident;
1763 info.className = className;
1764 next();
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();
1771 } else
1772 className = &m_vm->propertyNames->nullIdentifier;
1773 ASSERT(className);
1774
1775 TreeExpression parentClass = 0;
1776 if (consume(EXTENDS)) {
1777 parentClass = parseMemberExpression(context);
1778 failIfFalse(parentClass, "Cannot parse the parent class name");
1779 }
1780 const ConstructorKind constructorKind = parentClass ? ConstructorKind::Derived : ConstructorKind::Base;
1781
1782 consumeOrFail(OPENBRACE, "Expected opening '{' at the start of a class body");
1783
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)) {
1791 next();
1792 continue;
1793 }
1794
1795 JSTokenLocation methodLocation(tokenLocation());
1796 unsigned methodStart = tokenStart();
1797
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;
1800 if (isStaticMethod)
1801 next();
1802
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) {
1809 case STRING:
1810 ident = m_token.m_data.ident;
1811 ASSERT(ident);
1812 next();
1813 break;
1814 case IDENT:
1815 ident = m_token.m_data.ident;
1816 isGetter = *ident == propertyNames.get;
1817 isSetter = *ident == propertyNames.set;
1818 ASSERT(ident);
1819 break;
1820 case DOUBLE:
1821 case INTEGER:
1822 ident = &m_parserArena.identifierArena().makeNumericIdentifier(const_cast<VM*>(m_vm), m_token.m_data.doubleValue);
1823 ASSERT(ident);
1824 next();
1825 break;
1826 default:
1827 failDueToUnexpectedToken();
1828 }
1829
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");
1837 } else {
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;
1843
1844 TreeExpression method = context.createFunctionExpr(methodLocation, methodInfo);
1845 if (isConstructor) {
1846 semanticFailIfTrue(constructor, "Cannot declare multiple constructors in a single class");
1847 constructor = method;
1848 continue;
1849 }
1850
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);
1855 }
1856
1857 TreePropertyList& tail = isStaticMethod ? staticMethodsTail : instanceMethodsTail;
1858 if (tail)
1859 tail = context.createPropertyList(methodLocation, property, tail);
1860 else {
1861 tail = context.createPropertyList(methodLocation, property);
1862 if (isStaticMethod)
1863 staticMethods = tail;
1864 else
1865 instanceMethods = tail;
1866 }
1867 }
1868
1869 failIfFalse(popScope(classScope, TreeBuilder::NeedsFreeVariableInfo), "Parser error");
1870 consumeOrFail(CLOSEBRACE, "Expected a closing '}' after a class body");
1871
1872 return context.createClassExpr(location, *className, constructor, parentClass, instanceMethods, staticMethods);
1873 }
1874 #endif
1875
1876 struct LabelInfo {
1877 LabelInfo(const Identifier* ident, const JSTextPosition& start, const JSTextPosition& end)
1878 : m_ident(ident)
1879 , m_start(start)
1880 , m_end(end)
1881 {
1882 }
1883
1884 const Identifier* m_ident;
1885 JSTextPosition m_start;
1886 JSTextPosition m_end;
1887 };
1888
1889 template <typename LexerType>
1890 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionOrLabelStatement(TreeBuilder& context)
1891 {
1892
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.
1895 */
1896 Vector<LabelInfo> labels;
1897 JSTokenLocation location;
1898 do {
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);
1910 }
1911 const Identifier* ident = m_token.m_data.ident;
1912 JSTextPosition end = tokenEndPosition();
1913 next();
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));
1922 }
1923 } while (match(IDENT));
1924 bool isLoop = false;
1925 switch (m_token.m_type) {
1926 case FOR:
1927 case WHILE:
1928 case DO:
1929 isLoop = true;
1930 break;
1931
1932 default:
1933 break;
1934 }
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);
1939 }
1940 TreeStatement statement = parseStatement(context, unused);
1941 if (!m_syntaxAlreadyValidated) {
1942 for (size_t i = 0; i < labels.size(); i++)
1943 popLabel();
1944 }
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);
1949 }
1950 return statement;
1951 }
1952
1953 template <typename LexerType>
1954 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionStatement(TreeBuilder& context)
1955 {
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.
1961 case CLASSTOKEN:
1962 failWithMessage("'class' declaration is not directly within a block statement");
1963 break;
1964 default:
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
1967 break;
1968 }
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);
1975 }
1976
1977 template <typename LexerType>
1978 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseIfStatement(TreeBuilder& context)
1979 {
1980 ASSERT(match(IF));
1981 JSTokenLocation ifLocation(tokenLocation());
1982 int start = tokenLine();
1983 next();
1984 handleProductionOrFail(OPENPAREN, "(", "start", "'if' condition");
1985
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");
1990
1991 const Identifier* unused = 0;
1992 TreeStatement trueBlock = parseStatement(context, unused);
1993 failIfFalse(trueBlock, "Expected a statement as the body of an if block");
1994
1995 if (!match(ELSE))
1996 return context.createIfStatement(ifLocation, condition, trueBlock, 0, start, end);
1997
1998 Vector<TreeExpression> exprStack;
1999 Vector<std::pair<int, int>> posStack;
2000 Vector<JSTokenLocation> tokenLocationStack;
2001 Vector<TreeStatement> statementStack;
2002 bool trailingElse = false;
2003 do {
2004 JSTokenLocation tempLocation = tokenLocation();
2005 next();
2006 if (!match(IF)) {
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;
2012 break;
2013 }
2014 int innerStart = tokenLine();
2015 next();
2016
2017 handleProductionOrFail(OPENPAREN, "(", "start", "'if' condition");
2018
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));
2031
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);
2044 }
2045
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);
2060 }
2061
2062 return context.createIfStatement(ifLocation, condition, trueBlock, statementStack.last(), start, end);
2063 }
2064
2065 template <typename LexerType>
2066 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseExpression(TreeBuilder& context)
2067 {
2068 failIfStackOverflow();
2069 JSTokenLocation location(tokenLocation());
2070 TreeExpression node = parseAssignmentExpression(context);
2071 failIfFalse(node, "Cannot parse expression");
2072 context.setEndOffset(node, m_lastTokenEndPosition.offset);
2073 if (!match(COMMA))
2074 return node;
2075 next();
2076 m_nonTrivialExpressionCount++;
2077 m_nonLHSCount++;
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);
2089 }
2090 context.setEndOffset(head, m_lastTokenEndPosition.offset);
2091 return head;
2092 }
2093
2094
2095 template <typename LexerType>
2096 template <typename TreeBuilder> TreeExpression Parser<LexerType>::parseAssignmentExpression(TreeBuilder& context)
2097 {
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);
2108 if (rhs)
2109 return context.createDestructuringAssignment(location, pattern, rhs);
2110 }
2111 restoreSavePoint(savePoint);
2112 }
2113
2114 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
2115 if (isArrowFunctionParamters())
2116 return parseArrowFunctionExpression(context);
2117 #endif
2118
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");
2124
2125 return lhs;
2126 }
2127
2128 int assignmentStack = 0;
2129 Operator op;
2130 bool hadAssignment = false;
2131 while (true) {
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;
2145 default:
2146 goto end;
2147 }
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;
2159 }
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");
2165 break;
2166 }
2167 }
2168 end:
2169 if (hadAssignment)
2170 m_nonLHSCount++;
2171
2172 if (!TreeBuilder::CreatesAST)
2173 return lhs;
2174
2175 while (assignmentStack)
2176 lhs = context.createAssignment(location, assignmentStack, lhs, initialAssignmentCount, m_assignmentCount, lastTokenEndPosition());
2177
2178 return lhs;
2179 }
2180
2181 template <typename LexerType>
2182 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseConditionalExpression(TreeBuilder& context)
2183 {
2184 JSTokenLocation location(tokenLocation());
2185 TreeExpression cond = parseBinaryExpression(context);
2186 failIfFalse(cond, "Cannot parse expression");
2187 if (!match(QUESTION))
2188 return cond;
2189 m_nonTrivialExpressionCount++;
2190 m_nonLHSCount++;
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");
2196
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);
2201 }
2202
2203 ALWAYS_INLINE static bool isUnaryOp(JSTokenType token)
2204 {
2205 return token & UnaryOpTokenFlag;
2206 }
2207
2208 template <typename LexerType>
2209 int Parser<LexerType>::isBinaryOperator(JSTokenType token)
2210 {
2211 if (m_allowsIn)
2212 return token & (BinaryOpTokenPrecedenceMask << BinaryOpTokenAllowsInPrecedenceAdditionalShift);
2213 return token & BinaryOpTokenPrecedenceMask;
2214 }
2215
2216 template <typename LexerType>
2217 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseBinaryExpression(TreeBuilder& context)
2218 {
2219 int operandStackDepth = 0;
2220 int operatorStackDepth = 0;
2221 typename TreeBuilder::BinaryExprContext binaryExprContext(context);
2222 JSTokenLocation location(tokenLocation());
2223 while (true) {
2224 JSTextPosition exprStart = tokenStartPosition();
2225 int initialAssignments = m_assignmentCount;
2226 TreeExpression current = parseUnaryExpression(context);
2227 failIfFalse(current, "Cannot parse expression");
2228
2229 context.appendBinaryExpressionInfo(operandStackDepth, current, exprStart, lastTokenEndPosition(), lastTokenEndPosition(), initialAssignments != m_assignmentCount);
2230 int precedence = isBinaryOperator(m_token.m_type);
2231 if (!precedence)
2232 break;
2233 m_nonTrivialExpressionCount++;
2234 m_nonLHSCount++;
2235 int operatorToken = m_token.m_type;
2236 next(TreeBuilder::DontBuildStrings);
2237
2238 while (operatorStackDepth && context.operatorStackHasHigherPrecedence(operatorStackDepth, precedence)) {
2239 ASSERT(operandStackDepth > 1);
2240
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);
2246 }
2247 context.operatorStackAppend(operatorStackDepth, operatorToken, precedence);
2248 }
2249 while (operatorStackDepth) {
2250 ASSERT(operandStackDepth > 1);
2251
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);
2257 }
2258 return context.popOperandStack(operandStackDepth);
2259 }
2260
2261 template <typename LexerType>
2262 template <class TreeBuilder> TreeProperty Parser<LexerType>::parseProperty(TreeBuilder& context, bool complete)
2263 {
2264 bool wasIdent = false;
2265 switch (m_token.m_type) {
2266 namedProperty:
2267 case IDENT:
2268 wasIdent = true;
2269 FALLTHROUGH;
2270 case STRING: {
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);
2275 else
2276 nextExpectIdentifier(LexerFlagsIgnoreReservedWords | TreeBuilder::DontBuildKeywords);
2277
2278 if (match(COLON)) {
2279 next();
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);
2284 }
2285
2286 if (match(OPENPAREN)) {
2287 auto method = parsePropertyMethod(context, ident);
2288 propagateError();
2289 return context.createProperty(ident, method, PropertyNode::Constant, PropertyNode::KnownDirect, complete);
2290 }
2291
2292 failIfFalse(wasIdent, "Expected an identifier as property name");
2293
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);
2300 }
2301
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;
2307 else
2308 failWithMessage("Expected a ':' following the property name '", ident->impl(), "'");
2309 return parseGetterSetter(context, complete, type, getterOrSetterStartOffset);
2310 }
2311 case DOUBLE:
2312 case INTEGER: {
2313 double propertyName = m_token.m_data.doubleValue;
2314 next();
2315
2316 if (match(OPENPAREN)) {
2317 const Identifier& ident = m_parserArena.identifierArena().makeNumericIdentifier(const_cast<VM*>(m_vm), propertyName);
2318 auto method = parsePropertyMethod(context, &ident);
2319 propagateError();
2320 return context.createProperty(&ident, method, PropertyNode::Constant, PropertyNode::Unknown, complete);
2321 }
2322
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);
2328 }
2329 case OPENBRACKET: {
2330 next();
2331 auto propertyName = parseAssignmentExpression(context);
2332 failIfFalse(propertyName, "Cannot parse computed property name");
2333 handleProductionOrFail(CLOSEBRACKET, "]", "end", "computed property name");
2334
2335 if (match(OPENPAREN)) {
2336 auto method = parsePropertyMethod(context, &m_vm->propertyNames->nullIdentifier);
2337 propagateError();
2338 return context.createProperty(propertyName, method, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Computed), PropertyNode::KnownDirect, complete);
2339 }
2340
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);
2346 }
2347 default:
2348 failIfFalse(m_token.m_type & KeywordTokenFlag, "Expected a property name");
2349 goto namedProperty;
2350 }
2351 }
2352
2353 template <typename LexerType>
2354 template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePropertyMethod(TreeBuilder& context, const Identifier* methodName)
2355 {
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);
2362 }
2363
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)
2367 {
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;
2378 else
2379 failDueToUnexpectedToken();
2380 JSTokenLocation location(tokenLocation());
2381 next();
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");
2387 } else {
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");
2391 }
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);
2395 }
2396
2397 template <typename LexerType>
2398 template <class TreeBuilder> bool Parser<LexerType>::shouldCheckPropertyForUnderscoreProtoDuplicate(TreeBuilder& context, const TreeProperty& property)
2399 {
2400 if (m_syntaxAlreadyValidated)
2401 return false;
2402
2403 if (!context.getName(property))
2404 return false;
2405
2406 // A Constant property that is not a Computed or Shorthand Constant property.
2407 return context.getType(property) == PropertyNode::Constant;
2408 }
2409
2410 template <typename LexerType>
2411 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseObjectLiteral(TreeBuilder& context)
2412 {
2413 auto savePoint = createSavePoint();
2414 consumeOrFailWithFlags(OPENBRACE, TreeBuilder::DontBuildStrings, "Expected opening '{' at the start of an object literal");
2415
2416 int oldNonLHSCount = m_nonLHSCount;
2417
2418 JSTokenLocation location(tokenLocation());
2419 if (match(CLOSEBRACE)) {
2420 next();
2421 return context.createObjectLiteral(location);
2422 }
2423
2424 TreeProperty property = parseProperty(context, false);
2425 failIfFalse(property, "Cannot parse object literal property");
2426
2427 if (!m_syntaxAlreadyValidated && context.getType(property) & (PropertyNode::Getter | PropertyNode::Setter)) {
2428 restoreSavePoint(savePoint);
2429 return parseStrictObjectLiteral(context);
2430 }
2431
2432 bool seenUnderscoreProto = false;
2433 if (shouldCheckPropertyForUnderscoreProtoDuplicate(context, property))
2434 seenUnderscoreProto = *context.getName(property) == m_vm->propertyNames->underscoreProto;
2435
2436 TreePropertyList propertyList = context.createPropertyList(location, property);
2437 TreePropertyList tail = propertyList;
2438 while (match(COMMA)) {
2439 next(TreeBuilder::DontBuildStrings);
2440 if (match(CLOSEBRACE))
2441 break;
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);
2448 }
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;
2453 }
2454 }
2455 tail = context.createPropertyList(propertyLocation, property, tail);
2456 }
2457
2458 location = tokenLocation();
2459 handleProductionOrFail(CLOSEBRACE, "}", "end", "object literal");
2460
2461 m_nonLHSCount = oldNonLHSCount;
2462
2463 return context.createObjectLiteral(location, propertyList);
2464 }
2465
2466 template <typename LexerType>
2467 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseStrictObjectLiteral(TreeBuilder& context)
2468 {
2469 consumeOrFail(OPENBRACE, "Expected opening '{' at the start of an object literal");
2470
2471 int oldNonLHSCount = m_nonLHSCount;
2472
2473 JSTokenLocation location(tokenLocation());
2474 if (match(CLOSEBRACE)) {
2475 next();
2476 return context.createObjectLiteral(location);
2477 }
2478
2479 TreeProperty property = parseProperty(context, true);
2480 failIfFalse(property, "Cannot parse object literal property");
2481
2482 bool seenUnderscoreProto = false;
2483 if (shouldCheckPropertyForUnderscoreProtoDuplicate(context, property))
2484 seenUnderscoreProto = *context.getName(property) == m_vm->propertyNames->underscoreProto;
2485
2486 TreePropertyList propertyList = context.createPropertyList(location, property);
2487 TreePropertyList tail = propertyList;
2488 while (match(COMMA)) {
2489 next();
2490 if (match(CLOSEBRACE))
2491 break;
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;
2499 }
2500 }
2501 tail = context.createPropertyList(propertyLocation, property, tail);
2502 }
2503
2504 location = tokenLocation();
2505 handleProductionOrFail(CLOSEBRACE, "}", "end", "object literal");
2506
2507 m_nonLHSCount = oldNonLHSCount;
2508
2509 return context.createObjectLiteral(location, propertyList);
2510 }
2511
2512 template <typename LexerType>
2513 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseArrayLiteral(TreeBuilder& context)
2514 {
2515 consumeOrFailWithFlags(OPENBRACKET, TreeBuilder::DontBuildStrings, "Expected an opening '[' at the beginning of an array literal");
2516
2517 int oldNonLHSCount = m_nonLHSCount;
2518
2519 int elisions = 0;
2520 while (match(COMMA)) {
2521 next(TreeBuilder::DontBuildStrings);
2522 elisions++;
2523 }
2524 if (match(CLOSEBRACKET)) {
2525 JSTokenLocation location(tokenLocation());
2526 next(TreeBuilder::DontBuildStrings);
2527 return context.createArray(location, elisions);
2528 }
2529
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;
2535 next();
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);
2539 } else
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;
2544 elisions = 0;
2545 while (match(COMMA)) {
2546 next(TreeBuilder::DontBuildStrings);
2547 elisions = 0;
2548
2549 while (match(COMMA)) {
2550 next();
2551 elisions++;
2552 }
2553
2554 if (match(CLOSEBRACKET)) {
2555 JSTokenLocation location(tokenLocation());
2556 next(TreeBuilder::DontBuildStrings);
2557 return context.createArray(location, elisions, elementList);
2558 }
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;
2563 next();
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);
2568 continue;
2569 }
2570 TreeExpression elem = parseAssignmentExpression(context);
2571 failIfFalse(elem, "Cannot parse array literal element");
2572 tail = context.createElementList(tail, elisions, elem);
2573 }
2574
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");
2579 }
2580
2581 m_nonLHSCount = oldNonLHSCount;
2582
2583 return context.createArray(location, elementList);
2584 }
2585
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)
2589 {
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);
2594 }
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());
2600 next();
2601 return context.createTemplateString(location, *cooked, *raw);
2602 }
2603
2604 template <typename LexerType>
2605 template <class TreeBuilder> typename TreeBuilder::TemplateLiteral Parser<LexerType>::parseTemplateLiteral(TreeBuilder& context, typename LexerType::RawStringsBuildMode rawStringsBuildMode)
2606 {
2607 JSTokenLocation location(tokenLocation());
2608 bool elementIsTail = false;
2609
2610 auto headTemplateString = parseTemplateString(context, true, rawStringsBuildMode, elementIsTail);
2611 failIfFalse(headTemplateString, "Cannot parse head template element");
2612
2613 typename TreeBuilder::TemplateStringList templateStringList = context.createTemplateStringList(headTemplateString);
2614 typename TreeBuilder::TemplateStringList templateStringTail = templateStringList;
2615
2616 if (elementIsTail)
2617 return context.createTemplateLiteral(location, templateStringList);
2618
2619 failIfTrue(match(CLOSEBRACE), "Template literal expression cannot be empty");
2620 TreeExpression expression = parseExpression(context);
2621 failIfFalse(expression, "Cannot parse expression in template literal");
2622
2623 typename TreeBuilder::TemplateExpressionList templateExpressionList = context.createTemplateExpressionList(expression);
2624 typename TreeBuilder::TemplateExpressionList templateExpressionTail = templateExpressionList;
2625
2626 auto templateString = parseTemplateString(context, false, rawStringsBuildMode, elementIsTail);
2627 failIfFalse(templateString, "Cannot parse template element");
2628 templateStringTail = context.createTemplateStringList(templateStringTail, templateString);
2629
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");
2634
2635 templateExpressionTail = context.createTemplateExpressionList(templateExpressionTail, expression);
2636
2637 auto templateString = parseTemplateString(context, false, rawStringsBuildMode, elementIsTail);
2638 failIfFalse(templateString, "Cannot parse template element");
2639 templateStringTail = context.createTemplateStringList(templateStringTail, templateString);
2640 }
2641
2642 return context.createTemplateLiteral(location, templateStringList, templateExpressionList);
2643 }
2644 #endif
2645
2646 template <typename LexerType>
2647 template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePrimaryExpression(TreeBuilder& context)
2648 {
2649 failIfStackOverflow();
2650 switch (m_token.m_type) {
2651 case FUNCTION: {
2652 JSTokenLocation location(tokenLocation());
2653 unsigned functionKeywordStart = tokenStart();
2654 next();
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);
2659 }
2660 #if ENABLE(ES6_CLASS_SYNTAX)
2661 case CLASSTOKEN: {
2662 ParserClassInfo<TreeBuilder> info;
2663 return parseClass(context, FunctionNoRequirements, info);
2664 }
2665 #endif
2666 case OPENBRACE:
2667 if (strictMode())
2668 return parseStrictObjectLiteral(context);
2669 return parseObjectLiteral(context);
2670 case OPENBRACKET:
2671 return parseArrayLiteral(context);
2672 case OPENPAREN: {
2673 next();
2674 int oldNonLHSCount = m_nonLHSCount;
2675 TreeExpression result = parseExpression(context);
2676 m_nonLHSCount = oldNonLHSCount;
2677 handleProductionOrFail(CLOSEPAREN, ")", "end", "compound expression");
2678 return result;
2679 }
2680 case THISTOKEN: {
2681 JSTokenLocation location(tokenLocation());
2682 next();
2683 return context.thisExpr(location, m_thisTDZMode);
2684 }
2685 case IDENT: {
2686 JSTextPosition start = tokenStartPosition();
2687 const Identifier* ident = m_token.m_data.ident;
2688 JSTokenLocation location(tokenLocation());
2689 next();
2690 currentScope()->useVariable(ident, m_vm->propertyNames->eval == *ident);
2691 m_lastIdentifier = ident;
2692 return context.createResolve(location, ident, start);
2693 }
2694 case STRING: {
2695 const Identifier* ident = m_token.m_data.ident;
2696 JSTokenLocation location(tokenLocation());
2697 next();
2698 return context.createString(location, ident);
2699 }
2700 case DOUBLE: {
2701 double d = m_token.m_data.doubleValue;
2702 JSTokenLocation location(tokenLocation());
2703 next();
2704 return context.createDoubleExpr(location, d);
2705 }
2706 case INTEGER: {
2707 double d = m_token.m_data.doubleValue;
2708 JSTokenLocation location(tokenLocation());
2709 next();
2710 return context.createIntegerExpr(location, d);
2711 }
2712 case NULLTOKEN: {
2713 JSTokenLocation location(tokenLocation());
2714 next();
2715 return context.createNull(location);
2716 }
2717 case TRUETOKEN: {
2718 JSTokenLocation location(tokenLocation());
2719 next();
2720 return context.createBoolean(location, true);
2721 }
2722 case FALSETOKEN: {
2723 JSTokenLocation location(tokenLocation());
2724 next();
2725 return context.createBoolean(location, false);
2726 }
2727 case DIVEQUAL:
2728 case DIVIDE: {
2729 /* regexp */
2730 const Identifier* pattern;
2731 const Identifier* flags;
2732 if (match(DIVEQUAL))
2733 failIfFalse(m_lexer->scanRegExp(pattern, flags, '='), "Invalid regular expression");
2734 else
2735 failIfFalse(m_lexer->scanRegExp(pattern, flags), "Invalid regular expression");
2736
2737 JSTextPosition start = tokenStartPosition();
2738 JSTokenLocation location(tokenLocation());
2739 next();
2740 TreeExpression re = context.createRegExp(location, *pattern, *flags, start);
2741 if (!re) {
2742 const char* yarrErrorMsg = Yarr::checkSyntax(pattern->string());
2743 regexFail(yarrErrorMsg);
2744 }
2745 return re;
2746 }
2747 #if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
2748 case TEMPLATE:
2749 return parseTemplateLiteral(context, LexerType::RawStringsBuildMode::DontBuildRawStrings);
2750 #endif
2751 default:
2752 failDueToUnexpectedToken();
2753 }
2754 }
2755
2756 template <typename LexerType>
2757 template <class TreeBuilder> TreeArguments Parser<LexerType>::parseArguments(TreeBuilder& context, SpreadMode mode)
2758 {
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();
2764 }
2765 if (match(DOTDOTDOT) && mode == AllowSpread) {
2766 JSTokenLocation spreadLocation(tokenLocation());
2767 auto start = m_token.m_startPosition;
2768 auto divot = m_token.m_endPosition;
2769 next();
2770 auto spreadExpr = parseAssignmentExpression(context);
2771 auto end = m_lastTokenEndPosition;
2772 if (!spreadExpr)
2773 failWithMessage("Cannot parse spread expression");
2774 if (!consume(CLOSEPAREN)) {
2775 if (match(COMMA))
2776 semanticFail("Spread operator may only be applied to the last argument passed to a function");
2777 handleProductionOrFail(CLOSEPAREN, ")", "end", "argument list");
2778 }
2779 auto spread = context.createSpreadExpression(spreadLocation, spreadExpr, start, divot, end);
2780 TreeArgumentsList argList = context.createArgumentsList(location, spread);
2781 return context.createArguments(argList);
2782 }
2783 TreeExpression firstArg = parseAssignmentExpression(context);
2784 failIfFalse(firstArg, "Cannot parse function argument");
2785
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);
2794 }
2795 semanticFailIfTrue(match(DOTDOTDOT), "The '...' operator should come before the target expression");
2796 handleProductionOrFail(CLOSEPAREN, ")", "end", "argument list");
2797 return context.createArguments(argList);
2798 }
2799
2800 template <typename LexerType>
2801 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseMemberExpression(TreeBuilder& context)
2802 {
2803 TreeExpression base = 0;
2804 JSTextPosition expressionStart = tokenStartPosition();
2805 int newCount = 0;
2806 JSTokenLocation startLocation = tokenLocation();
2807 JSTokenLocation location;
2808 while (match(NEW)) {
2809 next();
2810 newCount++;
2811 }
2812
2813 #if ENABLE(ES6_CLASS_SYNTAX)
2814 bool baseIsSuper = match(SUPER);
2815 semanticFailIfTrue(baseIsSuper && newCount, "Cannot use new with super");
2816 #else
2817 bool baseIsSuper = false;
2818 #endif
2819
2820 if (baseIsSuper) {
2821 base = context.superExpr(location);
2822 next();
2823 currentScope()->setNeedsSuperBinding();
2824 } else
2825 base = parsePrimaryExpression(context);
2826
2827 failIfFalse(base, "Cannot parse base expression");
2828 while (true) {
2829 location = tokenLocation();
2830 switch (m_token.m_type) {
2831 case OPENBRACKET: {
2832 m_nonTrivialExpressionCount++;
2833 JSTextPosition expressionEnd = lastTokenEndPosition();
2834 next();
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;
2842 break;
2843 }
2844 case OPENPAREN: {
2845 m_nonTrivialExpressionCount++;
2846 int nonLHSCount = m_nonLHSCount;
2847 if (newCount) {
2848 newCount--;
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());
2853 } else {
2854 JSTextPosition expressionEnd = lastTokenEndPosition();
2855 TreeArguments arguments = parseArguments(context, AllowSpread);
2856 failIfFalse(arguments, "Cannot parse call arguments");
2857 if (baseIsSuper)
2858 currentScope()->setHasDirectSuper();
2859 base = context.makeFunctionCallNode(startLocation, base, arguments, expressionStart, expressionEnd, lastTokenEndPosition());
2860 }
2861 m_nonLHSCount = nonLHSCount;
2862 break;
2863 }
2864 case DOT: {
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());
2870 next();
2871 break;
2872 }
2873 #if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
2874 case TEMPLATE: {
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;
2882 break;
2883 }
2884 #endif
2885 default:
2886 goto endMemberExpression;
2887 }
2888 baseIsSuper = false;
2889 }
2890 endMemberExpression:
2891 semanticFailIfTrue(baseIsSuper, "Cannot reference super");
2892 while (newCount--)
2893 base = context.createNewExpr(location, base, expressionStart, lastTokenEndPosition());
2894 return base;
2895 }
2896
2897 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
2898 template <typename LexerType>
2899 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseArrowFunctionExpression(TreeBuilder& context)
2900 {
2901 JSTokenLocation location;
2902
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");
2908
2909 return context.createArrowFunctionExpr(location, info);
2910 }
2911 #endif
2912
2913 static const char* operatorString(bool prefix, unsigned tok)
2914 {
2915 switch (tok) {
2916 case MINUSMINUS:
2917 case AUTOMINUSMINUS:
2918 return prefix ? "prefix-decrement" : "decrement";
2919
2920 case PLUSPLUS:
2921 case AUTOPLUSPLUS:
2922 return prefix ? "prefix-increment" : "increment";
2923
2924 case EXCLAMATION:
2925 return "logical-not";
2926
2927 case TILDE:
2928 return "bitwise-not";
2929
2930 case TYPEOF:
2931 return "typeof";
2932
2933 case VOIDTOKEN:
2934 return "void";
2935
2936 case DELETETOKEN:
2937 return "delete";
2938 }
2939 RELEASE_ASSERT_NOT_REACHED();
2940 return "error";
2941 }
2942
2943 template <typename LexerType>
2944 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseUnaryExpression(TreeBuilder& context)
2945 {
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)) {
2953 if (strictMode()) {
2954 switch (m_token.m_type) {
2955 case PLUSPLUS:
2956 case MINUSMINUS:
2957 case AUTOPLUSPLUS:
2958 case AUTOMINUSMINUS:
2959 semanticFailIfTrue(requiresLExpr, "The ", operatorString(true, lastOperator), " operator requires a reference expression");
2960 modifiesExpr = true;
2961 requiresLExpr = true;
2962 break;
2963 case DELETETOKEN:
2964 semanticFailIfTrue(requiresLExpr, "The ", operatorString(true, lastOperator), " operator requires a reference expression");
2965 requiresLExpr = true;
2966 break;
2967 default:
2968 semanticFailIfTrue(requiresLExpr, "The ", operatorString(true, lastOperator), " operator requires a reference expression");
2969 break;
2970 }
2971 }
2972 lastOperator = m_token.m_type;
2973 m_nonLHSCount++;
2974 context.appendUnaryToken(tokenStackDepth, m_token.m_type, tokenStartPosition());
2975 next();
2976 m_nonTrivialExpressionCount++;
2977 }
2978 JSTextPosition subExprStart = tokenStartPosition();
2979 ASSERT(subExprStart.offset >= subExprStart.lineStartOffset);
2980 JSTokenLocation location(tokenLocation());
2981 TreeExpression expr = parseMemberExpression(context);
2982 if (!expr) {
2983 if (lastOperator)
2984 failWithMessage("Cannot parse subexpression of ", operatorString(true, lastOperator), "operator");
2985 failWithMessage("Cannot parse member expression");
2986 }
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;
2991 }
2992 failIfTrueIfStrict(isEvalOrArguments && modifiesExpr, "Cannot modify '", m_lastIdentifier->impl(), "' in strict mode");
2993 switch (m_token.m_type) {
2994 case PLUSPLUS:
2995 m_nonTrivialExpressionCount++;
2996 m_nonLHSCount++;
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;
3002 next();
3003 break;
3004 case MINUSMINUS:
3005 m_nonTrivialExpressionCount++;
3006 m_nonLHSCount++;
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;
3012 next();
3013 break;
3014 default:
3015 break;
3016 }
3017
3018 JSTextPosition end = lastTokenEndPosition();
3019
3020 if (!TreeBuilder::CreatesAST && (m_syntaxAlreadyValidated || !strictMode()))
3021 return expr;
3022
3023 location = tokenLocation();
3024 location.line = m_lexer->lastLineNumber();
3025 while (tokenStackDepth) {
3026 switch (context.unaryTokenStackLastType(tokenStackDepth)) {
3027 case EXCLAMATION:
3028 expr = context.createLogicalNot(location, expr);
3029 break;
3030 case TILDE:
3031 expr = context.makeBitwiseNotNode(location, expr);
3032 break;
3033 case MINUS:
3034 expr = context.makeNegateNode(location, expr);
3035 break;
3036 case PLUS:
3037 expr = context.createUnaryPlus(location, expr);
3038 break;
3039 case PLUSPLUS:
3040 case AUTOPLUSPLUS:
3041 expr = context.makePrefixNode(location, expr, OpPlusPlus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end);
3042 m_assignmentCount++;
3043 break;
3044 case MINUSMINUS:
3045 case AUTOMINUSMINUS:
3046 expr = context.makePrefixNode(location, expr, OpMinusMinus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end);
3047 m_assignmentCount++;
3048 break;
3049 case TYPEOF:
3050 expr = context.makeTypeOfNode(location, expr);
3051 break;
3052 case VOIDTOKEN:
3053 expr = context.createVoid(location, expr);
3054 break;
3055 case DELETETOKEN:
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);
3058 break;
3059 default:
3060 // If we get here something has gone horribly horribly wrong
3061 CRASH();
3062 }
3063 subExprStart = context.unaryTokenStackLastStart(tokenStackDepth);
3064 context.unaryTokenStackRemoveLast(tokenStackDepth);
3065 }
3066 return expr;
3067 }
3068
3069
3070 template <typename LexerType> void Parser<LexerType>::printUnexpectedTokenText(WTF::PrintStream& out)
3071 {
3072 switch (m_token.m_type) {
3073 case EOFTOK:
3074 out.print("Unexpected end of script");
3075 return;
3076 case UNTERMINATED_IDENTIFIER_ESCAPE_ERRORTOK:
3077 case UNTERMINATED_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK:
3078 out.print("Incomplete unicode escape in identifier: '", getToken(), "'");
3079 return;
3080 case UNTERMINATED_MULTILINE_COMMENT_ERRORTOK:
3081 out.print("Unterminated multiline comment");
3082 return;
3083 case UNTERMINATED_NUMERIC_LITERAL_ERRORTOK:
3084 out.print("Unterminated numeric literal '", getToken(), "'");
3085 return;
3086 case UNTERMINATED_STRING_LITERAL_ERRORTOK:
3087 out.print("Unterminated string literal '", getToken(), "'");
3088 return;
3089 case INVALID_IDENTIFIER_ESCAPE_ERRORTOK:
3090 out.print("Invalid escape in identifier: '", getToken(), "'");
3091 return;
3092 case INVALID_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK:
3093 out.print("Invalid unicode escape in identifier: '", getToken(), "'");
3094 return;
3095 case INVALID_NUMERIC_LITERAL_ERRORTOK:
3096 out.print("Invalid numeric literal: '", getToken(), "'");
3097 return;
3098 case INVALID_OCTAL_NUMBER_ERRORTOK:
3099 out.print("Invalid use of octal: '", getToken(), "'");
3100 return;
3101 case INVALID_STRING_LITERAL_ERRORTOK:
3102 out.print("Invalid string literal: '", getToken(), "'");
3103 return;
3104 case ERRORTOK:
3105 out.print("Unrecognized token '", getToken(), "'");
3106 return;
3107 case STRING:
3108 out.print("Unexpected string literal ", getToken());
3109 return;
3110 case INTEGER:
3111 case DOUBLE:
3112 out.print("Unexpected number '", getToken(), "'");
3113 return;
3114
3115 case RESERVED_IF_STRICT:
3116 out.print("Unexpected use of reserved word '", getToken(), "' in strict mode");
3117 return;
3118
3119 case RESERVED:
3120 out.print("Unexpected use of reserved word '", getToken(), "'");
3121 return;
3122
3123 case INVALID_PRIVATE_NAME_ERRORTOK:
3124 out.print("Invalid private name '", getToken(), "'");
3125 return;
3126
3127 case IDENT:
3128 out.print("Unexpected identifier '", getToken(), "'");
3129 return;
3130
3131 default:
3132 break;
3133 }
3134
3135 if (m_token.m_type & KeywordTokenFlag) {
3136 out.print("Unexpected keyword '", getToken(), "'");
3137 return;
3138 }
3139
3140 out.print("Unexpected token '", getToken(), "'");
3141 }
3142
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>>;
3146
3147 } // namespace JSC