]> git.saurik.com Git - apple/javascriptcore.git/blame - parser/Parser.cpp
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / parser / Parser.cpp
CommitLineData
9dae56ea
A
1/*
2 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
3 * Copyright (C) 2001 Peter Kelly (pmk@post.com)
93a37866 4 * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc. All rights reserved.
9dae56ea
A
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
6fe7ccc8
A
26#include "ASTBuilder.h"
27#include "CodeBlock.h"
9dae56ea 28#include "Debugger.h"
93a37866 29#include "JSCJSValueInlines.h"
9dae56ea 30#include "Lexer.h"
81345200 31#include "JSCInlines.h"
6fe7ccc8 32#include "SourceProvider.h"
93a37866 33#include "VM.h"
6fe7ccc8
A
34#include <utility>
35#include <wtf/HashFunctions.h>
81345200 36#include <wtf/StringPrintStream.h>
6fe7ccc8
A
37#include <wtf/WTFThreadData.h>
38
81345200
A
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)
93a37866 57#define failIfStackOverflow() do { if (!canRecurse()) failWithStackOverflow(); } while (0)
81345200
A
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)
93a37866 79
6fe7ccc8 80using namespace std;
9dae56ea
A
81
82namespace JSC {
83
81345200
A
84template <typename LexerType>
85void Parser<LexerType>::logError(bool)
86{
87 if (hasError())
88 return;
89 StringPrintStream stream;
90 printUnexpectedTokenText(stream);
91 setErrorMessage(stream.toString());
92}
93
94template <typename LexerType> template <typename A>
95void 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
108template <typename LexerType> template <typename A, typename B>
109void 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
122template <typename LexerType> template <typename A, typename B, typename C>
123void 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
136template <typename LexerType> template <typename A, typename B, typename C, typename D>
137void 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
150template <typename LexerType> template <typename A, typename B, typename C, typename D, typename E>
151void 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
164template <typename LexerType> template <typename A, typename B, typename C, typename D, typename E, typename F>
165void 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
178template <typename LexerType> template <typename A, typename B, typename C, typename D, typename E, typename F, typename G>
179void 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
6fe7ccc8 192template <typename LexerType>
ed1e77d3
A
193Parser<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)
93a37866 198 : m_vm(vm)
6fe7ccc8 199 , m_source(&source)
93a37866 200 , m_hasStackOverflow(false)
6fe7ccc8 201 , m_allowsIn(true)
6fe7ccc8
A
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)
81345200 208 , m_lastFunctionName(nullptr)
6fe7ccc8 209 , m_sourceElements(0)
ed1e77d3
A
210 , m_parsingBuiltin(builtinMode == JSParserBuiltinMode::Builtin)
211 , m_defaultConstructorKind(defaultConstructorKind)
212 , m_thisTDZMode(thisTDZMode)
9dae56ea 213{
ed1e77d3
A
214 m_lexer = std::make_unique<LexerType>(vm, builtinMode);
215 m_lexer->setCode(source, &m_parserArena);
81345200
A
216 m_token.m_location.line = source.firstLine();
217 m_token.m_location.startOffset = source.startOffset();
93a37866
A
218 m_token.m_location.endOffset = source.startOffset();
219 m_token.m_location.lineStartOffset = source.startOffset();
93a37866 220 m_functionCache = vm->addSourceProviderCache(source.provider());
6fe7ccc8 221 ScopeRef scope = pushScope();
ed1e77d3 222 if (codeType == JSParserCodeType::Function)
6fe7ccc8 223 scope->setIsFunction();
ed1e77d3 224 if (strictMode == JSParserStrictMode::Strict)
6fe7ccc8
A
225 scope->setStrictMode();
226 if (parameters) {
81345200
A
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 }
6fe7ccc8 247 }
93a37866
A
248 if (!name.isNull())
249 scope->declareCallee(&name);
6fe7ccc8 250 next();
6fe7ccc8 251}
9dae56ea 252
6fe7ccc8
A
253template <typename LexerType>
254Parser<LexerType>::~Parser()
255{
256}
9dae56ea 257
6fe7ccc8 258template <typename LexerType>
93a37866 259String Parser<LexerType>::parseInner()
6fe7ccc8 260{
93a37866 261 String parseError = String();
6fe7ccc8 262
ed1e77d3 263 ASTBuilder context(const_cast<VM*>(m_vm), m_parserArena, const_cast<SourceCode*>(m_source));
6fe7ccc8
A
264 if (m_lexer->isReparsing())
265 m_statementDepth--;
266 ScopeRef scope = currentScope();
ed1e77d3 267 SourceElements* sourceElements = parseSourceElements(context, CheckForStrictMode, StandardFunctionParseType);
93a37866
A
268 if (!sourceElements || !consume(EOFTOK)) {
269 if (hasError())
270 parseError = m_errorMessage;
271 else
272 parseError = ASCIILiteral("Parser error");
273 }
9dae56ea 274
6fe7ccc8 275 IdentifierSet capturedVariables;
81345200 276 bool modifiedParameter = false;
ed1e77d3
A
277 bool modifiedArguments = false;
278 scope->getCapturedVariables(capturedVariables, modifiedParameter, modifiedArguments);
81345200 279
6fe7ccc8
A
280 CodeFeatures features = context.features();
281 if (scope->strictMode())
282 features |= StrictModeFeature;
283 if (scope->shadowsArguments())
284 features |= ShadowsArgumentsFeature;
81345200
A
285 if (modifiedParameter)
286 features |= ModifiedParameterFeature;
ed1e77d3
A
287 if (modifiedArguments)
288 features |= ModifiedArgumentsFeature;
289 Vector<RefPtr<UniquedStringImpl>> closedVariables;
81345200 290 if (m_parsingBuiltin) {
81345200
A
291 IdentifierSet usedVariables;
292 scope->getUsedVariables(usedVariables);
293 for (const auto& variable : usedVariables) {
ed1e77d3
A
294 Identifier identifier = Identifier::fromUid(m_vm, variable.get());
295 if (scope->hasDeclaredVariable(identifier))
81345200
A
296 continue;
297
ed1e77d3
A
298 if (scope->hasDeclaredParameter(identifier))
299 continue;
300
301 if (variable == m_vm->propertyNames->arguments.impl())
81345200 302 continue;
ed1e77d3 303
81345200
A
304 closedVariables.append(variable);
305 }
ed1e77d3
A
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 }
81345200 319 }
6fe7ccc8 320 didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), features,
81345200 321 context.numConstants(), capturedVariables, WTF::move(closedVariables));
9dae56ea 322
6fe7ccc8 323 return parseError;
9dae56ea
A
324}
325
6fe7ccc8 326template <typename LexerType>
ed1e77d3
A
327void Parser<LexerType>::didFinishParsing(SourceElements* sourceElements, DeclarationStacks::VarStack& varStack,
328 DeclarationStacks::FunctionStack& funcStack, CodeFeatures features, int numConstants, IdentifierSet& capturedVars, const Vector<RefPtr<UniquedStringImpl>>&& closedVariables)
9dae56ea
A
329{
330 m_sourceElements = sourceElements;
ed1e77d3
A
331 m_varDeclarations.swap(varStack);
332 m_funcDeclarations.swap(funcStack);
14957cd0 333 m_capturedVariables.swap(capturedVars);
81345200 334 m_closedVariables = closedVariables;
9dae56ea 335 m_features = features;
9dae56ea
A
336 m_numConstants = numConstants;
337}
338
6fe7ccc8
A
339template <typename LexerType>
340bool Parser<LexerType>::allowAutomaticSemicolon()
341{
342 return match(CLOSEBRACE) || match(EOFTOK) || m_lexer->prevTerminator();
343}
344
345template <typename LexerType>
ed1e77d3 346template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseSourceElements(TreeBuilder& context, SourceElementsMode mode, FunctionParseType functionParseType)
6fe7ccc8
A
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;
81345200 353 auto savePoint = createSavePoint();
6fe7ccc8 354 bool hasSetStrict = false;
ed1e77d3
A
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)) {
6fe7ccc8
A
373 if (mode == CheckForStrictMode && !seenNonDirective) {
374 if (directive) {
375 // "use strict" must be the exact literal without escape sequences or line continuation.
93a37866 376 if (!hasSetStrict && directiveLiteralLength == lengthOfUseStrictLiteral && m_vm->propertyNames->useStrictIdentifier == *directive) {
6fe7ccc8
A
377 setStrictMode();
378 hasSetStrict = true;
81345200
A
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();
6fe7ccc8
A
394 continue;
395 }
396 } else
397 seenNonDirective = true;
398 }
399 context.appendStatement(sourceElements, statement);
400 }
93a37866 401
81345200 402 propagateError();
6fe7ccc8
A
403 return sourceElements;
404}
ed1e77d3
A
405template <typename LexerType>
406template <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}
6fe7ccc8
A
429
430template <typename LexerType>
431template <class TreeBuilder> TreeStatement Parser<LexerType>::parseVarDeclaration(TreeBuilder& context)
432{
433 ASSERT(match(VAR));
93a37866 434 JSTokenLocation location(tokenLocation());
6fe7ccc8
A
435 int start = tokenLine();
436 int end = 0;
437 int scratch;
ed1e77d3 438 TreeDestructuringPattern scratch1 = 0;
6fe7ccc8 439 TreeExpression scratch2 = 0;
81345200 440 JSTextPosition scratch3;
ed1e77d3 441 TreeExpression varDecls = parseVarDeclarationList(context, scratch, scratch1, scratch2, scratch3, scratch3, scratch3, VarDeclarationContext);
81345200
A
442 propagateError();
443 failIfFalse(autoSemiColon(), "Expected ';' after var declaration");
6fe7ccc8 444
93a37866 445 return context.createVarStatement(location, varDecls, start, end);
6fe7ccc8
A
446}
447
448template <typename LexerType>
449template <class TreeBuilder> TreeStatement Parser<LexerType>::parseConstDeclaration(TreeBuilder& context)
450{
451 ASSERT(match(CONSTTOKEN));
93a37866 452 JSTokenLocation location(tokenLocation());
6fe7ccc8
A
453 int start = tokenLine();
454 int end = 0;
455 TreeConstDeclList constDecls = parseConstDeclarationList(context);
81345200
A
456 propagateError();
457 failIfFalse(autoSemiColon(), "Expected ';' after const declaration");
6fe7ccc8 458
93a37866 459 return context.createConstStatement(location, constDecls, start, end);
6fe7ccc8
A
460}
461
462template <typename LexerType>
463template <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();
81345200 472 failIfFalse(statement, "Expected a statement following 'do'");
6fe7ccc8 473 int endLine = tokenLine();
93a37866 474 JSTokenLocation location(tokenLocation());
81345200
A
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");
6fe7ccc8 478 TreeExpression expr = parseExpression(context);
81345200
A
479 failIfFalse(expr, "Unable to parse do-while loop condition");
480 handleProductionOrFail(CLOSEPAREN, ")", "end", "do-while loop condition");
6fe7ccc8
A
481 if (match(SEMICOLON))
482 next(); // Always performs automatic semicolon insertion.
93a37866 483 return context.createDoWhileStatement(location, statement, expr, startLine, endLine);
6fe7ccc8
A
484}
485
486template <typename LexerType>
487template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWhileStatement(TreeBuilder& context)
488{
489 ASSERT(match(WHILE));
93a37866 490 JSTokenLocation location(tokenLocation());
6fe7ccc8
A
491 int startLine = tokenLine();
492 next();
81345200
A
493
494 handleProductionOrFail(OPENPAREN, "(", "start", "while loop condition");
495 semanticFailIfTrue(match(CLOSEPAREN), "Must provide an expression as a while loop condition");
6fe7ccc8 496 TreeExpression expr = parseExpression(context);
81345200 497 failIfFalse(expr, "Unable to parse while loop condition");
6fe7ccc8 498 int endLine = tokenLine();
81345200
A
499 handleProductionOrFail(CLOSEPAREN, ")", "end", "while loop condition");
500
6fe7ccc8
A
501 const Identifier* unused = 0;
502 startLoop();
503 TreeStatement statement = parseStatement(context, unused);
504 endLoop();
81345200 505 failIfFalse(statement, "Expected a statement as the body of a while loop");
93a37866 506 return context.createWhileStatement(location, expr, statement, startLine, endLine);
6fe7ccc8
A
507}
508
509template <typename LexerType>
ed1e77d3 510template <class TreeBuilder> TreeExpression Parser<LexerType>::parseVarDeclarationList(TreeBuilder& context, int& declarations, TreeDestructuringPattern& lastPattern, TreeExpression& lastInitializer, JSTextPosition& identStart, JSTextPosition& initStart, JSTextPosition& initEnd, VarDeclarationListContext declarationListContext)
6fe7ccc8 511{
ed1e77d3
A
512 TreeExpression head = 0;
513 TreeExpression tail = 0;
81345200 514 const Identifier* lastIdent;
ed1e77d3 515 JSToken lastIdentToken;
6fe7ccc8 516 do {
81345200 517 lastIdent = 0;
ed1e77d3 518 lastPattern = TreeDestructuringPattern(0);
93a37866 519 JSTokenLocation location(tokenLocation());
6fe7ccc8 520 next();
81345200
A
521 TreeExpression node = 0;
522 declarations++;
523 bool hasInitializer = false;
524 if (match(IDENT)) {
525 JSTextPosition varStart = tokenStartPosition();
ed1e77d3 526 JSTokenLocation varStartLocation(tokenLocation());
81345200
A
527 identStart = varStart;
528 const Identifier* name = m_token.m_data.ident;
529 lastIdent = name;
ed1e77d3 530 lastIdentToken = m_token;
81345200
A
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());
ed1e77d3
A
545 } else
546 node = context.createEmptyVarExpression(varStartLocation, *name);
81345200
A
547 } else {
548 lastIdent = 0;
ed1e77d3
A
549 auto pattern = parseDestructuringPattern(context, DestructureToVariables);
550 failIfFalse(pattern, "Cannot parse this destructuring pattern");
81345200 551 hasInitializer = match(EQUAL);
ed1e77d3 552 failIfTrue(declarationListContext == VarDeclarationContext && !hasInitializer, "Expected an initializer in destructuring variable declaration");
81345200
A
553 lastPattern = pattern;
554 if (hasInitializer) {
555 next(TreeBuilder::DontBuildStrings); // consume '='
ed1e77d3
A
556 TreeExpression rhs = parseAssignmentExpression(context);
557 node = context.createDestructuringAssignment(location, pattern, rhs);
81345200
A
558 lastInitializer = rhs;
559 }
560 }
6fe7ccc8 561
ed1e77d3
A
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);
6fe7ccc8 569 } while (match(COMMA));
81345200 570 if (lastIdent)
ed1e77d3
A
571 lastPattern = createBindingPattern(context, DestructureToVariables, *lastIdent, 0, lastIdentToken);
572 return head;
6fe7ccc8
A
573}
574
81345200 575template <typename LexerType>
ed1e77d3 576template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::createBindingPattern(TreeBuilder& context, DestructuringKind kind, const Identifier& name, int depth, JSToken token)
81345200 577{
81345200
A
578 ASSERT(!name.isNull());
579
ed1e77d3 580 ASSERT(name.impl()->isAtomic() || name.impl()->isSymbol());
81345200 581 if (depth) {
ed1e77d3
A
582 if (kind == DestructureToVariables)
583 failIfFalseIfStrict(declareVariable(&name), "Cannot destructure to a variable named '", name.impl(), "' in strict mode");
584 if (kind == DestructureToParameters) {
81345200
A
585 auto bindingResult = declareBoundParameter(&name);
586 if (bindingResult == Scope::StrictBindingFailed && strictMode()) {
ed1e77d3 587 semanticFailIfTrue(m_vm->propertyNames->arguments == name || m_vm->propertyNames->eval == name, "Cannot destructure to a parameter name '", name.impl(), "' in strict mode");
81345200 588 if (m_lastFunctionName && name == *m_lastFunctionName)
ed1e77d3 589 semanticFail("Cannot destructure to '", name.impl(), "' as it shadows the name of a strict mode function");
81345200
A
590 semanticFailureDueToKeyword("bound parameter name");
591 if (hasDeclaredParameter(name))
ed1e77d3 592 semanticFail("Cannot destructure to '", name.impl(), "' as it has already been declared");
81345200
A
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))
ed1e77d3
A
598 semanticFail("Cannot destructure to '", name.impl(), "' as it has already been declared");
599 semanticFail("Cannot destructure to a parameter named '", name.impl(), "'");
81345200
A
600 }
601 }
ed1e77d3 602 if (kind != DestructureToExpressions)
81345200
A
603 context.addVar(&name, DeclarationStacks::HasInitializer);
604
605 } else {
ed1e77d3 606 if (kind == DestructureToVariables) {
81345200
A
607 failIfFalseIfStrict(declareVariable(&name), "Cannot declare a variable named '", name.impl(), "' in strict mode");
608 context.addVar(&name, DeclarationStacks::HasInitializer);
609 }
610
ed1e77d3 611 if (kind == DestructureToParameters) {
81345200
A
612 bool declarationResult = declareParameter(&name);
613 if (!declarationResult && strictMode()) {
ed1e77d3 614 semanticFailIfTrue(m_vm->propertyNames->arguments == name || m_vm->propertyNames->eval == name, "Cannot destructure to a parameter name '", name.impl(), "' in strict mode");
81345200
A
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 }
ed1e77d3 624 return context.createBindingLocation(token.m_location, name, token.m_startPosition, token.m_endPosition);
81345200
A
625}
626
ed1e77d3 627#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
81345200 628template <typename LexerType>
ed1e77d3 629template <class TreeBuilder> TreeStatement Parser<LexerType>::parseArrowFunctionSingleExpressionBody(TreeBuilder& context, FunctionParseType parseType)
81345200 630{
ed1e77d3
A
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
663template <typename LexerType>
664template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::tryParseDestructuringPatternExpression(TreeBuilder& context)
665{
666 return parseDestructuringPattern(context, DestructureToExpressions);
81345200
A
667}
668
669template <typename LexerType>
ed1e77d3 670template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseDestructuringPattern(TreeBuilder& context, DestructuringKind kind, int depth)
81345200
A
671{
672 failIfStackOverflow();
673 int nonLHSCount = m_nonLHSCount;
ed1e77d3 674 TreeDestructuringPattern pattern;
81345200
A
675 switch (m_token.m_type) {
676 case OPENBRACKET: {
ed1e77d3 677 JSTextPosition divotStart = tokenStartPosition();
81345200
A
678 auto arrayPattern = context.createArrayPattern(m_token.m_location);
679 next();
ed1e77d3
A
680
681 bool restElementWasFound = false;
682
81345200
A
683 do {
684 while (match(COMMA)) {
685 context.appendArrayPatternSkipEntry(arrayPattern, m_token.m_location);
686 next();
687 }
688 propagateError();
ed1e77d3
A
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
81345200 708 JSTokenLocation location = m_token.m_location;
ed1e77d3
A
709 auto innerPattern = parseDestructuringPattern(context, kind, depth + 1);
710 if (kind == DestructureToExpressions && !innerPattern)
81345200 711 return 0;
ed1e77d3
A
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);
81345200 716 } while (consume(COMMA));
81345200 717
ed1e77d3
A
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());
81345200
A
722 pattern = arrayPattern;
723 break;
724 }
725 case OPENBRACE: {
ed1e77d3 726 auto objectPattern = context.createObjectPattern(m_token.m_location);
81345200 727 next();
81345200 728
81345200 729 do {
ed1e77d3
A
730 bool wasString = false;
731
732 if (match(CLOSEBRACE))
733 break;
734
81345200 735 Identifier propertyName;
ed1e77d3 736 TreeDestructuringPattern innerPattern = 0;
81345200
A
737 JSTokenLocation location = m_token.m_location;
738 if (match(IDENT)) {
739 propertyName = *m_token.m_data.ident;
ed1e77d3 740 JSToken identifierToken = m_token;
81345200
A
741 next();
742 if (consume(COLON))
ed1e77d3 743 innerPattern = parseDestructuringPattern(context, kind, depth + 1);
81345200 744 else
ed1e77d3 745 innerPattern = createBindingPattern(context, kind, propertyName, depth, identifierToken);
81345200
A
746 } else {
747 JSTokenType tokenType = m_token.m_type;
748 switch (m_token.m_type) {
ed1e77d3
A
749 case DOUBLE:
750 case INTEGER:
81345200
A
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)) {
ed1e77d3 759 if (kind == DestructureToExpressions)
81345200
A
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)) {
ed1e77d3 768 if (kind == DestructureToExpressions)
81345200 769 return 0;
ed1e77d3
A
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(), "'");
81345200 773
ed1e77d3 774 failWithMessage("Expected a ':' prior to a named destructuring property");
81345200 775 }
ed1e77d3 776 innerPattern = parseDestructuringPattern(context, kind, depth + 1);
81345200 777 }
ed1e77d3 778 if (kind == DestructureToExpressions && !innerPattern)
81345200 779 return 0;
ed1e77d3
A
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);
81345200 784 } while (consume(COMMA));
ed1e77d3
A
785
786 if (kind == DestructureToExpressions && !match(CLOSEBRACE))
81345200 787 return 0;
ed1e77d3 788 consumeOrFail(CLOSEBRACE, "Expected either a closing '}' or an ',' after a property destructuring pattern");
81345200
A
789 pattern = objectPattern;
790 break;
791 }
792
793 default: {
794 if (!match(IDENT)) {
ed1e77d3 795 if (kind == DestructureToExpressions)
81345200
A
796 return 0;
797 semanticFailureDueToKeyword("variable name");
798 failWithMessage("Expected a parameter pattern or a ')' in parameter list");
799 }
ed1e77d3 800 pattern = createBindingPattern(context, kind, *m_token.m_data.ident, depth, m_token);
81345200
A
801 next();
802 break;
803 }
804 }
805 m_nonLHSCount = nonLHSCount;
806 return pattern;
807}
808
ed1e77d3
A
809template <typename LexerType>
810template <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
6fe7ccc8
A
819template <typename LexerType>
820template <class TreeBuilder> TreeConstDeclList Parser<LexerType>::parseConstDeclarationList(TreeBuilder& context)
821{
81345200 822 failIfTrue(strictMode(), "Const declarations are not supported in strict mode");
6fe7ccc8
A
823 TreeConstDeclList constDecls = 0;
824 TreeConstDeclList tail = 0;
825 do {
93a37866 826 JSTokenLocation location(tokenLocation());
6fe7ccc8 827 next();
81345200 828 matchOrFail(IDENT, "Expected an identifier name in const declaration");
6fe7ccc8
A
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));
93a37866 834
6fe7ccc8
A
835 TreeExpression initializer = 0;
836 if (hasInitializer) {
837 next(TreeBuilder::DontBuildStrings); // consume '='
838 initializer = parseAssignmentExpression(context);
81345200 839 failIfFalse(!!initializer, "Unable to parse initializer");
6fe7ccc8 840 }
93a37866 841 tail = context.appendConstDecl(location, tail, name, initializer);
6fe7ccc8
A
842 if (!constDecls)
843 constDecls = tail;
844 } while (match(COMMA));
845 return constDecls;
846}
847
848template <typename LexerType>
849template <class TreeBuilder> TreeStatement Parser<LexerType>::parseForStatement(TreeBuilder& context)
850{
851 ASSERT(match(FOR));
93a37866 852 JSTokenLocation location(tokenLocation());
6fe7ccc8
A
853 int startLine = tokenLine();
854 next();
81345200 855 handleProductionOrFail(OPENPAREN, "(", "start", "for-loop header");
6fe7ccc8
A
856 int nonLHSCount = m_nonLHSCount;
857 int declarations = 0;
81345200
A
858 JSTextPosition declsStart;
859 JSTextPosition declsEnd;
6fe7ccc8 860 TreeExpression decls = 0;
ed1e77d3 861 TreeDestructuringPattern pattern = 0;
6fe7ccc8
A
862 if (match(VAR)) {
863 /*
864 for (var IDENT in expression) statement
6fe7ccc8
A
865 for (var varDeclarationList; expressionOpt; expressionOpt)
866 */
ed1e77d3 867 TreeDestructuringPattern forInTarget = 0;
6fe7ccc8
A
868 TreeExpression forInInitializer = 0;
869 m_allowsIn = false;
81345200
A
870 JSTextPosition initStart;
871 JSTextPosition initEnd;
ed1e77d3 872 decls = parseVarDeclarationList(context, declarations, forInTarget, forInInitializer, declsStart, initStart, initEnd, ForLoopContext);
6fe7ccc8 873 m_allowsIn = true;
81345200 874 propagateError();
93a37866 875
6fe7ccc8
A
876 // Remainder of a standard for loop is handled identically
877 if (match(SEMICOLON))
878 goto standardForLoop;
879
81345200
A
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
6fe7ccc8 886 // Handle for-in with var declaration
81345200
A
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 }
6fe7ccc8 895 TreeExpression expr = parseExpression(context);
81345200
A
896 failIfFalse(expr, "Expected expression to enumerate");
897 JSTextPosition exprEnd = lastTokenEndPosition();
6fe7ccc8
A
898
899 int endLine = tokenLine();
81345200
A
900
901 handleProductionOrFail(CLOSEPAREN, ")", "end", (isOfEnumeration ? "for-of header" : "for-in header"));
6fe7ccc8
A
902
903 const Identifier* unused = 0;
904 startLoop();
905 TreeStatement statement = parseStatement(context, unused);
906 endLoop();
81345200
A
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);
6fe7ccc8
A
911 }
912
913 if (!match(SEMICOLON)) {
81345200
A
914 if (match(OPENBRACE) || match(OPENBRACKET)) {
915 SavePoint savePoint = createSavePoint();
916 declsStart = tokenStartPosition();
ed1e77d3 917 pattern = tryParseDestructuringPatternExpression(context);
81345200
A
918 declsEnd = lastTokenEndPosition();
919 if (pattern && (match(INTOKEN) || (match(IDENT) && *m_token.m_data.ident == m_vm->propertyNames->of)))
920 goto enumerationLoop;
ed1e77d3 921 pattern = TreeDestructuringPattern(0);
81345200
A
922 restoreSavePoint(savePoint);
923 }
6fe7ccc8 924 m_allowsIn = false;
81345200 925 declsStart = tokenStartPosition();
6fe7ccc8 926 decls = parseExpression(context);
81345200 927 declsEnd = lastTokenEndPosition();
6fe7ccc8 928 m_allowsIn = true;
81345200 929 failIfFalse(decls, "Cannot parse for loop declarations");
6fe7ccc8
A
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);
81345200 940 failIfFalse(condition, "Cannot parse for loop condition expression");
6fe7ccc8 941 }
81345200 942 consumeOrFail(SEMICOLON, "Expected a ';' after the for loop condition expression");
6fe7ccc8
A
943
944 TreeExpression increment = 0;
945 if (!match(CLOSEPAREN)) {
946 increment = parseExpression(context);
81345200 947 failIfFalse(increment, "Cannot parse for loop iteration expression");
6fe7ccc8
A
948 }
949 int endLine = tokenLine();
81345200 950 handleProductionOrFail(CLOSEPAREN, ")", "end", "for-loop header");
6fe7ccc8
A
951 const Identifier* unused = 0;
952 startLoop();
953 TreeStatement statement = parseStatement(context, unused);
954 endLoop();
81345200 955 failIfFalse(statement, "Expected a statement as the body of a for loop");
93a37866 956 return context.createForLoop(location, decls, condition, increment, statement, startLine, endLine);
6fe7ccc8
A
957 }
958
959 // For-in loop
81345200
A
960enumerationLoop:
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 }
6fe7ccc8 968 TreeExpression expr = parseExpression(context);
81345200
A
969 failIfFalse(expr, "Cannot parse subject for-", isOfEnumeration ? "of" : "in", " statement");
970 JSTextPosition exprEnd = lastTokenEndPosition();
6fe7ccc8 971 int endLine = tokenLine();
81345200
A
972
973 handleProductionOrFail(CLOSEPAREN, ")", "end", (isOfEnumeration ? "for-of header" : "for-in header"));
6fe7ccc8
A
974 const Identifier* unused = 0;
975 startLoop();
976 TreeStatement statement = parseStatement(context, unused);
977 endLoop();
81345200
A
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);
6fe7ccc8
A
988}
989
990template <typename LexerType>
991template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBreakStatement(TreeBuilder& context)
992{
993 ASSERT(match(BREAK));
93a37866 994 JSTokenLocation location(tokenLocation());
81345200
A
995 JSTextPosition start = tokenStartPosition();
996 JSTextPosition end = tokenEndPosition();
6fe7ccc8
A
997 next();
998
999 if (autoSemiColon()) {
81345200 1000 semanticFailIfFalse(breakIsValid(), "'break' is only valid inside a switch or loop statement");
ed1e77d3 1001 return context.createBreakStatement(location, &m_vm->propertyNames->nullIdentifier, start, end);
6fe7ccc8 1002 }
81345200 1003 matchOrFail(IDENT, "Expected an identifier as the target for a break statement");
6fe7ccc8 1004 const Identifier* ident = m_token.m_data.ident;
81345200
A
1005 semanticFailIfFalse(getLabel(ident), "Cannot use the undeclared label '", ident->impl(), "'");
1006 end = tokenEndPosition();
6fe7ccc8 1007 next();
81345200
A
1008 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted break statement");
1009 return context.createBreakStatement(location, ident, start, end);
6fe7ccc8
A
1010}
1011
1012template <typename LexerType>
1013template <class TreeBuilder> TreeStatement Parser<LexerType>::parseContinueStatement(TreeBuilder& context)
1014{
1015 ASSERT(match(CONTINUE));
93a37866 1016 JSTokenLocation location(tokenLocation());
81345200
A
1017 JSTextPosition start = tokenStartPosition();
1018 JSTextPosition end = tokenEndPosition();
6fe7ccc8
A
1019 next();
1020
1021 if (autoSemiColon()) {
81345200 1022 semanticFailIfFalse(continueIsValid(), "'continue' is only valid inside a loop statement");
ed1e77d3 1023 return context.createContinueStatement(location, &m_vm->propertyNames->nullIdentifier, start, end);
6fe7ccc8 1024 }
81345200 1025 matchOrFail(IDENT, "Expected an identifier as the target for a continue statement");
6fe7ccc8
A
1026 const Identifier* ident = m_token.m_data.ident;
1027 ScopeLabelInfo* label = getLabel(ident);
81345200 1028 semanticFailIfFalse(label, "Cannot use the undeclared label '", ident->impl(), "'");
ed1e77d3 1029 semanticFailIfFalse(label->isLoop, "Cannot continue to the label '", ident->impl(), "' as it is not targeting a loop");
81345200 1030 end = tokenEndPosition();
6fe7ccc8 1031 next();
81345200
A
1032 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted continue statement");
1033 return context.createContinueStatement(location, ident, start, end);
6fe7ccc8
A
1034}
1035
1036template <typename LexerType>
1037template <class TreeBuilder> TreeStatement Parser<LexerType>::parseReturnStatement(TreeBuilder& context)
1038{
1039 ASSERT(match(RETURN));
93a37866 1040 JSTokenLocation location(tokenLocation());
81345200
A
1041 semanticFailIfFalse(currentScope()->isFunction(), "Return statements are only valid inside functions");
1042 JSTextPosition start = tokenStartPosition();
1043 JSTextPosition end = tokenEndPosition();
6fe7ccc8 1044 next();
81345200 1045 // We do the auto semicolon check before attempting to parse expression
6fe7ccc8
A
1046 // as we need to ensure the a line break after the return correctly terminates
1047 // the statement
1048 if (match(SEMICOLON))
81345200
A
1049 end = tokenEndPosition();
1050
6fe7ccc8 1051 if (autoSemiColon())
81345200 1052 return context.createReturnStatement(location, 0, start, end);
6fe7ccc8 1053 TreeExpression expr = parseExpression(context);
81345200
A
1054 failIfFalse(expr, "Cannot parse the return expression");
1055 end = lastTokenEndPosition();
6fe7ccc8 1056 if (match(SEMICOLON))
81345200
A
1057 end = tokenEndPosition();
1058 if (!autoSemiColon())
1059 failWithMessage("Expected a ';' following a return statement");
1060 return context.createReturnStatement(location, expr, start, end);
6fe7ccc8
A
1061}
1062
1063template <typename LexerType>
1064template <class TreeBuilder> TreeStatement Parser<LexerType>::parseThrowStatement(TreeBuilder& context)
1065{
1066 ASSERT(match(THROW));
93a37866 1067 JSTokenLocation location(tokenLocation());
81345200 1068 JSTextPosition start = tokenStartPosition();
6fe7ccc8 1069 next();
81345200
A
1070 failIfTrue(match(SEMICOLON), "Expected expression after 'throw'");
1071 semanticFailIfTrue(autoSemiColon(), "Cannot have a newline after 'throw'");
6fe7ccc8
A
1072
1073 TreeExpression expr = parseExpression(context);
81345200
A
1074 failIfFalse(expr, "Cannot parse expression for throw statement");
1075 JSTextPosition end = lastTokenEndPosition();
1076 failIfFalse(autoSemiColon(), "Expected a ';' after a throw statement");
6fe7ccc8 1077
81345200 1078 return context.createThrowStatement(location, expr, start, end);
6fe7ccc8
A
1079}
1080
1081template <typename LexerType>
1082template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWithStatement(TreeBuilder& context)
1083{
1084 ASSERT(match(WITH));
93a37866 1085 JSTokenLocation location(tokenLocation());
81345200 1086 semanticFailIfTrue(strictMode(), "'with' statements are not valid in strict mode");
6fe7ccc8
A
1087 currentScope()->setNeedsFullActivation();
1088 int startLine = tokenLine();
1089 next();
81345200
A
1090
1091 handleProductionOrFail(OPENPAREN, "(", "start", "subject of a 'with' statement");
6fe7ccc8
A
1092 int start = tokenStart();
1093 TreeExpression expr = parseExpression(context);
81345200
A
1094 failIfFalse(expr, "Cannot parse 'with' subject expression");
1095 JSTextPosition end = lastTokenEndPosition();
6fe7ccc8 1096 int endLine = tokenLine();
81345200 1097 handleProductionOrFail(CLOSEPAREN, ")", "start", "subject of a 'with' statement");
6fe7ccc8
A
1098 const Identifier* unused = 0;
1099 TreeStatement statement = parseStatement(context, unused);
81345200 1100 failIfFalse(statement, "A 'with' statement must have a body");
6fe7ccc8 1101
81345200 1102 return context.createWithStatement(location, expr, statement, start, end, startLine, endLine);
6fe7ccc8
A
1103}
1104
1105template <typename LexerType>
1106template <class TreeBuilder> TreeStatement Parser<LexerType>::parseSwitchStatement(TreeBuilder& context)
1107{
1108 ASSERT(match(SWITCH));
93a37866 1109 JSTokenLocation location(tokenLocation());
6fe7ccc8
A
1110 int startLine = tokenLine();
1111 next();
81345200 1112 handleProductionOrFail(OPENPAREN, "(", "start", "subject of a 'switch'");
6fe7ccc8 1113 TreeExpression expr = parseExpression(context);
81345200 1114 failIfFalse(expr, "Cannot parse switch subject expression");
6fe7ccc8 1115 int endLine = tokenLine();
81345200
A
1116
1117 handleProductionOrFail(CLOSEPAREN, ")", "end", "subject of a 'switch'");
1118 handleProductionOrFail(OPENBRACE, "{", "start", "body of a 'switch'");
6fe7ccc8
A
1119 startSwitch();
1120 TreeClauseList firstClauses = parseSwitchClauses(context);
81345200 1121 propagateError();
6fe7ccc8
A
1122
1123 TreeClause defaultClause = parseSwitchDefaultClause(context);
81345200 1124 propagateError();
6fe7ccc8
A
1125
1126 TreeClauseList secondClauses = parseSwitchClauses(context);
81345200 1127 propagateError();
6fe7ccc8 1128 endSwitch();
81345200 1129 handleProductionOrFail(CLOSEBRACE, "}", "end", "body of a 'switch'");
6fe7ccc8 1130
93a37866 1131 return context.createSwitchStatement(location, expr, firstClauses, defaultClause, secondClauses, startLine, endLine);
6fe7ccc8
A
1132
1133}
1134
1135template <typename LexerType>
1136template <class TreeBuilder> TreeClauseList Parser<LexerType>::parseSwitchClauses(TreeBuilder& context)
1137{
1138 if (!match(CASE))
1139 return 0;
ed1e77d3 1140 unsigned startOffset = tokenStart();
6fe7ccc8
A
1141 next();
1142 TreeExpression condition = parseExpression(context);
81345200
A
1143 failIfFalse(condition, "Cannot parse switch clause");
1144 consumeOrFail(COLON, "Expected a ':' after switch clause expression");
ed1e77d3 1145 TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode, StandardFunctionParseType);
81345200 1146 failIfFalse(statements, "Cannot parse the body of a switch clause");
6fe7ccc8 1147 TreeClause clause = context.createClause(condition, statements);
ed1e77d3 1148 context.setStartOffset(clause, startOffset);
6fe7ccc8
A
1149 TreeClauseList clauseList = context.createClauseList(clause);
1150 TreeClauseList tail = clauseList;
1151
1152 while (match(CASE)) {
ed1e77d3 1153 startOffset = tokenStart();
6fe7ccc8
A
1154 next();
1155 TreeExpression condition = parseExpression(context);
81345200
A
1156 failIfFalse(condition, "Cannot parse switch case expression");
1157 consumeOrFail(COLON, "Expected a ':' after switch clause expression");
ed1e77d3 1158 TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode, StandardFunctionParseType);
81345200 1159 failIfFalse(statements, "Cannot parse the body of a switch clause");
6fe7ccc8 1160 clause = context.createClause(condition, statements);
ed1e77d3 1161 context.setStartOffset(clause, startOffset);
6fe7ccc8
A
1162 tail = context.createClauseList(tail, clause);
1163 }
1164 return clauseList;
1165}
1166
1167template <typename LexerType>
1168template <class TreeBuilder> TreeClause Parser<LexerType>::parseSwitchDefaultClause(TreeBuilder& context)
1169{
1170 if (!match(DEFAULT))
1171 return 0;
ed1e77d3 1172 unsigned startOffset = tokenStart();
6fe7ccc8 1173 next();
81345200 1174 consumeOrFail(COLON, "Expected a ':' after switch default clause");
ed1e77d3 1175 TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode, StandardFunctionParseType);
81345200 1176 failIfFalse(statements, "Cannot parse the body of a switch default clause");
ed1e77d3
A
1177 TreeClause result = context.createClause(0, statements);
1178 context.setStartOffset(result, startOffset);
1179 return result;
6fe7ccc8
A
1180}
1181
1182template <typename LexerType>
1183template <class TreeBuilder> TreeStatement Parser<LexerType>::parseTryStatement(TreeBuilder& context)
1184{
1185 ASSERT(match(TRY));
93a37866 1186 JSTokenLocation location(tokenLocation());
6fe7ccc8 1187 TreeStatement tryBlock = 0;
93a37866 1188 const Identifier* ident = &m_vm->propertyNames->nullIdentifier;
6fe7ccc8
A
1189 TreeStatement catchBlock = 0;
1190 TreeStatement finallyBlock = 0;
1191 int firstLine = tokenLine();
1192 next();
81345200 1193 matchOrFail(OPENBRACE, "Expected a block statement as body of a try statement");
6fe7ccc8
A
1194
1195 tryBlock = parseBlockStatement(context);
81345200
A
1196 failIfFalse(tryBlock, "Cannot parse the body of try block");
1197 int lastLine = m_lastTokenEndPosition.line;
6fe7ccc8
A
1198
1199 if (match(CATCH)) {
1200 currentScope()->setNeedsFullActivation();
1201 next();
81345200
A
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 }
6fe7ccc8
A
1208 ident = m_token.m_data.ident;
1209 next();
1210 AutoPopScopeRef catchScope(this, pushScope());
81345200 1211 failIfFalseIfStrict(declareVariable(ident), "Cannot declare a catch variable named '", ident->impl(), "' in strict mode");
6fe7ccc8 1212 catchScope->preventNewDecls();
81345200
A
1213 handleProductionOrFail(CLOSEPAREN, ")", "end", "'catch' target");
1214 matchOrFail(OPENBRACE, "Expected exception handler to be a block statement");
6fe7ccc8 1215 catchBlock = parseBlockStatement(context);
81345200
A
1216 failIfFalse(catchBlock, "Unable to parse 'catch' block");
1217 failIfFalse(popScope(catchScope, TreeBuilder::NeedsFreeVariableInfo), "Parse error");
6fe7ccc8
A
1218 }
1219
1220 if (match(FINALLY)) {
1221 next();
81345200 1222 matchOrFail(OPENBRACE, "Expected block statement for finally body");
6fe7ccc8 1223 finallyBlock = parseBlockStatement(context);
81345200 1224 failIfFalse(finallyBlock, "Cannot parse finally body");
6fe7ccc8 1225 }
81345200 1226 failIfFalse(catchBlock || finallyBlock, "Try statements must have at least a catch or finally block");
93a37866 1227 return context.createTryStatement(location, tryBlock, ident, catchBlock, finallyBlock, firstLine, lastLine);
6fe7ccc8
A
1228}
1229
1230template <typename LexerType>
1231template <class TreeBuilder> TreeStatement Parser<LexerType>::parseDebuggerStatement(TreeBuilder& context)
1232{
1233 ASSERT(match(DEBUGGER));
93a37866 1234 JSTokenLocation location(tokenLocation());
6fe7ccc8
A
1235 int startLine = tokenLine();
1236 int endLine = startLine;
1237 next();
1238 if (match(SEMICOLON))
1239 startLine = tokenLine();
81345200 1240 failIfFalse(autoSemiColon(), "Debugger keyword must be followed by a ';'");
93a37866 1241 return context.createDebugger(location, startLine, endLine);
6fe7ccc8
A
1242}
1243
1244template <typename LexerType>
1245template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBlockStatement(TreeBuilder& context)
1246{
1247 ASSERT(match(OPENBRACE));
93a37866 1248 JSTokenLocation location(tokenLocation());
ed1e77d3 1249 int startOffset = m_token.m_data.offset;
6fe7ccc8
A
1250 int start = tokenLine();
1251 next();
1252 if (match(CLOSEBRACE)) {
ed1e77d3 1253 int endOffset = m_token.m_data.offset;
6fe7ccc8 1254 next();
ed1e77d3
A
1255 TreeStatement result = context.createBlockStatement(location, 0, start, m_lastTokenEndPosition.line);
1256 context.setStartOffset(result, startOffset);
1257 context.setEndOffset(result, endOffset);
1258 return result;
6fe7ccc8 1259 }
ed1e77d3 1260 TreeSourceElements subtree = parseSourceElements(context, DontCheckForStrictMode, StandardFunctionParseType);
81345200
A
1261 failIfFalse(subtree, "Cannot parse the body of the block statement");
1262 matchOrFail(CLOSEBRACE, "Expected a closing '}' at the end of a block statement");
ed1e77d3 1263 int endOffset = m_token.m_data.offset;
6fe7ccc8 1264 next();
ed1e77d3
A
1265 TreeStatement result = context.createBlockStatement(location, subtree, start, m_lastTokenEndPosition.line);
1266 context.setStartOffset(result, startOffset);
1267 context.setEndOffset(result, endOffset);
1268 return result;
6fe7ccc8
A
1269}
1270
1271template <typename LexerType>
1272template <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();
ed1e77d3
A
1279 TreeStatement result = 0;
1280 bool shouldSetEndOffset = true;
1281
6fe7ccc8
A
1282 switch (m_token.m_type) {
1283 case OPENBRACE:
ed1e77d3
A
1284 result = parseBlockStatement(context);
1285 shouldSetEndOffset = false;
1286 break;
6fe7ccc8 1287 case VAR:
ed1e77d3
A
1288 result = parseVarDeclaration(context);
1289 break;
6fe7ccc8 1290 case FUNCTION:
81345200 1291 failIfFalseIfStrict(m_statementDepth == 1, "Strict mode does not allow function declarations in a lexically nested statement");
ed1e77d3
A
1292 result = parseFunctionDeclaration(context);
1293 break;
93a37866
A
1294 case SEMICOLON: {
1295 JSTokenLocation location(tokenLocation());
6fe7ccc8 1296 next();
ed1e77d3
A
1297 result = context.createEmptyStatement(location);
1298 break;
93a37866 1299 }
6fe7ccc8 1300 case IF:
ed1e77d3
A
1301 result = parseIfStatement(context);
1302 break;
6fe7ccc8 1303 case DO:
ed1e77d3
A
1304 result = parseDoWhileStatement(context);
1305 break;
6fe7ccc8 1306 case WHILE:
ed1e77d3
A
1307 result = parseWhileStatement(context);
1308 break;
6fe7ccc8 1309 case FOR:
ed1e77d3
A
1310 result = parseForStatement(context);
1311 break;
6fe7ccc8 1312 case CONTINUE:
ed1e77d3
A
1313 result = parseContinueStatement(context);
1314 break;
6fe7ccc8 1315 case BREAK:
ed1e77d3
A
1316 result = parseBreakStatement(context);
1317 break;
6fe7ccc8 1318 case RETURN:
ed1e77d3
A
1319 result = parseReturnStatement(context);
1320 break;
6fe7ccc8 1321 case WITH:
ed1e77d3
A
1322 result = parseWithStatement(context);
1323 break;
6fe7ccc8 1324 case SWITCH:
ed1e77d3
A
1325 result = parseSwitchStatement(context);
1326 break;
6fe7ccc8 1327 case THROW:
ed1e77d3
A
1328 result = parseThrowStatement(context);
1329 break;
6fe7ccc8 1330 case TRY:
ed1e77d3
A
1331 result = parseTryStatement(context);
1332 break;
6fe7ccc8 1333 case DEBUGGER:
ed1e77d3
A
1334 result = parseDebuggerStatement(context);
1335 break;
6fe7ccc8
A
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:
ed1e77d3
A
1343 result = parseExpressionOrLabelStatement(context);
1344 break;
6fe7ccc8
A
1345 case STRING:
1346 directive = m_token.m_data.ident;
1347 if (directiveLiteralLength)
93a37866 1348 *directiveLiteralLength = m_token.m_location.endOffset - m_token.m_location.startOffset;
6fe7ccc8 1349 nonTrivialExpressionCount = m_nonTrivialExpressionCount;
81345200 1350 FALLTHROUGH;
6fe7ccc8
A
1351 default:
1352 TreeStatement exprStatement = parseExpressionStatement(context);
1353 if (directive && nonTrivialExpressionCount != m_nonTrivialExpressionCount)
1354 directive = 0;
ed1e77d3
A
1355 result = exprStatement;
1356 break;
6fe7ccc8 1357 }
ed1e77d3
A
1358
1359 if (result && shouldSetEndOffset)
1360 context.setEndOffset(result, m_lastTokenEndPosition.offset);
1361 return result;
6fe7ccc8
A
1362}
1363
1364template <typename LexerType>
1365template <class TreeBuilder> TreeFormalParameterList Parser<LexerType>::parseFormalParameters(TreeBuilder& context)
1366{
ed1e77d3 1367 auto parameter = parseDestructuringPattern(context, DestructureToParameters);
81345200
A
1368 failIfFalse(parameter, "Cannot parse parameter pattern");
1369 TreeFormalParameterList list = context.createFormalParameterList(parameter);
6fe7ccc8 1370 TreeFormalParameterList tail = list;
81345200 1371 while (consume(COMMA)) {
ed1e77d3 1372 parameter = parseDestructuringPattern(context, DestructureToParameters);
81345200
A
1373 failIfFalse(parameter, "Cannot parse parameter pattern");
1374 tail = context.createFormalParameterList(tail, parameter);
6fe7ccc8
A
1375 }
1376 return list;
1377}
1378
1379template <typename LexerType>
ed1e77d3
A
1380template <class TreeBuilder> TreeFunctionBody Parser<LexerType>::parseFunctionBody(
1381 TreeBuilder& context, int functionKeywordStart, int functionNameStart,
1382 int parametersStart, ConstructorKind constructorKind, FunctionParseType parseType)
6fe7ccc8 1383{
93a37866
A
1384 JSTokenLocation startLocation(tokenLocation());
1385 unsigned startColumn = tokenColumn();
93a37866 1386
ed1e77d3
A
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 }
81345200 1393 }
ed1e77d3 1394
6fe7ccc8
A
1395 DepthManager statementDepth(&m_statementDepth);
1396 m_statementDepth = 0;
93a37866 1397 typename TreeBuilder::FunctionBodyBuilder bodyBuilder(const_cast<VM*>(m_vm), m_lexer.get());
ed1e77d3
A
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
81345200 1403 unsigned endColumn = tokenColumn();
ed1e77d3 1404 return context.createFunctionBody(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind);
81345200
A
1405}
1406
1407static 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";
ed1e77d3
A
1416 case MethodMode:
1417 return "method";
1418#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
1419 case ArrowFunctionMode:
1420 return "arrow function";
1421#endif
81345200
A
1422 }
1423 RELEASE_ASSERT_NOT_REACHED();
1424 return nullptr;
6fe7ccc8
A
1425}
1426
ed1e77d3
A
1427template <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
6fe7ccc8 1483template <typename LexerType>
ed1e77d3 1484template <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)
6fe7ccc8
A
1485{
1486 AutoPopScopeRef functionScope(this, pushScope());
1487 functionScope->setIsFunction();
81345200
A
1488 int functionNameStart = m_token.m_location.startOffset;
1489 const Identifier* lastFunctionName = m_lastFunctionName;
1490 m_lastFunctionName = nullptr;
ed1e77d3
A
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;
81345200 1525 }
ed1e77d3
A
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;
81345200 1550 }
ed1e77d3 1551#endif
6fe7ccc8 1552 }
6fe7ccc8 1553
ed1e77d3
A
1554 bool isClassConstructor = constructorKind != ConstructorKind::None;
1555
1556 info.bodyStartLine = tokenLine();
1557 info.bodyStartColumn = m_token.m_data.offset - m_token.m_data.lineStartOffset;
93a37866 1558 JSTokenLocation startLocation(tokenLocation());
6fe7ccc8
A
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.
ed1e77d3 1561 if (const SourceProviderCacheItem* cachedInfo = TreeBuilder::CanUseFunctionCache ? findCachedFunctionInfo(info.startFunctionOffset) : 0) {
6fe7ccc8
A
1562 // If we're in a strict context, the cached function info must say it was strict too.
1563 ASSERT(!strictMode() || cachedInfo->strictMode);
93a37866
A
1564 JSTokenLocation endLocation;
1565
ed1e77d3
A
1566 endLocation.line = cachedInfo->lastTockenLine;
1567 endLocation.startOffset = cachedInfo->lastTockenStartOffset;
1568 endLocation.lineStartOffset = cachedInfo->lastTockenLineStartOffset;
81345200 1569
ed1e77d3 1570 bool endColumnIsOnStartLine = (endLocation.line == info.bodyStartLine);
93a37866 1571 ASSERT(endLocation.startOffset >= endLocation.lineStartOffset);
81345200
A
1572 unsigned bodyEndColumn = endColumnIsOnStartLine ?
1573 endLocation.startOffset - m_token.m_data.lineStartOffset :
1574 endLocation.startOffset - endLocation.lineStartOffset;
ed1e77d3 1575 unsigned currentLineStartOffset = m_token.m_location.lineStartOffset;
93a37866 1576
ed1e77d3
A
1577 info.body = context.createFunctionBody(
1578 startLocation, endLocation, info.bodyStartColumn, bodyEndColumn,
1579 functionKeywordStart, functionNameStart, parametersStart,
1580 cachedInfo->strictMode, constructorKind);
6fe7ccc8 1581
93a37866 1582 functionScope->restoreFromSourceProviderCache(cachedInfo);
81345200 1583 failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo), "Parser error");
6fe7ccc8 1584
ed1e77d3
A
1585 m_token = cachedInfo->endFunctionToken();
1586
1587 if (endColumnIsOnStartLine)
1588 m_token.m_location.lineStartOffset = currentLineStartOffset;
93a37866
A
1589
1590 m_lexer->setOffset(m_token.m_location.endOffset, m_token.m_location.lineStartOffset);
1591 m_lexer->setLineNumber(m_token.m_location.line);
ed1e77d3
A
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;
6fe7ccc8 1598
ed1e77d3
A
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());
6fe7ccc8 1612 next();
ed1e77d3
A
1613#endif
1614 info.bodyEndLine = m_lastTokenEndPosition.line;
6fe7ccc8
A
1615 return true;
1616 }
ed1e77d3 1617
81345200
A
1618 m_lastFunctionName = lastFunctionName;
1619 ParserState oldState = saveState();
ed1e77d3
A
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
81345200 1643 restoreState(oldState);
ed1e77d3
A
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;
6fe7ccc8 1665 }
ed1e77d3 1666#endif
6fe7ccc8
A
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.
93a37866 1670 static const int minimumFunctionLengthToCache = 16;
81345200 1671 std::unique_ptr<SourceProviderCacheItem> newInfo;
ed1e77d3 1672 int functionLength = info.endFunctionOffset - info.startFunctionOffset;
6fe7ccc8 1673 if (TreeBuilder::CanUseFunctionCache && m_functionCache && functionLength > minimumFunctionLengthToCache) {
93a37866 1674 SourceProviderCacheItemCreationParameters parameters;
ed1e77d3 1675 parameters.endFunctionOffset = info.endFunctionOffset;
81345200 1676 parameters.functionNameStart = functionNameStart;
ed1e77d3
A
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
93a37866
A
1687 functionScope->fillParametersForSourceProviderCache(parameters);
1688 newInfo = SourceProviderCacheItem::create(parameters);
6fe7ccc8
A
1689 }
1690
81345200 1691 failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo), "Parser error");
ed1e77d3
A
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
81345200 1701 matchOrFail(CLOSEBRACE, "Expected a closing '}' after a ", stringForFunctionMode(mode), " body");
ed1e77d3
A
1702 next();
1703#endif
6fe7ccc8 1704
93a37866 1705 if (newInfo)
ed1e77d3 1706 m_functionCache->add(info.startFunctionOffset, WTF::move(newInfo));
6fe7ccc8 1707
ed1e77d3 1708 info.bodyEndLine = m_lastTokenEndPosition.line;
6fe7ccc8
A
1709 return true;
1710}
1711
1712template <typename LexerType>
1713template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDeclaration(TreeBuilder& context)
1714{
1715 ASSERT(match(FUNCTION));
93a37866 1716 JSTokenLocation location(tokenLocation());
ed1e77d3 1717 unsigned functionKeywordStart = tokenStart();
6fe7ccc8 1718 next();
ed1e77d3
A
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)
1728template <typename LexerType>
1729template <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);
6fe7ccc8
A
1748}
1749
ed1e77d3
A
1750template <typename LexerType>
1751template <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
6fe7ccc8 1876struct LabelInfo {
81345200 1877 LabelInfo(const Identifier* ident, const JSTextPosition& start, const JSTextPosition& end)
6fe7ccc8
A
1878 : m_ident(ident)
1879 , m_start(start)
1880 , m_end(end)
1881 {
1882 }
1883
1884 const Identifier* m_ident;
81345200
A
1885 JSTextPosition m_start;
1886 JSTextPosition m_end;
6fe7ccc8
A
1887};
1888
1889template <typename LexerType>
1890template <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;
93a37866 1897 JSTokenLocation location;
6fe7ccc8 1898 do {
81345200 1899 JSTextPosition start = tokenStartPosition();
93a37866 1900 location = tokenLocation();
6fe7ccc8
A
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);
81345200
A
1906 failIfFalse(expression, "Cannot parse expression statement");
1907 if (!autoSemiColon())
1908 failDueToUnexpectedToken();
1909 return context.createExprStatement(location, expression, start, m_lastTokenEndPosition.line);
6fe7ccc8
A
1910 }
1911 const Identifier* ident = m_token.m_data.ident;
81345200 1912 JSTextPosition end = tokenEndPosition();
6fe7ccc8 1913 next();
81345200 1914 consumeOrFail(COLON, "Labels must be followed by a ':'");
6fe7ccc8
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++)
81345200
A
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));
6fe7ccc8
A
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 }
81345200 1945 failIfFalse(statement, "Cannot parse statement");
6fe7ccc8
A
1946 for (size_t i = 0; i < labels.size(); i++) {
1947 const LabelInfo& info = labels[labels.size() - i - 1];
81345200 1948 statement = context.createLabelStatement(location, info.m_ident, statement, info.m_start, info.m_end);
6fe7ccc8
A
1949 }
1950 return statement;
1951}
1952
1953template <typename LexerType>
1954template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionStatement(TreeBuilder& context)
1955{
ed1e77d3
A
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 }
81345200 1969 JSTextPosition start = tokenStartPosition();
93a37866 1970 JSTokenLocation location(tokenLocation());
6fe7ccc8 1971 TreeExpression expression = parseExpression(context);
81345200
A
1972 failIfFalse(expression, "Cannot parse expression statement");
1973 failIfFalse(autoSemiColon(), "Parse error");
1974 return context.createExprStatement(location, expression, start, m_lastTokenEndPosition.line);
6fe7ccc8
A
1975}
1976
1977template <typename LexerType>
1978template <class TreeBuilder> TreeStatement Parser<LexerType>::parseIfStatement(TreeBuilder& context)
1979{
1980 ASSERT(match(IF));
93a37866 1981 JSTokenLocation ifLocation(tokenLocation());
6fe7ccc8
A
1982 int start = tokenLine();
1983 next();
81345200 1984 handleProductionOrFail(OPENPAREN, "(", "start", "'if' condition");
93a37866 1985
6fe7ccc8 1986 TreeExpression condition = parseExpression(context);
81345200 1987 failIfFalse(condition, "Expected a expression as the condition for an if statement");
6fe7ccc8 1988 int end = tokenLine();
81345200 1989 handleProductionOrFail(CLOSEPAREN, ")", "end", "'if' condition");
93a37866 1990
6fe7ccc8
A
1991 const Identifier* unused = 0;
1992 TreeStatement trueBlock = parseStatement(context, unused);
81345200 1993 failIfFalse(trueBlock, "Expected a statement as the body of an if block");
93a37866 1994
6fe7ccc8 1995 if (!match(ELSE))
93a37866
A
1996 return context.createIfStatement(ifLocation, condition, trueBlock, 0, start, end);
1997
6fe7ccc8 1998 Vector<TreeExpression> exprStack;
81345200 1999 Vector<std::pair<int, int>> posStack;
93a37866 2000 Vector<JSTokenLocation> tokenLocationStack;
6fe7ccc8
A
2001 Vector<TreeStatement> statementStack;
2002 bool trailingElse = false;
2003 do {
93a37866 2004 JSTokenLocation tempLocation = tokenLocation();
6fe7ccc8
A
2005 next();
2006 if (!match(IF)) {
2007 const Identifier* unused = 0;
2008 TreeStatement block = parseStatement(context, unused);
81345200 2009 failIfFalse(block, "Expected a statement as the body of an else block");
6fe7ccc8
A
2010 statementStack.append(block);
2011 trailingElse = true;
2012 break;
2013 }
2014 int innerStart = tokenLine();
2015 next();
81345200
A
2016
2017 handleProductionOrFail(OPENPAREN, "(", "start", "'if' condition");
93a37866 2018
6fe7ccc8 2019 TreeExpression innerCondition = parseExpression(context);
81345200 2020 failIfFalse(innerCondition, "Expected a expression as the condition for an if statement");
6fe7ccc8 2021 int innerEnd = tokenLine();
81345200 2022 handleProductionOrFail(CLOSEPAREN, ")", "end", "'if' condition");
6fe7ccc8
A
2023 const Identifier* unused = 0;
2024 TreeStatement innerTrueBlock = parseStatement(context, unused);
81345200 2025 failIfFalse(innerTrueBlock, "Expected a statement as the body of an if block");
93a37866 2026 tokenLocationStack.append(tempLocation);
6fe7ccc8 2027 exprStack.append(innerCondition);
81345200 2028 posStack.append(std::make_pair(innerStart, innerEnd));
6fe7ccc8
A
2029 statementStack.append(innerTrueBlock);
2030 } while (match(ELSE));
93a37866 2031
6fe7ccc8
A
2032 if (!trailingElse) {
2033 TreeExpression condition = exprStack.last();
2034 exprStack.removeLast();
2035 TreeStatement trueBlock = statementStack.last();
2036 statementStack.removeLast();
81345200 2037 std::pair<int, int> pos = posStack.last();
6fe7ccc8 2038 posStack.removeLast();
93a37866
A
2039 JSTokenLocation elseLocation = tokenLocationStack.last();
2040 tokenLocationStack.removeLast();
ed1e77d3
A
2041 TreeStatement ifStatement = context.createIfStatement(elseLocation, condition, trueBlock, 0, pos.first, pos.second);
2042 context.setEndOffset(ifStatement, context.endOffset(trueBlock));
2043 statementStack.append(ifStatement);
6fe7ccc8 2044 }
93a37866 2045
6fe7ccc8
A
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();
81345200 2053 std::pair<int, int> pos = posStack.last();
6fe7ccc8 2054 posStack.removeLast();
93a37866
A
2055 JSTokenLocation elseLocation = tokenLocationStack.last();
2056 tokenLocationStack.removeLast();
ed1e77d3
A
2057 TreeStatement ifStatement = context.createIfStatement(elseLocation, condition, trueBlock, falseBlock, pos.first, pos.second);
2058 context.setEndOffset(ifStatement, context.endOffset(falseBlock));
2059 statementStack.append(ifStatement);
6fe7ccc8 2060 }
93a37866
A
2061
2062 return context.createIfStatement(ifLocation, condition, trueBlock, statementStack.last(), start, end);
6fe7ccc8
A
2063}
2064
2065template <typename LexerType>
2066template <class TreeBuilder> TreeExpression Parser<LexerType>::parseExpression(TreeBuilder& context)
2067{
2068 failIfStackOverflow();
93a37866 2069 JSTokenLocation location(tokenLocation());
6fe7ccc8 2070 TreeExpression node = parseAssignmentExpression(context);
81345200 2071 failIfFalse(node, "Cannot parse expression");
ed1e77d3 2072 context.setEndOffset(node, m_lastTokenEndPosition.offset);
6fe7ccc8
A
2073 if (!match(COMMA))
2074 return node;
2075 next();
2076 m_nonTrivialExpressionCount++;
2077 m_nonLHSCount++;
2078 TreeExpression right = parseAssignmentExpression(context);
81345200 2079 failIfFalse(right, "Cannot parse expression in a comma expression");
ed1e77d3
A
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);
6fe7ccc8
A
2083 while (match(COMMA)) {
2084 next(TreeBuilder::DontBuildStrings);
2085 right = parseAssignmentExpression(context);
81345200 2086 failIfFalse(right, "Cannot parse expression in a comma expression");
ed1e77d3
A
2087 context.setEndOffset(right, m_lastTokenEndPosition.offset);
2088 tail = context.appendToCommaExpr(location, head, tail, right);
6fe7ccc8 2089 }
ed1e77d3
A
2090 context.setEndOffset(head, m_lastTokenEndPosition.offset);
2091 return head;
6fe7ccc8
A
2092}
2093
ed1e77d3 2094
6fe7ccc8
A
2095template <typename LexerType>
2096template <typename TreeBuilder> TreeExpression Parser<LexerType>::parseAssignmentExpression(TreeBuilder& context)
2097{
2098 failIfStackOverflow();
81345200 2099 JSTextPosition start = tokenStartPosition();
93a37866 2100 JSTokenLocation location(tokenLocation());
6fe7ccc8
A
2101 int initialAssignmentCount = m_assignmentCount;
2102 int initialNonLHSCount = m_nonLHSCount;
81345200
A
2103 if (match(OPENBRACE) || match(OPENBRACKET)) {
2104 SavePoint savePoint = createSavePoint();
ed1e77d3 2105 auto pattern = tryParseDestructuringPatternExpression(context);
81345200
A
2106 if (pattern && consume(EQUAL)) {
2107 auto rhs = parseAssignmentExpression(context);
2108 if (rhs)
ed1e77d3 2109 return context.createDestructuringAssignment(location, pattern, rhs);
81345200
A
2110 }
2111 restoreSavePoint(savePoint);
2112 }
ed1e77d3
A
2113
2114#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
2115 if (isArrowFunctionParamters())
2116 return parseArrowFunctionExpression(context);
2117#endif
2118
6fe7ccc8 2119 TreeExpression lhs = parseConditionalExpression(context);
81345200
A
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
6fe7ccc8 2125 return lhs;
81345200 2126 }
6fe7ccc8
A
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;
81345200
A
2150 context.assignmentStackAppend(assignmentStack, lhs, start, tokenStartPosition(), m_assignmentCount, op);
2151 start = tokenStartPosition();
6fe7ccc8
A
2152 m_assignmentCount++;
2153 next(TreeBuilder::DontBuildStrings);
2154 if (strictMode() && m_lastIdentifier && context.isResolve(lhs)) {
81345200
A
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");
6fe7ccc8
A
2157 declareWrite(m_lastIdentifier);
2158 m_lastIdentifier = 0;
2159 }
81345200
A
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");
6fe7ccc8 2165 break;
81345200 2166 }
6fe7ccc8
A
2167 }
2168end:
2169 if (hadAssignment)
2170 m_nonLHSCount++;
2171
2172 if (!TreeBuilder::CreatesAST)
2173 return lhs;
2174
2175 while (assignmentStack)
81345200 2176 lhs = context.createAssignment(location, assignmentStack, lhs, initialAssignmentCount, m_assignmentCount, lastTokenEndPosition());
6fe7ccc8
A
2177
2178 return lhs;
2179}
2180
2181template <typename LexerType>
2182template <class TreeBuilder> TreeExpression Parser<LexerType>::parseConditionalExpression(TreeBuilder& context)
2183{
93a37866 2184 JSTokenLocation location(tokenLocation());
6fe7ccc8 2185 TreeExpression cond = parseBinaryExpression(context);
81345200 2186 failIfFalse(cond, "Cannot parse expression");
6fe7ccc8
A
2187 if (!match(QUESTION))
2188 return cond;
2189 m_nonTrivialExpressionCount++;
2190 m_nonLHSCount++;
2191 next(TreeBuilder::DontBuildStrings);
2192 TreeExpression lhs = parseAssignmentExpression(context);
81345200 2193 failIfFalse(lhs, "Cannot parse left hand side of ternary operator");
ed1e77d3 2194 context.setEndOffset(lhs, m_lastTokenEndPosition.offset);
81345200 2195 consumeOrFailWithFlags(COLON, TreeBuilder::DontBuildStrings, "Expected ':' in ternary operator");
6fe7ccc8
A
2196
2197 TreeExpression rhs = parseAssignmentExpression(context);
81345200 2198 failIfFalse(rhs, "Cannot parse right hand side of ternary operator");
ed1e77d3 2199 context.setEndOffset(rhs, m_lastTokenEndPosition.offset);
93a37866 2200 return context.createConditionalExpr(location, cond, lhs, rhs);
6fe7ccc8
A
2201}
2202
2203ALWAYS_INLINE static bool isUnaryOp(JSTokenType token)
2204{
2205 return token & UnaryOpTokenFlag;
2206}
2207
2208template <typename LexerType>
2209int Parser<LexerType>::isBinaryOperator(JSTokenType token)
2210{
2211 if (m_allowsIn)
2212 return token & (BinaryOpTokenPrecedenceMask << BinaryOpTokenAllowsInPrecedenceAdditionalShift);
2213 return token & BinaryOpTokenPrecedenceMask;
2214}
2215
2216template <typename LexerType>
2217template <class TreeBuilder> TreeExpression Parser<LexerType>::parseBinaryExpression(TreeBuilder& context)
2218{
6fe7ccc8
A
2219 int operandStackDepth = 0;
2220 int operatorStackDepth = 0;
2221 typename TreeBuilder::BinaryExprContext binaryExprContext(context);
93a37866 2222 JSTokenLocation location(tokenLocation());
6fe7ccc8 2223 while (true) {
81345200 2224 JSTextPosition exprStart = tokenStartPosition();
6fe7ccc8
A
2225 int initialAssignments = m_assignmentCount;
2226 TreeExpression current = parseUnaryExpression(context);
81345200 2227 failIfFalse(current, "Cannot parse expression");
6fe7ccc8 2228
81345200 2229 context.appendBinaryExpressionInfo(operandStackDepth, current, exprStart, lastTokenEndPosition(), lastTokenEndPosition(), initialAssignments != m_assignmentCount);
6fe7ccc8
A
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);
93a37866 2244 context.appendBinaryOperation(location, operandStackDepth, operatorStackDepth, lhs, rhs);
6fe7ccc8
A
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);
93a37866 2255 context.appendBinaryOperation(location, operandStackDepth, operatorStackDepth, lhs, rhs);
6fe7ccc8
A
2256 context.operatorStackPop(operatorStackDepth);
2257 }
2258 return context.popOperandStack(operandStackDepth);
2259}
2260
2261template <typename LexerType>
81345200 2262template <class TreeBuilder> TreeProperty Parser<LexerType>::parseProperty(TreeBuilder& context, bool complete)
6fe7ccc8
A
2263{
2264 bool wasIdent = false;
2265 switch (m_token.m_type) {
2266 namedProperty:
2267 case IDENT:
2268 wasIdent = true;
81345200 2269 FALLTHROUGH;
6fe7ccc8
A
2270 case STRING: {
2271 const Identifier* ident = m_token.m_data.ident;
ed1e77d3 2272 unsigned getterOrSetterStartOffset = tokenStart();
93a37866 2273 if (complete || (wasIdent && (*ident == m_vm->propertyNames->get || *ident == m_vm->propertyNames->set)))
6fe7ccc8
A
2274 nextExpectIdentifier(LexerFlagsIgnoreReservedWords);
2275 else
2276 nextExpectIdentifier(LexerFlagsIgnoreReservedWords | TreeBuilder::DontBuildKeywords);
ed1e77d3 2277
6fe7ccc8
A
2278 if (match(COLON)) {
2279 next();
2280 TreeExpression node = parseAssignmentExpression(context);
81345200 2281 failIfFalse(node, "Cannot parse expression for property declaration");
ed1e77d3
A
2282 context.setEndOffset(node, m_lexer->currentOffset());
2283 return context.createProperty(ident, node, PropertyNode::Constant, PropertyNode::Unknown, complete);
6fe7ccc8 2284 }
ed1e77d3
A
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
81345200 2292 failIfFalse(wasIdent, "Expected an identifier as property name");
ed1e77d3
A
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
6fe7ccc8 2302 PropertyNode::Type type;
93a37866 2303 if (*ident == m_vm->propertyNames->get)
6fe7ccc8 2304 type = PropertyNode::Getter;
93a37866 2305 else if (*ident == m_vm->propertyNames->set)
6fe7ccc8
A
2306 type = PropertyNode::Setter;
2307 else
81345200 2308 failWithMessage("Expected a ':' following the property name '", ident->impl(), "'");
ed1e77d3 2309 return parseGetterSetter(context, complete, type, getterOrSetterStartOffset);
6fe7ccc8 2310 }
ed1e77d3
A
2311 case DOUBLE:
2312 case INTEGER: {
6fe7ccc8
A
2313 double propertyName = m_token.m_data.doubleValue;
2314 next();
ed1e77d3
A
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
81345200 2323 consumeOrFail(COLON, "Expected ':' after property name");
6fe7ccc8 2324 TreeExpression node = parseAssignmentExpression(context);
81345200 2325 failIfFalse(node, "Cannot parse expression for property declaration");
ed1e77d3
A
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);
81345200
A
2328 }
2329 case OPENBRACKET: {
2330 next();
ed1e77d3 2331 auto propertyName = parseAssignmentExpression(context);
81345200 2332 failIfFalse(propertyName, "Cannot parse computed property name");
81345200 2333 handleProductionOrFail(CLOSEBRACKET, "]", "end", "computed property name");
ed1e77d3
A
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
81345200
A
2341 consumeOrFail(COLON, "Expected ':' after property name");
2342 TreeExpression node = parseAssignmentExpression(context);
2343 failIfFalse(node, "Cannot parse expression for property declaration");
ed1e77d3
A
2344 context.setEndOffset(node, m_lexer->currentOffset());
2345 return context.createProperty(propertyName, node, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Computed), PropertyNode::Unknown, complete);
6fe7ccc8
A
2346 }
2347 default:
81345200 2348 failIfFalse(m_token.m_type & KeywordTokenFlag, "Expected a property name");
6fe7ccc8
A
2349 goto namedProperty;
2350 }
2351}
2352
ed1e77d3
A
2353template <typename LexerType>
2354template <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
2364template <typename LexerType>
2365template <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
2397template <typename LexerType>
2398template <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
6fe7ccc8
A
2410template <typename LexerType>
2411template <class TreeBuilder> TreeExpression Parser<LexerType>::parseObjectLiteral(TreeBuilder& context)
2412{
81345200
A
2413 auto savePoint = createSavePoint();
2414 consumeOrFailWithFlags(OPENBRACE, TreeBuilder::DontBuildStrings, "Expected opening '{' at the start of an object literal");
93a37866 2415
6fe7ccc8 2416 int oldNonLHSCount = m_nonLHSCount;
ed1e77d3
A
2417
2418 JSTokenLocation location(tokenLocation());
6fe7ccc8
A
2419 if (match(CLOSEBRACE)) {
2420 next();
93a37866 2421 return context.createObjectLiteral(location);
6fe7ccc8
A
2422 }
2423
81345200
A
2424 TreeProperty property = parseProperty(context, false);
2425 failIfFalse(property, "Cannot parse object literal property");
ed1e77d3
A
2426
2427 if (!m_syntaxAlreadyValidated && context.getType(property) & (PropertyNode::Getter | PropertyNode::Setter)) {
81345200 2428 restoreSavePoint(savePoint);
6fe7ccc8
A
2429 return parseStrictObjectLiteral(context);
2430 }
ed1e77d3
A
2431
2432 bool seenUnderscoreProto = false;
2433 if (shouldCheckPropertyForUnderscoreProtoDuplicate(context, property))
2434 seenUnderscoreProto = *context.getName(property) == m_vm->propertyNames->underscoreProto;
2435
93a37866 2436 TreePropertyList propertyList = context.createPropertyList(location, property);
6fe7ccc8
A
2437 TreePropertyList tail = propertyList;
2438 while (match(COMMA)) {
2439 next(TreeBuilder::DontBuildStrings);
6fe7ccc8
A
2440 if (match(CLOSEBRACE))
2441 break;
93a37866 2442 JSTokenLocation propertyLocation(tokenLocation());
81345200
A
2443 property = parseProperty(context, false);
2444 failIfFalse(property, "Cannot parse object literal property");
ed1e77d3 2445 if (!m_syntaxAlreadyValidated && context.getType(property) & (PropertyNode::Getter | PropertyNode::Setter)) {
81345200 2446 restoreSavePoint(savePoint);
6fe7ccc8
A
2447 return parseStrictObjectLiteral(context);
2448 }
ed1e77d3
A
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 }
93a37866 2455 tail = context.createPropertyList(propertyLocation, property, tail);
6fe7ccc8 2456 }
93a37866
A
2457
2458 location = tokenLocation();
81345200 2459 handleProductionOrFail(CLOSEBRACE, "}", "end", "object literal");
6fe7ccc8
A
2460
2461 m_nonLHSCount = oldNonLHSCount;
2462
93a37866 2463 return context.createObjectLiteral(location, propertyList);
6fe7ccc8
A
2464}
2465
2466template <typename LexerType>
2467template <class TreeBuilder> TreeExpression Parser<LexerType>::parseStrictObjectLiteral(TreeBuilder& context)
2468{
81345200 2469 consumeOrFail(OPENBRACE, "Expected opening '{' at the start of an object literal");
6fe7ccc8
A
2470
2471 int oldNonLHSCount = m_nonLHSCount;
2472
93a37866 2473 JSTokenLocation location(tokenLocation());
6fe7ccc8
A
2474 if (match(CLOSEBRACE)) {
2475 next();
93a37866 2476 return context.createObjectLiteral(location);
6fe7ccc8
A
2477 }
2478
81345200
A
2479 TreeProperty property = parseProperty(context, true);
2480 failIfFalse(property, "Cannot parse object literal property");
ed1e77d3
A
2481
2482 bool seenUnderscoreProto = false;
2483 if (shouldCheckPropertyForUnderscoreProtoDuplicate(context, property))
2484 seenUnderscoreProto = *context.getName(property) == m_vm->propertyNames->underscoreProto;
2485
93a37866 2486 TreePropertyList propertyList = context.createPropertyList(location, property);
6fe7ccc8
A
2487 TreePropertyList tail = propertyList;
2488 while (match(COMMA)) {
2489 next();
6fe7ccc8
A
2490 if (match(CLOSEBRACE))
2491 break;
93a37866 2492 JSTokenLocation propertyLocation(tokenLocation());
81345200
A
2493 property = parseProperty(context, true);
2494 failIfFalse(property, "Cannot parse object literal property");
ed1e77d3
A
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;
6fe7ccc8
A
2499 }
2500 }
93a37866 2501 tail = context.createPropertyList(propertyLocation, property, tail);
6fe7ccc8 2502 }
93a37866
A
2503
2504 location = tokenLocation();
81345200 2505 handleProductionOrFail(CLOSEBRACE, "}", "end", "object literal");
6fe7ccc8
A
2506
2507 m_nonLHSCount = oldNonLHSCount;
2508
93a37866 2509 return context.createObjectLiteral(location, propertyList);
6fe7ccc8
A
2510}
2511
2512template <typename LexerType>
2513template <class TreeBuilder> TreeExpression Parser<LexerType>::parseArrayLiteral(TreeBuilder& context)
2514{
81345200 2515 consumeOrFailWithFlags(OPENBRACKET, TreeBuilder::DontBuildStrings, "Expected an opening '[' at the beginning of an array literal");
6fe7ccc8
A
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)) {
93a37866 2525 JSTokenLocation location(tokenLocation());
6fe7ccc8 2526 next(TreeBuilder::DontBuildStrings);
93a37866 2527 return context.createArray(location, elisions);
6fe7ccc8
A
2528 }
2529
81345200
A
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");
6fe7ccc8
A
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)) {
93a37866 2555 JSTokenLocation location(tokenLocation());
6fe7ccc8 2556 next(TreeBuilder::DontBuildStrings);
93a37866 2557 return context.createArray(location, elisions, elementList);
6fe7ccc8 2558 }
81345200
A
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 }
6fe7ccc8 2570 TreeExpression elem = parseAssignmentExpression(context);
81345200 2571 failIfFalse(elem, "Cannot parse array literal element");
6fe7ccc8
A
2572 tail = context.createElementList(tail, elisions, elem);
2573 }
93a37866
A
2574
2575 JSTokenLocation location(tokenLocation());
81345200
A
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 }
6fe7ccc8
A
2580
2581 m_nonLHSCount = oldNonLHSCount;
2582
93a37866 2583 return context.createArray(location, elementList);
6fe7ccc8
A
2584}
2585
ed1e77d3
A
2586#if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
2587template <typename LexerType>
2588template <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
2604template <typename LexerType>
2605template <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
6fe7ccc8
A
2646template <typename LexerType>
2647template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePrimaryExpression(TreeBuilder& context)
2648{
2649 failIfStackOverflow();
2650 switch (m_token.m_type) {
ed1e77d3
A
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
6fe7ccc8
A
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;
81345200 2677 handleProductionOrFail(CLOSEPAREN, ")", "end", "compound expression");
6fe7ccc8
A
2678 return result;
2679 }
2680 case THISTOKEN: {
93a37866 2681 JSTokenLocation location(tokenLocation());
6fe7ccc8 2682 next();
ed1e77d3 2683 return context.thisExpr(location, m_thisTDZMode);
6fe7ccc8
A
2684 }
2685 case IDENT: {
81345200 2686 JSTextPosition start = tokenStartPosition();
6fe7ccc8 2687 const Identifier* ident = m_token.m_data.ident;
93a37866 2688 JSTokenLocation location(tokenLocation());
6fe7ccc8 2689 next();
93a37866 2690 currentScope()->useVariable(ident, m_vm->propertyNames->eval == *ident);
6fe7ccc8 2691 m_lastIdentifier = ident;
81345200 2692 return context.createResolve(location, ident, start);
6fe7ccc8
A
2693 }
2694 case STRING: {
2695 const Identifier* ident = m_token.m_data.ident;
93a37866 2696 JSTokenLocation location(tokenLocation());
6fe7ccc8 2697 next();
93a37866 2698 return context.createString(location, ident);
6fe7ccc8 2699 }
ed1e77d3 2700 case DOUBLE: {
6fe7ccc8 2701 double d = m_token.m_data.doubleValue;
93a37866 2702 JSTokenLocation location(tokenLocation());
6fe7ccc8 2703 next();
ed1e77d3
A
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);
6fe7ccc8
A
2711 }
2712 case NULLTOKEN: {
93a37866 2713 JSTokenLocation location(tokenLocation());
6fe7ccc8 2714 next();
93a37866 2715 return context.createNull(location);
6fe7ccc8
A
2716 }
2717 case TRUETOKEN: {
93a37866 2718 JSTokenLocation location(tokenLocation());
6fe7ccc8 2719 next();
93a37866 2720 return context.createBoolean(location, true);
6fe7ccc8
A
2721 }
2722 case FALSETOKEN: {
93a37866 2723 JSTokenLocation location(tokenLocation());
6fe7ccc8 2724 next();
93a37866 2725 return context.createBoolean(location, false);
6fe7ccc8
A
2726 }
2727 case DIVEQUAL:
2728 case DIVIDE: {
2729 /* regexp */
2730 const Identifier* pattern;
2731 const Identifier* flags;
2732 if (match(DIVEQUAL))
81345200 2733 failIfFalse(m_lexer->scanRegExp(pattern, flags, '='), "Invalid regular expression");
6fe7ccc8 2734 else
81345200 2735 failIfFalse(m_lexer->scanRegExp(pattern, flags), "Invalid regular expression");
6fe7ccc8 2736
81345200 2737 JSTextPosition start = tokenStartPosition();
93a37866 2738 JSTokenLocation location(tokenLocation());
6fe7ccc8 2739 next();
81345200 2740 TreeExpression re = context.createRegExp(location, *pattern, *flags, start);
6fe7ccc8 2741 if (!re) {
93a37866 2742 const char* yarrErrorMsg = Yarr::checkSyntax(pattern->string());
81345200 2743 regexFail(yarrErrorMsg);
6fe7ccc8
A
2744 }
2745 return re;
2746 }
ed1e77d3
A
2747#if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
2748 case TEMPLATE:
2749 return parseTemplateLiteral(context, LexerType::RawStringsBuildMode::DontBuildRawStrings);
2750#endif
6fe7ccc8 2751 default:
81345200 2752 failDueToUnexpectedToken();
6fe7ccc8
A
2753 }
2754}
2755
2756template <typename LexerType>
81345200 2757template <class TreeBuilder> TreeArguments Parser<LexerType>::parseArguments(TreeBuilder& context, SpreadMode mode)
6fe7ccc8 2758{
81345200 2759 consumeOrFailWithFlags(OPENPAREN, TreeBuilder::DontBuildStrings, "Expected opening '(' at start of argument list");
93a37866 2760 JSTokenLocation location(tokenLocation());
6fe7ccc8
A
2761 if (match(CLOSEPAREN)) {
2762 next(TreeBuilder::DontBuildStrings);
2763 return context.createArguments();
2764 }
81345200
A
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 }
6fe7ccc8 2783 TreeExpression firstArg = parseAssignmentExpression(context);
81345200 2784 failIfFalse(firstArg, "Cannot parse function argument");
6fe7ccc8 2785
93a37866 2786 TreeArgumentsList argList = context.createArgumentsList(location, firstArg);
6fe7ccc8
A
2787 TreeArgumentsList tail = argList;
2788 while (match(COMMA)) {
93a37866 2789 JSTokenLocation argumentLocation(tokenLocation());
6fe7ccc8
A
2790 next(TreeBuilder::DontBuildStrings);
2791 TreeExpression arg = parseAssignmentExpression(context);
81345200 2792 failIfFalse(arg, "Cannot parse function argument");
93a37866 2793 tail = context.createArgumentsList(argumentLocation, tail, arg);
6fe7ccc8 2794 }
81345200
A
2795 semanticFailIfTrue(match(DOTDOTDOT), "The '...' operator should come before the target expression");
2796 handleProductionOrFail(CLOSEPAREN, ")", "end", "argument list");
6fe7ccc8
A
2797 return context.createArguments(argList);
2798}
2799
2800template <typename LexerType>
2801template <class TreeBuilder> TreeExpression Parser<LexerType>::parseMemberExpression(TreeBuilder& context)
2802{
2803 TreeExpression base = 0;
81345200 2804 JSTextPosition expressionStart = tokenStartPosition();
6fe7ccc8 2805 int newCount = 0;
ed1e77d3 2806 JSTokenLocation startLocation = tokenLocation();
93a37866 2807 JSTokenLocation location;
6fe7ccc8
A
2808 while (match(NEW)) {
2809 next();
2810 newCount++;
2811 }
ed1e77d3
A
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);
6fe7ccc8 2822 next();
ed1e77d3 2823 currentScope()->setNeedsSuperBinding();
6fe7ccc8
A
2824 } else
2825 base = parsePrimaryExpression(context);
ed1e77d3 2826
81345200 2827 failIfFalse(base, "Cannot parse base expression");
6fe7ccc8 2828 while (true) {
93a37866 2829 location = tokenLocation();
6fe7ccc8
A
2830 switch (m_token.m_type) {
2831 case OPENBRACKET: {
2832 m_nonTrivialExpressionCount++;
81345200 2833 JSTextPosition expressionEnd = lastTokenEndPosition();
6fe7ccc8
A
2834 next();
2835 int nonLHSCount = m_nonLHSCount;
2836 int initialAssignments = m_assignmentCount;
2837 TreeExpression property = parseExpression(context);
81345200
A
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");
6fe7ccc8
A
2841 m_nonLHSCount = nonLHSCount;
2842 break;
2843 }
2844 case OPENPAREN: {
2845 m_nonTrivialExpressionCount++;
2846 int nonLHSCount = m_nonLHSCount;
2847 if (newCount) {
2848 newCount--;
81345200
A
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());
6fe7ccc8 2853 } else {
81345200
A
2854 JSTextPosition expressionEnd = lastTokenEndPosition();
2855 TreeArguments arguments = parseArguments(context, AllowSpread);
2856 failIfFalse(arguments, "Cannot parse call arguments");
ed1e77d3
A
2857 if (baseIsSuper)
2858 currentScope()->setHasDirectSuper();
2859 base = context.makeFunctionCallNode(startLocation, base, arguments, expressionStart, expressionEnd, lastTokenEndPosition());
6fe7ccc8
A
2860 }
2861 m_nonLHSCount = nonLHSCount;
2862 break;
2863 }
2864 case DOT: {
2865 m_nonTrivialExpressionCount++;
81345200 2866 JSTextPosition expressionEnd = lastTokenEndPosition();
6fe7ccc8 2867 nextExpectIdentifier(LexerFlagsIgnoreReservedWords | TreeBuilder::DontBuildKeywords);
81345200
A
2868 matchOrFail(IDENT, "Expected a property name after '.'");
2869 base = context.createDotAccess(location, base, m_token.m_data.ident, expressionStart, expressionEnd, tokenEndPosition());
6fe7ccc8
A
2870 next();
2871 break;
2872 }
ed1e77d3
A
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
6fe7ccc8
A
2885 default:
2886 goto endMemberExpression;
2887 }
ed1e77d3 2888 baseIsSuper = false;
6fe7ccc8
A
2889 }
2890endMemberExpression:
ed1e77d3 2891 semanticFailIfTrue(baseIsSuper, "Cannot reference super");
6fe7ccc8 2892 while (newCount--)
81345200 2893 base = context.createNewExpr(location, base, expressionStart, lastTokenEndPosition());
6fe7ccc8
A
2894 return base;
2895}
2896
ed1e77d3
A
2897#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
2898template <typename LexerType>
2899template <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
81345200
A
2913static 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
6fe7ccc8
A
2943template <typename LexerType>
2944template <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;
81345200 2951 unsigned lastOperator = 0;
6fe7ccc8
A
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:
81345200 2959 semanticFailIfTrue(requiresLExpr, "The ", operatorString(true, lastOperator), " operator requires a reference expression");
6fe7ccc8
A
2960 modifiesExpr = true;
2961 requiresLExpr = true;
2962 break;
2963 case DELETETOKEN:
81345200 2964 semanticFailIfTrue(requiresLExpr, "The ", operatorString(true, lastOperator), " operator requires a reference expression");
6fe7ccc8
A
2965 requiresLExpr = true;
2966 break;
2967 default:
81345200 2968 semanticFailIfTrue(requiresLExpr, "The ", operatorString(true, lastOperator), " operator requires a reference expression");
6fe7ccc8
A
2969 break;
2970 }
2971 }
81345200 2972 lastOperator = m_token.m_type;
6fe7ccc8 2973 m_nonLHSCount++;
81345200 2974 context.appendUnaryToken(tokenStackDepth, m_token.m_type, tokenStartPosition());
6fe7ccc8
A
2975 next();
2976 m_nonTrivialExpressionCount++;
2977 }
81345200
A
2978 JSTextPosition subExprStart = tokenStartPosition();
2979 ASSERT(subExprStart.offset >= subExprStart.lineStartOffset);
93a37866 2980 JSTokenLocation location(tokenLocation());
6fe7ccc8 2981 TreeExpression expr = parseMemberExpression(context);
81345200
A
2982 if (!expr) {
2983 if (lastOperator)
2984 failWithMessage("Cannot parse subexpression of ", operatorString(true, lastOperator), "operator");
2985 failWithMessage("Cannot parse member expression");
2986 }
6fe7ccc8
A
2987 bool isEvalOrArguments = false;
2988 if (strictMode() && !m_syntaxAlreadyValidated) {
2989 if (context.isResolve(expr))
93a37866 2990 isEvalOrArguments = *m_lastIdentifier == m_vm->propertyNames->eval || *m_lastIdentifier == m_vm->propertyNames->arguments;
6fe7ccc8 2991 }
81345200 2992 failIfTrueIfStrict(isEvalOrArguments && modifiesExpr, "Cannot modify '", m_lastIdentifier->impl(), "' in strict mode");
6fe7ccc8
A
2993 switch (m_token.m_type) {
2994 case PLUSPLUS:
2995 m_nonTrivialExpressionCount++;
2996 m_nonLHSCount++;
81345200 2997 expr = context.makePostfixNode(location, expr, OpPlusPlus, subExprStart, lastTokenEndPosition(), tokenEndPosition());
6fe7ccc8 2998 m_assignmentCount++;
81345200
A
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;
6fe7ccc8
A
3002 next();
3003 break;
3004 case MINUSMINUS:
3005 m_nonTrivialExpressionCount++;
3006 m_nonLHSCount++;
81345200 3007 expr = context.makePostfixNode(location, expr, OpMinusMinus, subExprStart, lastTokenEndPosition(), tokenEndPosition());
6fe7ccc8 3008 m_assignmentCount++;
81345200
A
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;
6fe7ccc8
A
3012 next();
3013 break;
3014 default:
3015 break;
3016 }
3017
81345200 3018 JSTextPosition end = lastTokenEndPosition();
93a37866 3019
6fe7ccc8
A
3020 if (!TreeBuilder::CreatesAST && (m_syntaxAlreadyValidated || !strictMode()))
3021 return expr;
93a37866
A
3022
3023 location = tokenLocation();
3024 location.line = m_lexer->lastLineNumber();
6fe7ccc8
A
3025 while (tokenStackDepth) {
3026 switch (context.unaryTokenStackLastType(tokenStackDepth)) {
3027 case EXCLAMATION:
93a37866 3028 expr = context.createLogicalNot(location, expr);
6fe7ccc8
A
3029 break;
3030 case TILDE:
93a37866 3031 expr = context.makeBitwiseNotNode(location, expr);
6fe7ccc8
A
3032 break;
3033 case MINUS:
93a37866 3034 expr = context.makeNegateNode(location, expr);
6fe7ccc8
A
3035 break;
3036 case PLUS:
93a37866 3037 expr = context.createUnaryPlus(location, expr);
6fe7ccc8
A
3038 break;
3039 case PLUSPLUS:
3040 case AUTOPLUSPLUS:
81345200 3041 expr = context.makePrefixNode(location, expr, OpPlusPlus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end);
6fe7ccc8
A
3042 m_assignmentCount++;
3043 break;
3044 case MINUSMINUS:
3045 case AUTOMINUSMINUS:
81345200 3046 expr = context.makePrefixNode(location, expr, OpMinusMinus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end);
6fe7ccc8
A
3047 m_assignmentCount++;
3048 break;
3049 case TYPEOF:
93a37866 3050 expr = context.makeTypeOfNode(location, expr);
6fe7ccc8
A
3051 break;
3052 case VOIDTOKEN:
93a37866 3053 expr = context.createVoid(location, expr);
6fe7ccc8
A
3054 break;
3055 case DELETETOKEN:
81345200
A
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);
6fe7ccc8
A
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
6fe7ccc8 3069
81345200
A
3070template <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;
ed1e77d3
A
3110 case INTEGER:
3111 case DOUBLE:
81345200
A
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
3144template class Parser<Lexer<LChar>>;
3145template class Parser<Lexer<UChar>>;
3146
9dae56ea 3147} // namespace JSC