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