1/* 2 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) 3 * Copyright (C) 2001 Peter Kelly (pmk@post.com) 4 * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc. All rights reserved. 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Library General Public 8 * License as published by the Free Software Foundation; either 9 * version 2 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Library General Public License for more details. 15 * 16 * You should have received a copy of the GNU Library General Public License 17 * along with this library; see the file COPYING.LIB. If not, write to 18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA. 20 * 21 */ 22 23#include "config.h" 24#include "Parser.h" 25 26#include "ASTBuilder.h" 27#include "CodeBlock.h" 28#include "Debugger.h" 29#include "JSCJSValueInlines.h" 30#include "Lexer.h" 31#include "NodeInfo.h" 32#include "JSCInlines.h" 33#include "SourceProvider.h" 34#include "VM.h" 35#include <utility> 36#include <wtf/HashFunctions.h> 37#include <wtf/OwnPtr.h> 38#include <wtf/StringPrintStream.h> 39#include <wtf/WTFThreadData.h> 40 41 42#define updateErrorMessage(shouldPrintToken, ...) do {\ 43 propagateError(); \ 44 logError(shouldPrintToken, __VA_ARGS__); \ 45} while (0) 46 47#define propagateError() do { if (hasError()) return 0; } while (0) 48#define internalFailWithMessage(shouldPrintToken, ...) do { updateErrorMessage(shouldPrintToken, __VA_ARGS__); return 0; } while (0) 49#define handleErrorToken() do { if (m_token.m_type == EOFTOK || m_token.m_type & ErrorTokenFlag) { failDueToUnexpectedToken(); } } while (0) 50#define failWithMessage(...) do { { handleErrorToken(); updateErrorMessage(true, __VA_ARGS__); } return 0; } while (0) 51#define failWithStackOverflow() do { updateErrorMessage(false, "Stack exhausted"); m_hasStackOverflow = true; return 0; } while (0) 52#define failIfFalse(cond, ...) do { if (!(cond)) { handleErrorToken(); internalFailWithMessage(true, __VA_ARGS__); } } while (0) 53#define failIfTrue(cond, ...) do { if (cond) { handleErrorToken(); internalFailWithMessage(true, __VA_ARGS__); } } while (0) 54#define failIfTrueIfStrict(cond, ...) do { if ((cond) && strictMode()) internalFailWithMessage(false, __VA_ARGS__); } while (0) 55#define failIfFalseIfStrict(cond, ...) do { if ((!(cond)) && strictMode()) internalFailWithMessage(false, __VA_ARGS__); } while (0) 56#define consumeOrFail(tokenType, ...) do { if (!consume(tokenType)) { handleErrorToken(); internalFailWithMessage(true, __VA_ARGS__); } } while (0) 57#define consumeOrFailWithFlags(tokenType, flags, ...) do { if (!consume(tokenType, flags)) { handleErrorToken(); internalFailWithMessage(true, __VA_ARGS__); } } while (0) 58#define matchOrFail(tokenType, ...) do { if (!match(tokenType)) { handleErrorToken(); internalFailWithMessage(true, __VA_ARGS__); } } while (0) 59#define failIfStackOverflow() do { if (!canRecurse()) failWithStackOverflow(); } while (0) 60#define semanticFail(...) do { internalFailWithMessage(false, __VA_ARGS__); } while (0) 61#define semanticFailIfTrue(cond, ...) do { if (cond) internalFailWithMessage(false, __VA_ARGS__); } while (0) 62#define semanticFailIfFalse(cond, ...) do { if (!(cond)) internalFailWithMessage(false, __VA_ARGS__); } while (0) 63#define regexFail(failure) do { setErrorMessage(failure); return 0; } while (0) 64#define failDueToUnexpectedToken() do {\ 65 logError(true);\ 66 return 0;\ 67} while (0) 68 69#define handleProductionOrFail(token, tokenString, operation, production) do {\ 70 consumeOrFail(token, "Expected '", tokenString, "' to ", operation, " a ", production);\ 71} while (0) 72 73#define semanticFailureDueToKeyword(...) do { \ 74 if (strictMode() && m_token.m_type == RESERVED_IF_STRICT) \ 75 semanticFail("Cannot use the reserved word '", getToken(), "' as a ", __VA_ARGS__, " in strict mode"); \ 76 if (m_token.m_type == RESERVED || m_token.m_type == RESERVED_IF_STRICT) \ 77 semanticFail("Cannot use the reserved word '", getToken(), "' as a ", __VA_ARGS__); \ 78 if (m_token.m_type & KeywordTokenFlag) \ 79 semanticFail("Cannot use the keyword '", getToken(), "' as a ", __VA_ARGS__); \ 80} while (0) 81 82using namespace std; 83 84namespace JSC { 85 86template <typename LexerType> 87void Parser<LexerType>::logError(bool) 88{ 89 if (hasError()) 90 return; 91 StringPrintStream stream; 92 printUnexpectedTokenText(stream); 93 setErrorMessage(stream.toString()); 94} 95 96template <typename LexerType> template <typename A> 97void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1) 98{ 99 if (hasError()) 100 return; 101 StringPrintStream stream; 102 if (shouldPrintToken) { 103 printUnexpectedTokenText(stream); 104 stream.print(". "); 105 } 106 stream.print(value1, "."); 107 setErrorMessage(stream.toString()); 108} 109 110template <typename LexerType> template <typename A, typename B> 111void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2) 112{ 113 if (hasError()) 114 return; 115 StringPrintStream stream; 116 if (shouldPrintToken) { 117 printUnexpectedTokenText(stream); 118 stream.print(". "); 119 } 120 stream.print(value1, value2, "."); 121 setErrorMessage(stream.toString()); 122} 123 124template <typename LexerType> template <typename A, typename B, typename C> 125void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2, const C& value3) 126{ 127 if (hasError()) 128 return; 129 StringPrintStream stream; 130 if (shouldPrintToken) { 131 printUnexpectedTokenText(stream); 132 stream.print(". "); 133 } 134 stream.print(value1, value2, value3, "."); 135 setErrorMessage(stream.toString()); 136} 137 138template <typename LexerType> template <typename A, typename B, typename C, typename D> 139void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2, const C& value3, const D& value4) 140{ 141 if (hasError()) 142 return; 143 StringPrintStream stream; 144 if (shouldPrintToken) { 145 printUnexpectedTokenText(stream); 146 stream.print(". "); 147 } 148 stream.print(value1, value2, value3, value4, "."); 149 setErrorMessage(stream.toString()); 150} 151 152template <typename LexerType> template <typename A, typename B, typename C, typename D, typename E> 153void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2, const C& value3, const D& value4, const E& value5) 154{ 155 if (hasError()) 156 return; 157 StringPrintStream stream; 158 if (shouldPrintToken) { 159 printUnexpectedTokenText(stream); 160 stream.print(". "); 161 } 162 stream.print(value1, value2, value3, value4, value5, "."); 163 setErrorMessage(stream.toString()); 164} 165 166template <typename LexerType> template <typename A, typename B, typename C, typename D, typename E, typename F> 167void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2, const C& value3, const D& value4, const E& value5, const F& value6) 168{ 169 if (hasError()) 170 return; 171 StringPrintStream stream; 172 if (shouldPrintToken) { 173 printUnexpectedTokenText(stream); 174 stream.print(". "); 175 } 176 stream.print(value1, value2, value3, value4, value5, value6, "."); 177 setErrorMessage(stream.toString()); 178} 179 180template <typename LexerType> template <typename A, typename B, typename C, typename D, typename E, typename F, typename G> 181void 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) 182{ 183 if (hasError()) 184 return; 185 StringPrintStream stream; 186 if (shouldPrintToken) { 187 printUnexpectedTokenText(stream); 188 stream.print(". "); 189 } 190 stream.print(value1, value2, value3, value4, value5, value6, value7, "."); 191 setErrorMessage(stream.toString()); 192} 193 194template <typename LexerType> 195Parser<LexerType>::Parser(VM* vm, const SourceCode& source, FunctionParameters* parameters, const Identifier& name, JSParserStrictness strictness, JSParserMode parserMode) 196 : m_vm(vm) 197 , m_source(&source) 198 , m_hasStackOverflow(false) 199 , m_allowsIn(true) 200 , m_assignmentCount(0) 201 , m_nonLHSCount(0) 202 , m_syntaxAlreadyValidated(source.provider()->isValid()) 203 , m_statementDepth(0) 204 , m_nonTrivialExpressionCount(0) 205 , m_lastIdentifier(0) 206 , m_lastFunctionName(nullptr) 207 , m_sourceElements(0) 208 , m_parsingBuiltin(strictness == JSParseBuiltin) 209{ 210 m_lexer = adoptPtr(new LexerType(vm, strictness)); 211 m_arena = m_vm->parserArena.get(); 212 m_lexer->setCode(source, m_arena); 213 m_token.m_location.line = source.firstLine(); 214 m_token.m_location.startOffset = source.startOffset(); 215 m_token.m_location.endOffset = source.startOffset(); 216 m_token.m_location.lineStartOffset = source.startOffset(); 217 m_functionCache = vm->addSourceProviderCache(source.provider()); 218 ScopeRef scope = pushScope(); 219 if (parserMode == JSParseFunctionCode) 220 scope->setIsFunction(); 221 if (strictness == JSParseStrict) 222 scope->setStrictMode(); 223 if (parameters) { 224 bool hadBindingParameters = false; 225 for (unsigned i = 0; i < parameters->size(); i++) { 226 auto parameter = parameters->at(i); 227 if (!parameter->isBindingNode()) { 228 hadBindingParameters = true; 229 continue; 230 } 231 scope->declareParameter(&static_cast<BindingNode*>(parameter)->boundProperty()); 232 } 233 if (hadBindingParameters) { 234 Vector<Identifier> boundParameterNames; 235 for (unsigned i = 0; i < parameters->size(); i++) { 236 auto parameter = parameters->at(i); 237 if (parameter->isBindingNode()) 238 continue; 239 parameter->collectBoundIdentifiers(boundParameterNames); 240 } 241 for (auto& boundParameterName : boundParameterNames) 242 scope->declareVariable(&boundParameterName); 243 } 244 } 245 if (!name.isNull()) 246 scope->declareCallee(&name); 247 next(); 248} 249 250template <typename LexerType> 251Parser<LexerType>::~Parser() 252{ 253} 254 255template <typename LexerType> 256String Parser<LexerType>::parseInner() 257{ 258 String parseError = String(); 259 260 ASTBuilder context(const_cast<VM*>(m_vm), const_cast<SourceCode*>(m_source)); 261 if (m_lexer->isReparsing()) 262 m_statementDepth--; 263 ScopeRef scope = currentScope(); 264 SourceElements* sourceElements = parseSourceElements(context, CheckForStrictMode); 265 if (!sourceElements || !consume(EOFTOK)) { 266 if (hasError()) 267 parseError = m_errorMessage; 268 else 269 parseError = ASCIILiteral("Parser error"); 270 } 271 272 IdentifierSet capturedVariables; 273 bool modifiedParameter = false; 274 scope->getCapturedVariables(capturedVariables, modifiedParameter); 275 276 CodeFeatures features = context.features(); 277 if (scope->strictMode()) 278 features |= StrictModeFeature; 279 if (scope->shadowsArguments()) 280 features |= ShadowsArgumentsFeature; 281 if (modifiedParameter) 282 features |= ModifiedParameterFeature; 283 284 Vector<RefPtr<StringImpl>> closedVariables; 285 if (m_parsingBuiltin) { 286 RELEASE_ASSERT(!capturedVariables.size()); 287 IdentifierSet usedVariables; 288 scope->getUsedVariables(usedVariables); 289 for (const auto& variable : usedVariables) { 290 if (scope->hasDeclaredVariable(Identifier(m_vm, variable.get()))) 291 continue; 292 293 if (scope->hasDeclaredParameter(Identifier(m_vm, variable.get()))) 294 continue; 295 closedVariables.append(variable); 296 } 297 } 298 didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), features, 299 context.numConstants(), capturedVariables, WTF::move(closedVariables)); 300 301 return parseError; 302} 303 304template <typename LexerType> 305void Parser<LexerType>::didFinishParsing(SourceElements* sourceElements, ParserArenaData<DeclarationStacks::VarStack>* varStack, 306 ParserArenaData<DeclarationStacks::FunctionStack>* funcStack, CodeFeatures features, int numConstants, IdentifierSet& capturedVars, const Vector<RefPtr<StringImpl>>&& closedVariables) 307{ 308 m_sourceElements = sourceElements; 309 m_varDeclarations = varStack; 310 m_funcDeclarations = funcStack; 311 m_capturedVariables.swap(capturedVars); 312 m_closedVariables = closedVariables; 313 m_features = features; 314 m_numConstants = numConstants; 315} 316 317template <typename LexerType> 318bool Parser<LexerType>::allowAutomaticSemicolon() 319{ 320 return match(CLOSEBRACE) || match(EOFTOK) || m_lexer->prevTerminator(); 321} 322 323template <typename LexerType> 324template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseSourceElements(TreeBuilder& context, SourceElementsMode mode) 325{ 326 const unsigned lengthOfUseStrictLiteral = 12; // "use strict".length 327 TreeSourceElements sourceElements = context.createSourceElements(); 328 bool seenNonDirective = false; 329 const Identifier* directive = 0; 330 unsigned directiveLiteralLength = 0; 331 auto savePoint = createSavePoint(); 332 bool hasSetStrict = false; 333 while (TreeStatement statement = parseStatement(context, directive, &directiveLiteralLength)) { 334 if (mode == CheckForStrictMode && !seenNonDirective) { 335 if (directive) { 336 // "use strict" must be the exact literal without escape sequences or line continuation. 337 if (!hasSetStrict && directiveLiteralLength == lengthOfUseStrictLiteral && m_vm->propertyNames->useStrictIdentifier == *directive) { 338 setStrictMode(); 339 hasSetStrict = true; 340 if (!isValidStrictMode()) { 341 if (m_lastFunctionName) { 342 if (m_vm->propertyNames->arguments == *m_lastFunctionName) 343 semanticFail("Cannot name a function 'arguments' in strict mode"); 344 if (m_vm->propertyNames->eval == *m_lastFunctionName) 345 semanticFail("Cannot name a function 'eval' in strict mode"); 346 } 347 if (hasDeclaredVariable(m_vm->propertyNames->arguments)) 348 semanticFail("Cannot declare a variable named 'arguments' in strict mode"); 349 if (hasDeclaredVariable(m_vm->propertyNames->eval)) 350 semanticFail("Cannot declare a variable named 'eval' in strict mode"); 351 semanticFailIfFalse(isValidStrictMode(), "Invalid parameters or function name in strict mode"); 352 } 353 restoreSavePoint(savePoint); 354 propagateError(); 355 continue; 356 } 357 } else 358 seenNonDirective = true; 359 } 360 context.appendStatement(sourceElements, statement); 361 } 362 363 propagateError(); 364 return sourceElements; 365} 366 367template <typename LexerType> 368template <class TreeBuilder> TreeStatement Parser<LexerType>::parseVarDeclaration(TreeBuilder& context) 369{ 370 ASSERT(match(VAR)); 371 JSTokenLocation location(tokenLocation()); 372 int start = tokenLine(); 373 int end = 0; 374 int scratch; 375 TreeDeconstructionPattern scratch1 = 0; 376 TreeExpression scratch2 = 0; 377 JSTextPosition scratch3; 378 TreeExpression varDecls = parseVarDeclarationList(context, scratch, scratch1, scratch2, scratch3, scratch3, scratch3); 379 propagateError(); 380 failIfFalse(autoSemiColon(), "Expected ';' after var declaration"); 381 382 return context.createVarStatement(location, varDecls, start, end); 383} 384 385template <typename LexerType> 386template <class TreeBuilder> TreeStatement Parser<LexerType>::parseConstDeclaration(TreeBuilder& context) 387{ 388 ASSERT(match(CONSTTOKEN)); 389 JSTokenLocation location(tokenLocation()); 390 int start = tokenLine(); 391 int end = 0; 392 TreeConstDeclList constDecls = parseConstDeclarationList(context); 393 propagateError(); 394 failIfFalse(autoSemiColon(), "Expected ';' after const declaration"); 395 396 return context.createConstStatement(location, constDecls, start, end); 397} 398 399template <typename LexerType> 400template <class TreeBuilder> TreeStatement Parser<LexerType>::parseDoWhileStatement(TreeBuilder& context) 401{ 402 ASSERT(match(DO)); 403 int startLine = tokenLine(); 404 next(); 405 const Identifier* unused = 0; 406 startLoop(); 407 TreeStatement statement = parseStatement(context, unused); 408 endLoop(); 409 failIfFalse(statement, "Expected a statement following 'do'"); 410 int endLine = tokenLine(); 411 JSTokenLocation location(tokenLocation()); 412 handleProductionOrFail(WHILE, "while", "end", "do-while loop"); 413 handleProductionOrFail(OPENPAREN, "(", "start", "do-while loop condition"); 414 semanticFailIfTrue(match(CLOSEPAREN), "Must provide an expression as a do-while loop condition"); 415 TreeExpression expr = parseExpression(context); 416 failIfFalse(expr, "Unable to parse do-while loop condition"); 417 handleProductionOrFail(CLOSEPAREN, ")", "end", "do-while loop condition"); 418 if (match(SEMICOLON)) 419 next(); // Always performs automatic semicolon insertion. 420 return context.createDoWhileStatement(location, statement, expr, startLine, endLine); 421} 422 423template <typename LexerType> 424template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWhileStatement(TreeBuilder& context) 425{ 426 ASSERT(match(WHILE)); 427 JSTokenLocation location(tokenLocation()); 428 int startLine = tokenLine(); 429 next(); 430 431 handleProductionOrFail(OPENPAREN, "(", "start", "while loop condition"); 432 semanticFailIfTrue(match(CLOSEPAREN), "Must provide an expression as a while loop condition"); 433 TreeExpression expr = parseExpression(context); 434 failIfFalse(expr, "Unable to parse while loop condition"); 435 int endLine = tokenLine(); 436 handleProductionOrFail(CLOSEPAREN, ")", "end", "while loop condition"); 437 438 const Identifier* unused = 0; 439 startLoop(); 440 TreeStatement statement = parseStatement(context, unused); 441 endLoop(); 442 failIfFalse(statement, "Expected a statement as the body of a while loop"); 443 return context.createWhileStatement(location, expr, statement, startLine, endLine); 444} 445 446template <typename LexerType> 447template <class TreeBuilder> TreeExpression Parser<LexerType>::parseVarDeclarationList(TreeBuilder& context, int& declarations, TreeDeconstructionPattern& lastPattern, TreeExpression& lastInitializer, JSTextPosition& identStart, JSTextPosition& initStart, JSTextPosition& initEnd) 448{ 449 TreeExpression varDecls = 0; 450 const Identifier* lastIdent; 451 do { 452 lastIdent = 0; 453 lastPattern = 0; 454 JSTokenLocation location(tokenLocation()); 455 next(); 456 TreeExpression node = 0; 457 declarations++; 458 bool hasInitializer = false; 459 if (match(IDENT)) { 460 JSTextPosition varStart = tokenStartPosition(); 461 identStart = varStart; 462 const Identifier* name = m_token.m_data.ident; 463 lastIdent = name; 464 next(); 465 hasInitializer = match(EQUAL); 466 failIfFalseIfStrict(declareVariable(name), "Cannot declare a variable named ", name->impl(), " in strict mode"); 467 context.addVar(name, (hasInitializer || (!m_allowsIn && (match(INTOKEN) || isofToken()))) ? DeclarationStacks::HasInitializer : 0); 468 if (hasInitializer) { 469 JSTextPosition varDivot = tokenStartPosition() + 1; 470 initStart = tokenStartPosition(); 471 next(TreeBuilder::DontBuildStrings); // consume '=' 472 TreeExpression initializer = parseAssignmentExpression(context); 473 initEnd = lastTokenEndPosition(); 474 lastInitializer = initializer; 475 failIfFalse(initializer, "Expected expression as the intializer for the variable '", name->impl(), "'"); 476 477 node = context.createAssignResolve(location, *name, initializer, varStart, varDivot, lastTokenEndPosition()); 478 } 479 } else { 480 lastIdent = 0; 481 auto pattern = parseDeconstructionPattern(context, DeconstructToVariables); 482 failIfFalse(pattern, "Cannot parse this deconstruction pattern"); 483 hasInitializer = match(EQUAL); 484 lastPattern = pattern; 485 if (hasInitializer) { 486 next(TreeBuilder::DontBuildStrings); // consume '=' 487 TreeExpression rhs = parseExpression(context); 488 node = context.createDeconstructingAssignment(location, pattern, rhs); 489 lastInitializer = rhs; 490 } 491 } 492 493 if (hasInitializer) { 494 if (!varDecls) 495 varDecls = node; 496 else 497 varDecls = context.combineCommaNodes(location, varDecls, node); 498 } 499 } while (match(COMMA)); 500 if (lastIdent) 501 lastPattern = createBindingPattern(context, DeconstructToVariables, *lastIdent, 0); 502 return varDecls; 503} 504 505template <typename LexerType> 506template <class TreeBuilder> TreeDeconstructionPattern Parser<LexerType>::createBindingPattern(TreeBuilder& context, DeconstructionKind kind, const Identifier& name, int depth) 507{ 508 ASSERT(!name.isEmpty()); 509 ASSERT(!name.isNull()); 510 511 ASSERT(name.impl()->isAtomic()); 512 if (depth) { 513 if (kind == DeconstructToVariables) 514 failIfFalseIfStrict(declareVariable(&name), "Cannot deconstruct to a variable named '", name.impl(), "' in strict mode"); 515 if (kind == DeconstructToParameters) { 516 auto bindingResult = declareBoundParameter(&name); 517 if (bindingResult == Scope::StrictBindingFailed && strictMode()) { 518 semanticFailIfTrue(m_vm->propertyNames->arguments == name || m_vm->propertyNames->eval == name, "Cannot deconstruct to a parameter name '", name.impl(), "' in strict mode"); 519 if (m_lastFunctionName && name == *m_lastFunctionName) 520 semanticFail("Cannot deconstruct to '", name.impl(), "' as it shadows the name of a strict mode function"); 521 semanticFailureDueToKeyword("bound parameter name"); 522 if (hasDeclaredParameter(name)) 523 semanticFail("Cannot deconstruct to '", name.impl(), "' as it has already been declared"); 524 semanticFail("Cannot bind to a parameter named '", name.impl(), "' in strict mode"); 525 } 526 if (bindingResult == Scope::BindingFailed) { 527 semanticFailureDueToKeyword("bound parameter name"); 528 if (hasDeclaredParameter(name)) 529 semanticFail("Cannot deconstruct to '", name.impl(), "' as it has already been declared"); 530 semanticFail("Cannot deconstruct to a parameter named '", name.impl(), "'"); 531 } 532 } 533 if (kind != DeconstructToExpressions) 534 context.addVar(&name, DeclarationStacks::HasInitializer); 535 536 } else { 537 if (kind == DeconstructToVariables) { 538 failIfFalseIfStrict(declareVariable(&name), "Cannot declare a variable named '", name.impl(), "' in strict mode"); 539 context.addVar(&name, DeclarationStacks::HasInitializer); 540 } 541 542 if (kind == DeconstructToParameters) { 543 bool declarationResult = declareParameter(&name); 544 if (!declarationResult && strictMode()) { 545 semanticFailIfTrue(m_vm->propertyNames->arguments == name || m_vm->propertyNames->eval == name, "Cannot deconstruct to a parameter name '", name.impl(), "' in strict mode"); 546 if (m_lastFunctionName && name == *m_lastFunctionName) 547 semanticFail("Cannot declare a parameter named '", name.impl(), "' as it shadows the name of a strict mode function"); 548 semanticFailureDueToKeyword("parameter name"); 549 if (hasDeclaredParameter(name)) 550 semanticFail("Cannot declare a parameter named '", name.impl(), "' in strict mode as it has already been declared"); 551 semanticFail("Cannot declare a parameter named '", name.impl(), "' in strict mode"); 552 } 553 } 554 } 555 return context.createBindingLocation(m_token.m_location, name, m_token.m_startPosition, m_token.m_endPosition); 556} 557 558template <typename LexerType> 559template <class TreeBuilder> TreeDeconstructionPattern Parser<LexerType>::tryParseDeconstructionPatternExpression(TreeBuilder& context) 560{ 561 return parseDeconstructionPattern(context, DeconstructToExpressions); 562} 563 564template <typename LexerType> 565template <class TreeBuilder> TreeDeconstructionPattern Parser<LexerType>::parseDeconstructionPattern(TreeBuilder& context, DeconstructionKind kind, int depth) 566{ 567 failIfStackOverflow(); 568 int nonLHSCount = m_nonLHSCount; 569 TreeDeconstructionPattern pattern; 570 switch (m_token.m_type) { 571 case OPENBRACKET: { 572 auto arrayPattern = context.createArrayPattern(m_token.m_location); 573 next(); 574 if (kind == DeconstructToExpressions && match(CLOSEBRACKET)) 575 return 0; 576 failIfTrue(match(CLOSEBRACKET), "There must be at least one bound property in an array deconstruction pattern"); 577 do { 578 while (match(COMMA)) { 579 context.appendArrayPatternSkipEntry(arrayPattern, m_token.m_location); 580 next(); 581 } 582 propagateError(); 583 JSTokenLocation location = m_token.m_location; 584 auto innerPattern = parseDeconstructionPattern(context, kind, depth + 1); 585 if (kind == DeconstructToExpressions && !innerPattern) 586 return 0; 587 failIfFalse(innerPattern, "Cannot parse this deconstruction pattern"); 588 context.appendArrayPatternEntry(arrayPattern, location, innerPattern); 589 } while (consume(COMMA)); 590 591 if (kind == DeconstructToExpressions && !match(CLOSEBRACKET)) 592 return 0; 593 594 consumeOrFail(CLOSEBRACKET, "Expected either a closing ']' or a ',' following an element deconstruction pattern"); 595 pattern = arrayPattern; 596 break; 597 } 598 case OPENBRACE: { 599 next(); 600 601 if (kind == DeconstructToExpressions && match(CLOSEBRACE)) 602 return 0; 603 604 failIfTrue(match(CLOSEBRACE), "There must be at least one bound property in an object deconstruction pattern"); 605 auto objectPattern = context.createObjectPattern(m_token.m_location); 606 bool wasString = false; 607 do { 608 Identifier propertyName; 609 TreeDeconstructionPattern innerPattern = 0; 610 JSTokenLocation location = m_token.m_location; 611 if (match(IDENT)) { 612 propertyName = *m_token.m_data.ident; 613 next(); 614 if (consume(COLON)) 615 innerPattern = parseDeconstructionPattern(context, kind, depth + 1); 616 else 617 innerPattern = createBindingPattern(context, kind, propertyName, depth); 618 } else { 619 JSTokenType tokenType = m_token.m_type; 620 switch (m_token.m_type) { 621 case NUMBER: 622 propertyName = Identifier::from(m_vm, m_token.m_data.doubleValue); 623 break; 624 case STRING: 625 propertyName = *m_token.m_data.ident; 626 wasString = true; 627 break; 628 default: 629 if (m_token.m_type != RESERVED && m_token.m_type != RESERVED_IF_STRICT && !(m_token.m_type & KeywordTokenFlag)) { 630 if (kind == DeconstructToExpressions) 631 return 0; 632 failWithMessage("Expected a property name"); 633 } 634 propertyName = *m_token.m_data.ident; 635 break; 636 } 637 next(); 638 if (!consume(COLON)) { 639 if (kind == DeconstructToExpressions) 640 return 0; 641 semanticFailIfTrue(tokenType == RESERVED, "Cannot use abbreviated deconstruction syntax for reserved name '", propertyName.impl(), "'"); 642 semanticFailIfTrue(tokenType == RESERVED_IF_STRICT, "Cannot use abbreviated deconstruction syntax for reserved name '", propertyName.impl(), "' in strict mode"); 643 semanticFailIfTrue(tokenType & KeywordTokenFlag, "Cannot use abbreviated deconstruction syntax for keyword '", propertyName.impl(), "'"); 644 645 failWithMessage("Expected a ':' prior to named property deconstruction"); 646 } 647 innerPattern = parseDeconstructionPattern(context, kind, depth + 1); 648 } 649 if (kind == DeconstructToExpressions && !innerPattern) 650 return 0; 651 failIfFalse(innerPattern, "Cannot parse this deconstruction pattern"); 652 context.appendObjectPatternEntry(objectPattern, location, wasString, propertyName, innerPattern); 653 } while (consume(COMMA)); 654 if (kind == DeconstructToExpressions && !match(CLOSEBRACE)) 655 return 0; 656 consumeOrFail(CLOSEBRACE, "Expected either a closing '}' or an ',' after a property deconstruction pattern"); 657 pattern = objectPattern; 658 break; 659 } 660 661 default: { 662 if (!match(IDENT)) { 663 if (kind == DeconstructToExpressions) 664 return 0; 665 semanticFailureDueToKeyword("variable name"); 666 failWithMessage("Expected a parameter pattern or a ')' in parameter list"); 667 } 668 pattern = createBindingPattern(context, kind, *m_token.m_data.ident, depth); 669 next(); 670 break; 671 } 672 } 673 m_nonLHSCount = nonLHSCount; 674 return pattern; 675} 676 677template <typename LexerType> 678template <class TreeBuilder> TreeConstDeclList Parser<LexerType>::parseConstDeclarationList(TreeBuilder& context) 679{ 680 failIfTrue(strictMode(), "Const declarations are not supported in strict mode"); 681 TreeConstDeclList constDecls = 0; 682 TreeConstDeclList tail = 0; 683 do { 684 JSTokenLocation location(tokenLocation()); 685 next(); 686 matchOrFail(IDENT, "Expected an identifier name in const declaration"); 687 const Identifier* name = m_token.m_data.ident; 688 next(); 689 bool hasInitializer = match(EQUAL); 690 declareVariable(name); 691 context.addVar(name, DeclarationStacks::IsConstant | (hasInitializer ? DeclarationStacks::HasInitializer : 0)); 692 693 TreeExpression initializer = 0; 694 if (hasInitializer) { 695 next(TreeBuilder::DontBuildStrings); // consume '=' 696 initializer = parseAssignmentExpression(context); 697 failIfFalse(!!initializer, "Unable to parse initializer"); 698 } 699 tail = context.appendConstDecl(location, tail, name, initializer); 700 if (!constDecls) 701 constDecls = tail; 702 } while (match(COMMA)); 703 return constDecls; 704} 705 706template <typename LexerType> 707template <class TreeBuilder> TreeStatement Parser<LexerType>::parseForStatement(TreeBuilder& context) 708{ 709 ASSERT(match(FOR)); 710 JSTokenLocation location(tokenLocation()); 711 int startLine = tokenLine(); 712 next(); 713 handleProductionOrFail(OPENPAREN, "(", "start", "for-loop header"); 714 int nonLHSCount = m_nonLHSCount; 715 int declarations = 0; 716 JSTextPosition declsStart; 717 JSTextPosition declsEnd; 718 TreeExpression decls = 0; 719 TreeDeconstructionPattern pattern = 0; 720 if (match(VAR)) { 721 /* 722 for (var IDENT in expression) statement 723 for (var varDeclarationList; expressionOpt; expressionOpt) 724 */ 725 TreeDeconstructionPattern forInTarget = 0; 726 TreeExpression forInInitializer = 0; 727 m_allowsIn = false; 728 JSTextPosition initStart; 729 JSTextPosition initEnd; 730 decls = parseVarDeclarationList(context, declarations, forInTarget, forInInitializer, declsStart, initStart, initEnd); 731 m_allowsIn = true; 732 propagateError(); 733 734 // Remainder of a standard for loop is handled identically 735 if (match(SEMICOLON)) 736 goto standardForLoop; 737 738 failIfFalse(declarations == 1, "can only declare a single variable in an enumeration"); 739 failIfTrueIfStrict(forInInitializer, "Cannot use initialiser syntax in a strict mode enumeration"); 740 741 if (forInInitializer) 742 failIfFalse(context.isBindingNode(forInTarget), "Cannot use initialiser syntax when binding to a pattern during enumeration"); 743 744 // Handle for-in with var declaration 745 JSTextPosition inLocation = tokenStartPosition(); 746 bool isOfEnumeration = false; 747 if (!consume(INTOKEN)) { 748 failIfFalse(match(IDENT) && *m_token.m_data.ident == m_vm->propertyNames->of, "Expected either 'in' or 'of' in enumeration syntax"); 749 isOfEnumeration = true; 750 failIfTrue(forInInitializer, "Cannot use initialiser syntax in a for-of enumeration"); 751 next(); 752 } 753 TreeExpression expr = parseExpression(context); 754 failIfFalse(expr, "Expected expression to enumerate"); 755 JSTextPosition exprEnd = lastTokenEndPosition(); 756 757 int endLine = tokenLine(); 758 759 handleProductionOrFail(CLOSEPAREN, ")", "end", (isOfEnumeration ? "for-of header" : "for-in header")); 760 761 const Identifier* unused = 0; 762 startLoop(); 763 TreeStatement statement = parseStatement(context, unused); 764 endLoop(); 765 failIfFalse(statement, "Expected statement as body of for-", isOfEnumeration ? "of" : "in", " statement"); 766 if (isOfEnumeration) 767 return context.createForOfLoop(location, forInTarget, expr, statement, declsStart, inLocation, exprEnd, startLine, endLine); 768 return context.createForInLoop(location, forInTarget, expr, statement, declsStart, inLocation, exprEnd, startLine, endLine); 769 } 770 771 if (!match(SEMICOLON)) { 772 if (match(OPENBRACE) || match(OPENBRACKET)) { 773 SavePoint savePoint = createSavePoint(); 774 declsStart = tokenStartPosition(); 775 pattern = tryParseDeconstructionPatternExpression(context); 776 declsEnd = lastTokenEndPosition(); 777 if (pattern && (match(INTOKEN) || (match(IDENT) && *m_token.m_data.ident == m_vm->propertyNames->of))) 778 goto enumerationLoop; 779 pattern = 0; 780 restoreSavePoint(savePoint); 781 } 782 m_allowsIn = false; 783 declsStart = tokenStartPosition(); 784 decls = parseExpression(context); 785 declsEnd = lastTokenEndPosition(); 786 m_allowsIn = true; 787 failIfFalse(decls, "Cannot parse for loop declarations"); 788 } 789 790 if (match(SEMICOLON)) { 791 standardForLoop: 792 // Standard for loop 793 next(); 794 TreeExpression condition = 0; 795 796 if (!match(SEMICOLON)) { 797 condition = parseExpression(context); 798 failIfFalse(condition, "Cannot parse for loop condition expression"); 799 } 800 consumeOrFail(SEMICOLON, "Expected a ';' after the for loop condition expression"); 801 802 TreeExpression increment = 0; 803 if (!match(CLOSEPAREN)) { 804 increment = parseExpression(context); 805 failIfFalse(increment, "Cannot parse for loop iteration expression"); 806 } 807 int endLine = tokenLine(); 808 handleProductionOrFail(CLOSEPAREN, ")", "end", "for-loop header"); 809 const Identifier* unused = 0; 810 startLoop(); 811 TreeStatement statement = parseStatement(context, unused); 812 endLoop(); 813 failIfFalse(statement, "Expected a statement as the body of a for loop"); 814 return context.createForLoop(location, decls, condition, increment, statement, startLine, endLine); 815 } 816 817 // For-in loop 818enumerationLoop: 819 failIfFalse(nonLHSCount == m_nonLHSCount, "Expected a reference on the left hand side of an enumeration statement"); 820 bool isOfEnumeration = false; 821 if (!consume(INTOKEN)) { 822 failIfFalse(match(IDENT) && *m_token.m_data.ident == m_vm->propertyNames->of, "Expected either 'in' or 'of' in enumeration syntax"); 823 isOfEnumeration = true; 824 next(); 825 } 826 TreeExpression expr = parseExpression(context); 827 failIfFalse(expr, "Cannot parse subject for-", isOfEnumeration ? "of" : "in", " statement"); 828 JSTextPosition exprEnd = lastTokenEndPosition(); 829 int endLine = tokenLine(); 830 831 handleProductionOrFail(CLOSEPAREN, ")", "end", (isOfEnumeration ? "for-of header" : "for-in header")); 832 const Identifier* unused = 0; 833 startLoop(); 834 TreeStatement statement = parseStatement(context, unused); 835 endLoop(); 836 failIfFalse(statement, "Expected a statement as the body of a for-", isOfEnumeration ? "of" : "in", "loop"); 837 if (pattern) { 838 ASSERT(!decls); 839 if (isOfEnumeration) 840 return context.createForOfLoop(location, pattern, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine); 841 return context.createForInLoop(location, pattern, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine); 842 } 843 if (isOfEnumeration) 844 return context.createForOfLoop(location, decls, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine); 845 return context.createForInLoop(location, decls, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine); 846} 847 848template <typename LexerType> 849template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBreakStatement(TreeBuilder& context) 850{ 851 ASSERT(match(BREAK)); 852 JSTokenLocation location(tokenLocation()); 853 JSTextPosition start = tokenStartPosition(); 854 JSTextPosition end = tokenEndPosition(); 855 next(); 856 857 if (autoSemiColon()) { 858 semanticFailIfFalse(breakIsValid(), "'break' is only valid inside a switch or loop statement"); 859 return context.createBreakStatement(location, start, end); 860 } 861 matchOrFail(IDENT, "Expected an identifier as the target for a break statement"); 862 const Identifier* ident = m_token.m_data.ident; 863 semanticFailIfFalse(getLabel(ident), "Cannot use the undeclared label '", ident->impl(), "'"); 864 end = tokenEndPosition(); 865 next(); 866 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted break statement"); 867 return context.createBreakStatement(location, ident, start, end); 868} 869 870template <typename LexerType> 871template <class TreeBuilder> TreeStatement Parser<LexerType>::parseContinueStatement(TreeBuilder& context) 872{ 873 ASSERT(match(CONTINUE)); 874 JSTokenLocation location(tokenLocation()); 875 JSTextPosition start = tokenStartPosition(); 876 JSTextPosition end = tokenEndPosition(); 877 next(); 878 879 if (autoSemiColon()) { 880 semanticFailIfFalse(continueIsValid(), "'continue' is only valid inside a loop statement"); 881 return context.createContinueStatement(location, start, end); 882 } 883 matchOrFail(IDENT, "Expected an identifier as the target for a continue statement"); 884 const Identifier* ident = m_token.m_data.ident; 885 ScopeLabelInfo* label = getLabel(ident); 886 semanticFailIfFalse(label, "Cannot use the undeclared label '", ident->impl(), "'"); 887 semanticFailIfFalse(label->m_isLoop, "Cannot continue to the label '", ident->impl(), "' as it is not targeting a loop"); 888 end = tokenEndPosition(); 889 next(); 890 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted continue statement"); 891 return context.createContinueStatement(location, ident, start, end); 892} 893 894template <typename LexerType> 895template <class TreeBuilder> TreeStatement Parser<LexerType>::parseReturnStatement(TreeBuilder& context) 896{ 897 ASSERT(match(RETURN)); 898 JSTokenLocation location(tokenLocation()); 899 semanticFailIfFalse(currentScope()->isFunction(), "Return statements are only valid inside functions"); 900 JSTextPosition start = tokenStartPosition(); 901 JSTextPosition end = tokenEndPosition(); 902 next(); 903 // We do the auto semicolon check before attempting to parse expression 904 // as we need to ensure the a line break after the return correctly terminates 905 // the statement 906 if (match(SEMICOLON)) 907 end = tokenEndPosition(); 908 909 if (autoSemiColon()) 910 return context.createReturnStatement(location, 0, start, end); 911 TreeExpression expr = parseExpression(context); 912 failIfFalse(expr, "Cannot parse the return expression"); 913 end = lastTokenEndPosition(); 914 if (match(SEMICOLON)) 915 end = tokenEndPosition(); 916 if (!autoSemiColon()) 917 failWithMessage("Expected a ';' following a return statement"); 918 return context.createReturnStatement(location, expr, start, end); 919} 920 921template <typename LexerType> 922template <class TreeBuilder> TreeStatement Parser<LexerType>::parseThrowStatement(TreeBuilder& context) 923{ 924 ASSERT(match(THROW)); 925 JSTokenLocation location(tokenLocation()); 926 JSTextPosition start = tokenStartPosition(); 927 next(); 928 failIfTrue(match(SEMICOLON), "Expected expression after 'throw'"); 929 semanticFailIfTrue(autoSemiColon(), "Cannot have a newline after 'throw'"); 930 931 TreeExpression expr = parseExpression(context); 932 failIfFalse(expr, "Cannot parse expression for throw statement"); 933 JSTextPosition end = lastTokenEndPosition(); 934 failIfFalse(autoSemiColon(), "Expected a ';' after a throw statement"); 935 936 return context.createThrowStatement(location, expr, start, end); 937} 938 939template <typename LexerType> 940template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWithStatement(TreeBuilder& context) 941{ 942 ASSERT(match(WITH)); 943 JSTokenLocation location(tokenLocation()); 944 semanticFailIfTrue(strictMode(), "'with' statements are not valid in strict mode"); 945 currentScope()->setNeedsFullActivation(); 946 int startLine = tokenLine(); 947 next(); 948 949 handleProductionOrFail(OPENPAREN, "(", "start", "subject of a 'with' statement"); 950 int start = tokenStart(); 951 TreeExpression expr = parseExpression(context); 952 failIfFalse(expr, "Cannot parse 'with' subject expression"); 953 JSTextPosition end = lastTokenEndPosition(); 954 int endLine = tokenLine(); 955 handleProductionOrFail(CLOSEPAREN, ")", "start", "subject of a 'with' statement"); 956 const Identifier* unused = 0; 957 TreeStatement statement = parseStatement(context, unused); 958 failIfFalse(statement, "A 'with' statement must have a body"); 959 960 return context.createWithStatement(location, expr, statement, start, end, startLine, endLine); 961} 962 963template <typename LexerType> 964template <class TreeBuilder> TreeStatement Parser<LexerType>::parseSwitchStatement(TreeBuilder& context) 965{ 966 ASSERT(match(SWITCH)); 967 JSTokenLocation location(tokenLocation()); 968 int startLine = tokenLine(); 969 next(); 970 handleProductionOrFail(OPENPAREN, "(", "start", "subject of a 'switch'"); 971 TreeExpression expr = parseExpression(context); 972 failIfFalse(expr, "Cannot parse switch subject expression"); 973 int endLine = tokenLine(); 974 975 handleProductionOrFail(CLOSEPAREN, ")", "end", "subject of a 'switch'"); 976 handleProductionOrFail(OPENBRACE, "{", "start", "body of a 'switch'"); 977 startSwitch(); 978 TreeClauseList firstClauses = parseSwitchClauses(context); 979 propagateError(); 980 981 TreeClause defaultClause = parseSwitchDefaultClause(context); 982 propagateError(); 983 984 TreeClauseList secondClauses = parseSwitchClauses(context); 985 propagateError(); 986 endSwitch(); 987 handleProductionOrFail(CLOSEBRACE, "}", "end", "body of a 'switch'"); 988 989 return context.createSwitchStatement(location, expr, firstClauses, defaultClause, secondClauses, startLine, endLine); 990 991} 992 993template <typename LexerType> 994template <class TreeBuilder> TreeClauseList Parser<LexerType>::parseSwitchClauses(TreeBuilder& context) 995{ 996 if (!match(CASE)) 997 return 0; 998 next(); 999 TreeExpression condition = parseExpression(context); 1000 failIfFalse(condition, "Cannot parse switch clause"); 1001 consumeOrFail(COLON, "Expected a ':' after switch clause expression"); 1002 TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode); 1003 failIfFalse(statements, "Cannot parse the body of a switch clause"); 1004 TreeClause clause = context.createClause(condition, statements); 1005 TreeClauseList clauseList = context.createClauseList(clause); 1006 TreeClauseList tail = clauseList; 1007 1008 while (match(CASE)) { 1009 next(); 1010 TreeExpression condition = parseExpression(context); 1011 failIfFalse(condition, "Cannot parse switch case expression"); 1012 consumeOrFail(COLON, "Expected a ':' after switch clause expression"); 1013 TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode); 1014 failIfFalse(statements, "Cannot parse the body of a switch clause"); 1015 clause = context.createClause(condition, statements); 1016 tail = context.createClauseList(tail, clause); 1017 } 1018 return clauseList; 1019} 1020 1021template <typename LexerType> 1022template <class TreeBuilder> TreeClause Parser<LexerType>::parseSwitchDefaultClause(TreeBuilder& context) 1023{ 1024 if (!match(DEFAULT)) 1025 return 0; 1026 next(); 1027 consumeOrFail(COLON, "Expected a ':' after switch default clause"); 1028 TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode); 1029 failIfFalse(statements, "Cannot parse the body of a switch default clause"); 1030 return context.createClause(0, statements); 1031} 1032 1033template <typename LexerType> 1034template <class TreeBuilder> TreeStatement Parser<LexerType>::parseTryStatement(TreeBuilder& context) 1035{ 1036 ASSERT(match(TRY)); 1037 JSTokenLocation location(tokenLocation()); 1038 TreeStatement tryBlock = 0; 1039 const Identifier* ident = &m_vm->propertyNames->nullIdentifier; 1040 TreeStatement catchBlock = 0; 1041 TreeStatement finallyBlock = 0; 1042 int firstLine = tokenLine(); 1043 next(); 1044 matchOrFail(OPENBRACE, "Expected a block statement as body of a try statement"); 1045 1046 tryBlock = parseBlockStatement(context); 1047 failIfFalse(tryBlock, "Cannot parse the body of try block"); 1048 int lastLine = m_lastTokenEndPosition.line; 1049 1050 if (match(CATCH)) { 1051 currentScope()->setNeedsFullActivation(); 1052 next(); 1053 1054 handleProductionOrFail(OPENPAREN, "(", "start", "'catch' target"); 1055 if (!match(IDENT)) { 1056 semanticFailureDueToKeyword("catch variable name"); 1057 failWithMessage("Expected identifier name as catch target"); 1058 } 1059 ident = m_token.m_data.ident; 1060 next(); 1061 AutoPopScopeRef catchScope(this, pushScope()); 1062 failIfFalseIfStrict(declareVariable(ident), "Cannot declare a catch variable named '", ident->impl(), "' in strict mode"); 1063 catchScope->preventNewDecls(); 1064 handleProductionOrFail(CLOSEPAREN, ")", "end", "'catch' target"); 1065 matchOrFail(OPENBRACE, "Expected exception handler to be a block statement"); 1066 catchBlock = parseBlockStatement(context); 1067 failIfFalse(catchBlock, "Unable to parse 'catch' block"); 1068 failIfFalse(popScope(catchScope, TreeBuilder::NeedsFreeVariableInfo), "Parse error"); 1069 } 1070 1071 if (match(FINALLY)) { 1072 next(); 1073 matchOrFail(OPENBRACE, "Expected block statement for finally body"); 1074 finallyBlock = parseBlockStatement(context); 1075 failIfFalse(finallyBlock, "Cannot parse finally body"); 1076 } 1077 failIfFalse(catchBlock || finallyBlock, "Try statements must have at least a catch or finally block"); 1078 return context.createTryStatement(location, tryBlock, ident, catchBlock, finallyBlock, firstLine, lastLine); 1079} 1080 1081template <typename LexerType> 1082template <class TreeBuilder> TreeStatement Parser<LexerType>::parseDebuggerStatement(TreeBuilder& context) 1083{ 1084 ASSERT(match(DEBUGGER)); 1085 JSTokenLocation location(tokenLocation()); 1086 int startLine = tokenLine(); 1087 int endLine = startLine; 1088 next(); 1089 if (match(SEMICOLON)) 1090 startLine = tokenLine(); 1091 failIfFalse(autoSemiColon(), "Debugger keyword must be followed by a ';'"); 1092 return context.createDebugger(location, startLine, endLine); 1093} 1094 1095template <typename LexerType> 1096template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBlockStatement(TreeBuilder& context) 1097{ 1098 ASSERT(match(OPENBRACE)); 1099 JSTokenLocation location(tokenLocation()); 1100 int start = tokenLine(); 1101 next(); 1102 if (match(CLOSEBRACE)) { 1103 next(); 1104 return context.createBlockStatement(location, 0, start, m_lastTokenEndPosition.line); 1105 } 1106 TreeSourceElements subtree = parseSourceElements(context, DontCheckForStrictMode); 1107 failIfFalse(subtree, "Cannot parse the body of the block statement"); 1108 matchOrFail(CLOSEBRACE, "Expected a closing '}' at the end of a block statement"); 1109 next(); 1110 return context.createBlockStatement(location, subtree, start, m_lastTokenEndPosition.line); 1111} 1112 1113template <typename LexerType> 1114template <class TreeBuilder> TreeStatement Parser<LexerType>::parseStatement(TreeBuilder& context, const Identifier*& directive, unsigned* directiveLiteralLength) 1115{ 1116 DepthManager statementDepth(&m_statementDepth); 1117 m_statementDepth++; 1118 directive = 0; 1119 int nonTrivialExpressionCount = 0; 1120 failIfStackOverflow(); 1121 switch (m_token.m_type) { 1122 case OPENBRACE: 1123 return parseBlockStatement(context); 1124 case VAR: 1125 return parseVarDeclaration(context); 1126 case CONSTTOKEN: 1127 return parseConstDeclaration(context); 1128 case FUNCTION: 1129 failIfFalseIfStrict(m_statementDepth == 1, "Strict mode does not allow function declarations in a lexically nested statement"); 1130 return parseFunctionDeclaration(context); 1131 case SEMICOLON: { 1132 JSTokenLocation location(tokenLocation()); 1133 next(); 1134 return context.createEmptyStatement(location); 1135 } 1136 case IF: 1137 return parseIfStatement(context); 1138 case DO: 1139 return parseDoWhileStatement(context); 1140 case WHILE: 1141 return parseWhileStatement(context); 1142 case FOR: 1143 return parseForStatement(context); 1144 case CONTINUE: 1145 return parseContinueStatement(context); 1146 case BREAK: 1147 return parseBreakStatement(context); 1148 case RETURN: 1149 return parseReturnStatement(context); 1150 case WITH: 1151 return parseWithStatement(context); 1152 case SWITCH: 1153 return parseSwitchStatement(context); 1154 case THROW: 1155 return parseThrowStatement(context); 1156 case TRY: 1157 return parseTryStatement(context); 1158 case DEBUGGER: 1159 return parseDebuggerStatement(context); 1160 case EOFTOK: 1161 case CASE: 1162 case CLOSEBRACE: 1163 case DEFAULT: 1164 // These tokens imply the end of a set of source elements 1165 return 0; 1166 case IDENT: 1167 return parseExpressionOrLabelStatement(context); 1168 case STRING: 1169 directive = m_token.m_data.ident; 1170 if (directiveLiteralLength) 1171 *directiveLiteralLength = m_token.m_location.endOffset - m_token.m_location.startOffset; 1172 nonTrivialExpressionCount = m_nonTrivialExpressionCount; 1173 FALLTHROUGH; 1174 default: 1175 TreeStatement exprStatement = parseExpressionStatement(context); 1176 if (directive && nonTrivialExpressionCount != m_nonTrivialExpressionCount) 1177 directive = 0; 1178 return exprStatement; 1179 } 1180} 1181 1182template <typename LexerType> 1183template <class TreeBuilder> TreeFormalParameterList Parser<LexerType>::parseFormalParameters(TreeBuilder& context) 1184{ 1185 auto parameter = parseDeconstructionPattern(context, DeconstructToParameters); 1186 failIfFalse(parameter, "Cannot parse parameter pattern"); 1187 TreeFormalParameterList list = context.createFormalParameterList(parameter); 1188 TreeFormalParameterList tail = list; 1189 while (consume(COMMA)) { 1190 parameter = parseDeconstructionPattern(context, DeconstructToParameters); 1191 failIfFalse(parameter, "Cannot parse parameter pattern"); 1192 tail = context.createFormalParameterList(tail, parameter); 1193 } 1194 return list; 1195} 1196 1197template <typename LexerType> 1198template <class TreeBuilder> TreeFunctionBody Parser<LexerType>::parseFunctionBody(TreeBuilder& context) 1199{ 1200 JSTokenLocation startLocation(tokenLocation()); 1201 unsigned startColumn = tokenColumn(); 1202 next(); 1203 1204 if (match(CLOSEBRACE)) { 1205 unsigned endColumn = tokenColumn(); 1206 return context.createFunctionBody(startLocation, tokenLocation(), startColumn, endColumn, strictMode()); 1207 } 1208 DepthManager statementDepth(&m_statementDepth); 1209 m_statementDepth = 0; 1210 typename TreeBuilder::FunctionBodyBuilder bodyBuilder(const_cast<VM*>(m_vm), m_lexer.get()); 1211 failIfFalse(parseSourceElements(bodyBuilder, CheckForStrictMode), "Cannot parse body of this function"); 1212 unsigned endColumn = tokenColumn(); 1213 return context.createFunctionBody(startLocation, tokenLocation(), startColumn, endColumn, strictMode()); 1214} 1215 1216static const char* stringForFunctionMode(FunctionParseMode mode) 1217{ 1218 switch (mode) { 1219 case GetterMode: 1220 return "getter"; 1221 case SetterMode: 1222 return "setter"; 1223 case FunctionMode: 1224 return "function"; 1225 } 1226 RELEASE_ASSERT_NOT_REACHED(); 1227 return nullptr; 1228} 1229 1230template <typename LexerType> 1231template <class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuilder& context, FunctionRequirements requirements, FunctionParseMode mode, bool nameIsInContainingScope, const Identifier*& name, TreeFormalParameterList& parameters, TreeFunctionBody& body, unsigned& openBraceOffset, unsigned& closeBraceOffset, int& bodyStartLine, unsigned& bodyStartColumn) 1232{ 1233 AutoPopScopeRef functionScope(this, pushScope()); 1234 functionScope->setIsFunction(); 1235 int functionNameStart = m_token.m_location.startOffset; 1236 const Identifier* lastFunctionName = m_lastFunctionName; 1237 m_lastFunctionName = nullptr; 1238 if (match(IDENT)) { 1239 name = m_token.m_data.ident; 1240 m_lastFunctionName = name; 1241 next(); 1242 if (!nameIsInContainingScope) 1243 failIfFalseIfStrict(functionScope->declareVariable(name), "'", name->impl(), "' is not a valid ", stringForFunctionMode(mode), " name in strict mode"); 1244 } else if (requirements == FunctionNeedsName) { 1245 if (match(OPENPAREN) && mode == FunctionMode) 1246 semanticFail("Function statements must have a name"); 1247 semanticFailureDueToKeyword(stringForFunctionMode(mode), " name"); 1248 failDueToUnexpectedToken(); 1249 return false; 1250 } 1251 if (!consume(OPENPAREN)) { 1252 semanticFailureDueToKeyword(stringForFunctionMode(mode), " name"); 1253 failWithMessage("Expected an opening '(' before a ", stringForFunctionMode(mode), "'s parameter list"); 1254 } 1255 if (!match(CLOSEPAREN)) { 1256 parameters = parseFormalParameters(context); 1257 failIfFalse(parameters, "Cannot parse parameters for this ", stringForFunctionMode(mode)); 1258 } 1259 consumeOrFail(CLOSEPAREN, "Expected a ')' or a ',' after a parameter declaration"); 1260 matchOrFail(OPENBRACE, "Expected an opening '{' at the start of a ", stringForFunctionMode(mode), " body"); 1261 1262 openBraceOffset = m_token.m_data.offset; 1263 bodyStartLine = tokenLine(); 1264 bodyStartColumn = m_token.m_data.offset - m_token.m_data.lineStartOffset; 1265 JSTokenLocation startLocation(tokenLocation()); 1266 1267 // If we know about this function already, we can use the cached info and skip the parser to the end of the function. 1268 if (const SourceProviderCacheItem* cachedInfo = TreeBuilder::CanUseFunctionCache ? findCachedFunctionInfo(openBraceOffset) : 0) { 1269 // If we're in a strict context, the cached function info must say it was strict too. 1270 ASSERT(!strictMode() || cachedInfo->strictMode); 1271 JSTokenLocation endLocation; 1272 1273 endLocation.line = cachedInfo->closeBraceLine; 1274 endLocation.startOffset = cachedInfo->closeBraceOffset; 1275 endLocation.lineStartOffset = cachedInfo->closeBraceLineStartOffset; 1276 1277 bool endColumnIsOnStartLine = (endLocation.line == bodyStartLine); 1278 ASSERT(endLocation.startOffset >= endLocation.lineStartOffset); 1279 unsigned bodyEndColumn = endColumnIsOnStartLine ? 1280 endLocation.startOffset - m_token.m_data.lineStartOffset : 1281 endLocation.startOffset - endLocation.lineStartOffset; 1282 1283 body = context.createFunctionBody(startLocation, endLocation, bodyStartColumn, bodyEndColumn, cachedInfo->strictMode); 1284 1285 functionScope->restoreFromSourceProviderCache(cachedInfo); 1286 failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo), "Parser error"); 1287 1288 closeBraceOffset = cachedInfo->closeBraceOffset; 1289 1290 context.setFunctionNameStart(body, functionNameStart); 1291 m_token = cachedInfo->closeBraceToken(); 1292 1293 m_lexer->setOffset(m_token.m_location.endOffset, m_token.m_location.lineStartOffset); 1294 m_lexer->setLineNumber(m_token.m_location.line); 1295 1296 next(); 1297 return true; 1298 } 1299 m_lastFunctionName = lastFunctionName; 1300 ParserState oldState = saveState(); 1301 body = parseFunctionBody(context); 1302 restoreState(oldState); 1303 failIfFalse(body, "Cannot parse the body of this ", stringForFunctionMode(mode)); 1304 if (functionScope->strictMode() && name) { 1305 RELEASE_ASSERT(mode == FunctionMode); 1306 semanticFailIfTrue(m_vm->propertyNames->arguments == *name, "'", name->impl(), "' is not a valid function name in strict mode"); 1307 semanticFailIfTrue(m_vm->propertyNames->eval == *name, "'", name->impl(), "' is not a valid function name in strict mode"); 1308 } 1309 closeBraceOffset = m_token.m_data.offset; 1310 unsigned closeBraceLine = m_token.m_data.line; 1311 unsigned closeBraceLineStartOffset = m_token.m_data.lineStartOffset; 1312 1313 // Cache the tokenizer state and the function scope the first time the function is parsed. 1314 // Any future reparsing can then skip the function. 1315 static const int minimumFunctionLengthToCache = 16; 1316 std::unique_ptr<SourceProviderCacheItem> newInfo; 1317 int functionLength = closeBraceOffset - openBraceOffset; 1318 if (TreeBuilder::CanUseFunctionCache && m_functionCache && functionLength > minimumFunctionLengthToCache) { 1319 SourceProviderCacheItemCreationParameters parameters; 1320 parameters.functionNameStart = functionNameStart; 1321 parameters.closeBraceLine = closeBraceLine; 1322 parameters.closeBraceOffset = closeBraceOffset; 1323 parameters.closeBraceLineStartOffset = closeBraceLineStartOffset; 1324 functionScope->fillParametersForSourceProviderCache(parameters); 1325 newInfo = SourceProviderCacheItem::create(parameters); 1326 1327 } 1328 context.setFunctionNameStart(body, functionNameStart); 1329 1330 failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo), "Parser error"); 1331 matchOrFail(CLOSEBRACE, "Expected a closing '}' after a ", stringForFunctionMode(mode), " body"); 1332 1333 if (newInfo) 1334 m_functionCache->add(openBraceOffset, WTF::move(newInfo)); 1335 1336 next(); 1337 return true; 1338} 1339 1340template <typename LexerType> 1341template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDeclaration(TreeBuilder& context) 1342{ 1343 ASSERT(match(FUNCTION)); 1344 JSTokenLocation location(tokenLocation()); 1345 next(); 1346 const Identifier* name = 0; 1347 TreeFormalParameterList parameters = 0; 1348 TreeFunctionBody body = 0; 1349 unsigned openBraceOffset = 0; 1350 unsigned closeBraceOffset = 0; 1351 int bodyStartLine = 0; 1352 unsigned bodyStartColumn = 0; 1353 failIfFalse((parseFunctionInfo(context, FunctionNeedsName, FunctionMode, true, name, parameters, body, openBraceOffset, closeBraceOffset, bodyStartLine, bodyStartColumn)), "Cannot parse this function"); 1354 failIfFalse(name, "Function statements must have a name"); 1355 failIfFalseIfStrict(declareVariable(name), "Cannot declare a function named '", name->impl(), "' in strict mode"); 1356 return context.createFuncDeclStatement(location, name, body, parameters, openBraceOffset, closeBraceOffset, bodyStartLine, m_lastTokenEndPosition.line, bodyStartColumn); 1357} 1358 1359struct LabelInfo { 1360 LabelInfo(const Identifier* ident, const JSTextPosition& start, const JSTextPosition& end) 1361 : m_ident(ident) 1362 , m_start(start) 1363 , m_end(end) 1364 { 1365 } 1366 1367 const Identifier* m_ident; 1368 JSTextPosition m_start; 1369 JSTextPosition m_end; 1370}; 1371 1372template <typename LexerType> 1373template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionOrLabelStatement(TreeBuilder& context) 1374{ 1375 1376 /* Expression and Label statements are ambiguous at LL(1), so we have a 1377 * special case that looks for a colon as the next character in the input. 1378 */ 1379 Vector<LabelInfo> labels; 1380 JSTokenLocation location; 1381 do { 1382 JSTextPosition start = tokenStartPosition(); 1383 location = tokenLocation(); 1384 if (!nextTokenIsColon()) { 1385 // If we hit this path we're making a expression statement, which 1386 // by definition can't make use of continue/break so we can just 1387 // ignore any labels we might have accumulated. 1388 TreeExpression expression = parseExpression(context); 1389 failIfFalse(expression, "Cannot parse expression statement"); 1390 if (!autoSemiColon()) 1391 failDueToUnexpectedToken(); 1392 return context.createExprStatement(location, expression, start, m_lastTokenEndPosition.line); 1393 } 1394 const Identifier* ident = m_token.m_data.ident; 1395 JSTextPosition end = tokenEndPosition(); 1396 next(); 1397 consumeOrFail(COLON, "Labels must be followed by a ':'"); 1398 if (!m_syntaxAlreadyValidated) { 1399 // This is O(N^2) over the current list of consecutive labels, but I 1400 // have never seen more than one label in a row in the real world. 1401 for (size_t i = 0; i < labels.size(); i++) 1402 failIfTrue(ident->impl() == labels[i].m_ident->impl(), "Attempted to redeclare the label '", ident->impl(), "'"); 1403 failIfTrue(getLabel(ident), "Cannot find scope for the label '", ident->impl(), "'"); 1404 labels.append(LabelInfo(ident, start, end)); 1405 } 1406 } while (match(IDENT)); 1407 bool isLoop = false; 1408 switch (m_token.m_type) { 1409 case FOR: 1410 case WHILE: 1411 case DO: 1412 isLoop = true; 1413 break; 1414 1415 default: 1416 break; 1417 } 1418 const Identifier* unused = 0; 1419 if (!m_syntaxAlreadyValidated) { 1420 for (size_t i = 0; i < labels.size(); i++) 1421 pushLabel(labels[i].m_ident, isLoop); 1422 } 1423 TreeStatement statement = parseStatement(context, unused); 1424 if (!m_syntaxAlreadyValidated) { 1425 for (size_t i = 0; i < labels.size(); i++) 1426 popLabel(); 1427 } 1428 failIfFalse(statement, "Cannot parse statement"); 1429 for (size_t i = 0; i < labels.size(); i++) { 1430 const LabelInfo& info = labels[labels.size() - i - 1]; 1431 statement = context.createLabelStatement(location, info.m_ident, statement, info.m_start, info.m_end); 1432 } 1433 return statement; 1434} 1435 1436template <typename LexerType> 1437template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionStatement(TreeBuilder& context) 1438{ 1439 JSTextPosition start = tokenStartPosition(); 1440 JSTokenLocation location(tokenLocation()); 1441 TreeExpression expression = parseExpression(context); 1442 failIfFalse(expression, "Cannot parse expression statement"); 1443 failIfFalse(autoSemiColon(), "Parse error"); 1444 return context.createExprStatement(location, expression, start, m_lastTokenEndPosition.line); 1445} 1446 1447template <typename LexerType> 1448template <class TreeBuilder> TreeStatement Parser<LexerType>::parseIfStatement(TreeBuilder& context) 1449{ 1450 ASSERT(match(IF)); 1451 JSTokenLocation ifLocation(tokenLocation()); 1452 int start = tokenLine(); 1453 next(); 1454 handleProductionOrFail(OPENPAREN, "(", "start", "'if' condition"); 1455 1456 TreeExpression condition = parseExpression(context); 1457 failIfFalse(condition, "Expected a expression as the condition for an if statement"); 1458 int end = tokenLine(); 1459 handleProductionOrFail(CLOSEPAREN, ")", "end", "'if' condition"); 1460 1461 const Identifier* unused = 0; 1462 TreeStatement trueBlock = parseStatement(context, unused); 1463 failIfFalse(trueBlock, "Expected a statement as the body of an if block"); 1464 1465 if (!match(ELSE)) 1466 return context.createIfStatement(ifLocation, condition, trueBlock, 0, start, end); 1467 1468 Vector<TreeExpression> exprStack; 1469 Vector<std::pair<int, int>> posStack; 1470 Vector<JSTokenLocation> tokenLocationStack; 1471 Vector<TreeStatement> statementStack; 1472 bool trailingElse = false; 1473 do { 1474 JSTokenLocation tempLocation = tokenLocation(); 1475 next(); 1476 if (!match(IF)) { 1477 const Identifier* unused = 0; 1478 TreeStatement block = parseStatement(context, unused); 1479 failIfFalse(block, "Expected a statement as the body of an else block"); 1480 statementStack.append(block); 1481 trailingElse = true; 1482 break; 1483 } 1484 int innerStart = tokenLine(); 1485 next(); 1486 1487 handleProductionOrFail(OPENPAREN, "(", "start", "'if' condition"); 1488 1489 TreeExpression innerCondition = parseExpression(context); 1490 failIfFalse(innerCondition, "Expected a expression as the condition for an if statement"); 1491 int innerEnd = tokenLine(); 1492 handleProductionOrFail(CLOSEPAREN, ")", "end", "'if' condition"); 1493 const Identifier* unused = 0; 1494 TreeStatement innerTrueBlock = parseStatement(context, unused); 1495 failIfFalse(innerTrueBlock, "Expected a statement as the body of an if block"); 1496 tokenLocationStack.append(tempLocation); 1497 exprStack.append(innerCondition); 1498 posStack.append(std::make_pair(innerStart, innerEnd)); 1499 statementStack.append(innerTrueBlock); 1500 } while (match(ELSE)); 1501 1502 if (!trailingElse) { 1503 TreeExpression condition = exprStack.last(); 1504 exprStack.removeLast(); 1505 TreeStatement trueBlock = statementStack.last(); 1506 statementStack.removeLast(); 1507 std::pair<int, int> pos = posStack.last(); 1508 posStack.removeLast(); 1509 JSTokenLocation elseLocation = tokenLocationStack.last(); 1510 tokenLocationStack.removeLast(); 1511 statementStack.append(context.createIfStatement(elseLocation, condition, trueBlock, 0, pos.first, pos.second)); 1512 } 1513 1514 while (!exprStack.isEmpty()) { 1515 TreeExpression condition = exprStack.last(); 1516 exprStack.removeLast(); 1517 TreeStatement falseBlock = statementStack.last(); 1518 statementStack.removeLast(); 1519 TreeStatement trueBlock = statementStack.last(); 1520 statementStack.removeLast(); 1521 std::pair<int, int> pos = posStack.last(); 1522 posStack.removeLast(); 1523 JSTokenLocation elseLocation = tokenLocationStack.last(); 1524 tokenLocationStack.removeLast(); 1525 statementStack.append(context.createIfStatement(elseLocation, condition, trueBlock, falseBlock, pos.first, pos.second)); 1526 } 1527 1528 return context.createIfStatement(ifLocation, condition, trueBlock, statementStack.last(), start, end); 1529} 1530 1531template <typename LexerType> 1532template <class TreeBuilder> TreeExpression Parser<LexerType>::parseExpression(TreeBuilder& context) 1533{ 1534 failIfStackOverflow(); 1535 JSTokenLocation location(tokenLocation()); 1536 TreeExpression node = parseAssignmentExpression(context); 1537 failIfFalse(node, "Cannot parse expression"); 1538 if (!match(COMMA)) 1539 return node; 1540 next(); 1541 m_nonTrivialExpressionCount++; 1542 m_nonLHSCount++; 1543 TreeExpression right = parseAssignmentExpression(context); 1544 failIfFalse(right, "Cannot parse expression in a comma expression"); 1545 typename TreeBuilder::Comma commaNode = context.createCommaExpr(location, node, right); 1546 while (match(COMMA)) { 1547 next(TreeBuilder::DontBuildStrings); 1548 right = parseAssignmentExpression(context); 1549 failIfFalse(right, "Cannot parse expression in a comma expression"); 1550 context.appendToComma(commaNode, right); 1551 } 1552 return commaNode; 1553} 1554 1555template <typename LexerType> 1556template <typename TreeBuilder> TreeExpression Parser<LexerType>::parseAssignmentExpression(TreeBuilder& context) 1557{ 1558 failIfStackOverflow(); 1559 JSTextPosition start = tokenStartPosition(); 1560 JSTokenLocation location(tokenLocation()); 1561 int initialAssignmentCount = m_assignmentCount; 1562 int initialNonLHSCount = m_nonLHSCount; 1563 if (match(OPENBRACE) || match(OPENBRACKET)) { 1564 SavePoint savePoint = createSavePoint(); 1565 auto pattern = tryParseDeconstructionPatternExpression(context); 1566 if (pattern && consume(EQUAL)) { 1567 auto rhs = parseAssignmentExpression(context); 1568 if (rhs) 1569 return context.createDeconstructingAssignment(location, pattern, rhs); 1570 } 1571 restoreSavePoint(savePoint); 1572 } 1573 TreeExpression lhs = parseConditionalExpression(context); 1574 failIfFalse(lhs, "Cannot parse expression"); 1575 if (initialNonLHSCount != m_nonLHSCount) { 1576 if (m_token.m_type >= EQUAL && m_token.m_type <= OREQUAL) 1577 semanticFail("Left hand side of operator '", getToken(), "' must be a reference"); 1578 1579 return lhs; 1580 } 1581 1582 int assignmentStack = 0; 1583 Operator op; 1584 bool hadAssignment = false; 1585 while (true) { 1586 switch (m_token.m_type) { 1587 case EQUAL: op = OpEqual; break; 1588 case PLUSEQUAL: op = OpPlusEq; break; 1589 case MINUSEQUAL: op = OpMinusEq; break; 1590 case MULTEQUAL: op = OpMultEq; break; 1591 case DIVEQUAL: op = OpDivEq; break; 1592 case LSHIFTEQUAL: op = OpLShift; break; 1593 case RSHIFTEQUAL: op = OpRShift; break; 1594 case URSHIFTEQUAL: op = OpURShift; break; 1595 case ANDEQUAL: op = OpAndEq; break; 1596 case XOREQUAL: op = OpXOrEq; break; 1597 case OREQUAL: op = OpOrEq; break; 1598 case MODEQUAL: op = OpModEq; break; 1599 default: 1600 goto end; 1601 } 1602 m_nonTrivialExpressionCount++; 1603 hadAssignment = true; 1604 context.assignmentStackAppend(assignmentStack, lhs, start, tokenStartPosition(), m_assignmentCount, op); 1605 start = tokenStartPosition(); 1606 m_assignmentCount++; 1607 next(TreeBuilder::DontBuildStrings); 1608 if (strictMode() && m_lastIdentifier && context.isResolve(lhs)) { 1609 failIfTrueIfStrict(m_vm->propertyNames->eval == *m_lastIdentifier, "Cannot modify 'eval' in strict mode"); 1610 failIfTrueIfStrict(m_vm->propertyNames->arguments == *m_lastIdentifier, "Cannot modify 'arguments' in strict mode"); 1611 declareWrite(m_lastIdentifier); 1612 m_lastIdentifier = 0; 1613 } 1614 lhs = parseAssignmentExpression(context); 1615 failIfFalse(lhs, "Cannot parse the right hand side of an assignment expression"); 1616 if (initialNonLHSCount != m_nonLHSCount) { 1617 if (m_token.m_type >= EQUAL && m_token.m_type <= OREQUAL) 1618 semanticFail("Left hand side of operator '", getToken(), "' must be a reference"); 1619 break; 1620 } 1621 } 1622end: 1623 if (hadAssignment) 1624 m_nonLHSCount++; 1625 1626 if (!TreeBuilder::CreatesAST) 1627 return lhs; 1628 1629 while (assignmentStack) 1630 lhs = context.createAssignment(location, assignmentStack, lhs, initialAssignmentCount, m_assignmentCount, lastTokenEndPosition()); 1631 1632 return lhs; 1633} 1634 1635template <typename LexerType> 1636template <class TreeBuilder> TreeExpression Parser<LexerType>::parseConditionalExpression(TreeBuilder& context) 1637{ 1638 JSTokenLocation location(tokenLocation()); 1639 TreeExpression cond = parseBinaryExpression(context); 1640 failIfFalse(cond, "Cannot parse expression"); 1641 if (!match(QUESTION)) 1642 return cond; 1643 m_nonTrivialExpressionCount++; 1644 m_nonLHSCount++; 1645 next(TreeBuilder::DontBuildStrings); 1646 TreeExpression lhs = parseAssignmentExpression(context); 1647 failIfFalse(lhs, "Cannot parse left hand side of ternary operator"); 1648 consumeOrFailWithFlags(COLON, TreeBuilder::DontBuildStrings, "Expected ':' in ternary operator"); 1649 1650 TreeExpression rhs = parseAssignmentExpression(context); 1651 failIfFalse(rhs, "Cannot parse right hand side of ternary operator"); 1652 return context.createConditionalExpr(location, cond, lhs, rhs); 1653} 1654 1655ALWAYS_INLINE static bool isUnaryOp(JSTokenType token) 1656{ 1657 return token & UnaryOpTokenFlag; 1658} 1659 1660template <typename LexerType> 1661int Parser<LexerType>::isBinaryOperator(JSTokenType token) 1662{ 1663 if (m_allowsIn) 1664 return token & (BinaryOpTokenPrecedenceMask << BinaryOpTokenAllowsInPrecedenceAdditionalShift); 1665 return token & BinaryOpTokenPrecedenceMask; 1666} 1667 1668template <typename LexerType> 1669template <class TreeBuilder> TreeExpression Parser<LexerType>::parseBinaryExpression(TreeBuilder& context) 1670{ 1671 1672 int operandStackDepth = 0; 1673 int operatorStackDepth = 0; 1674 typename TreeBuilder::BinaryExprContext binaryExprContext(context); 1675 JSTokenLocation location(tokenLocation()); 1676 while (true) { 1677 JSTextPosition exprStart = tokenStartPosition(); 1678 int initialAssignments = m_assignmentCount; 1679 TreeExpression current = parseUnaryExpression(context); 1680 failIfFalse(current, "Cannot parse expression"); 1681 1682 context.appendBinaryExpressionInfo(operandStackDepth, current, exprStart, lastTokenEndPosition(), lastTokenEndPosition(), initialAssignments != m_assignmentCount); 1683 int precedence = isBinaryOperator(m_token.m_type); 1684 if (!precedence) 1685 break; 1686 m_nonTrivialExpressionCount++; 1687 m_nonLHSCount++; 1688 int operatorToken = m_token.m_type; 1689 next(TreeBuilder::DontBuildStrings); 1690 1691 while (operatorStackDepth && context.operatorStackHasHigherPrecedence(operatorStackDepth, precedence)) { 1692 ASSERT(operandStackDepth > 1); 1693 1694 typename TreeBuilder::BinaryOperand rhs = context.getFromOperandStack(-1); 1695 typename TreeBuilder::BinaryOperand lhs = context.getFromOperandStack(-2); 1696 context.shrinkOperandStackBy(operandStackDepth, 2); 1697 context.appendBinaryOperation(location, operandStackDepth, operatorStackDepth, lhs, rhs); 1698 context.operatorStackPop(operatorStackDepth); 1699 } 1700 context.operatorStackAppend(operatorStackDepth, operatorToken, precedence); 1701 } 1702 while (operatorStackDepth) { 1703 ASSERT(operandStackDepth > 1); 1704 1705 typename TreeBuilder::BinaryOperand rhs = context.getFromOperandStack(-1); 1706 typename TreeBuilder::BinaryOperand lhs = context.getFromOperandStack(-2); 1707 context.shrinkOperandStackBy(operandStackDepth, 2); 1708 context.appendBinaryOperation(location, operandStackDepth, operatorStackDepth, lhs, rhs); 1709 context.operatorStackPop(operatorStackDepth); 1710 } 1711 return context.popOperandStack(operandStackDepth); 1712} 1713 1714template <typename LexerType> 1715template <class TreeBuilder> TreeProperty Parser<LexerType>::parseProperty(TreeBuilder& context, bool complete) 1716{ 1717 bool wasIdent = false; 1718 switch (m_token.m_type) { 1719 namedProperty: 1720 case IDENT: 1721 wasIdent = true; 1722 FALLTHROUGH; 1723 case STRING: { 1724 const Identifier* ident = m_token.m_data.ident; 1725 if (complete || (wasIdent && (*ident == m_vm->propertyNames->get || *ident == m_vm->propertyNames->set))) 1726 nextExpectIdentifier(LexerFlagsIgnoreReservedWords); 1727 else 1728 nextExpectIdentifier(LexerFlagsIgnoreReservedWords | TreeBuilder::DontBuildKeywords); 1729 1730 if (match(COLON)) { 1731 next(); 1732 TreeExpression node = parseAssignmentExpression(context); 1733 failIfFalse(node, "Cannot parse expression for property declaration"); 1734 return context.createProperty(ident, node, PropertyNode::Constant, complete); 1735 } 1736 failIfFalse(wasIdent, "Expected an identifier as property name"); 1737 const Identifier* accessorName = 0; 1738 TreeFormalParameterList parameters = 0; 1739 TreeFunctionBody body = 0; 1740 unsigned openBraceOffset = 0; 1741 unsigned closeBraceOffset = 0; 1742 int bodyStartLine = 0; 1743 unsigned bodyStartColumn = 0; 1744 PropertyNode::Type type; 1745 if (*ident == m_vm->propertyNames->get) 1746 type = PropertyNode::Getter; 1747 else if (*ident == m_vm->propertyNames->set) 1748 type = PropertyNode::Setter; 1749 else 1750 failWithMessage("Expected a ':' following the property name '", ident->impl(), "'"); 1751 const Identifier* stringPropertyName = 0; 1752 double numericPropertyName = 0; 1753 if (m_token.m_type == IDENT || m_token.m_type == STRING) 1754 stringPropertyName = m_token.m_data.ident; 1755 else if (m_token.m_type == NUMBER) 1756 numericPropertyName = m_token.m_data.doubleValue; 1757 else 1758 failDueToUnexpectedToken(); 1759 JSTokenLocation location(tokenLocation()); 1760 next(); 1761 if (type == PropertyNode::Getter) { 1762 failIfFalse(match(OPENPAREN), "Expected a parameter list for getter definition"); 1763 failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, GetterMode, false, accessorName, parameters, body, openBraceOffset, closeBraceOffset, bodyStartLine, bodyStartColumn)), "Cannot parse getter definition"); 1764 } else { 1765 failIfFalse(match(OPENPAREN), "Expected a parameter list for setter definition"); 1766 failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, SetterMode, false, accessorName, parameters, body, openBraceOffset, closeBraceOffset, bodyStartLine, bodyStartColumn)), "Cannot parse setter definition"); 1767 } 1768 if (stringPropertyName) 1769 return context.createGetterOrSetterProperty(location, type, complete, stringPropertyName, parameters, body, openBraceOffset, closeBraceOffset, bodyStartLine, m_lastTokenEndPosition.line, bodyStartColumn); 1770 return context.createGetterOrSetterProperty(const_cast<VM*>(m_vm), location, type, complete, numericPropertyName, parameters, body, openBraceOffset, closeBraceOffset, bodyStartLine, m_lastTokenEndPosition.line, bodyStartColumn); 1771 } 1772 case NUMBER: { 1773 double propertyName = m_token.m_data.doubleValue; 1774 next(); 1775 consumeOrFail(COLON, "Expected ':' after property name"); 1776 TreeExpression node = parseAssignmentExpression(context); 1777 failIfFalse(node, "Cannot parse expression for property declaration"); 1778 return context.createProperty(const_cast<VM*>(m_vm), propertyName, node, PropertyNode::Constant, complete); 1779 } 1780 case OPENBRACKET: { 1781 next(); 1782 auto propertyName = parseExpression(context); 1783 failIfFalse(propertyName, "Cannot parse computed property name"); 1784 1785 handleProductionOrFail(CLOSEBRACKET, "]", "end", "computed property name"); 1786 consumeOrFail(COLON, "Expected ':' after property name"); 1787 TreeExpression node = parseAssignmentExpression(context); 1788 failIfFalse(node, "Cannot parse expression for property declaration"); 1789 return context.createProperty(const_cast<VM*>(m_vm), propertyName, node, PropertyNode::Constant, complete); 1790 } 1791 default: 1792 failIfFalse(m_token.m_type & KeywordTokenFlag, "Expected a property name"); 1793 goto namedProperty; 1794 } 1795} 1796 1797template <typename LexerType> 1798template <class TreeBuilder> TreeExpression Parser<LexerType>::parseObjectLiteral(TreeBuilder& context) 1799{ 1800 auto savePoint = createSavePoint(); 1801 consumeOrFailWithFlags(OPENBRACE, TreeBuilder::DontBuildStrings, "Expected opening '{' at the start of an object literal"); 1802 JSTokenLocation location(tokenLocation()); 1803 1804 int oldNonLHSCount = m_nonLHSCount; 1805 1806 if (match(CLOSEBRACE)) { 1807 next(); 1808 return context.createObjectLiteral(location); 1809 } 1810 1811 TreeProperty property = parseProperty(context, false); 1812 failIfFalse(property, "Cannot parse object literal property"); 1813 if (!m_syntaxAlreadyValidated && context.getType(property) != PropertyNode::Constant) { 1814 restoreSavePoint(savePoint); 1815 return parseStrictObjectLiteral(context); 1816 } 1817 TreePropertyList propertyList = context.createPropertyList(location, property); 1818 TreePropertyList tail = propertyList; 1819 while (match(COMMA)) { 1820 next(TreeBuilder::DontBuildStrings); 1821 // allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939 1822 if (match(CLOSEBRACE)) 1823 break; 1824 JSTokenLocation propertyLocation(tokenLocation()); 1825 property = parseProperty(context, false); 1826 failIfFalse(property, "Cannot parse object literal property"); 1827 if (!m_syntaxAlreadyValidated && context.getType(property) != PropertyNode::Constant) { 1828 restoreSavePoint(savePoint); 1829 return parseStrictObjectLiteral(context); 1830 } 1831 tail = context.createPropertyList(propertyLocation, property, tail); 1832 } 1833 1834 location = tokenLocation(); 1835 handleProductionOrFail(CLOSEBRACE, "}", "end", "object literal"); 1836 1837 m_nonLHSCount = oldNonLHSCount; 1838 1839 return context.createObjectLiteral(location, propertyList); 1840} 1841 1842template <typename LexerType> 1843template <class TreeBuilder> TreeExpression Parser<LexerType>::parseStrictObjectLiteral(TreeBuilder& context) 1844{ 1845 consumeOrFail(OPENBRACE, "Expected opening '{' at the start of an object literal"); 1846 1847 int oldNonLHSCount = m_nonLHSCount; 1848 1849 JSTokenLocation location(tokenLocation()); 1850 if (match(CLOSEBRACE)) { 1851 next(); 1852 return context.createObjectLiteral(location); 1853 } 1854 1855 TreeProperty property = parseProperty(context, true); 1856 failIfFalse(property, "Cannot parse object literal property"); 1857 1858 typedef HashMap<RefPtr<StringImpl>, unsigned, IdentifierRepHash> ObjectValidationMap; 1859 ObjectValidationMap objectValidator; 1860 // Add the first property 1861 if (!m_syntaxAlreadyValidated && context.getName(property)) 1862 objectValidator.add(context.getName(property)->impl(), context.getType(property)); 1863 1864 TreePropertyList propertyList = context.createPropertyList(location, property); 1865 TreePropertyList tail = propertyList; 1866 while (match(COMMA)) { 1867 next(); 1868 // allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939 1869 if (match(CLOSEBRACE)) 1870 break; 1871 JSTokenLocation propertyLocation(tokenLocation()); 1872 property = parseProperty(context, true); 1873 failIfFalse(property, "Cannot parse object literal property"); 1874 if (!m_syntaxAlreadyValidated && context.getName(property)) { 1875 ObjectValidationMap::AddResult propertyEntry = objectValidator.add(context.getName(property)->impl(), context.getType(property)); 1876 if (!propertyEntry.isNewEntry) { 1877 semanticFailIfTrue(propertyEntry.iterator->value == PropertyNode::Constant, "Attempted to redefine property '", propertyEntry.iterator->key.get(), "'"); 1878 semanticFailIfTrue(context.getType(property) == PropertyNode::Constant, "Attempted to redefine property '", propertyEntry.iterator->key.get(), "'"); 1879 semanticFailIfTrue(context.getType(property) & propertyEntry.iterator->value, "Attempted to redefine property '", propertyEntry.iterator->key.get(), "'"); 1880 propertyEntry.iterator->value |= context.getType(property); 1881 } 1882 } 1883 tail = context.createPropertyList(propertyLocation, property, tail); 1884 } 1885 1886 location = tokenLocation(); 1887 handleProductionOrFail(CLOSEBRACE, "}", "end", "object literal"); 1888 1889 m_nonLHSCount = oldNonLHSCount; 1890 1891 return context.createObjectLiteral(location, propertyList); 1892} 1893 1894template <typename LexerType> 1895template <class TreeBuilder> TreeExpression Parser<LexerType>::parseArrayLiteral(TreeBuilder& context) 1896{ 1897 consumeOrFailWithFlags(OPENBRACKET, TreeBuilder::DontBuildStrings, "Expected an opening '[' at the beginning of an array literal"); 1898 1899 int oldNonLHSCount = m_nonLHSCount; 1900 1901 int elisions = 0; 1902 while (match(COMMA)) { 1903 next(TreeBuilder::DontBuildStrings); 1904 elisions++; 1905 } 1906 if (match(CLOSEBRACKET)) { 1907 JSTokenLocation location(tokenLocation()); 1908 next(TreeBuilder::DontBuildStrings); 1909 return context.createArray(location, elisions); 1910 } 1911 1912 TreeExpression elem; 1913 if (UNLIKELY(match(DOTDOTDOT))) { 1914 auto spreadLocation = m_token.m_location; 1915 auto start = m_token.m_startPosition; 1916 auto divot = m_token.m_endPosition; 1917 next(); 1918 auto spreadExpr = parseAssignmentExpression(context); 1919 failIfFalse(spreadExpr, "Cannot parse subject of a spread operation"); 1920 elem = context.createSpreadExpression(spreadLocation, spreadExpr, start, divot, m_lastTokenEndPosition); 1921 } else 1922 elem = parseAssignmentExpression(context); 1923 failIfFalse(elem, "Cannot parse array literal element"); 1924 typename TreeBuilder::ElementList elementList = context.createElementList(elisions, elem); 1925 typename TreeBuilder::ElementList tail = elementList; 1926 elisions = 0; 1927 while (match(COMMA)) { 1928 next(TreeBuilder::DontBuildStrings); 1929 elisions = 0; 1930 1931 while (match(COMMA)) { 1932 next(); 1933 elisions++; 1934 } 1935 1936 if (match(CLOSEBRACKET)) { 1937 JSTokenLocation location(tokenLocation()); 1938 next(TreeBuilder::DontBuildStrings); 1939 return context.createArray(location, elisions, elementList); 1940 } 1941 if (UNLIKELY(match(DOTDOTDOT))) { 1942 auto spreadLocation = m_token.m_location; 1943 auto start = m_token.m_startPosition; 1944 auto divot = m_token.m_endPosition; 1945 next(); 1946 TreeExpression elem = parseAssignmentExpression(context); 1947 failIfFalse(elem, "Cannot parse subject of a spread operation"); 1948 auto spread = context.createSpreadExpression(spreadLocation, elem, start, divot, m_lastTokenEndPosition); 1949 tail = context.createElementList(tail, elisions, spread); 1950 continue; 1951 } 1952 TreeExpression elem = parseAssignmentExpression(context); 1953 failIfFalse(elem, "Cannot parse array literal element"); 1954 tail = context.createElementList(tail, elisions, elem); 1955 } 1956 1957 JSTokenLocation location(tokenLocation()); 1958 if (!consume(CLOSEBRACKET)) { 1959 failIfFalse(match(DOTDOTDOT), "Expected either a closing ']' or a ',' following an array element"); 1960 semanticFail("The '...' operator should come before a target expression"); 1961 } 1962 1963 m_nonLHSCount = oldNonLHSCount; 1964 1965 return context.createArray(location, elementList); 1966} 1967 1968template <typename LexerType> 1969template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePrimaryExpression(TreeBuilder& context) 1970{ 1971 failIfStackOverflow(); 1972 switch (m_token.m_type) { 1973 case OPENBRACE: 1974 if (strictMode()) 1975 return parseStrictObjectLiteral(context); 1976 return parseObjectLiteral(context); 1977 case OPENBRACKET: 1978 return parseArrayLiteral(context); 1979 case OPENPAREN: { 1980 next(); 1981 int oldNonLHSCount = m_nonLHSCount; 1982 TreeExpression result = parseExpression(context); 1983 m_nonLHSCount = oldNonLHSCount; 1984 handleProductionOrFail(CLOSEPAREN, ")", "end", "compound expression"); 1985 return result; 1986 } 1987 case THISTOKEN: { 1988 JSTokenLocation location(tokenLocation()); 1989 next(); 1990 return context.thisExpr(location); 1991 } 1992 case IDENT: { 1993 JSTextPosition start = tokenStartPosition(); 1994 const Identifier* ident = m_token.m_data.ident; 1995 JSTokenLocation location(tokenLocation()); 1996 next(); 1997 currentScope()->useVariable(ident, m_vm->propertyNames->eval == *ident); 1998 m_lastIdentifier = ident; 1999 return context.createResolve(location, ident, start); 2000 } 2001 case STRING: { 2002 const Identifier* ident = m_token.m_data.ident; 2003 JSTokenLocation location(tokenLocation()); 2004 next(); 2005 return context.createString(location, ident); 2006 } 2007 case NUMBER: { 2008 double d = m_token.m_data.doubleValue; 2009 JSTokenLocation location(tokenLocation()); 2010 next(); 2011 return context.createNumberExpr(location, d); 2012 } 2013 case NULLTOKEN: { 2014 JSTokenLocation location(tokenLocation()); 2015 next(); 2016 return context.createNull(location); 2017 } 2018 case TRUETOKEN: { 2019 JSTokenLocation location(tokenLocation()); 2020 next(); 2021 return context.createBoolean(location, true); 2022 } 2023 case FALSETOKEN: { 2024 JSTokenLocation location(tokenLocation()); 2025 next(); 2026 return context.createBoolean(location, false); 2027 } 2028 case DIVEQUAL: 2029 case DIVIDE: { 2030 /* regexp */ 2031 const Identifier* pattern; 2032 const Identifier* flags; 2033 if (match(DIVEQUAL)) 2034 failIfFalse(m_lexer->scanRegExp(pattern, flags, '='), "Invalid regular expression"); 2035 else 2036 failIfFalse(m_lexer->scanRegExp(pattern, flags), "Invalid regular expression"); 2037 2038 JSTextPosition start = tokenStartPosition(); 2039 JSTokenLocation location(tokenLocation()); 2040 next(); 2041 TreeExpression re = context.createRegExp(location, *pattern, *flags, start); 2042 if (!re) { 2043 const char* yarrErrorMsg = Yarr::checkSyntax(pattern->string()); 2044 regexFail(yarrErrorMsg); 2045 } 2046 return re; 2047 } 2048 default: 2049 failDueToUnexpectedToken(); 2050 } 2051} 2052 2053template <typename LexerType> 2054template <class TreeBuilder> TreeArguments Parser<LexerType>::parseArguments(TreeBuilder& context, SpreadMode mode) 2055{ 2056 consumeOrFailWithFlags(OPENPAREN, TreeBuilder::DontBuildStrings, "Expected opening '(' at start of argument list"); 2057 JSTokenLocation location(tokenLocation()); 2058 if (match(CLOSEPAREN)) { 2059 next(TreeBuilder::DontBuildStrings); 2060 return context.createArguments(); 2061 } 2062 if (match(DOTDOTDOT) && mode == AllowSpread) { 2063 JSTokenLocation spreadLocation(tokenLocation()); 2064 auto start = m_token.m_startPosition; 2065 auto divot = m_token.m_endPosition; 2066 next(); 2067 auto spreadExpr = parseAssignmentExpression(context); 2068 auto end = m_lastTokenEndPosition; 2069 if (!spreadExpr) 2070 failWithMessage("Cannot parse spread expression"); 2071 if (!consume(CLOSEPAREN)) { 2072 if (match(COMMA)) 2073 semanticFail("Spread operator may only be applied to the last argument passed to a function"); 2074 handleProductionOrFail(CLOSEPAREN, ")", "end", "argument list"); 2075 } 2076 auto spread = context.createSpreadExpression(spreadLocation, spreadExpr, start, divot, end); 2077 TreeArgumentsList argList = context.createArgumentsList(location, spread); 2078 return context.createArguments(argList); 2079 } 2080 TreeExpression firstArg = parseAssignmentExpression(context); 2081 failIfFalse(firstArg, "Cannot parse function argument"); 2082 2083 TreeArgumentsList argList = context.createArgumentsList(location, firstArg); 2084 TreeArgumentsList tail = argList; 2085 while (match(COMMA)) { 2086 JSTokenLocation argumentLocation(tokenLocation()); 2087 next(TreeBuilder::DontBuildStrings); 2088 TreeExpression arg = parseAssignmentExpression(context); 2089 failIfFalse(arg, "Cannot parse function argument"); 2090 tail = context.createArgumentsList(argumentLocation, tail, arg); 2091 } 2092 semanticFailIfTrue(match(DOTDOTDOT), "The '...' operator should come before the target expression"); 2093 handleProductionOrFail(CLOSEPAREN, ")", "end", "argument list"); 2094 return context.createArguments(argList); 2095} 2096 2097template <typename LexerType> 2098template <class TreeBuilder> TreeExpression Parser<LexerType>::parseMemberExpression(TreeBuilder& context) 2099{ 2100 TreeExpression base = 0; 2101 JSTextPosition expressionStart = tokenStartPosition(); 2102 int newCount = 0; 2103 JSTokenLocation location; 2104 while (match(NEW)) { 2105 next(); 2106 newCount++; 2107 } 2108 2109 if (match(FUNCTION)) { 2110 const Identifier* name = &m_vm->propertyNames->nullIdentifier; 2111 TreeFormalParameterList parameters = 0; 2112 TreeFunctionBody body = 0; 2113 unsigned openBraceOffset = 0; 2114 unsigned closeBraceOffset = 0; 2115 int bodyStartLine = 0; 2116 unsigned bodyStartColumn = 0; 2117 location = tokenLocation(); 2118 next(); 2119 failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, FunctionMode, false, name, parameters, body, openBraceOffset, closeBraceOffset, bodyStartLine, bodyStartColumn)), "Cannot parse function expression"); 2120 base = context.createFunctionExpr(location, name, body, parameters, openBraceOffset, closeBraceOffset, bodyStartLine, m_lastTokenEndPosition.line, bodyStartColumn); 2121 } else 2122 base = parsePrimaryExpression(context); 2123 2124 failIfFalse(base, "Cannot parse base expression"); 2125 while (true) { 2126 location = tokenLocation(); 2127 switch (m_token.m_type) { 2128 case OPENBRACKET: { 2129 m_nonTrivialExpressionCount++; 2130 JSTextPosition expressionEnd = lastTokenEndPosition(); 2131 next(); 2132 int nonLHSCount = m_nonLHSCount; 2133 int initialAssignments = m_assignmentCount; 2134 TreeExpression property = parseExpression(context); 2135 failIfFalse(property, "Cannot parse subscript expression"); 2136 base = context.createBracketAccess(location, base, property, initialAssignments != m_assignmentCount, expressionStart, expressionEnd, tokenEndPosition()); 2137 handleProductionOrFail(CLOSEBRACKET, "]", "end", "subscript expression"); 2138 m_nonLHSCount = nonLHSCount; 2139 break; 2140 } 2141 case OPENPAREN: { 2142 m_nonTrivialExpressionCount++; 2143 int nonLHSCount = m_nonLHSCount; 2144 if (newCount) { 2145 newCount--; 2146 JSTextPosition expressionEnd = lastTokenEndPosition(); 2147 TreeArguments arguments = parseArguments(context, AllowSpread); 2148 failIfFalse(arguments, "Cannot parse call arguments"); 2149 base = context.createNewExpr(location, base, arguments, expressionStart, expressionEnd, lastTokenEndPosition()); 2150 } else { 2151 JSTextPosition expressionEnd = lastTokenEndPosition(); 2152 TreeArguments arguments = parseArguments(context, AllowSpread); 2153 failIfFalse(arguments, "Cannot parse call arguments"); 2154 base = context.makeFunctionCallNode(location, base, arguments, expressionStart, expressionEnd, lastTokenEndPosition()); 2155 } 2156 m_nonLHSCount = nonLHSCount; 2157 break; 2158 } 2159 case DOT: { 2160 m_nonTrivialExpressionCount++; 2161 JSTextPosition expressionEnd = lastTokenEndPosition(); 2162 nextExpectIdentifier(LexerFlagsIgnoreReservedWords | TreeBuilder::DontBuildKeywords); 2163 matchOrFail(IDENT, "Expected a property name after '.'"); 2164 base = context.createDotAccess(location, base, m_token.m_data.ident, expressionStart, expressionEnd, tokenEndPosition()); 2165 next(); 2166 break; 2167 } 2168 default: 2169 goto endMemberExpression; 2170 } 2171 } 2172endMemberExpression: 2173 while (newCount--) 2174 base = context.createNewExpr(location, base, expressionStart, lastTokenEndPosition()); 2175 return base; 2176} 2177 2178static const char* operatorString(bool prefix, unsigned tok) 2179{ 2180 switch (tok) { 2181 case MINUSMINUS: 2182 case AUTOMINUSMINUS: 2183 return prefix ? "prefix-decrement" : "decrement"; 2184 2185 case PLUSPLUS: 2186 case AUTOPLUSPLUS: 2187 return prefix ? "prefix-increment" : "increment"; 2188 2189 case EXCLAMATION: 2190 return "logical-not"; 2191 2192 case TILDE: 2193 return "bitwise-not"; 2194 2195 case TYPEOF: 2196 return "typeof"; 2197 2198 case VOIDTOKEN: 2199 return "void"; 2200 2201 case DELETETOKEN: 2202 return "delete"; 2203 } 2204 RELEASE_ASSERT_NOT_REACHED(); 2205 return "error"; 2206} 2207 2208template <typename LexerType> 2209template <class TreeBuilder> TreeExpression Parser<LexerType>::parseUnaryExpression(TreeBuilder& context) 2210{ 2211 typename TreeBuilder::UnaryExprContext unaryExprContext(context); 2212 AllowInOverride allowInOverride(this); 2213 int tokenStackDepth = 0; 2214 bool modifiesExpr = false; 2215 bool requiresLExpr = false; 2216 unsigned lastOperator = 0; 2217 while (isUnaryOp(m_token.m_type)) { 2218 if (strictMode()) { 2219 switch (m_token.m_type) { 2220 case PLUSPLUS: 2221 case MINUSMINUS: 2222 case AUTOPLUSPLUS: 2223 case AUTOMINUSMINUS: 2224 semanticFailIfTrue(requiresLExpr, "The ", operatorString(true, lastOperator), " operator requires a reference expression"); 2225 modifiesExpr = true; 2226 requiresLExpr = true; 2227 break; 2228 case DELETETOKEN: 2229 semanticFailIfTrue(requiresLExpr, "The ", operatorString(true, lastOperator), " operator requires a reference expression"); 2230 requiresLExpr = true; 2231 break; 2232 default: 2233 semanticFailIfTrue(requiresLExpr, "The ", operatorString(true, lastOperator), " operator requires a reference expression"); 2234 break; 2235 } 2236 } 2237 lastOperator = m_token.m_type; 2238 m_nonLHSCount++; 2239 context.appendUnaryToken(tokenStackDepth, m_token.m_type, tokenStartPosition()); 2240 next(); 2241 m_nonTrivialExpressionCount++; 2242 } 2243 JSTextPosition subExprStart = tokenStartPosition(); 2244 ASSERT(subExprStart.offset >= subExprStart.lineStartOffset); 2245 JSTokenLocation location(tokenLocation()); 2246 TreeExpression expr = parseMemberExpression(context); 2247 if (!expr) { 2248 if (lastOperator) 2249 failWithMessage("Cannot parse subexpression of ", operatorString(true, lastOperator), "operator"); 2250 failWithMessage("Cannot parse member expression"); 2251 } 2252 bool isEvalOrArguments = false; 2253 if (strictMode() && !m_syntaxAlreadyValidated) { 2254 if (context.isResolve(expr)) 2255 isEvalOrArguments = *m_lastIdentifier == m_vm->propertyNames->eval || *m_lastIdentifier == m_vm->propertyNames->arguments; 2256 } 2257 failIfTrueIfStrict(isEvalOrArguments && modifiesExpr, "Cannot modify '", m_lastIdentifier->impl(), "' in strict mode"); 2258 switch (m_token.m_type) { 2259 case PLUSPLUS: 2260 m_nonTrivialExpressionCount++; 2261 m_nonLHSCount++; 2262 expr = context.makePostfixNode(location, expr, OpPlusPlus, subExprStart, lastTokenEndPosition(), tokenEndPosition()); 2263 m_assignmentCount++; 2264 failIfTrueIfStrict(isEvalOrArguments, "Cannot modify '", m_lastIdentifier->impl(), "' in strict mode"); 2265 semanticFailIfTrue(requiresLExpr, "The ", operatorString(false, lastOperator), " operator requires a reference expression"); 2266 lastOperator = PLUSPLUS; 2267 next(); 2268 break; 2269 case MINUSMINUS: 2270 m_nonTrivialExpressionCount++; 2271 m_nonLHSCount++; 2272 expr = context.makePostfixNode(location, expr, OpMinusMinus, subExprStart, lastTokenEndPosition(), tokenEndPosition()); 2273 m_assignmentCount++; 2274 failIfTrueIfStrict(isEvalOrArguments, "'", m_lastIdentifier->impl(), "' cannot be modified in strict mode"); 2275 semanticFailIfTrue(requiresLExpr, "The ", operatorString(false, lastOperator), " operator requires a reference expression"); 2276 lastOperator = PLUSPLUS; 2277 next(); 2278 break; 2279 default: 2280 break; 2281 } 2282 2283 JSTextPosition end = lastTokenEndPosition(); 2284 2285 if (!TreeBuilder::CreatesAST && (m_syntaxAlreadyValidated || !strictMode())) 2286 return expr; 2287 2288 location = tokenLocation(); 2289 location.line = m_lexer->lastLineNumber(); 2290 while (tokenStackDepth) { 2291 switch (context.unaryTokenStackLastType(tokenStackDepth)) { 2292 case EXCLAMATION: 2293 expr = context.createLogicalNot(location, expr); 2294 break; 2295 case TILDE: 2296 expr = context.makeBitwiseNotNode(location, expr); 2297 break; 2298 case MINUS: 2299 expr = context.makeNegateNode(location, expr); 2300 break; 2301 case PLUS: 2302 expr = context.createUnaryPlus(location, expr); 2303 break; 2304 case PLUSPLUS: 2305 case AUTOPLUSPLUS: 2306 expr = context.makePrefixNode(location, expr, OpPlusPlus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end); 2307 m_assignmentCount++; 2308 break; 2309 case MINUSMINUS: 2310 case AUTOMINUSMINUS: 2311 expr = context.makePrefixNode(location, expr, OpMinusMinus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end); 2312 m_assignmentCount++; 2313 break; 2314 case TYPEOF: 2315 expr = context.makeTypeOfNode(location, expr); 2316 break; 2317 case VOIDTOKEN: 2318 expr = context.createVoid(location, expr); 2319 break; 2320 case DELETETOKEN: 2321 failIfTrueIfStrict(context.isResolve(expr), "Cannot delete unqualified property '", m_lastIdentifier->impl(), "' in strict mode"); 2322 expr = context.makeDeleteNode(location, expr, context.unaryTokenStackLastStart(tokenStackDepth), end, end); 2323 break; 2324 default: 2325 // If we get here something has gone horribly horribly wrong 2326 CRASH(); 2327 } 2328 subExprStart = context.unaryTokenStackLastStart(tokenStackDepth); 2329 context.unaryTokenStackRemoveLast(tokenStackDepth); 2330 } 2331 return expr; 2332} 2333 2334 2335template <typename LexerType> void Parser<LexerType>::printUnexpectedTokenText(WTF::PrintStream& out) 2336{ 2337 switch (m_token.m_type) { 2338 case EOFTOK: 2339 out.print("Unexpected end of script"); 2340 return; 2341 case UNTERMINATED_IDENTIFIER_ESCAPE_ERRORTOK: 2342 case UNTERMINATED_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK: 2343 out.print("Incomplete unicode escape in identifier: '", getToken(), "'"); 2344 return; 2345 case UNTERMINATED_MULTILINE_COMMENT_ERRORTOK: 2346 out.print("Unterminated multiline comment"); 2347 return; 2348 case UNTERMINATED_NUMERIC_LITERAL_ERRORTOK: 2349 out.print("Unterminated numeric literal '", getToken(), "'"); 2350 return; 2351 case UNTERMINATED_STRING_LITERAL_ERRORTOK: 2352 out.print("Unterminated string literal '", getToken(), "'"); 2353 return; 2354 case INVALID_IDENTIFIER_ESCAPE_ERRORTOK: 2355 out.print("Invalid escape in identifier: '", getToken(), "'"); 2356 return; 2357 case INVALID_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK: 2358 out.print("Invalid unicode escape in identifier: '", getToken(), "'"); 2359 return; 2360 case INVALID_NUMERIC_LITERAL_ERRORTOK: 2361 out.print("Invalid numeric literal: '", getToken(), "'"); 2362 return; 2363 case INVALID_OCTAL_NUMBER_ERRORTOK: 2364 out.print("Invalid use of octal: '", getToken(), "'"); 2365 return; 2366 case INVALID_STRING_LITERAL_ERRORTOK: 2367 out.print("Invalid string literal: '", getToken(), "'"); 2368 return; 2369 case ERRORTOK: 2370 out.print("Unrecognized token '", getToken(), "'"); 2371 return; 2372 case STRING: 2373 out.print("Unexpected string literal ", getToken()); 2374 return; 2375 case NUMBER: 2376 out.print("Unexpected number '", getToken(), "'"); 2377 return; 2378 2379 case RESERVED_IF_STRICT: 2380 out.print("Unexpected use of reserved word '", getToken(), "' in strict mode"); 2381 return; 2382 2383 case RESERVED: 2384 out.print("Unexpected use of reserved word '", getToken(), "'"); 2385 return; 2386 2387 case INVALID_PRIVATE_NAME_ERRORTOK: 2388 out.print("Invalid private name '", getToken(), "'"); 2389 return; 2390 2391 case IDENT: 2392 out.print("Unexpected identifier '", getToken(), "'"); 2393 return; 2394 2395 default: 2396 break; 2397 } 2398 2399 if (m_token.m_type & KeywordTokenFlag) { 2400 out.print("Unexpected keyword '", getToken(), "'"); 2401 return; 2402 } 2403 2404 out.print("Unexpected token '", getToken(), "'"); 2405} 2406 2407// Instantiate the two flavors of Parser we need instead of putting most of this file in Parser.h 2408template class Parser<Lexer<LChar>>; 2409template class Parser<Lexer<UChar>>; 2410 2411} // namespace JSC 2412