2  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org) 
   3  *  Copyright (C) 2001 Peter Kelly (pmk@post.com) 
   4  *  Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc. All rights reserved. 
   6  *  This library is free software; you can redistribute it and/or 
   7  *  modify it under the terms of the GNU Library General Public 
   8  *  License as published by the Free Software Foundation; either 
   9  *  version 2 of the License, or (at your option) any later version. 
  11  *  This library is distributed in the hope that it will be useful, 
  12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of 
  13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
  14  *  Library General Public License for more details. 
  16  *  You should have received a copy of the GNU Library General Public License 
  17  *  along with this library; see the file COPYING.LIB.  If not, write to 
  18  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
  19  *  Boston, MA 02110-1301, USA. 
  26 #include "ASTBuilder.h" 
  27 #include "CodeBlock.h" 
  29 #include "JSCJSValueInlines.h" 
  32 #include "JSCInlines.h" 
  33 #include "SourceProvider.h" 
  36 #include <wtf/HashFunctions.h> 
  37 #include <wtf/OwnPtr.h> 
  38 #include <wtf/StringPrintStream.h> 
  39 #include <wtf/WTFThreadData.h> 
  42 #define updateErrorMessage(shouldPrintToken, ...) do {\ 
  44     logError(shouldPrintToken, __VA_ARGS__); \ 
  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 {\ 
  69 #define handleProductionOrFail(token, tokenString, operation, production) do {\ 
  70     consumeOrFail(token, "Expected '", tokenString, "' to ", operation, " a ", production);\ 
  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__); \ 
  86 template <typename LexerType
> 
  87 void Parser
<LexerType
>::logError(bool) 
  91     StringPrintStream stream
; 
  92     printUnexpectedTokenText(stream
); 
  93     setErrorMessage(stream
.toString()); 
  96 template <typename LexerType
> template <typename A
> 
  97 void Parser
<LexerType
>::logError(bool shouldPrintToken
, const A
& value1
) 
 101     StringPrintStream stream
; 
 102     if (shouldPrintToken
) { 
 103         printUnexpectedTokenText(stream
); 
 106     stream
.print(value1
, "."); 
 107     setErrorMessage(stream
.toString()); 
 110 template <typename LexerType
> template <typename A
, typename B
> 
 111 void Parser
<LexerType
>::logError(bool shouldPrintToken
, const A
& value1
, const B
& value2
) 
 115     StringPrintStream stream
; 
 116     if (shouldPrintToken
) { 
 117         printUnexpectedTokenText(stream
); 
 120     stream
.print(value1
, value2
, "."); 
 121     setErrorMessage(stream
.toString()); 
 124 template <typename LexerType
> template <typename A
, typename B
, typename C
> 
 125 void Parser
<LexerType
>::logError(bool shouldPrintToken
, const A
& value1
, const B
& value2
, const C
& value3
) 
 129     StringPrintStream stream
; 
 130     if (shouldPrintToken
) { 
 131         printUnexpectedTokenText(stream
); 
 134     stream
.print(value1
, value2
, value3
, "."); 
 135     setErrorMessage(stream
.toString()); 
 138 template <typename LexerType
> template <typename A
, typename B
, typename C
, typename D
> 
 139 void Parser
<LexerType
>::logError(bool shouldPrintToken
, const A
& value1
, const B
& value2
, const C
& value3
, const D
& value4
) 
 143     StringPrintStream stream
; 
 144     if (shouldPrintToken
) { 
 145         printUnexpectedTokenText(stream
); 
 148     stream
.print(value1
, value2
, value3
, value4
, "."); 
 149     setErrorMessage(stream
.toString()); 
 152 template <typename LexerType
> template <typename A
, typename B
, typename C
, typename D
, typename E
> 
 153 void Parser
<LexerType
>::logError(bool shouldPrintToken
, const A
& value1
, const B
& value2
, const C
& value3
, const D
& value4
, const E
& value5
) 
 157     StringPrintStream stream
; 
 158     if (shouldPrintToken
) { 
 159         printUnexpectedTokenText(stream
); 
 162     stream
.print(value1
, value2
, value3
, value4
, value5
, "."); 
 163     setErrorMessage(stream
.toString()); 
 166 template <typename LexerType
> template <typename A
, typename B
, typename C
, typename D
, typename E
, typename F
> 
 167 void Parser
<LexerType
>::logError(bool shouldPrintToken
, const A
& value1
, const B
& value2
, const C
& value3
, const D
& value4
, const E
& value5
, const F
& value6
) 
 171     StringPrintStream stream
; 
 172     if (shouldPrintToken
) { 
 173         printUnexpectedTokenText(stream
); 
 176     stream
.print(value1
, value2
, value3
, value4
, value5
, value6
, "."); 
 177     setErrorMessage(stream
.toString()); 
 180 template <typename LexerType
> template <typename A
, typename B
, typename C
, typename D
, typename E
, typename F
, typename G
> 
 181 void Parser
<LexerType
>::logError(bool shouldPrintToken
, const A
& value1
, const B
& value2
, const C
& value3
, const D
& value4
, const E
& value5
, const F
& value6
, const G
& value7
) 
 185     StringPrintStream stream
; 
 186     if (shouldPrintToken
) { 
 187         printUnexpectedTokenText(stream
); 
 190     stream
.print(value1
, value2
, value3
, value4
, value5
, value6
, value7
, "."); 
 191     setErrorMessage(stream
.toString()); 
 194 template <typename LexerType
> 
 195 Parser
<LexerType
>::Parser(VM
* vm
, const SourceCode
& source
, FunctionParameters
* parameters
, const Identifier
& name
, JSParserStrictness strictness
, JSParserMode parserMode
) 
 198     , m_hasStackOverflow(false) 
 200     , m_assignmentCount(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
) 
 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(); 
 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; 
 231             scope
->declareParameter(&static_cast<BindingNode
*>(parameter
)->boundProperty()); 
 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()) 
 239                 parameter
->collectBoundIdentifiers(boundParameterNames
); 
 241             for (auto& boundParameterName 
: boundParameterNames
) 
 242                 scope
->declareVariable(&boundParameterName
); 
 246         scope
->declareCallee(&name
); 
 250 template <typename LexerType
> 
 251 Parser
<LexerType
>::~Parser() 
 255 template <typename LexerType
> 
 256 String Parser
<LexerType
>::parseInner() 
 258     String parseError 
= String(); 
 260     ASTBuilder 
context(const_cast<VM
*>(m_vm
), const_cast<SourceCode
*>(m_source
)); 
 261     if (m_lexer
->isReparsing()) 
 263     ScopeRef scope 
= currentScope(); 
 264     SourceElements
* sourceElements 
= parseSourceElements(context
, CheckForStrictMode
); 
 265     if (!sourceElements 
|| !consume(EOFTOK
)) { 
 267             parseError 
= m_errorMessage
; 
 269             parseError 
= ASCIILiteral("Parser error"); 
 272     IdentifierSet capturedVariables
; 
 273     bool modifiedParameter 
= false; 
 274     scope
->getCapturedVariables(capturedVariables
, modifiedParameter
); 
 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
; 
 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()))) 
 293             if (scope
->hasDeclaredParameter(Identifier(m_vm
, variable
.get()))) 
 295             closedVariables
.append(variable
); 
 298     didFinishParsing(sourceElements
, context
.varDeclarations(), context
.funcDeclarations(), features
, 
 299         context
.numConstants(), capturedVariables
, WTF::move(closedVariables
)); 
 304 template <typename LexerType
> 
 305 void 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
) 
 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
; 
 317 template <typename LexerType
> 
 318 bool Parser
<LexerType
>::allowAutomaticSemicolon() 
 320     return match(CLOSEBRACE
) || match(EOFTOK
) || m_lexer
->prevTerminator(); 
 323 template <typename LexerType
> 
 324 template <class TreeBuilder
> TreeSourceElements Parser
<LexerType
>::parseSourceElements(TreeBuilder
& context
, SourceElementsMode mode
) 
 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
) { 
 336                 // "use strict" must be the exact literal without escape sequences or line continuation. 
 337                 if (!hasSetStrict 
&& directiveLiteralLength 
== lengthOfUseStrictLiteral 
&& m_vm
->propertyNames
->useStrictIdentifier 
== *directive
) { 
 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"); 
 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"); 
 353                     restoreSavePoint(savePoint
); 
 358                 seenNonDirective 
= true; 
 360         context
.appendStatement(sourceElements
, statement
); 
 364     return sourceElements
; 
 367 template <typename LexerType
> 
 368 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseVarDeclaration(TreeBuilder
& context
) 
 371     JSTokenLocation 
location(tokenLocation()); 
 372     int start 
= tokenLine(); 
 375     TreeDeconstructionPattern scratch1 
= 0; 
 376     TreeExpression scratch2 
= 0; 
 377     JSTextPosition scratch3
; 
 378     TreeExpression varDecls 
= parseVarDeclarationList(context
, scratch
, scratch1
, scratch2
, scratch3
, scratch3
, scratch3
); 
 380     failIfFalse(autoSemiColon(), "Expected ';' after var declaration"); 
 382     return context
.createVarStatement(location
, varDecls
, start
, end
); 
 385 template <typename LexerType
> 
 386 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseConstDeclaration(TreeBuilder
& context
) 
 388     ASSERT(match(CONSTTOKEN
)); 
 389     JSTokenLocation 
location(tokenLocation()); 
 390     int start 
= tokenLine(); 
 392     TreeConstDeclList constDecls 
= parseConstDeclarationList(context
); 
 394     failIfFalse(autoSemiColon(), "Expected ';' after const declaration"); 
 396     return context
.createConstStatement(location
, constDecls
, start
, end
); 
 399 template <typename LexerType
> 
 400 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseDoWhileStatement(TreeBuilder
& context
) 
 403     int startLine 
= tokenLine(); 
 405     const Identifier
* unused 
= 0; 
 407     TreeStatement statement 
= parseStatement(context
, unused
); 
 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
); 
 423 template <typename LexerType
> 
 424 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseWhileStatement(TreeBuilder
& context
) 
 426     ASSERT(match(WHILE
)); 
 427     JSTokenLocation 
location(tokenLocation()); 
 428     int startLine 
= tokenLine(); 
 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"); 
 438     const Identifier
* unused 
= 0; 
 440     TreeStatement statement 
= parseStatement(context
, unused
); 
 442     failIfFalse(statement
, "Expected a statement as the body of a while loop"); 
 443     return context
.createWhileStatement(location
, expr
, statement
, startLine
, endLine
); 
 446 template <typename LexerType
> 
 447 template <class TreeBuilder
> TreeExpression Parser
<LexerType
>::parseVarDeclarationList(TreeBuilder
& context
, int& declarations
, TreeDeconstructionPattern
& lastPattern
, TreeExpression
& lastInitializer
, JSTextPosition
& identStart
, JSTextPosition
& initStart
, JSTextPosition
& initEnd
) 
 449     TreeExpression varDecls 
= 0; 
 450     const Identifier
* lastIdent
; 
 454         JSTokenLocation 
location(tokenLocation()); 
 456         TreeExpression node 
= 0; 
 458         bool hasInitializer 
= false; 
 460             JSTextPosition varStart 
= tokenStartPosition(); 
 461             identStart 
= varStart
; 
 462             const Identifier
* name 
= m_token
.m_data
.ident
; 
 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(), "'"); 
 477                 node 
= context
.createAssignResolve(location
, *name
, initializer
, varStart
, varDivot
, lastTokenEndPosition()); 
 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
; 
 493         if (hasInitializer
) { 
 497                 varDecls 
= context
.combineCommaNodes(location
, varDecls
, node
); 
 499     } while (match(COMMA
)); 
 501         lastPattern 
= createBindingPattern(context
, DeconstructToVariables
, *lastIdent
, 0); 
 505 template <typename LexerType
> 
 506 template <class TreeBuilder
> TreeDeconstructionPattern Parser
<LexerType
>::createBindingPattern(TreeBuilder
& context
, DeconstructionKind kind
, const Identifier
& name
, int depth
) 
 508     ASSERT(!name
.isEmpty()); 
 509     ASSERT(!name
.isNull()); 
 511     ASSERT(name
.impl()->isAtomic()); 
 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"); 
 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(), "'"); 
 533         if (kind 
!= DeconstructToExpressions
) 
 534             context
.addVar(&name
, DeclarationStacks::HasInitializer
); 
 537         if (kind 
== DeconstructToVariables
) { 
 538             failIfFalseIfStrict(declareVariable(&name
), "Cannot declare a variable named '", name
.impl(), "' in strict mode"); 
 539             context
.addVar(&name
, DeclarationStacks::HasInitializer
); 
 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"); 
 555     return context
.createBindingLocation(m_token
.m_location
, name
, m_token
.m_startPosition
, m_token
.m_endPosition
); 
 558 template <typename LexerType
> 
 559 template <class TreeBuilder
> TreeDeconstructionPattern Parser
<LexerType
>::tryParseDeconstructionPatternExpression(TreeBuilder
& context
) 
 561     return parseDeconstructionPattern(context
, DeconstructToExpressions
); 
 564 template <typename LexerType
> 
 565 template <class TreeBuilder
> TreeDeconstructionPattern Parser
<LexerType
>::parseDeconstructionPattern(TreeBuilder
& context
, DeconstructionKind kind
, int depth
) 
 567     failIfStackOverflow(); 
 568     int nonLHSCount 
= m_nonLHSCount
; 
 569     TreeDeconstructionPattern pattern
; 
 570     switch (m_token
.m_type
) { 
 572         auto arrayPattern 
= context
.createArrayPattern(m_token
.m_location
); 
 574         if (kind 
== DeconstructToExpressions 
&& match(CLOSEBRACKET
)) 
 576         failIfTrue(match(CLOSEBRACKET
), "There must be at least one bound property in an array deconstruction pattern"); 
 578             while (match(COMMA
)) { 
 579                 context
.appendArrayPatternSkipEntry(arrayPattern
, m_token
.m_location
); 
 583             JSTokenLocation location 
= m_token
.m_location
; 
 584             auto innerPattern 
= parseDeconstructionPattern(context
, kind
, depth 
+ 1); 
 585             if (kind 
== DeconstructToExpressions 
&& !innerPattern
) 
 587             failIfFalse(innerPattern
, "Cannot parse this deconstruction pattern"); 
 588             context
.appendArrayPatternEntry(arrayPattern
, location
, innerPattern
); 
 589         } while (consume(COMMA
)); 
 591         if (kind 
== DeconstructToExpressions 
&& !match(CLOSEBRACKET
)) 
 594         consumeOrFail(CLOSEBRACKET
, "Expected either a closing ']' or a ',' following an element deconstruction pattern"); 
 595         pattern 
= arrayPattern
; 
 601         if (kind 
== DeconstructToExpressions 
&& match(CLOSEBRACE
)) 
 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; 
 608             Identifier propertyName
; 
 609             TreeDeconstructionPattern innerPattern 
= 0; 
 610             JSTokenLocation location 
= m_token
.m_location
; 
 612                 propertyName 
= *m_token
.m_data
.ident
; 
 615                     innerPattern 
= parseDeconstructionPattern(context
, kind
, depth 
+ 1); 
 617                     innerPattern 
= createBindingPattern(context
, kind
, propertyName
, depth
); 
 619                 JSTokenType tokenType 
= m_token
.m_type
; 
 620                 switch (m_token
.m_type
) { 
 622                     propertyName 
= Identifier::from(m_vm
, m_token
.m_data
.doubleValue
); 
 625                     propertyName 
= *m_token
.m_data
.ident
; 
 629                     if (m_token
.m_type 
!= RESERVED 
&& m_token
.m_type 
!= RESERVED_IF_STRICT 
&& !(m_token
.m_type 
& KeywordTokenFlag
)) { 
 630                         if (kind 
== DeconstructToExpressions
) 
 632                         failWithMessage("Expected a property name"); 
 634                     propertyName 
= *m_token
.m_data
.ident
; 
 638                 if (!consume(COLON
)) { 
 639                     if (kind 
== DeconstructToExpressions
) 
 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(), "'"); 
 645                     failWithMessage("Expected a ':' prior to named property deconstruction"); 
 647                 innerPattern 
= parseDeconstructionPattern(context
, kind
, depth 
+ 1); 
 649             if (kind 
== DeconstructToExpressions 
&& !innerPattern
) 
 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
)) 
 656         consumeOrFail(CLOSEBRACE
, "Expected either a closing '}' or an ',' after a property deconstruction pattern"); 
 657         pattern 
= objectPattern
; 
 663             if (kind 
== DeconstructToExpressions
) 
 665             semanticFailureDueToKeyword("variable name"); 
 666             failWithMessage("Expected a parameter pattern or a ')' in parameter list"); 
 668         pattern 
= createBindingPattern(context
, kind
, *m_token
.m_data
.ident
, depth
); 
 673     m_nonLHSCount 
= nonLHSCount
; 
 677 template <typename LexerType
> 
 678 template <class TreeBuilder
> TreeConstDeclList Parser
<LexerType
>::parseConstDeclarationList(TreeBuilder
& context
) 
 680     failIfTrue(strictMode(), "Const declarations are not supported in strict mode"); 
 681     TreeConstDeclList constDecls 
= 0; 
 682     TreeConstDeclList tail 
= 0; 
 684         JSTokenLocation 
location(tokenLocation()); 
 686         matchOrFail(IDENT
, "Expected an identifier name in const declaration"); 
 687         const Identifier
* name 
= m_token
.m_data
.ident
; 
 689         bool hasInitializer 
= match(EQUAL
); 
 690         declareVariable(name
); 
 691         context
.addVar(name
, DeclarationStacks::IsConstant 
| (hasInitializer 
? DeclarationStacks::HasInitializer 
: 0)); 
 693         TreeExpression initializer 
= 0; 
 694         if (hasInitializer
) { 
 695             next(TreeBuilder::DontBuildStrings
); // consume '=' 
 696             initializer 
= parseAssignmentExpression(context
); 
 697             failIfFalse(!!initializer
, "Unable to parse initializer"); 
 699         tail 
= context
.appendConstDecl(location
, tail
, name
, initializer
); 
 702     } while (match(COMMA
)); 
 706 template <typename LexerType
> 
 707 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseForStatement(TreeBuilder
& context
) 
 710     JSTokenLocation 
location(tokenLocation()); 
 711     int startLine 
= tokenLine(); 
 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; 
 722          for (var IDENT in expression) statement 
 723          for (var varDeclarationList; expressionOpt; expressionOpt) 
 725         TreeDeconstructionPattern forInTarget 
= 0; 
 726         TreeExpression forInInitializer 
= 0; 
 728         JSTextPosition initStart
; 
 729         JSTextPosition initEnd
; 
 730         decls 
= parseVarDeclarationList(context
, declarations
, forInTarget
, forInInitializer
, declsStart
, initStart
, initEnd
); 
 734         // Remainder of a standard for loop is handled identically 
 735         if (match(SEMICOLON
)) 
 736             goto standardForLoop
; 
 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"); 
 741         if (forInInitializer
) 
 742             failIfFalse(context
.isBindingNode(forInTarget
), "Cannot use initialiser syntax when binding to a pattern during enumeration"); 
 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"); 
 753         TreeExpression expr 
= parseExpression(context
); 
 754         failIfFalse(expr
, "Expected expression to enumerate"); 
 755         JSTextPosition exprEnd 
= lastTokenEndPosition(); 
 757         int endLine 
= tokenLine(); 
 759         handleProductionOrFail(CLOSEPAREN
, ")", "end", (isOfEnumeration 
? "for-of header" : "for-in header")); 
 761         const Identifier
* unused 
= 0; 
 763         TreeStatement statement 
= parseStatement(context
, unused
); 
 765         failIfFalse(statement
, "Expected statement as body of for-", isOfEnumeration 
? "of" : "in", " statement"); 
 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
); 
 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
; 
 780             restoreSavePoint(savePoint
); 
 783         declsStart 
= tokenStartPosition(); 
 784         decls 
= parseExpression(context
); 
 785         declsEnd 
= lastTokenEndPosition(); 
 787         failIfFalse(decls
, "Cannot parse for loop declarations"); 
 790     if (match(SEMICOLON
)) { 
 794         TreeExpression condition 
= 0; 
 796         if (!match(SEMICOLON
)) { 
 797             condition 
= parseExpression(context
); 
 798             failIfFalse(condition
, "Cannot parse for loop condition expression"); 
 800         consumeOrFail(SEMICOLON
, "Expected a ';' after the for loop condition expression"); 
 802         TreeExpression increment 
= 0; 
 803         if (!match(CLOSEPAREN
)) { 
 804             increment 
= parseExpression(context
); 
 805             failIfFalse(increment
, "Cannot parse for loop iteration expression"); 
 807         int endLine 
= tokenLine(); 
 808         handleProductionOrFail(CLOSEPAREN
, ")", "end", "for-loop header"); 
 809         const Identifier
* unused 
= 0; 
 811         TreeStatement statement 
= parseStatement(context
, unused
); 
 813         failIfFalse(statement
, "Expected a statement as the body of a for loop"); 
 814         return context
.createForLoop(location
, decls
, condition
, increment
, statement
, startLine
, endLine
); 
 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; 
 826     TreeExpression expr 
= parseExpression(context
); 
 827     failIfFalse(expr
, "Cannot parse subject for-", isOfEnumeration 
? "of" : "in", " statement"); 
 828     JSTextPosition exprEnd 
= lastTokenEndPosition(); 
 829     int endLine 
= tokenLine(); 
 831     handleProductionOrFail(CLOSEPAREN
, ")", "end", (isOfEnumeration 
? "for-of header" : "for-in header")); 
 832     const Identifier
* unused 
= 0; 
 834     TreeStatement statement 
= parseStatement(context
, unused
); 
 836     failIfFalse(statement
, "Expected a statement as the body of a for-", isOfEnumeration 
? "of" : "in", "loop"); 
 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
); 
 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
); 
 848 template <typename LexerType
> 
 849 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseBreakStatement(TreeBuilder
& context
) 
 851     ASSERT(match(BREAK
)); 
 852     JSTokenLocation 
location(tokenLocation()); 
 853     JSTextPosition start 
= tokenStartPosition(); 
 854     JSTextPosition end 
= tokenEndPosition(); 
 857     if (autoSemiColon()) { 
 858         semanticFailIfFalse(breakIsValid(), "'break' is only valid inside a switch or loop statement"); 
 859         return context
.createBreakStatement(location
, start
, end
); 
 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(); 
 866     failIfFalse(autoSemiColon(), "Expected a ';' following a targeted break statement"); 
 867     return context
.createBreakStatement(location
, ident
, start
, end
); 
 870 template <typename LexerType
> 
 871 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseContinueStatement(TreeBuilder
& context
) 
 873     ASSERT(match(CONTINUE
)); 
 874     JSTokenLocation 
location(tokenLocation()); 
 875     JSTextPosition start 
= tokenStartPosition(); 
 876     JSTextPosition end 
= tokenEndPosition(); 
 879     if (autoSemiColon()) { 
 880         semanticFailIfFalse(continueIsValid(), "'continue' is only valid inside a loop statement"); 
 881         return context
.createContinueStatement(location
, start
, end
); 
 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(); 
 890     failIfFalse(autoSemiColon(), "Expected a ';' following a targeted continue statement"); 
 891     return context
.createContinueStatement(location
, ident
, start
, end
); 
 894 template <typename LexerType
> 
 895 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseReturnStatement(TreeBuilder
& context
) 
 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(); 
 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 
 906     if (match(SEMICOLON
)) 
 907         end 
= tokenEndPosition(); 
 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
); 
 921 template <typename LexerType
> 
 922 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseThrowStatement(TreeBuilder
& context
) 
 924     ASSERT(match(THROW
)); 
 925     JSTokenLocation 
location(tokenLocation()); 
 926     JSTextPosition start 
= tokenStartPosition(); 
 928     failIfTrue(match(SEMICOLON
), "Expected expression after 'throw'"); 
 929     semanticFailIfTrue(autoSemiColon(), "Cannot have a newline after 'throw'"); 
 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"); 
 936     return context
.createThrowStatement(location
, expr
, start
, end
); 
 939 template <typename LexerType
> 
 940 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseWithStatement(TreeBuilder
& context
) 
 943     JSTokenLocation 
location(tokenLocation()); 
 944     semanticFailIfTrue(strictMode(), "'with' statements are not valid in strict mode"); 
 945     currentScope()->setNeedsFullActivation(); 
 946     int startLine 
= tokenLine(); 
 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"); 
 960     return context
.createWithStatement(location
, expr
, statement
, start
, end
, startLine
, endLine
); 
 963 template <typename LexerType
> 
 964 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseSwitchStatement(TreeBuilder
& context
) 
 966     ASSERT(match(SWITCH
)); 
 967     JSTokenLocation 
location(tokenLocation()); 
 968     int startLine 
= tokenLine(); 
 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(); 
 975     handleProductionOrFail(CLOSEPAREN
, ")", "end", "subject of a 'switch'"); 
 976     handleProductionOrFail(OPENBRACE
, "{", "start", "body of a 'switch'"); 
 978     TreeClauseList firstClauses 
= parseSwitchClauses(context
); 
 981     TreeClause defaultClause 
= parseSwitchDefaultClause(context
); 
 984     TreeClauseList secondClauses 
= parseSwitchClauses(context
); 
 987     handleProductionOrFail(CLOSEBRACE
, "}", "end", "body of a 'switch'"); 
 989     return context
.createSwitchStatement(location
, expr
, firstClauses
, defaultClause
, secondClauses
, startLine
, endLine
); 
 993 template <typename LexerType
> 
 994 template <class TreeBuilder
> TreeClauseList Parser
<LexerType
>::parseSwitchClauses(TreeBuilder
& context
) 
 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
; 
1008     while (match(CASE
)) { 
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
); 
1021 template <typename LexerType
> 
1022 template <class TreeBuilder
> TreeClause Parser
<LexerType
>::parseSwitchDefaultClause(TreeBuilder
& context
) 
1024     if (!match(DEFAULT
)) 
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
); 
1033 template <typename LexerType
> 
1034 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseTryStatement(TreeBuilder
& context
) 
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(); 
1044     matchOrFail(OPENBRACE
, "Expected a block statement as body of a try statement"); 
1046     tryBlock 
= parseBlockStatement(context
); 
1047     failIfFalse(tryBlock
, "Cannot parse the body of try block"); 
1048     int lastLine 
= m_lastTokenEndPosition
.line
; 
1051         currentScope()->setNeedsFullActivation(); 
1054         handleProductionOrFail(OPENPAREN
, "(", "start", "'catch' target"); 
1055         if (!match(IDENT
)) { 
1056             semanticFailureDueToKeyword("catch variable name"); 
1057             failWithMessage("Expected identifier name as catch target"); 
1059         ident 
= m_token
.m_data
.ident
; 
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"); 
1071     if (match(FINALLY
)) { 
1073         matchOrFail(OPENBRACE
, "Expected block statement for finally body"); 
1074         finallyBlock 
= parseBlockStatement(context
); 
1075         failIfFalse(finallyBlock
, "Cannot parse finally body"); 
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
); 
1081 template <typename LexerType
> 
1082 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseDebuggerStatement(TreeBuilder
& context
) 
1084     ASSERT(match(DEBUGGER
)); 
1085     JSTokenLocation 
location(tokenLocation()); 
1086     int startLine 
= tokenLine(); 
1087     int endLine 
= startLine
; 
1089     if (match(SEMICOLON
)) 
1090         startLine 
= tokenLine(); 
1091     failIfFalse(autoSemiColon(), "Debugger keyword must be followed by a ';'"); 
1092     return context
.createDebugger(location
, startLine
, endLine
); 
1095 template <typename LexerType
> 
1096 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseBlockStatement(TreeBuilder
& context
) 
1098     ASSERT(match(OPENBRACE
)); 
1099     JSTokenLocation 
location(tokenLocation()); 
1100     int start 
= tokenLine(); 
1102     if (match(CLOSEBRACE
)) { 
1104         return context
.createBlockStatement(location
, 0, start
, m_lastTokenEndPosition
.line
); 
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"); 
1110     return context
.createBlockStatement(location
, subtree
, start
, m_lastTokenEndPosition
.line
); 
1113 template <typename LexerType
> 
1114 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseStatement(TreeBuilder
& context
, const Identifier
*& directive
, unsigned* directiveLiteralLength
) 
1116     DepthManager 
statementDepth(&m_statementDepth
); 
1119     int nonTrivialExpressionCount 
= 0; 
1120     failIfStackOverflow(); 
1121     switch (m_token
.m_type
) { 
1123         return parseBlockStatement(context
); 
1125         return parseVarDeclaration(context
); 
1127         return parseConstDeclaration(context
); 
1129         failIfFalseIfStrict(m_statementDepth 
== 1, "Strict mode does not allow function declarations in a lexically nested statement"); 
1130         return parseFunctionDeclaration(context
); 
1132         JSTokenLocation 
location(tokenLocation()); 
1134         return context
.createEmptyStatement(location
); 
1137         return parseIfStatement(context
); 
1139         return parseDoWhileStatement(context
); 
1141         return parseWhileStatement(context
); 
1143         return parseForStatement(context
); 
1145         return parseContinueStatement(context
); 
1147         return parseBreakStatement(context
); 
1149         return parseReturnStatement(context
); 
1151         return parseWithStatement(context
); 
1153         return parseSwitchStatement(context
); 
1155         return parseThrowStatement(context
); 
1157         return parseTryStatement(context
); 
1159         return parseDebuggerStatement(context
); 
1164         // These tokens imply the end of a set of source elements 
1167         return parseExpressionOrLabelStatement(context
); 
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
; 
1175         TreeStatement exprStatement 
= parseExpressionStatement(context
); 
1176         if (directive 
&& nonTrivialExpressionCount 
!= m_nonTrivialExpressionCount
) 
1178         return exprStatement
; 
1182 template <typename LexerType
> 
1183 template <class TreeBuilder
> TreeFormalParameterList Parser
<LexerType
>::parseFormalParameters(TreeBuilder
& context
) 
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
); 
1197 template <typename LexerType
> 
1198 template <class TreeBuilder
> TreeFunctionBody Parser
<LexerType
>::parseFunctionBody(TreeBuilder
& context
) 
1200     JSTokenLocation 
startLocation(tokenLocation()); 
1201     unsigned startColumn 
= tokenColumn(); 
1204     if (match(CLOSEBRACE
)) { 
1205         unsigned endColumn 
= tokenColumn(); 
1206         return context
.createFunctionBody(startLocation
, tokenLocation(), startColumn
, endColumn
, strictMode()); 
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()); 
1216 static const char* stringForFunctionMode(FunctionParseMode mode
) 
1226     RELEASE_ASSERT_NOT_REACHED(); 
1230 template <typename LexerType
> 
1231 template <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
) 
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; 
1239         name 
= m_token
.m_data
.ident
; 
1240         m_lastFunctionName 
= name
; 
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(); 
1251     if (!consume(OPENPAREN
)) { 
1252         semanticFailureDueToKeyword(stringForFunctionMode(mode
), " name"); 
1253         failWithMessage("Expected an opening '(' before a ", stringForFunctionMode(mode
), "'s parameter list"); 
1255     if (!match(CLOSEPAREN
)) { 
1256         parameters 
= parseFormalParameters(context
); 
1257         failIfFalse(parameters
, "Cannot parse parameters for this ", stringForFunctionMode(mode
)); 
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"); 
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()); 
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
; 
1273         endLocation
.line 
= cachedInfo
->closeBraceLine
; 
1274         endLocation
.startOffset 
= cachedInfo
->closeBraceOffset
; 
1275         endLocation
.lineStartOffset 
= cachedInfo
->closeBraceLineStartOffset
; 
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
; 
1283         body 
= context
.createFunctionBody(startLocation
, endLocation
, bodyStartColumn
, bodyEndColumn
, cachedInfo
->strictMode
); 
1285         functionScope
->restoreFromSourceProviderCache(cachedInfo
); 
1286         failIfFalse(popScope(functionScope
, TreeBuilder::NeedsFreeVariableInfo
), "Parser error"); 
1288         closeBraceOffset 
= cachedInfo
->closeBraceOffset
; 
1290         context
.setFunctionNameStart(body
, functionNameStart
); 
1291         m_token 
= cachedInfo
->closeBraceToken(); 
1293         m_lexer
->setOffset(m_token
.m_location
.endOffset
, m_token
.m_location
.lineStartOffset
); 
1294         m_lexer
->setLineNumber(m_token
.m_location
.line
); 
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"); 
1309     closeBraceOffset 
= m_token
.m_data
.offset
; 
1310     unsigned closeBraceLine 
= m_token
.m_data
.line
; 
1311     unsigned closeBraceLineStartOffset 
= m_token
.m_data
.lineStartOffset
; 
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
); 
1328     context
.setFunctionNameStart(body
, functionNameStart
); 
1330     failIfFalse(popScope(functionScope
, TreeBuilder::NeedsFreeVariableInfo
), "Parser error"); 
1331     matchOrFail(CLOSEBRACE
, "Expected a closing '}' after a ", stringForFunctionMode(mode
), " body"); 
1334         m_functionCache
->add(openBraceOffset
, WTF::move(newInfo
)); 
1340 template <typename LexerType
> 
1341 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseFunctionDeclaration(TreeBuilder
& context
) 
1343     ASSERT(match(FUNCTION
)); 
1344     JSTokenLocation 
location(tokenLocation()); 
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
); 
1360     LabelInfo(const Identifier
* ident
, const JSTextPosition
& start
, const JSTextPosition
& end
) 
1367     const Identifier
* m_ident
; 
1368     JSTextPosition m_start
; 
1369     JSTextPosition m_end
; 
1372 template <typename LexerType
> 
1373 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseExpressionOrLabelStatement(TreeBuilder
& context
) 
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. 
1379     Vector
<LabelInfo
> labels
; 
1380     JSTokenLocation location
; 
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
); 
1394         const Identifier
* ident 
= m_token
.m_data
.ident
; 
1395         JSTextPosition end 
= tokenEndPosition(); 
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
)); 
1406     } while (match(IDENT
)); 
1407     bool isLoop 
= false; 
1408     switch (m_token
.m_type
) { 
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
); 
1423     TreeStatement statement 
= parseStatement(context
, unused
); 
1424     if (!m_syntaxAlreadyValidated
) { 
1425         for (size_t i 
= 0; i 
< labels
.size(); i
++) 
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
); 
1436 template <typename LexerType
> 
1437 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseExpressionStatement(TreeBuilder
& context
) 
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
); 
1447 template <typename LexerType
> 
1448 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseIfStatement(TreeBuilder
& context
) 
1451     JSTokenLocation 
ifLocation(tokenLocation()); 
1452     int start 
= tokenLine(); 
1454     handleProductionOrFail(OPENPAREN
, "(", "start", "'if' condition"); 
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"); 
1461     const Identifier
* unused 
= 0; 
1462     TreeStatement trueBlock 
= parseStatement(context
, unused
); 
1463     failIfFalse(trueBlock
, "Expected a statement as the body of an if block"); 
1466         return context
.createIfStatement(ifLocation
, condition
, trueBlock
, 0, start
, end
); 
1468     Vector
<TreeExpression
> exprStack
; 
1469     Vector
<std::pair
<int, int>> posStack
; 
1470     Vector
<JSTokenLocation
> tokenLocationStack
; 
1471     Vector
<TreeStatement
> statementStack
; 
1472     bool trailingElse 
= false; 
1474         JSTokenLocation tempLocation 
= tokenLocation(); 
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; 
1484         int innerStart 
= tokenLine(); 
1487         handleProductionOrFail(OPENPAREN
, "(", "start", "'if' condition"); 
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
)); 
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
)); 
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
)); 
1528     return context
.createIfStatement(ifLocation
, condition
, trueBlock
, statementStack
.last(), start
, end
); 
1531 template <typename LexerType
> 
1532 template <class TreeBuilder
> TreeExpression Parser
<LexerType
>::parseExpression(TreeBuilder
& context
) 
1534     failIfStackOverflow(); 
1535     JSTokenLocation 
location(tokenLocation()); 
1536     TreeExpression node 
= parseAssignmentExpression(context
); 
1537     failIfFalse(node
, "Cannot parse expression"); 
1541     m_nonTrivialExpressionCount
++; 
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
); 
1555 template <typename LexerType
> 
1556 template <typename TreeBuilder
> TreeExpression Parser
<LexerType
>::parseAssignmentExpression(TreeBuilder
& context
) 
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
); 
1569                 return context
.createDeconstructingAssignment(location
, pattern
, rhs
); 
1571         restoreSavePoint(savePoint
); 
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"); 
1582     int assignmentStack 
= 0; 
1584     bool hadAssignment 
= false; 
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; 
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; 
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"); 
1626     if (!TreeBuilder::CreatesAST
) 
1629     while (assignmentStack
) 
1630         lhs 
= context
.createAssignment(location
, assignmentStack
, lhs
, initialAssignmentCount
, m_assignmentCount
, lastTokenEndPosition()); 
1635 template <typename LexerType
> 
1636 template <class TreeBuilder
> TreeExpression Parser
<LexerType
>::parseConditionalExpression(TreeBuilder
& context
) 
1638     JSTokenLocation 
location(tokenLocation()); 
1639     TreeExpression cond 
= parseBinaryExpression(context
); 
1640     failIfFalse(cond
, "Cannot parse expression"); 
1641     if (!match(QUESTION
)) 
1643     m_nonTrivialExpressionCount
++; 
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"); 
1650     TreeExpression rhs 
= parseAssignmentExpression(context
); 
1651     failIfFalse(rhs
, "Cannot parse right hand side of ternary operator"); 
1652     return context
.createConditionalExpr(location
, cond
, lhs
, rhs
); 
1655 ALWAYS_INLINE 
static bool isUnaryOp(JSTokenType token
) 
1657     return token 
& UnaryOpTokenFlag
; 
1660 template <typename LexerType
> 
1661 int Parser
<LexerType
>::isBinaryOperator(JSTokenType token
) 
1664         return token 
& (BinaryOpTokenPrecedenceMask 
<< BinaryOpTokenAllowsInPrecedenceAdditionalShift
); 
1665     return token 
& BinaryOpTokenPrecedenceMask
; 
1668 template <typename LexerType
> 
1669 template <class TreeBuilder
> TreeExpression Parser
<LexerType
>::parseBinaryExpression(TreeBuilder
& context
) 
1672     int operandStackDepth 
= 0; 
1673     int operatorStackDepth 
= 0; 
1674     typename 
TreeBuilder::BinaryExprContext 
binaryExprContext(context
); 
1675     JSTokenLocation 
location(tokenLocation()); 
1677         JSTextPosition exprStart 
= tokenStartPosition(); 
1678         int initialAssignments 
= m_assignmentCount
; 
1679         TreeExpression current 
= parseUnaryExpression(context
); 
1680         failIfFalse(current
, "Cannot parse expression"); 
1682         context
.appendBinaryExpressionInfo(operandStackDepth
, current
, exprStart
, lastTokenEndPosition(), lastTokenEndPosition(), initialAssignments 
!= m_assignmentCount
); 
1683         int precedence 
= isBinaryOperator(m_token
.m_type
); 
1686         m_nonTrivialExpressionCount
++; 
1688         int operatorToken 
= m_token
.m_type
; 
1689         next(TreeBuilder::DontBuildStrings
); 
1691         while (operatorStackDepth 
&&  context
.operatorStackHasHigherPrecedence(operatorStackDepth
, precedence
)) { 
1692             ASSERT(operandStackDepth 
> 1); 
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
); 
1700         context
.operatorStackAppend(operatorStackDepth
, operatorToken
, precedence
); 
1702     while (operatorStackDepth
) { 
1703         ASSERT(operandStackDepth 
> 1); 
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
); 
1711     return context
.popOperandStack(operandStackDepth
); 
1714 template <typename LexerType
> 
1715 template <class TreeBuilder
> TreeProperty Parser
<LexerType
>::parseProperty(TreeBuilder
& context
, bool complete
) 
1717     bool wasIdent 
= false; 
1718     switch (m_token
.m_type
) { 
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
); 
1728             nextExpectIdentifier(LexerFlagsIgnoreReservedWords 
| TreeBuilder::DontBuildKeywords
); 
1732             TreeExpression node 
= parseAssignmentExpression(context
); 
1733             failIfFalse(node
, "Cannot parse expression for property declaration"); 
1734             return context
.createProperty(ident
, node
, PropertyNode::Constant
, complete
); 
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
; 
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
; 
1758             failDueToUnexpectedToken(); 
1759         JSTokenLocation 
location(tokenLocation()); 
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"); 
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"); 
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
); 
1773         double propertyName 
= m_token
.m_data
.doubleValue
; 
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
); 
1782         auto propertyName 
= parseExpression(context
); 
1783         failIfFalse(propertyName
, "Cannot parse computed property name"); 
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
); 
1792         failIfFalse(m_token
.m_type 
& KeywordTokenFlag
, "Expected a property name"); 
1797 template <typename LexerType
> 
1798 template <class TreeBuilder
> TreeExpression Parser
<LexerType
>::parseObjectLiteral(TreeBuilder
& context
) 
1800     auto savePoint 
= createSavePoint(); 
1801     consumeOrFailWithFlags(OPENBRACE
, TreeBuilder::DontBuildStrings
, "Expected opening '{' at the start of an object literal"); 
1802     JSTokenLocation 
location(tokenLocation()); 
1804     int oldNonLHSCount 
= m_nonLHSCount
; 
1806     if (match(CLOSEBRACE
)) { 
1808         return context
.createObjectLiteral(location
); 
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
); 
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
)) 
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
); 
1831         tail 
= context
.createPropertyList(propertyLocation
, property
, tail
); 
1834     location 
= tokenLocation(); 
1835     handleProductionOrFail(CLOSEBRACE
, "}", "end", "object literal"); 
1837     m_nonLHSCount 
= oldNonLHSCount
; 
1839     return context
.createObjectLiteral(location
, propertyList
); 
1842 template <typename LexerType
> 
1843 template <class TreeBuilder
> TreeExpression Parser
<LexerType
>::parseStrictObjectLiteral(TreeBuilder
& context
) 
1845     consumeOrFail(OPENBRACE
, "Expected opening '{' at the start of an object literal"); 
1847     int oldNonLHSCount 
= m_nonLHSCount
; 
1849     JSTokenLocation 
location(tokenLocation()); 
1850     if (match(CLOSEBRACE
)) { 
1852         return context
.createObjectLiteral(location
); 
1855     TreeProperty property 
= parseProperty(context
, true); 
1856     failIfFalse(property
, "Cannot parse object literal property"); 
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
)); 
1864     TreePropertyList propertyList 
= context
.createPropertyList(location
, property
); 
1865     TreePropertyList tail 
= propertyList
; 
1866     while (match(COMMA
)) { 
1868         // allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939 
1869         if (match(CLOSEBRACE
)) 
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
); 
1883         tail 
= context
.createPropertyList(propertyLocation
, property
, tail
); 
1886     location 
= tokenLocation(); 
1887     handleProductionOrFail(CLOSEBRACE
, "}", "end", "object literal"); 
1889     m_nonLHSCount 
= oldNonLHSCount
; 
1891     return context
.createObjectLiteral(location
, propertyList
); 
1894 template <typename LexerType
> 
1895 template <class TreeBuilder
> TreeExpression Parser
<LexerType
>::parseArrayLiteral(TreeBuilder
& context
) 
1897     consumeOrFailWithFlags(OPENBRACKET
, TreeBuilder::DontBuildStrings
, "Expected an opening '[' at the beginning of an array literal"); 
1899     int oldNonLHSCount 
= m_nonLHSCount
; 
1902     while (match(COMMA
)) { 
1903         next(TreeBuilder::DontBuildStrings
); 
1906     if (match(CLOSEBRACKET
)) { 
1907         JSTokenLocation 
location(tokenLocation()); 
1908         next(TreeBuilder::DontBuildStrings
); 
1909         return context
.createArray(location
, elisions
); 
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
; 
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
); 
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
; 
1927     while (match(COMMA
)) { 
1928         next(TreeBuilder::DontBuildStrings
); 
1931         while (match(COMMA
)) { 
1936         if (match(CLOSEBRACKET
)) { 
1937             JSTokenLocation 
location(tokenLocation()); 
1938             next(TreeBuilder::DontBuildStrings
); 
1939             return context
.createArray(location
, elisions
, elementList
); 
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
; 
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
); 
1952         TreeExpression elem 
= parseAssignmentExpression(context
); 
1953         failIfFalse(elem
, "Cannot parse array literal element"); 
1954         tail 
= context
.createElementList(tail
, elisions
, elem
); 
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"); 
1963     m_nonLHSCount 
= oldNonLHSCount
; 
1965     return context
.createArray(location
, elementList
); 
1968 template <typename LexerType
> 
1969 template <class TreeBuilder
> TreeExpression Parser
<LexerType
>::parsePrimaryExpression(TreeBuilder
& context
) 
1971     failIfStackOverflow(); 
1972     switch (m_token
.m_type
) { 
1975             return parseStrictObjectLiteral(context
); 
1976         return parseObjectLiteral(context
); 
1978         return parseArrayLiteral(context
); 
1981         int oldNonLHSCount 
= m_nonLHSCount
; 
1982         TreeExpression result 
= parseExpression(context
); 
1983         m_nonLHSCount 
= oldNonLHSCount
; 
1984         handleProductionOrFail(CLOSEPAREN
, ")", "end", "compound expression"); 
1988         JSTokenLocation 
location(tokenLocation()); 
1990         return context
.thisExpr(location
); 
1993         JSTextPosition start 
= tokenStartPosition(); 
1994         const Identifier
* ident 
= m_token
.m_data
.ident
; 
1995         JSTokenLocation 
location(tokenLocation()); 
1997         currentScope()->useVariable(ident
, m_vm
->propertyNames
->eval 
== *ident
); 
1998         m_lastIdentifier 
= ident
; 
1999         return context
.createResolve(location
, ident
, start
); 
2002         const Identifier
* ident 
= m_token
.m_data
.ident
; 
2003         JSTokenLocation 
location(tokenLocation()); 
2005         return context
.createString(location
, ident
); 
2008         double d 
= m_token
.m_data
.doubleValue
; 
2009         JSTokenLocation 
location(tokenLocation()); 
2011         return context
.createNumberExpr(location
, d
); 
2014         JSTokenLocation 
location(tokenLocation()); 
2016         return context
.createNull(location
); 
2019         JSTokenLocation 
location(tokenLocation()); 
2021         return context
.createBoolean(location
, true); 
2024         JSTokenLocation 
location(tokenLocation()); 
2026         return context
.createBoolean(location
, false); 
2031         const Identifier
* pattern
; 
2032         const Identifier
* flags
; 
2033         if (match(DIVEQUAL
)) 
2034             failIfFalse(m_lexer
->scanRegExp(pattern
, flags
, '='), "Invalid regular expression"); 
2036             failIfFalse(m_lexer
->scanRegExp(pattern
, flags
), "Invalid regular expression"); 
2038         JSTextPosition start 
= tokenStartPosition(); 
2039         JSTokenLocation 
location(tokenLocation()); 
2041         TreeExpression re 
= context
.createRegExp(location
, *pattern
, *flags
, start
); 
2043             const char* yarrErrorMsg 
= Yarr::checkSyntax(pattern
->string()); 
2044             regexFail(yarrErrorMsg
); 
2049         failDueToUnexpectedToken(); 
2053 template <typename LexerType
> 
2054 template <class TreeBuilder
> TreeArguments Parser
<LexerType
>::parseArguments(TreeBuilder
& context
, SpreadMode mode
) 
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(); 
2062     if (match(DOTDOTDOT
) && mode 
== AllowSpread
) { 
2063         JSTokenLocation 
spreadLocation(tokenLocation()); 
2064         auto start 
= m_token
.m_startPosition
; 
2065         auto divot 
= m_token
.m_endPosition
; 
2067         auto spreadExpr 
= parseAssignmentExpression(context
); 
2068         auto end 
= m_lastTokenEndPosition
; 
2070             failWithMessage("Cannot parse spread expression"); 
2071         if (!consume(CLOSEPAREN
)) { 
2073                 semanticFail("Spread operator may only be applied to the last argument passed to a function"); 
2074             handleProductionOrFail(CLOSEPAREN
, ")", "end", "argument list"); 
2076         auto spread 
= context
.createSpreadExpression(spreadLocation
, spreadExpr
, start
, divot
, end
); 
2077         TreeArgumentsList argList 
= context
.createArgumentsList(location
, spread
); 
2078         return context
.createArguments(argList
); 
2080     TreeExpression firstArg 
= parseAssignmentExpression(context
); 
2081     failIfFalse(firstArg
, "Cannot parse function argument"); 
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
); 
2092     semanticFailIfTrue(match(DOTDOTDOT
), "The '...' operator should come before the target expression"); 
2093     handleProductionOrFail(CLOSEPAREN
, ")", "end", "argument list"); 
2094     return context
.createArguments(argList
); 
2097 template <typename LexerType
> 
2098 template <class TreeBuilder
> TreeExpression Parser
<LexerType
>::parseMemberExpression(TreeBuilder
& context
) 
2100     TreeExpression base 
= 0; 
2101     JSTextPosition expressionStart 
= tokenStartPosition(); 
2103     JSTokenLocation location
; 
2104     while (match(NEW
)) { 
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(); 
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
); 
2122         base 
= parsePrimaryExpression(context
); 
2124     failIfFalse(base
, "Cannot parse base expression"); 
2126         location 
= tokenLocation(); 
2127         switch (m_token
.m_type
) { 
2129             m_nonTrivialExpressionCount
++; 
2130             JSTextPosition expressionEnd 
= lastTokenEndPosition(); 
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
; 
2142             m_nonTrivialExpressionCount
++; 
2143             int nonLHSCount 
= m_nonLHSCount
; 
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()); 
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()); 
2156             m_nonLHSCount 
= nonLHSCount
; 
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()); 
2169             goto endMemberExpression
; 
2172 endMemberExpression
: 
2174         base 
= context
.createNewExpr(location
, base
, expressionStart
, lastTokenEndPosition()); 
2178 static const char* operatorString(bool prefix
, unsigned tok
) 
2182     case AUTOMINUSMINUS
: 
2183         return prefix 
? "prefix-decrement" : "decrement"; 
2187         return prefix 
? "prefix-increment" : "increment"; 
2190         return "logical-not"; 
2193         return "bitwise-not"; 
2204     RELEASE_ASSERT_NOT_REACHED(); 
2208 template <typename LexerType
> 
2209 template <class TreeBuilder
> TreeExpression Parser
<LexerType
>::parseUnaryExpression(TreeBuilder
& context
) 
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
)) { 
2219             switch (m_token
.m_type
) { 
2223             case AUTOMINUSMINUS
: 
2224                 semanticFailIfTrue(requiresLExpr
, "The ", operatorString(true, lastOperator
), " operator requires a reference expression"); 
2225                 modifiesExpr 
= true; 
2226                 requiresLExpr 
= true; 
2229                 semanticFailIfTrue(requiresLExpr
, "The ", operatorString(true, lastOperator
), " operator requires a reference expression"); 
2230                 requiresLExpr 
= true; 
2233                 semanticFailIfTrue(requiresLExpr
, "The ", operatorString(true, lastOperator
), " operator requires a reference expression"); 
2237         lastOperator 
= m_token
.m_type
; 
2239         context
.appendUnaryToken(tokenStackDepth
, m_token
.m_type
, tokenStartPosition()); 
2241         m_nonTrivialExpressionCount
++; 
2243     JSTextPosition subExprStart 
= tokenStartPosition(); 
2244     ASSERT(subExprStart
.offset 
>= subExprStart
.lineStartOffset
); 
2245     JSTokenLocation 
location(tokenLocation()); 
2246     TreeExpression expr 
= parseMemberExpression(context
); 
2249             failWithMessage("Cannot parse subexpression of ", operatorString(true, lastOperator
), "operator"); 
2250         failWithMessage("Cannot parse member expression"); 
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
; 
2257     failIfTrueIfStrict(isEvalOrArguments 
&& modifiesExpr
, "Cannot modify '", m_lastIdentifier
->impl(), "' in strict mode"); 
2258     switch (m_token
.m_type
) { 
2260         m_nonTrivialExpressionCount
++; 
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
; 
2270         m_nonTrivialExpressionCount
++; 
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
; 
2283     JSTextPosition end 
= lastTokenEndPosition(); 
2285     if (!TreeBuilder::CreatesAST 
&& (m_syntaxAlreadyValidated 
|| !strictMode())) 
2288     location 
= tokenLocation(); 
2289     location
.line 
= m_lexer
->lastLineNumber(); 
2290     while (tokenStackDepth
) { 
2291         switch (context
.unaryTokenStackLastType(tokenStackDepth
)) { 
2293             expr 
= context
.createLogicalNot(location
, expr
); 
2296             expr 
= context
.makeBitwiseNotNode(location
, expr
); 
2299             expr 
= context
.makeNegateNode(location
, expr
); 
2302             expr 
= context
.createUnaryPlus(location
, expr
); 
2306             expr 
= context
.makePrefixNode(location
, expr
, OpPlusPlus
, context
.unaryTokenStackLastStart(tokenStackDepth
), subExprStart 
+ 1, end
); 
2307             m_assignmentCount
++; 
2310         case AUTOMINUSMINUS
: 
2311             expr 
= context
.makePrefixNode(location
, expr
, OpMinusMinus
, context
.unaryTokenStackLastStart(tokenStackDepth
), subExprStart 
+ 1, end
); 
2312             m_assignmentCount
++; 
2315             expr 
= context
.makeTypeOfNode(location
, expr
); 
2318             expr 
= context
.createVoid(location
, expr
); 
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
); 
2325             // If we get here something has gone horribly horribly wrong 
2328         subExprStart 
= context
.unaryTokenStackLastStart(tokenStackDepth
); 
2329         context
.unaryTokenStackRemoveLast(tokenStackDepth
); 
2335 template <typename LexerType
> void Parser
<LexerType
>::printUnexpectedTokenText(WTF::PrintStream
& out
) 
2337     switch (m_token
.m_type
) { 
2339         out
.print("Unexpected end of script"); 
2341     case UNTERMINATED_IDENTIFIER_ESCAPE_ERRORTOK
: 
2342     case UNTERMINATED_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK
: 
2343         out
.print("Incomplete unicode escape in identifier: '", getToken(), "'"); 
2345     case UNTERMINATED_MULTILINE_COMMENT_ERRORTOK
: 
2346         out
.print("Unterminated multiline comment"); 
2348     case UNTERMINATED_NUMERIC_LITERAL_ERRORTOK
: 
2349         out
.print("Unterminated numeric literal '", getToken(), "'"); 
2351     case UNTERMINATED_STRING_LITERAL_ERRORTOK
: 
2352         out
.print("Unterminated string literal '", getToken(), "'"); 
2354     case INVALID_IDENTIFIER_ESCAPE_ERRORTOK
: 
2355         out
.print("Invalid escape in identifier: '", getToken(), "'"); 
2357     case INVALID_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK
: 
2358         out
.print("Invalid unicode escape in identifier: '", getToken(), "'"); 
2360     case INVALID_NUMERIC_LITERAL_ERRORTOK
: 
2361         out
.print("Invalid numeric literal: '", getToken(), "'"); 
2363     case INVALID_OCTAL_NUMBER_ERRORTOK
: 
2364         out
.print("Invalid use of octal: '", getToken(), "'"); 
2366     case INVALID_STRING_LITERAL_ERRORTOK
: 
2367         out
.print("Invalid string literal: '", getToken(), "'"); 
2370         out
.print("Unrecognized token '", getToken(), "'"); 
2373         out
.print("Unexpected string literal ", getToken()); 
2376         out
.print("Unexpected number '", getToken(), "'"); 
2379     case RESERVED_IF_STRICT
: 
2380         out
.print("Unexpected use of reserved word '", getToken(), "' in strict mode"); 
2384         out
.print("Unexpected use of reserved word '", getToken(), "'"); 
2387     case INVALID_PRIVATE_NAME_ERRORTOK
: 
2388         out
.print("Invalid private name '", getToken(), "'"); 
2392         out
.print("Unexpected identifier '", getToken(), "'"); 
2399     if (m_token
.m_type 
& KeywordTokenFlag
) { 
2400         out
.print("Unexpected keyword '", getToken(), "'"); 
2404     out
.print("Unexpected token '", getToken(), "'"); 
2407 // Instantiate the two flavors of Parser we need instead of putting most of this file in Parser.h 
2408 template class Parser
<Lexer
<LChar
>>; 
2409 template class Parser
<Lexer
<UChar
>>;