2 * Copyright (C) 2010 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
32 #include "CodeBlock.h"
33 #include "JSGlobalData.h"
35 #include "ASTBuilder.h"
36 #include "SourceProvider.h"
37 #include "SourceProviderCacheItem.h"
38 #include <wtf/HashFunctions.h>
39 #include <wtf/OwnPtr.h>
40 #include <wtf/WTFThreadData.h>
46 #define fail() do { m_error = true; return 0; } while (0)
47 #define failIfFalse(cond) do { if (!(cond)) fail(); } while (0)
48 #define failIfTrue(cond) do { if ((cond)) fail(); } while (0)
49 #define failIfTrueIfStrict(cond) do { if ((cond) && strictMode()) fail(); } while (0)
50 #define failIfFalseIfStrict(cond) do { if ((!(cond)) && strictMode()) fail(); } while (0)
51 #define consumeOrFail(tokenType) do { if (!consume(tokenType)) fail(); } while (0)
52 #define consumeOrFailWithFlags(tokenType, flags) do { if (!consume(tokenType, flags)) fail(); } while (0)
53 #define matchOrFail(tokenType) do { if (!match(tokenType)) fail(); } while (0)
54 #define failIfStackOverflow() do { failIfFalse(canRecurse()); } while (0)
56 // Macros to make the more common TreeBuilder types a little less verbose
57 #define TreeStatement typename TreeBuilder::Statement
58 #define TreeExpression typename TreeBuilder::Expression
59 #define TreeFormalParameterList typename TreeBuilder::FormalParameterList
60 #define TreeSourceElements typename TreeBuilder::SourceElements
61 #define TreeClause typename TreeBuilder::Clause
62 #define TreeClauseList typename TreeBuilder::ClauseList
63 #define TreeConstDeclList typename TreeBuilder::ConstDeclList
64 #define TreeArguments typename TreeBuilder::Arguments
65 #define TreeArgumentsList typename TreeBuilder::ArgumentsList
66 #define TreeFunctionBody typename TreeBuilder::FunctionBody
67 #define TreeProperty typename TreeBuilder::Property
68 #define TreePropertyList typename TreeBuilder::PropertyList
70 COMPILE_ASSERT(LastUntaggedToken
< 64, LessThan64UntaggedTokens
);
74 JSParser(Lexer
*, JSGlobalData
*, FunctionParameters
*, bool isStrictContext
, bool isFunction
, SourceProvider
*);
75 const char* parseProgram();
77 struct AllowInOverride
{
78 AllowInOverride(JSParser
* parser
)
80 , m_oldAllowsIn(parser
->m_allowsIn
)
82 parser
->m_allowsIn
= true;
86 m_parser
->m_allowsIn
= m_oldAllowsIn
;
92 struct ScopeLabelInfo
{
93 ScopeLabelInfo(StringImpl
* ident
, bool isLoop
)
102 ALWAYS_INLINE
void next(unsigned lexType
= 0)
104 m_lastLine
= m_token
.m_info
.line
;
105 m_lastTokenEnd
= m_token
.m_info
.endOffset
;
106 m_lexer
->setLastLineNumber(m_lastLine
);
107 m_token
.m_type
= m_lexer
->lex(&m_token
.m_data
, &m_token
.m_info
, lexType
, strictMode());
110 ALWAYS_INLINE
void nextExpectIdentifier(unsigned lexType
= 0)
112 m_lastLine
= m_token
.m_info
.line
;
113 m_lastTokenEnd
= m_token
.m_info
.endOffset
;
114 m_lexer
->setLastLineNumber(m_lastLine
);
115 m_token
.m_type
= m_lexer
->lexExpectIdentifier(&m_token
.m_data
, &m_token
.m_info
, lexType
, strictMode());
118 ALWAYS_INLINE
bool nextTokenIsColon()
120 return m_lexer
->nextTokenIsColon();
123 ALWAYS_INLINE
bool consume(JSTokenType expected
, unsigned flags
= 0)
125 bool result
= m_token
.m_type
== expected
;
131 ALWAYS_INLINE
bool match(JSTokenType expected
)
133 return m_token
.m_type
== expected
;
136 ALWAYS_INLINE
int tokenStart()
138 return m_token
.m_info
.startOffset
;
141 ALWAYS_INLINE
int tokenLine()
143 return m_token
.m_info
.line
;
146 ALWAYS_INLINE
int tokenEnd()
148 return m_token
.m_info
.endOffset
;
151 void startLoop() { currentScope()->startLoop(); }
152 void endLoop() { currentScope()->endLoop(); }
153 void startSwitch() { currentScope()->startSwitch(); }
154 void endSwitch() { currentScope()->endSwitch(); }
155 void setStrictMode() { currentScope()->setStrictMode(); }
156 bool strictMode() { return currentScope()->strictMode(); }
157 bool isValidStrictMode() { return currentScope()->isValidStrictMode(); }
158 bool declareParameter(const Identifier
* ident
) { return currentScope()->declareParameter(ident
); }
161 ScopeRef current
= currentScope();
162 while (!current
->breakIsValid()) {
163 if (!current
.hasContainingScope())
165 current
= current
.containingScope();
169 bool continueIsValid()
171 ScopeRef current
= currentScope();
172 while (!current
->continueIsValid()) {
173 if (!current
.hasContainingScope())
175 current
= current
.containingScope();
179 void pushLabel(const Identifier
* label
, bool isLoop
) { currentScope()->pushLabel(label
, isLoop
); }
180 void popLabel() { currentScope()->popLabel(); }
181 ScopeLabelInfo
* getLabel(const Identifier
* label
)
183 ScopeRef current
= currentScope();
184 ScopeLabelInfo
* result
= 0;
185 while (!(result
= current
->getLabel(label
))) {
186 if (!current
.hasContainingScope())
188 current
= current
.containingScope();
193 enum SourceElementsMode
{ CheckForStrictMode
, DontCheckForStrictMode
};
194 template <SourceElementsMode mode
, class TreeBuilder
> TreeSourceElements
parseSourceElements(TreeBuilder
&);
195 template <class TreeBuilder
> TreeStatement
parseStatement(TreeBuilder
&, const Identifier
*& directive
);
196 template <class TreeBuilder
> TreeStatement
parseFunctionDeclaration(TreeBuilder
&);
197 template <class TreeBuilder
> TreeStatement
parseVarDeclaration(TreeBuilder
&);
198 template <class TreeBuilder
> TreeStatement
parseConstDeclaration(TreeBuilder
&);
199 template <class TreeBuilder
> TreeStatement
parseDoWhileStatement(TreeBuilder
&);
200 template <class TreeBuilder
> TreeStatement
parseWhileStatement(TreeBuilder
&);
201 template <class TreeBuilder
> TreeStatement
parseForStatement(TreeBuilder
&);
202 template <class TreeBuilder
> TreeStatement
parseBreakStatement(TreeBuilder
&);
203 template <class TreeBuilder
> TreeStatement
parseContinueStatement(TreeBuilder
&);
204 template <class TreeBuilder
> TreeStatement
parseReturnStatement(TreeBuilder
&);
205 template <class TreeBuilder
> TreeStatement
parseThrowStatement(TreeBuilder
&);
206 template <class TreeBuilder
> TreeStatement
parseWithStatement(TreeBuilder
&);
207 template <class TreeBuilder
> TreeStatement
parseSwitchStatement(TreeBuilder
&);
208 template <class TreeBuilder
> TreeClauseList
parseSwitchClauses(TreeBuilder
&);
209 template <class TreeBuilder
> TreeClause
parseSwitchDefaultClause(TreeBuilder
&);
210 template <class TreeBuilder
> TreeStatement
parseTryStatement(TreeBuilder
&);
211 template <class TreeBuilder
> TreeStatement
parseDebuggerStatement(TreeBuilder
&);
212 template <class TreeBuilder
> TreeStatement
parseExpressionStatement(TreeBuilder
&);
213 template <class TreeBuilder
> TreeStatement
parseExpressionOrLabelStatement(TreeBuilder
&);
214 template <class TreeBuilder
> TreeStatement
parseIfStatement(TreeBuilder
&);
215 template <class TreeBuilder
> ALWAYS_INLINE TreeStatement
parseBlockStatement(TreeBuilder
&);
216 template <class TreeBuilder
> TreeExpression
parseExpression(TreeBuilder
&);
217 template <class TreeBuilder
> TreeExpression
parseAssignmentExpression(TreeBuilder
&);
218 template <class TreeBuilder
> ALWAYS_INLINE TreeExpression
parseConditionalExpression(TreeBuilder
&);
219 template <class TreeBuilder
> ALWAYS_INLINE TreeExpression
parseBinaryExpression(TreeBuilder
&);
220 template <class TreeBuilder
> ALWAYS_INLINE TreeExpression
parseUnaryExpression(TreeBuilder
&);
221 template <class TreeBuilder
> TreeExpression
parseMemberExpression(TreeBuilder
&);
222 template <class TreeBuilder
> ALWAYS_INLINE TreeExpression
parsePrimaryExpression(TreeBuilder
&);
223 template <class TreeBuilder
> ALWAYS_INLINE TreeExpression
parseArrayLiteral(TreeBuilder
&);
224 template <class TreeBuilder
> ALWAYS_INLINE TreeExpression
parseObjectLiteral(TreeBuilder
&);
225 template <class TreeBuilder
> ALWAYS_INLINE TreeExpression
parseStrictObjectLiteral(TreeBuilder
&);
226 template <class TreeBuilder
> ALWAYS_INLINE TreeArguments
parseArguments(TreeBuilder
&);
227 template <bool strict
, class TreeBuilder
> ALWAYS_INLINE TreeProperty
parseProperty(TreeBuilder
&);
228 template <class TreeBuilder
> ALWAYS_INLINE TreeFunctionBody
parseFunctionBody(TreeBuilder
&);
229 template <class TreeBuilder
> ALWAYS_INLINE TreeFormalParameterList
parseFormalParameters(TreeBuilder
&);
230 template <class TreeBuilder
> ALWAYS_INLINE TreeExpression
parseVarDeclarationList(TreeBuilder
&, int& declarations
, const Identifier
*& lastIdent
, TreeExpression
& lastInitializer
, int& identStart
, int& initStart
, int& initEnd
);
231 template <class TreeBuilder
> ALWAYS_INLINE TreeConstDeclList
parseConstDeclarationList(TreeBuilder
& context
);
232 enum FunctionRequirements
{ FunctionNoRequirements
, FunctionNeedsName
};
233 template <FunctionRequirements
, bool nameIsInContainingScope
, class TreeBuilder
> bool parseFunctionInfo(TreeBuilder
&, const Identifier
*&, TreeFormalParameterList
&, TreeFunctionBody
&, int& openBrace
, int& closeBrace
, int& bodyStartLine
);
234 ALWAYS_INLINE
int isBinaryOperator(JSTokenType token
);
235 bool allowAutomaticSemicolon();
239 if (m_token
.m_type
== SEMICOLON
) {
243 return allowAutomaticSemicolon();
248 return m_stack
.recursionCheck();
251 int lastTokenEnd() const
253 return m_lastTokenEnd
;
260 const char* m_errorMessage
;
261 JSGlobalData
* m_globalData
;
266 int m_assignmentCount
;
268 bool m_syntaxAlreadyValidated
;
269 int m_statementDepth
;
270 int m_nonTrivialExpressionCount
;
271 const Identifier
* m_lastIdentifier
;
273 struct DepthManager
{
274 DepthManager(int* depth
)
275 : m_originalDepth(*depth
)
282 *m_depth
= m_originalDepth
;
291 Scope(JSGlobalData
* globalData
, bool isFunction
, bool strictMode
)
292 : m_globalData(globalData
)
293 , m_shadowsArguments(false)
295 , m_needsFullActivation(false)
296 , m_allowsNewDecls(true)
297 , m_strictMode(strictMode
)
298 , m_isFunction(isFunction
)
299 , m_isFunctionBoundary(false)
300 , m_isValidStrictMode(true)
306 Scope(const Scope
& rhs
)
307 : m_globalData(rhs
.m_globalData
)
308 , m_shadowsArguments(rhs
.m_shadowsArguments
)
309 , m_usesEval(rhs
.m_usesEval
)
310 , m_needsFullActivation(rhs
.m_needsFullActivation
)
311 , m_allowsNewDecls(rhs
.m_allowsNewDecls
)
312 , m_strictMode(rhs
.m_strictMode
)
313 , m_isFunction(rhs
.m_isFunction
)
314 , m_isFunctionBoundary(rhs
.m_isFunctionBoundary
)
315 , m_isValidStrictMode(rhs
.m_isValidStrictMode
)
316 , m_loopDepth(rhs
.m_loopDepth
)
317 , m_switchDepth(rhs
.m_switchDepth
)
320 m_labels
= adoptPtr(new LabelStack
);
322 typedef LabelStack::const_iterator iterator
;
323 iterator end
= rhs
.m_labels
->end();
324 for (iterator it
= rhs
.m_labels
->begin(); it
!= end
; ++it
)
325 m_labels
->append(ScopeLabelInfo(it
->m_ident
, it
->m_isLoop
));
329 void startSwitch() { m_switchDepth
++; }
330 void endSwitch() { m_switchDepth
--; }
331 void startLoop() { m_loopDepth
++; }
332 void endLoop() { ASSERT(m_loopDepth
); m_loopDepth
--; }
333 bool inLoop() { return !!m_loopDepth
; }
334 bool breakIsValid() { return m_loopDepth
|| m_switchDepth
; }
335 bool continueIsValid() { return m_loopDepth
; }
337 void pushLabel(const Identifier
* label
, bool isLoop
)
340 m_labels
= adoptPtr(new LabelStack
);
341 m_labels
->append(ScopeLabelInfo(label
->impl(), isLoop
));
347 ASSERT(m_labels
->size());
348 m_labels
->removeLast();
351 ScopeLabelInfo
* getLabel(const Identifier
* label
)
355 for (int i
= m_labels
->size(); i
> 0; i
--) {
356 if (m_labels
->at(i
- 1).m_ident
== label
->impl())
357 return &m_labels
->at(i
- 1);
365 m_isFunctionBoundary
= true;
367 bool isFunction() { return m_isFunction
; }
368 bool isFunctionBoundary() { return m_isFunctionBoundary
; }
370 bool declareVariable(const Identifier
* ident
)
372 bool isValidStrictMode
= m_globalData
->propertyNames
->eval
!= *ident
&& m_globalData
->propertyNames
->arguments
!= *ident
;
373 m_isValidStrictMode
= m_isValidStrictMode
&& isValidStrictMode
;
374 m_declaredVariables
.add(ident
->ustring().impl());
375 return isValidStrictMode
;
378 void declareWrite(const Identifier
* ident
)
380 ASSERT(m_strictMode
);
381 m_writtenVariables
.add(ident
->impl());
384 void preventNewDecls() { m_allowsNewDecls
= false; }
385 bool allowsNewDecls() const { return m_allowsNewDecls
; }
387 bool declareParameter(const Identifier
* ident
)
389 bool isArguments
= m_globalData
->propertyNames
->arguments
== *ident
;
390 bool isValidStrictMode
= m_declaredVariables
.add(ident
->ustring().impl()).second
&& m_globalData
->propertyNames
->eval
!= *ident
&& !isArguments
;
391 m_isValidStrictMode
= m_isValidStrictMode
&& isValidStrictMode
;
393 m_shadowsArguments
= true;
394 return isValidStrictMode
;
397 void useVariable(const Identifier
* ident
, bool isEval
)
399 m_usesEval
|= isEval
;
400 m_usedVariables
.add(ident
->ustring().impl());
403 void setNeedsFullActivation() { m_needsFullActivation
= true; }
405 bool collectFreeVariables(Scope
* nestedScope
, bool shouldTrackClosedVariables
)
407 if (nestedScope
->m_usesEval
)
409 IdentifierSet::iterator end
= nestedScope
->m_usedVariables
.end();
410 for (IdentifierSet::iterator ptr
= nestedScope
->m_usedVariables
.begin(); ptr
!= end
; ++ptr
) {
411 if (nestedScope
->m_declaredVariables
.contains(*ptr
))
413 m_usedVariables
.add(*ptr
);
414 if (shouldTrackClosedVariables
)
415 m_closedVariables
.add(*ptr
);
417 if (nestedScope
->m_writtenVariables
.size()) {
418 IdentifierSet::iterator end
= nestedScope
->m_writtenVariables
.end();
419 for (IdentifierSet::iterator ptr
= nestedScope
->m_writtenVariables
.begin(); ptr
!= end
; ++ptr
) {
420 if (nestedScope
->m_declaredVariables
.contains(*ptr
))
422 m_writtenVariables
.add(*ptr
);
429 void getUncapturedWrittenVariables(IdentifierSet
& writtenVariables
)
431 IdentifierSet::iterator end
= m_writtenVariables
.end();
432 for (IdentifierSet::iterator ptr
= m_writtenVariables
.begin(); ptr
!= end
; ++ptr
) {
433 if (!m_declaredVariables
.contains(*ptr
))
434 writtenVariables
.add(*ptr
);
438 void getCapturedVariables(IdentifierSet
& capturedVariables
)
440 if (m_needsFullActivation
|| m_usesEval
) {
441 capturedVariables
.swap(m_declaredVariables
);
444 for (IdentifierSet::iterator ptr
= m_closedVariables
.begin(); ptr
!= m_closedVariables
.end(); ++ptr
) {
445 if (!m_declaredVariables
.contains(*ptr
))
447 capturedVariables
.add(*ptr
);
450 void setStrictMode() { m_strictMode
= true; }
451 bool strictMode() const { return m_strictMode
; }
452 bool isValidStrictMode() const { return m_isValidStrictMode
; }
453 bool shadowsArguments() const { return m_shadowsArguments
; }
455 void copyCapturedVariablesToVector(const IdentifierSet
& capturedVariables
, Vector
<RefPtr
<StringImpl
> >& vector
)
457 IdentifierSet::iterator end
= capturedVariables
.end();
458 for (IdentifierSet::iterator it
= capturedVariables
.begin(); it
!= end
; ++it
) {
459 if (m_declaredVariables
.contains(*it
))
463 vector
.shrinkToFit();
466 void saveFunctionInfo(SourceProviderCacheItem
* info
)
468 ASSERT(m_isFunction
);
469 info
->usesEval
= m_usesEval
;
470 copyCapturedVariablesToVector(m_writtenVariables
, info
->writtenVariables
);
471 copyCapturedVariablesToVector(m_usedVariables
, info
->usedVariables
);
474 void restoreFunctionInfo(const SourceProviderCacheItem
* info
)
476 ASSERT(m_isFunction
);
477 m_usesEval
= info
->usesEval
;
478 unsigned size
= info
->usedVariables
.size();
479 for (unsigned i
= 0; i
< size
; ++i
)
480 m_usedVariables
.add(info
->usedVariables
[i
]);
481 size
= info
->writtenVariables
.size();
482 for (unsigned i
= 0; i
< size
; ++i
)
483 m_writtenVariables
.add(info
->writtenVariables
[i
]);
487 JSGlobalData
* m_globalData
;
488 bool m_shadowsArguments
: 1;
490 bool m_needsFullActivation
: 1;
491 bool m_allowsNewDecls
: 1;
492 bool m_strictMode
: 1;
493 bool m_isFunction
: 1;
494 bool m_isFunctionBoundary
: 1;
495 bool m_isValidStrictMode
: 1;
499 typedef Vector
<ScopeLabelInfo
, 2> LabelStack
;
500 OwnPtr
<LabelStack
> m_labels
;
501 IdentifierSet m_declaredVariables
;
502 IdentifierSet m_usedVariables
;
503 IdentifierSet m_closedVariables
;
504 IdentifierSet m_writtenVariables
;
507 typedef Vector
<Scope
, 10> ScopeStack
;
510 ScopeRef(ScopeStack
* scopeStack
, unsigned index
)
511 : m_scopeStack(scopeStack
)
515 Scope
* operator->() { return &m_scopeStack
->at(m_index
); }
516 unsigned index() const { return m_index
; }
518 bool hasContainingScope()
520 return m_index
&& !m_scopeStack
->at(m_index
).isFunctionBoundary();
523 ScopeRef
containingScope()
525 ASSERT(hasContainingScope());
526 return ScopeRef(m_scopeStack
, m_index
- 1);
530 ScopeStack
* m_scopeStack
;
534 struct AutoPopScopeRef
: public ScopeRef
{
535 AutoPopScopeRef(JSParser
* parser
, ScopeRef scope
)
544 m_parser
->popScope(*this, false);
556 ScopeRef
currentScope()
558 return ScopeRef(&m_scopeStack
, m_scopeStack
.size() - 1);
563 bool isFunction
= false;
564 bool isStrict
= false;
565 if (!m_scopeStack
.isEmpty()) {
566 isStrict
= m_scopeStack
.last().strictMode();
567 isFunction
= m_scopeStack
.last().isFunction();
569 m_scopeStack
.append(Scope(m_globalData
, isFunction
, isStrict
));
570 return currentScope();
573 bool popScopeInternal(ScopeRef
& scope
, bool shouldTrackClosedVariables
)
575 ASSERT_UNUSED(scope
, scope
.index() == m_scopeStack
.size() - 1);
576 ASSERT(m_scopeStack
.size() > 1);
577 bool result
= m_scopeStack
[m_scopeStack
.size() - 2].collectFreeVariables(&m_scopeStack
.last(), shouldTrackClosedVariables
);
578 m_scopeStack
.removeLast();
582 bool popScope(ScopeRef
& scope
, bool shouldTrackClosedVariables
)
584 return popScopeInternal(scope
, shouldTrackClosedVariables
);
587 bool popScope(AutoPopScopeRef
& scope
, bool shouldTrackClosedVariables
)
590 return popScopeInternal(scope
, shouldTrackClosedVariables
);
593 bool declareVariable(const Identifier
* ident
)
595 unsigned i
= m_scopeStack
.size() - 1;
596 ASSERT(i
< m_scopeStack
.size());
597 while (!m_scopeStack
[i
].allowsNewDecls()) {
599 ASSERT(i
< m_scopeStack
.size());
601 return m_scopeStack
[i
].declareVariable(ident
);
604 void declareWrite(const Identifier
* ident
)
606 if (!m_syntaxAlreadyValidated
)
607 m_scopeStack
.last().declareWrite(ident
);
610 ScopeStack m_scopeStack
;
612 const SourceProviderCacheItem
* findCachedFunctionInfo(int openBracePos
)
614 return m_functionCache
? m_functionCache
->get(openBracePos
) : 0;
617 SourceProviderCache
* m_functionCache
;
620 const char* jsParse(JSGlobalData
* globalData
, FunctionParameters
* parameters
, JSParserStrictness strictness
, JSParserMode parserMode
, const SourceCode
* source
)
622 JSParser
parser(globalData
->lexer
, globalData
, parameters
, strictness
== JSParseStrict
, parserMode
== JSParseFunctionCode
, source
->provider());
623 return parser
.parseProgram();
626 JSParser::JSParser(Lexer
* lexer
, JSGlobalData
* globalData
, FunctionParameters
* parameters
, bool inStrictContext
, bool isFunction
, SourceProvider
* provider
)
628 , m_stack(globalData
->stack())
630 , m_errorMessage("Parse error")
631 , m_globalData(globalData
)
635 , m_assignmentCount(0)
637 , m_syntaxAlreadyValidated(provider
->isValid())
638 , m_statementDepth(0)
639 , m_nonTrivialExpressionCount(0)
640 , m_lastIdentifier(0)
641 , m_functionCache(m_lexer
->sourceProvider()->cache())
643 ScopeRef scope
= pushScope();
645 scope
->setIsFunction();
647 scope
->setStrictMode();
649 for (unsigned i
= 0; i
< parameters
->size(); i
++)
650 scope
->declareParameter(¶meters
->at(i
));
653 m_lexer
->setLastLineNumber(tokenLine());
656 const char* JSParser::parseProgram()
658 unsigned oldFunctionCacheSize
= m_functionCache
? m_functionCache
->byteSize() : 0;
659 ASTBuilder
context(m_globalData
, m_lexer
);
660 if (m_lexer
->isReparsing())
662 ScopeRef scope
= currentScope();
663 SourceElements
* sourceElements
= parseSourceElements
<CheckForStrictMode
>(context
);
664 if (!sourceElements
|| !consume(EOFTOK
))
665 return m_errorMessage
;
666 IdentifierSet capturedVariables
;
667 scope
->getCapturedVariables(capturedVariables
);
668 CodeFeatures features
= context
.features();
669 if (scope
->strictMode())
670 features
|= StrictModeFeature
;
671 if (scope
->shadowsArguments())
672 features
|= ShadowsArgumentsFeature
;
674 unsigned functionCacheSize
= m_functionCache
? m_functionCache
->byteSize() : 0;
675 if (functionCacheSize
!= oldFunctionCacheSize
)
676 m_lexer
->sourceProvider()->notifyCacheSizeChanged(functionCacheSize
- oldFunctionCacheSize
);
678 m_globalData
->parser
->didFinishParsing(sourceElements
, context
.varDeclarations(), context
.funcDeclarations(), features
,
679 m_lastLine
, context
.numConstants(), capturedVariables
);
683 bool JSParser::allowAutomaticSemicolon()
685 return match(CLOSEBRACE
) || match(EOFTOK
) || m_lexer
->prevTerminator();
688 template <JSParser::SourceElementsMode mode
, class TreeBuilder
> TreeSourceElements
JSParser::parseSourceElements(TreeBuilder
& context
)
690 TreeSourceElements sourceElements
= context
.createSourceElements();
691 bool seenNonDirective
= false;
692 const Identifier
* directive
= 0;
693 unsigned startOffset
= m_token
.m_info
.startOffset
;
694 unsigned oldLastLineNumber
= m_lexer
->lastLineNumber();
695 unsigned oldLineNumber
= m_lexer
->lineNumber();
696 bool hasSetStrict
= false;
697 while (TreeStatement statement
= parseStatement(context
, directive
)) {
698 if (mode
== CheckForStrictMode
&& !seenNonDirective
) {
700 if (!hasSetStrict
&& m_globalData
->propertyNames
->useStrictIdentifier
== *directive
) {
703 failIfFalse(isValidStrictMode());
704 m_lexer
->setOffset(startOffset
);
706 m_lexer
->setLastLineNumber(oldLastLineNumber
);
707 m_lexer
->setLineNumber(oldLineNumber
);
712 seenNonDirective
= true;
714 context
.appendStatement(sourceElements
, statement
);
719 return sourceElements
;
722 template <class TreeBuilder
> TreeStatement
JSParser::parseVarDeclaration(TreeBuilder
& context
)
725 int start
= tokenLine();
728 const Identifier
* scratch1
= 0;
729 TreeExpression scratch2
= 0;
731 TreeExpression varDecls
= parseVarDeclarationList(context
, scratch
, scratch1
, scratch2
, scratch3
, scratch3
, scratch3
);
733 failIfFalse(autoSemiColon());
735 return context
.createVarStatement(varDecls
, start
, end
);
738 template <class TreeBuilder
> TreeStatement
JSParser::parseConstDeclaration(TreeBuilder
& context
)
740 ASSERT(match(CONSTTOKEN
));
741 int start
= tokenLine();
743 TreeConstDeclList constDecls
= parseConstDeclarationList(context
);
745 failIfFalse(autoSemiColon());
747 return context
.createConstStatement(constDecls
, start
, end
);
750 template <class TreeBuilder
> TreeStatement
JSParser::parseDoWhileStatement(TreeBuilder
& context
)
753 int startLine
= tokenLine();
755 const Identifier
* unused
= 0;
757 TreeStatement statement
= parseStatement(context
, unused
);
759 failIfFalse(statement
);
760 int endLine
= tokenLine();
761 consumeOrFail(WHILE
);
762 consumeOrFail(OPENPAREN
);
763 TreeExpression expr
= parseExpression(context
);
765 consumeOrFail(CLOSEPAREN
);
766 if (match(SEMICOLON
))
767 next(); // Always performs automatic semicolon insertion.
768 return context
.createDoWhileStatement(statement
, expr
, startLine
, endLine
);
771 template <class TreeBuilder
> TreeStatement
JSParser::parseWhileStatement(TreeBuilder
& context
)
773 ASSERT(match(WHILE
));
774 int startLine
= tokenLine();
776 consumeOrFail(OPENPAREN
);
777 TreeExpression expr
= parseExpression(context
);
779 int endLine
= tokenLine();
780 consumeOrFail(CLOSEPAREN
);
781 const Identifier
* unused
= 0;
783 TreeStatement statement
= parseStatement(context
, unused
);
785 failIfFalse(statement
);
786 return context
.createWhileStatement(expr
, statement
, startLine
, endLine
);
789 template <class TreeBuilder
> TreeExpression
JSParser::parseVarDeclarationList(TreeBuilder
& context
, int& declarations
, const Identifier
*& lastIdent
, TreeExpression
& lastInitializer
, int& identStart
, int& initStart
, int& initEnd
)
791 TreeExpression varDecls
= 0;
797 int varStart
= tokenStart();
798 identStart
= varStart
;
799 const Identifier
* name
= m_token
.m_data
.ident
;
802 bool hasInitializer
= match(EQUAL
);
803 failIfFalseIfStrict(declareVariable(name
));
804 context
.addVar(name
, (hasInitializer
|| (!m_allowsIn
&& match(INTOKEN
))) ? DeclarationStacks::HasInitializer
: 0);
805 if (hasInitializer
) {
806 int varDivot
= tokenStart() + 1;
807 initStart
= tokenStart();
808 next(TreeBuilder::DontBuildStrings
); // consume '='
809 int initialAssignments
= m_assignmentCount
;
810 TreeExpression initializer
= parseAssignmentExpression(context
);
811 initEnd
= lastTokenEnd();
812 lastInitializer
= initializer
;
813 failIfFalse(initializer
);
815 TreeExpression node
= context
.createAssignResolve(*name
, initializer
, initialAssignments
!= m_assignmentCount
, varStart
, varDivot
, lastTokenEnd());
819 varDecls
= context
.combineCommaNodes(varDecls
, node
);
821 } while (match(COMMA
));
825 template <class TreeBuilder
> TreeConstDeclList
JSParser::parseConstDeclarationList(TreeBuilder
& context
)
827 failIfTrue(strictMode());
828 TreeConstDeclList constDecls
= 0;
829 TreeConstDeclList tail
= 0;
833 const Identifier
* name
= m_token
.m_data
.ident
;
835 bool hasInitializer
= match(EQUAL
);
836 declareVariable(name
);
837 context
.addVar(name
, DeclarationStacks::IsConstant
| (hasInitializer
? DeclarationStacks::HasInitializer
: 0));
838 TreeExpression initializer
= 0;
839 if (hasInitializer
) {
840 next(TreeBuilder::DontBuildStrings
); // consume '='
841 initializer
= parseAssignmentExpression(context
);
843 tail
= context
.appendConstDecl(tail
, name
, initializer
);
846 } while (match(COMMA
));
850 template <class TreeBuilder
> TreeStatement
JSParser::parseForStatement(TreeBuilder
& context
)
853 int startLine
= tokenLine();
855 consumeOrFail(OPENPAREN
);
856 int nonLHSCount
= m_nonLHSCount
;
857 int declarations
= 0;
860 TreeExpression decls
= 0;
861 bool hasDeclaration
= false;
864 for (var IDENT in expression) statement
865 for (var IDENT = expression in expression) statement
866 for (var varDeclarationList; expressionOpt; expressionOpt)
868 hasDeclaration
= true;
869 const Identifier
* forInTarget
= 0;
870 TreeExpression forInInitializer
= 0;
874 decls
= parseVarDeclarationList(context
, declarations
, forInTarget
, forInInitializer
, declsStart
, initStart
, initEnd
);
879 // Remainder of a standard for loop is handled identically
880 if (match(SEMICOLON
))
881 goto standardForLoop
;
883 failIfFalse(declarations
== 1);
885 // Handle for-in with var declaration
886 int inLocation
= tokenStart();
887 if (!consume(INTOKEN
))
890 TreeExpression expr
= parseExpression(context
);
892 int exprEnd
= lastTokenEnd();
894 int endLine
= tokenLine();
895 consumeOrFail(CLOSEPAREN
);
897 const Identifier
* unused
= 0;
899 TreeStatement statement
= parseStatement(context
, unused
);
901 failIfFalse(statement
);
903 return context
.createForInLoop(forInTarget
, forInInitializer
, expr
, statement
, declsStart
, inLocation
, exprEnd
, initStart
, initEnd
, startLine
, endLine
);
906 if (!match(SEMICOLON
)) {
908 declsStart
= tokenStart();
909 decls
= parseExpression(context
);
910 declsEnd
= lastTokenEnd();
915 if (match(SEMICOLON
)) {
919 TreeExpression condition
= 0;
921 if (!match(SEMICOLON
)) {
922 condition
= parseExpression(context
);
923 failIfFalse(condition
);
925 consumeOrFail(SEMICOLON
);
927 TreeExpression increment
= 0;
928 if (!match(CLOSEPAREN
)) {
929 increment
= parseExpression(context
);
930 failIfFalse(increment
);
932 int endLine
= tokenLine();
933 consumeOrFail(CLOSEPAREN
);
934 const Identifier
* unused
= 0;
936 TreeStatement statement
= parseStatement(context
, unused
);
938 failIfFalse(statement
);
939 return context
.createForLoop(decls
, condition
, increment
, statement
, hasDeclaration
, startLine
, endLine
);
943 failIfFalse(nonLHSCount
== m_nonLHSCount
);
944 consumeOrFail(INTOKEN
);
945 TreeExpression expr
= parseExpression(context
);
947 int exprEnd
= lastTokenEnd();
948 int endLine
= tokenLine();
949 consumeOrFail(CLOSEPAREN
);
950 const Identifier
* unused
= 0;
952 TreeStatement statement
= parseStatement(context
, unused
);
954 failIfFalse(statement
);
956 return context
.createForInLoop(decls
, expr
, statement
, declsStart
, declsEnd
, exprEnd
, startLine
, endLine
);
959 template <class TreeBuilder
> TreeStatement
JSParser::parseBreakStatement(TreeBuilder
& context
)
961 ASSERT(match(BREAK
));
962 int startCol
= tokenStart();
963 int endCol
= tokenEnd();
964 int startLine
= tokenLine();
965 int endLine
= tokenLine();
968 if (autoSemiColon()) {
969 failIfFalse(breakIsValid());
970 return context
.createBreakStatement(startCol
, endCol
, startLine
, endLine
);
973 const Identifier
* ident
= m_token
.m_data
.ident
;
974 failIfFalse(getLabel(ident
));
976 endLine
= tokenLine();
978 failIfFalse(autoSemiColon());
979 return context
.createBreakStatement(ident
, startCol
, endCol
, startLine
, endLine
);
982 template <class TreeBuilder
> TreeStatement
JSParser::parseContinueStatement(TreeBuilder
& context
)
984 ASSERT(match(CONTINUE
));
985 int startCol
= tokenStart();
986 int endCol
= tokenEnd();
987 int startLine
= tokenLine();
988 int endLine
= tokenLine();
991 if (autoSemiColon()) {
992 failIfFalse(continueIsValid());
993 return context
.createContinueStatement(startCol
, endCol
, startLine
, endLine
);
996 const Identifier
* ident
= m_token
.m_data
.ident
;
997 ScopeLabelInfo
* label
= getLabel(ident
);
999 failIfFalse(label
->m_isLoop
);
1000 endCol
= tokenEnd();
1001 endLine
= tokenLine();
1003 failIfFalse(autoSemiColon());
1004 return context
.createContinueStatement(ident
, startCol
, endCol
, startLine
, endLine
);
1007 template <class TreeBuilder
> TreeStatement
JSParser::parseReturnStatement(TreeBuilder
& context
)
1009 ASSERT(match(RETURN
));
1010 failIfFalse(currentScope()->isFunction());
1011 int startLine
= tokenLine();
1012 int endLine
= startLine
;
1013 int start
= tokenStart();
1014 int end
= tokenEnd();
1016 // We do the auto semicolon check before attempting to parse an expression
1017 // as we need to ensure the a line break after the return correctly terminates
1019 if (match(SEMICOLON
))
1020 endLine
= tokenLine();
1021 if (autoSemiColon())
1022 return context
.createReturnStatement(0, start
, end
, startLine
, endLine
);
1023 TreeExpression expr
= parseExpression(context
);
1025 end
= lastTokenEnd();
1026 if (match(SEMICOLON
))
1027 endLine
= tokenLine();
1028 failIfFalse(autoSemiColon());
1029 return context
.createReturnStatement(expr
, start
, end
, startLine
, endLine
);
1032 template <class TreeBuilder
> TreeStatement
JSParser::parseThrowStatement(TreeBuilder
& context
)
1034 ASSERT(match(THROW
));
1035 int eStart
= tokenStart();
1036 int startLine
= tokenLine();
1039 failIfTrue(autoSemiColon());
1041 TreeExpression expr
= parseExpression(context
);
1043 int eEnd
= lastTokenEnd();
1044 int endLine
= tokenLine();
1045 failIfFalse(autoSemiColon());
1047 return context
.createThrowStatement(expr
, eStart
, eEnd
, startLine
, endLine
);
1050 template <class TreeBuilder
> TreeStatement
JSParser::parseWithStatement(TreeBuilder
& context
)
1052 ASSERT(match(WITH
));
1053 failIfTrue(strictMode());
1054 currentScope()->setNeedsFullActivation();
1055 int startLine
= tokenLine();
1057 consumeOrFail(OPENPAREN
);
1058 int start
= tokenStart();
1059 TreeExpression expr
= parseExpression(context
);
1061 int end
= lastTokenEnd();
1063 int endLine
= tokenLine();
1064 consumeOrFail(CLOSEPAREN
);
1065 const Identifier
* unused
= 0;
1066 TreeStatement statement
= parseStatement(context
, unused
);
1067 failIfFalse(statement
);
1069 return context
.createWithStatement(expr
, statement
, start
, end
, startLine
, endLine
);
1072 template <class TreeBuilder
> TreeStatement
JSParser::parseSwitchStatement(TreeBuilder
& context
)
1074 ASSERT(match(SWITCH
));
1075 int startLine
= tokenLine();
1077 consumeOrFail(OPENPAREN
);
1078 TreeExpression expr
= parseExpression(context
);
1080 int endLine
= tokenLine();
1081 consumeOrFail(CLOSEPAREN
);
1082 consumeOrFail(OPENBRACE
);
1084 TreeClauseList firstClauses
= parseSwitchClauses(context
);
1085 failIfTrue(m_error
);
1087 TreeClause defaultClause
= parseSwitchDefaultClause(context
);
1088 failIfTrue(m_error
);
1090 TreeClauseList secondClauses
= parseSwitchClauses(context
);
1091 failIfTrue(m_error
);
1093 consumeOrFail(CLOSEBRACE
);
1095 return context
.createSwitchStatement(expr
, firstClauses
, defaultClause
, secondClauses
, startLine
, endLine
);
1099 template <class TreeBuilder
> TreeClauseList
JSParser::parseSwitchClauses(TreeBuilder
& context
)
1104 TreeExpression condition
= parseExpression(context
);
1105 failIfFalse(condition
);
1106 consumeOrFail(COLON
);
1107 TreeSourceElements statements
= parseSourceElements
<DontCheckForStrictMode
>(context
);
1108 failIfFalse(statements
);
1109 TreeClause clause
= context
.createClause(condition
, statements
);
1110 TreeClauseList clauseList
= context
.createClauseList(clause
);
1111 TreeClauseList tail
= clauseList
;
1113 while (match(CASE
)) {
1115 TreeExpression condition
= parseExpression(context
);
1116 failIfFalse(condition
);
1117 consumeOrFail(COLON
);
1118 TreeSourceElements statements
= parseSourceElements
<DontCheckForStrictMode
>(context
);
1119 failIfFalse(statements
);
1120 clause
= context
.createClause(condition
, statements
);
1121 tail
= context
.createClauseList(tail
, clause
);
1126 template <class TreeBuilder
> TreeClause
JSParser::parseSwitchDefaultClause(TreeBuilder
& context
)
1128 if (!match(DEFAULT
))
1131 consumeOrFail(COLON
);
1132 TreeSourceElements statements
= parseSourceElements
<DontCheckForStrictMode
>(context
);
1133 failIfFalse(statements
);
1134 return context
.createClause(0, statements
);
1137 template <class TreeBuilder
> TreeStatement
JSParser::parseTryStatement(TreeBuilder
& context
)
1140 TreeStatement tryBlock
= 0;
1141 const Identifier
* ident
= &m_globalData
->propertyNames
->nullIdentifier
;
1142 bool catchHasEval
= false;
1143 TreeStatement catchBlock
= 0;
1144 TreeStatement finallyBlock
= 0;
1145 int firstLine
= tokenLine();
1147 matchOrFail(OPENBRACE
);
1149 tryBlock
= parseBlockStatement(context
);
1150 failIfFalse(tryBlock
);
1151 int lastLine
= m_lastLine
;
1154 currentScope()->setNeedsFullActivation();
1156 consumeOrFail(OPENPAREN
);
1158 ident
= m_token
.m_data
.ident
;
1160 AutoPopScopeRef
catchScope(this, pushScope());
1161 failIfFalseIfStrict(catchScope
->declareVariable(ident
));
1162 catchScope
->preventNewDecls();
1163 consumeOrFail(CLOSEPAREN
);
1164 matchOrFail(OPENBRACE
);
1165 int initialEvalCount
= context
.evalCount();
1166 catchBlock
= parseBlockStatement(context
);
1167 failIfFalse(catchBlock
);
1168 catchHasEval
= initialEvalCount
!= context
.evalCount();
1169 failIfFalse(popScope(catchScope
, TreeBuilder::NeedsFreeVariableInfo
));
1172 if (match(FINALLY
)) {
1174 matchOrFail(OPENBRACE
);
1175 finallyBlock
= parseBlockStatement(context
);
1176 failIfFalse(finallyBlock
);
1178 failIfFalse(catchBlock
|| finallyBlock
);
1179 return context
.createTryStatement(tryBlock
, ident
, catchHasEval
, catchBlock
, finallyBlock
, firstLine
, lastLine
);
1182 template <class TreeBuilder
> TreeStatement
JSParser::parseDebuggerStatement(TreeBuilder
& context
)
1184 ASSERT(match(DEBUGGER
));
1185 int startLine
= tokenLine();
1186 int endLine
= startLine
;
1188 if (match(SEMICOLON
))
1189 startLine
= tokenLine();
1190 failIfFalse(autoSemiColon());
1191 return context
.createDebugger(startLine
, endLine
);
1194 template <class TreeBuilder
> TreeStatement
JSParser::parseBlockStatement(TreeBuilder
& context
)
1196 ASSERT(match(OPENBRACE
));
1197 int start
= tokenLine();
1199 if (match(CLOSEBRACE
)) {
1201 return context
.createBlockStatement(0, start
, m_lastLine
);
1203 TreeSourceElements subtree
= parseSourceElements
<DontCheckForStrictMode
>(context
);
1204 failIfFalse(subtree
);
1205 matchOrFail(CLOSEBRACE
);
1207 return context
.createBlockStatement(subtree
, start
, m_lastLine
);
1210 template <class TreeBuilder
> TreeStatement
JSParser::parseStatement(TreeBuilder
& context
, const Identifier
*& directive
)
1212 DepthManager
statementDepth(&m_statementDepth
);
1215 int nonTrivialExpressionCount
= 0;
1216 failIfStackOverflow();
1217 switch (m_token
.m_type
) {
1219 return parseBlockStatement(context
);
1221 return parseVarDeclaration(context
);
1223 return parseConstDeclaration(context
);
1225 failIfFalseIfStrict(m_statementDepth
== 1);
1226 return parseFunctionDeclaration(context
);
1229 return context
.createEmptyStatement();
1231 return parseIfStatement(context
);
1233 return parseDoWhileStatement(context
);
1235 return parseWhileStatement(context
);
1237 return parseForStatement(context
);
1239 return parseContinueStatement(context
);
1241 return parseBreakStatement(context
);
1243 return parseReturnStatement(context
);
1245 return parseWithStatement(context
);
1247 return parseSwitchStatement(context
);
1249 return parseThrowStatement(context
);
1251 return parseTryStatement(context
);
1253 return parseDebuggerStatement(context
);
1258 // These tokens imply the end of a set of source elements
1261 return parseExpressionOrLabelStatement(context
);
1263 directive
= m_token
.m_data
.ident
;
1264 nonTrivialExpressionCount
= m_nonTrivialExpressionCount
;
1266 TreeStatement exprStatement
= parseExpressionStatement(context
);
1267 if (directive
&& nonTrivialExpressionCount
!= m_nonTrivialExpressionCount
)
1269 return exprStatement
;
1273 template <class TreeBuilder
> TreeFormalParameterList
JSParser::parseFormalParameters(TreeBuilder
& context
)
1276 failIfFalseIfStrict(declareParameter(m_token
.m_data
.ident
));
1277 TreeFormalParameterList list
= context
.createFormalParameterList(*m_token
.m_data
.ident
);
1278 TreeFormalParameterList tail
= list
;
1280 while (match(COMMA
)) {
1283 const Identifier
* ident
= m_token
.m_data
.ident
;
1284 failIfFalseIfStrict(declareParameter(ident
));
1286 tail
= context
.createFormalParameterList(tail
, *ident
);
1291 template <class TreeBuilder
> TreeFunctionBody
JSParser::parseFunctionBody(TreeBuilder
& context
)
1293 if (match(CLOSEBRACE
))
1294 return context
.createFunctionBody(strictMode());
1295 DepthManager
statementDepth(&m_statementDepth
);
1296 m_statementDepth
= 0;
1297 typename
TreeBuilder::FunctionBodyBuilder
bodyBuilder(m_globalData
, m_lexer
);
1298 failIfFalse(parseSourceElements
<CheckForStrictMode
>(bodyBuilder
));
1299 return context
.createFunctionBody(strictMode());
1302 template <JSParser::FunctionRequirements requirements
, bool nameIsInContainingScope
, class TreeBuilder
> bool JSParser::parseFunctionInfo(TreeBuilder
& context
, const Identifier
*& name
, TreeFormalParameterList
& parameters
, TreeFunctionBody
& body
, int& openBracePos
, int& closeBracePos
, int& bodyStartLine
)
1304 AutoPopScopeRef
functionScope(this, pushScope());
1305 functionScope
->setIsFunction();
1307 name
= m_token
.m_data
.ident
;
1308 failIfTrue(*name
== m_globalData
->propertyNames
->underscoreProto
);
1310 if (!nameIsInContainingScope
)
1311 failIfFalseIfStrict(functionScope
->declareVariable(name
));
1312 } else if (requirements
== FunctionNeedsName
)
1314 consumeOrFail(OPENPAREN
);
1315 if (!match(CLOSEPAREN
)) {
1316 parameters
= parseFormalParameters(context
);
1317 failIfFalse(parameters
);
1319 consumeOrFail(CLOSEPAREN
);
1320 matchOrFail(OPENBRACE
);
1322 openBracePos
= m_token
.m_data
.intValue
;
1323 bodyStartLine
= tokenLine();
1325 if (const SourceProviderCacheItem
* cachedInfo
= TreeBuilder::CanUseFunctionCache
? findCachedFunctionInfo(openBracePos
) : 0) {
1326 // If we know about this function already, we can use the cached info and skip the parser to the end of the function.
1327 body
= context
.createFunctionBody(strictMode());
1329 functionScope
->restoreFunctionInfo(cachedInfo
);
1330 failIfFalse(popScope(functionScope
, TreeBuilder::NeedsFreeVariableInfo
));
1332 closeBracePos
= cachedInfo
->closeBracePos
;
1333 m_token
= cachedInfo
->closeBraceToken();
1334 m_lexer
->setOffset(m_token
.m_info
.endOffset
);
1335 m_lexer
->setLineNumber(m_token
.m_info
.line
);
1343 body
= parseFunctionBody(context
);
1345 if (functionScope
->strictMode() && name
) {
1346 failIfTrue(m_globalData
->propertyNames
->arguments
== *name
);
1347 failIfTrue(m_globalData
->propertyNames
->eval
== *name
);
1349 closeBracePos
= m_token
.m_data
.intValue
;
1351 // Cache the tokenizer state and the function scope the first time the function is parsed.
1352 // Any future reparsing can then skip the function.
1353 static const int minimumFunctionLengthToCache
= 64;
1354 OwnPtr
<SourceProviderCacheItem
> newInfo
;
1355 int functionLength
= closeBracePos
- openBracePos
;
1356 if (TreeBuilder::CanUseFunctionCache
&& m_functionCache
&& functionLength
> minimumFunctionLengthToCache
) {
1357 newInfo
= adoptPtr(new SourceProviderCacheItem(m_token
.m_info
.line
, closeBracePos
));
1358 functionScope
->saveFunctionInfo(newInfo
.get());
1361 failIfFalse(popScope(functionScope
, TreeBuilder::NeedsFreeVariableInfo
));
1362 matchOrFail(CLOSEBRACE
);
1365 unsigned approximateByteSize
= newInfo
->approximateByteSize();
1366 m_functionCache
->add(openBracePos
, newInfo
.release(), approximateByteSize
);
1373 template <class TreeBuilder
> TreeStatement
JSParser::parseFunctionDeclaration(TreeBuilder
& context
)
1375 ASSERT(match(FUNCTION
));
1377 const Identifier
* name
= 0;
1378 TreeFormalParameterList parameters
= 0;
1379 TreeFunctionBody body
= 0;
1380 int openBracePos
= 0;
1381 int closeBracePos
= 0;
1382 int bodyStartLine
= 0;
1383 failIfFalse((parseFunctionInfo
<FunctionNeedsName
, true>(context
, name
, parameters
, body
, openBracePos
, closeBracePos
, bodyStartLine
)));
1385 failIfFalseIfStrict(declareVariable(name
));
1386 return context
.createFuncDeclStatement(name
, body
, parameters
, openBracePos
, closeBracePos
, bodyStartLine
, m_lastLine
);
1390 LabelInfo(const Identifier
* ident
, int start
, int end
)
1397 const Identifier
* m_ident
;
1402 template <class TreeBuilder
> TreeStatement
JSParser::parseExpressionOrLabelStatement(TreeBuilder
& context
)
1405 /* Expression and Label statements are ambiguous at LL(1), so we have a
1406 * special case that looks for a colon as the next character in the input.
1408 Vector
<LabelInfo
> labels
;
1411 int start
= tokenStart();
1412 int startLine
= tokenLine();
1413 if (!nextTokenIsColon()) {
1414 // If we hit this path we're making a expression statement, which
1415 // by definition can't make use of continue/break so we can just
1416 // ignore any labels we might have accumulated.
1417 TreeExpression expression
= parseExpression(context
);
1418 failIfFalse(expression
);
1419 failIfFalse(autoSemiColon());
1420 return context
.createExprStatement(expression
, startLine
, m_lastLine
);
1422 const Identifier
* ident
= m_token
.m_data
.ident
;
1423 int end
= tokenEnd();
1425 consumeOrFail(COLON
);
1426 if (!m_syntaxAlreadyValidated
) {
1427 // This is O(N^2) over the current list of consecutive labels, but I
1428 // have never seen more than one label in a row in the real world.
1429 for (size_t i
= 0; i
< labels
.size(); i
++)
1430 failIfTrue(ident
->impl() == labels
[i
].m_ident
->impl());
1431 failIfTrue(getLabel(ident
));
1432 labels
.append(LabelInfo(ident
, start
, end
));
1434 } while (match(IDENT
));
1435 bool isLoop
= false;
1436 switch (m_token
.m_type
) {
1446 const Identifier
* unused
= 0;
1447 if (!m_syntaxAlreadyValidated
) {
1448 for (size_t i
= 0; i
< labels
.size(); i
++)
1449 pushLabel(labels
[i
].m_ident
, isLoop
);
1451 TreeStatement statement
= parseStatement(context
, unused
);
1452 if (!m_syntaxAlreadyValidated
) {
1453 for (size_t i
= 0; i
< labels
.size(); i
++)
1456 failIfFalse(statement
);
1457 for (size_t i
= 0; i
< labels
.size(); i
++) {
1458 const LabelInfo
& info
= labels
[labels
.size() - i
- 1];
1459 statement
= context
.createLabelStatement(info
.m_ident
, statement
, info
.m_start
, info
.m_end
);
1464 template <class TreeBuilder
> TreeStatement
JSParser::parseExpressionStatement(TreeBuilder
& context
)
1466 int startLine
= tokenLine();
1467 TreeExpression expression
= parseExpression(context
);
1468 failIfFalse(expression
);
1469 failIfFalse(autoSemiColon());
1470 return context
.createExprStatement(expression
, startLine
, m_lastLine
);
1473 template <class TreeBuilder
> TreeStatement
JSParser::parseIfStatement(TreeBuilder
& context
)
1477 int start
= tokenLine();
1480 consumeOrFail(OPENPAREN
);
1482 TreeExpression condition
= parseExpression(context
);
1483 failIfFalse(condition
);
1484 int end
= tokenLine();
1485 consumeOrFail(CLOSEPAREN
);
1487 const Identifier
* unused
= 0;
1488 TreeStatement trueBlock
= parseStatement(context
, unused
);
1489 failIfFalse(trueBlock
);
1492 return context
.createIfStatement(condition
, trueBlock
, start
, end
);
1494 Vector
<TreeExpression
> exprStack
;
1495 Vector
<pair
<int, int> > posStack
;
1496 Vector
<TreeStatement
> statementStack
;
1497 bool trailingElse
= false;
1501 const Identifier
* unused
= 0;
1502 TreeStatement block
= parseStatement(context
, unused
);
1504 statementStack
.append(block
);
1505 trailingElse
= true;
1508 int innerStart
= tokenLine();
1511 consumeOrFail(OPENPAREN
);
1513 TreeExpression innerCondition
= parseExpression(context
);
1514 failIfFalse(innerCondition
);
1515 int innerEnd
= tokenLine();
1516 consumeOrFail(CLOSEPAREN
);
1517 const Identifier
* unused
= 0;
1518 TreeStatement innerTrueBlock
= parseStatement(context
, unused
);
1519 failIfFalse(innerTrueBlock
);
1520 exprStack
.append(innerCondition
);
1521 posStack
.append(make_pair(innerStart
, innerEnd
));
1522 statementStack
.append(innerTrueBlock
);
1523 } while (match(ELSE
));
1525 if (!trailingElse
) {
1526 TreeExpression condition
= exprStack
.last();
1527 exprStack
.removeLast();
1528 TreeStatement trueBlock
= statementStack
.last();
1529 statementStack
.removeLast();
1530 pair
<int, int> pos
= posStack
.last();
1531 posStack
.removeLast();
1532 statementStack
.append(context
.createIfStatement(condition
, trueBlock
, pos
.first
, pos
.second
));
1535 while (!exprStack
.isEmpty()) {
1536 TreeExpression condition
= exprStack
.last();
1537 exprStack
.removeLast();
1538 TreeStatement falseBlock
= statementStack
.last();
1539 statementStack
.removeLast();
1540 TreeStatement trueBlock
= statementStack
.last();
1541 statementStack
.removeLast();
1542 pair
<int, int> pos
= posStack
.last();
1543 posStack
.removeLast();
1544 statementStack
.append(context
.createIfStatement(condition
, trueBlock
, falseBlock
, pos
.first
, pos
.second
));
1547 return context
.createIfStatement(condition
, trueBlock
, statementStack
.last(), start
, end
);
1550 template <class TreeBuilder
> TreeExpression
JSParser::parseExpression(TreeBuilder
& context
)
1552 failIfStackOverflow();
1553 TreeExpression node
= parseAssignmentExpression(context
);
1558 m_nonTrivialExpressionCount
++;
1560 TreeExpression right
= parseAssignmentExpression(context
);
1562 typename
TreeBuilder::Comma commaNode
= context
.createCommaExpr(node
, right
);
1563 while (match(COMMA
)) {
1564 next(TreeBuilder::DontBuildStrings
);
1565 right
= parseAssignmentExpression(context
);
1567 context
.appendToComma(commaNode
, right
);
1573 template <typename TreeBuilder
> TreeExpression
JSParser::parseAssignmentExpression(TreeBuilder
& context
)
1575 failIfStackOverflow();
1576 int start
= tokenStart();
1577 int initialAssignmentCount
= m_assignmentCount
;
1578 int initialNonLHSCount
= m_nonLHSCount
;
1579 TreeExpression lhs
= parseConditionalExpression(context
);
1581 if (initialNonLHSCount
!= m_nonLHSCount
)
1584 int assignmentStack
= 0;
1586 bool hadAssignment
= false;
1588 switch (m_token
.m_type
) {
1589 case EQUAL
: op
= OpEqual
; break;
1590 case PLUSEQUAL
: op
= OpPlusEq
; break;
1591 case MINUSEQUAL
: op
= OpMinusEq
; break;
1592 case MULTEQUAL
: op
= OpMultEq
; break;
1593 case DIVEQUAL
: op
= OpDivEq
; break;
1594 case LSHIFTEQUAL
: op
= OpLShift
; break;
1595 case RSHIFTEQUAL
: op
= OpRShift
; break;
1596 case URSHIFTEQUAL
: op
= OpURShift
; break;
1597 case ANDEQUAL
: op
= OpAndEq
; break;
1598 case XOREQUAL
: op
= OpXOrEq
; break;
1599 case OREQUAL
: op
= OpOrEq
; break;
1600 case MODEQUAL
: op
= OpModEq
; break;
1604 m_nonTrivialExpressionCount
++;
1605 hadAssignment
= true;
1606 context
.assignmentStackAppend(assignmentStack
, lhs
, start
, tokenStart(), m_assignmentCount
, op
);
1607 start
= tokenStart();
1608 m_assignmentCount
++;
1609 next(TreeBuilder::DontBuildStrings
);
1610 if (strictMode() && m_lastIdentifier
&& context
.isResolve(lhs
)) {
1611 failIfTrueIfStrict(m_globalData
->propertyNames
->eval
== *m_lastIdentifier
);
1612 failIfTrueIfStrict(m_globalData
->propertyNames
->arguments
== *m_lastIdentifier
);
1613 declareWrite(m_lastIdentifier
);
1614 m_lastIdentifier
= 0;
1616 lhs
= parseConditionalExpression(context
);
1618 if (initialNonLHSCount
!= m_nonLHSCount
)
1625 if (!TreeBuilder::CreatesAST
)
1628 while (assignmentStack
)
1629 lhs
= context
.createAssignment(assignmentStack
, lhs
, initialAssignmentCount
, m_assignmentCount
, lastTokenEnd());
1634 template <class TreeBuilder
> TreeExpression
JSParser::parseConditionalExpression(TreeBuilder
& context
)
1636 TreeExpression cond
= parseBinaryExpression(context
);
1638 if (!match(QUESTION
))
1640 m_nonTrivialExpressionCount
++;
1642 next(TreeBuilder::DontBuildStrings
);
1643 TreeExpression lhs
= parseAssignmentExpression(context
);
1644 consumeOrFailWithFlags(COLON
, TreeBuilder::DontBuildStrings
);
1646 TreeExpression rhs
= parseAssignmentExpression(context
);
1648 return context
.createConditionalExpr(cond
, lhs
, rhs
);
1651 ALWAYS_INLINE
static bool isUnaryOp(JSTokenType token
)
1653 return token
& UnaryOpTokenFlag
;
1656 int JSParser::isBinaryOperator(JSTokenType token
)
1659 return token
& (BinaryOpTokenPrecedenceMask
<< BinaryOpTokenAllowsInPrecedenceAdditionalShift
);
1660 return token
& BinaryOpTokenPrecedenceMask
;
1663 template <class TreeBuilder
> TreeExpression
JSParser::parseBinaryExpression(TreeBuilder
& context
)
1666 int operandStackDepth
= 0;
1667 int operatorStackDepth
= 0;
1668 typename
TreeBuilder::BinaryExprContext
binaryExprContext(context
);
1670 int exprStart
= tokenStart();
1671 int initialAssignments
= m_assignmentCount
;
1672 TreeExpression current
= parseUnaryExpression(context
);
1673 failIfFalse(current
);
1675 context
.appendBinaryExpressionInfo(operandStackDepth
, current
, exprStart
, lastTokenEnd(), lastTokenEnd(), initialAssignments
!= m_assignmentCount
);
1676 int precedence
= isBinaryOperator(m_token
.m_type
);
1679 m_nonTrivialExpressionCount
++;
1681 int operatorToken
= m_token
.m_type
;
1682 next(TreeBuilder::DontBuildStrings
);
1684 while (operatorStackDepth
&& context
.operatorStackHasHigherPrecedence(operatorStackDepth
, precedence
)) {
1685 ASSERT(operandStackDepth
> 1);
1687 typename
TreeBuilder::BinaryOperand rhs
= context
.getFromOperandStack(-1);
1688 typename
TreeBuilder::BinaryOperand lhs
= context
.getFromOperandStack(-2);
1689 context
.shrinkOperandStackBy(operandStackDepth
, 2);
1690 context
.appendBinaryOperation(operandStackDepth
, operatorStackDepth
, lhs
, rhs
);
1691 context
.operatorStackPop(operatorStackDepth
);
1693 context
.operatorStackAppend(operatorStackDepth
, operatorToken
, precedence
);
1695 while (operatorStackDepth
) {
1696 ASSERT(operandStackDepth
> 1);
1698 typename
TreeBuilder::BinaryOperand rhs
= context
.getFromOperandStack(-1);
1699 typename
TreeBuilder::BinaryOperand lhs
= context
.getFromOperandStack(-2);
1700 context
.shrinkOperandStackBy(operandStackDepth
, 2);
1701 context
.appendBinaryOperation(operandStackDepth
, operatorStackDepth
, lhs
, rhs
);
1702 context
.operatorStackPop(operatorStackDepth
);
1704 return context
.popOperandStack(operandStackDepth
);
1708 template <bool complete
, class TreeBuilder
> TreeProperty
JSParser::parseProperty(TreeBuilder
& context
)
1710 bool wasIdent
= false;
1711 switch (m_token
.m_type
) {
1716 const Identifier
* ident
= m_token
.m_data
.ident
;
1717 if (complete
|| (wasIdent
&& (*ident
== m_globalData
->propertyNames
->get
|| *ident
== m_globalData
->propertyNames
->set
)))
1718 nextExpectIdentifier(Lexer::IgnoreReservedWords
);
1720 nextExpectIdentifier(Lexer::IgnoreReservedWords
| TreeBuilder::DontBuildKeywords
);
1724 TreeExpression node
= parseAssignmentExpression(context
);
1726 return context
.template createProperty
<complete
>(ident
, node
, PropertyNode::Constant
);
1728 failIfFalse(wasIdent
);
1730 const Identifier
* accessorName
= 0;
1731 TreeFormalParameterList parameters
= 0;
1732 TreeFunctionBody body
= 0;
1733 int openBracePos
= 0;
1734 int closeBracePos
= 0;
1735 int bodyStartLine
= 0;
1736 PropertyNode::Type type
;
1737 if (*ident
== m_globalData
->propertyNames
->get
)
1738 type
= PropertyNode::Getter
;
1739 else if (*ident
== m_globalData
->propertyNames
->set
)
1740 type
= PropertyNode::Setter
;
1743 failIfFalse((parseFunctionInfo
<FunctionNeedsName
, false>(context
, accessorName
, parameters
, body
, openBracePos
, closeBracePos
, bodyStartLine
)));
1744 return context
.template createGetterOrSetterProperty
<complete
>(type
, accessorName
, parameters
, body
, openBracePos
, closeBracePos
, bodyStartLine
, m_lastLine
);
1747 double propertyName
= m_token
.m_data
.doubleValue
;
1749 consumeOrFail(COLON
);
1750 TreeExpression node
= parseAssignmentExpression(context
);
1752 return context
.template createProperty
<complete
>(m_globalData
, propertyName
, node
, PropertyNode::Constant
);
1755 failIfFalse(m_token
.m_type
& KeywordTokenFlag
);
1760 template <class TreeBuilder
> TreeExpression
JSParser::parseObjectLiteral(TreeBuilder
& context
)
1762 int startOffset
= m_token
.m_data
.intValue
;
1763 consumeOrFailWithFlags(OPENBRACE
, TreeBuilder::DontBuildStrings
);
1765 if (match(CLOSEBRACE
)) {
1767 return context
.createObjectLiteral();
1770 TreeProperty property
= parseProperty
<false>(context
);
1771 failIfFalse(property
);
1772 if (!m_syntaxAlreadyValidated
&& context
.getType(property
) != PropertyNode::Constant
) {
1773 m_lexer
->setOffset(startOffset
);
1775 return parseStrictObjectLiteral(context
);
1777 TreePropertyList propertyList
= context
.createPropertyList(property
);
1778 TreePropertyList tail
= propertyList
;
1779 while (match(COMMA
)) {
1780 next(TreeBuilder::DontBuildStrings
);
1781 // allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939
1782 if (match(CLOSEBRACE
))
1784 property
= parseProperty
<false>(context
);
1785 failIfFalse(property
);
1786 if (!m_syntaxAlreadyValidated
&& context
.getType(property
) != PropertyNode::Constant
) {
1787 m_lexer
->setOffset(startOffset
);
1789 return parseStrictObjectLiteral(context
);
1791 tail
= context
.createPropertyList(property
, tail
);
1794 consumeOrFail(CLOSEBRACE
);
1796 return context
.createObjectLiteral(propertyList
);
1799 template <class TreeBuilder
> TreeExpression
JSParser::parseStrictObjectLiteral(TreeBuilder
& context
)
1801 consumeOrFail(OPENBRACE
);
1803 if (match(CLOSEBRACE
)) {
1805 return context
.createObjectLiteral();
1808 TreeProperty property
= parseProperty
<true>(context
);
1809 failIfFalse(property
);
1811 typedef HashMap
<RefPtr
<StringImpl
>, unsigned, IdentifierRepHash
> ObjectValidationMap
;
1812 ObjectValidationMap objectValidator
;
1813 // Add the first property
1814 if (!m_syntaxAlreadyValidated
)
1815 objectValidator
.add(context
.getName(property
).impl(), context
.getType(property
));
1817 TreePropertyList propertyList
= context
.createPropertyList(property
);
1818 TreePropertyList tail
= propertyList
;
1819 while (match(COMMA
)) {
1821 // allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939
1822 if (match(CLOSEBRACE
))
1824 property
= parseProperty
<true>(context
);
1825 failIfFalse(property
);
1826 if (!m_syntaxAlreadyValidated
) {
1827 std::pair
<ObjectValidationMap::iterator
, bool> propertyEntryIter
= objectValidator
.add(context
.getName(property
).impl(), context
.getType(property
));
1828 if (!propertyEntryIter
.second
) {
1829 failIfTrue(propertyEntryIter
.first
->second
== PropertyNode::Constant
);
1830 failIfTrue(context
.getType(property
) == PropertyNode::Constant
);
1831 failIfTrue(context
.getType(property
) & propertyEntryIter
.first
->second
);
1832 propertyEntryIter
.first
->second
|= context
.getType(property
);
1835 tail
= context
.createPropertyList(property
, tail
);
1838 consumeOrFail(CLOSEBRACE
);
1840 return context
.createObjectLiteral(propertyList
);
1843 template <class TreeBuilder
> TreeExpression
JSParser::parseArrayLiteral(TreeBuilder
& context
)
1845 consumeOrFailWithFlags(OPENBRACKET
, TreeBuilder::DontBuildStrings
);
1848 while (match(COMMA
)) {
1849 next(TreeBuilder::DontBuildStrings
);
1852 if (match(CLOSEBRACKET
)) {
1853 next(TreeBuilder::DontBuildStrings
);
1854 return context
.createArray(elisions
);
1857 TreeExpression elem
= parseAssignmentExpression(context
);
1859 typename
TreeBuilder::ElementList elementList
= context
.createElementList(elisions
, elem
);
1860 typename
TreeBuilder::ElementList tail
= elementList
;
1862 while (match(COMMA
)) {
1863 next(TreeBuilder::DontBuildStrings
);
1866 while (match(COMMA
)) {
1871 if (match(CLOSEBRACKET
)) {
1872 next(TreeBuilder::DontBuildStrings
);
1873 return context
.createArray(elisions
, elementList
);
1875 TreeExpression elem
= parseAssignmentExpression(context
);
1877 tail
= context
.createElementList(tail
, elisions
, elem
);
1880 consumeOrFail(CLOSEBRACKET
);
1882 return context
.createArray(elementList
);
1885 template <class TreeBuilder
> TreeExpression
JSParser::parsePrimaryExpression(TreeBuilder
& context
)
1887 switch (m_token
.m_type
) {
1890 return parseStrictObjectLiteral(context
);
1891 return parseObjectLiteral(context
);
1893 return parseArrayLiteral(context
);
1896 int oldNonLHSCount
= m_nonLHSCount
;
1897 TreeExpression result
= parseExpression(context
);
1898 m_nonLHSCount
= oldNonLHSCount
;
1899 consumeOrFail(CLOSEPAREN
);
1905 return context
.thisExpr();
1908 int start
= tokenStart();
1909 const Identifier
* ident
= m_token
.m_data
.ident
;
1911 currentScope()->useVariable(ident
, m_globalData
->propertyNames
->eval
== *ident
);
1912 m_lastIdentifier
= ident
;
1913 return context
.createResolve(ident
, start
);
1916 const Identifier
* ident
= m_token
.m_data
.ident
;
1918 return context
.createString(ident
);
1921 double d
= m_token
.m_data
.doubleValue
;
1923 return context
.createNumberExpr(d
);
1927 return context
.createNull();
1931 return context
.createBoolean(true);
1935 return context
.createBoolean(false);
1940 const Identifier
* pattern
;
1941 const Identifier
* flags
;
1942 if (match(DIVEQUAL
))
1943 failIfFalse(m_lexer
->scanRegExp(pattern
, flags
, '='));
1945 failIfFalse(m_lexer
->scanRegExp(pattern
, flags
));
1947 int start
= tokenStart();
1949 TreeExpression re
= context
.createRegExp(*pattern
, *flags
, start
);
1951 m_errorMessage
= Yarr::checkSyntax(pattern
->ustring());
1952 ASSERT(m_errorMessage
);
1962 template <class TreeBuilder
> TreeArguments
JSParser::parseArguments(TreeBuilder
& context
)
1964 consumeOrFailWithFlags(OPENPAREN
, TreeBuilder::DontBuildStrings
);
1965 if (match(CLOSEPAREN
)) {
1966 next(TreeBuilder::DontBuildStrings
);
1967 return context
.createArguments();
1969 TreeExpression firstArg
= parseAssignmentExpression(context
);
1970 failIfFalse(firstArg
);
1972 TreeArgumentsList argList
= context
.createArgumentsList(firstArg
);
1973 TreeArgumentsList tail
= argList
;
1974 while (match(COMMA
)) {
1975 next(TreeBuilder::DontBuildStrings
);
1976 TreeExpression arg
= parseAssignmentExpression(context
);
1978 tail
= context
.createArgumentsList(tail
, arg
);
1980 consumeOrFail(CLOSEPAREN
);
1981 return context
.createArguments(argList
);
1984 template <class TreeBuilder
> TreeExpression
JSParser::parseMemberExpression(TreeBuilder
& context
)
1986 TreeExpression base
= 0;
1987 int start
= tokenStart();
1988 int expressionStart
= start
;
1990 while (match(NEW
)) {
1995 if (match(FUNCTION
)) {
1996 const Identifier
* name
= &m_globalData
->propertyNames
->nullIdentifier
;
1997 TreeFormalParameterList parameters
= 0;
1998 TreeFunctionBody body
= 0;
1999 int openBracePos
= 0;
2000 int closeBracePos
= 0;
2001 int bodyStartLine
= 0;
2003 failIfFalse((parseFunctionInfo
<FunctionNoRequirements
, false>(context
, name
, parameters
, body
, openBracePos
, closeBracePos
, bodyStartLine
)));
2004 base
= context
.createFunctionExpr(name
, body
, parameters
, openBracePos
, closeBracePos
, bodyStartLine
, m_lastLine
);
2006 base
= parsePrimaryExpression(context
);
2010 switch (m_token
.m_type
) {
2012 m_nonTrivialExpressionCount
++;
2013 int expressionEnd
= lastTokenEnd();
2015 int nonLHSCount
= m_nonLHSCount
;
2016 int initialAssignments
= m_assignmentCount
;
2017 TreeExpression property
= parseExpression(context
);
2018 failIfFalse(property
);
2019 base
= context
.createBracketAccess(base
, property
, initialAssignments
!= m_assignmentCount
, expressionStart
, expressionEnd
, tokenEnd());
2020 if (!consume(CLOSEBRACKET
))
2022 m_nonLHSCount
= nonLHSCount
;
2026 m_nonTrivialExpressionCount
++;
2029 if (match(OPENPAREN
)) {
2030 int exprEnd
= lastTokenEnd();
2031 TreeArguments arguments
= parseArguments(context
);
2032 failIfFalse(arguments
);
2033 base
= context
.createNewExpr(base
, arguments
, start
, exprEnd
, lastTokenEnd());
2035 base
= context
.createNewExpr(base
, start
, lastTokenEnd());
2037 int nonLHSCount
= m_nonLHSCount
;
2038 int expressionEnd
= lastTokenEnd();
2039 TreeArguments arguments
= parseArguments(context
);
2040 failIfFalse(arguments
);
2041 base
= context
.makeFunctionCallNode(base
, arguments
, expressionStart
, expressionEnd
, lastTokenEnd());
2042 m_nonLHSCount
= nonLHSCount
;
2047 m_nonTrivialExpressionCount
++;
2048 int expressionEnd
= lastTokenEnd();
2049 nextExpectIdentifier(Lexer::IgnoreReservedWords
| TreeBuilder::DontBuildKeywords
);
2051 base
= context
.createDotAccess(base
, m_token
.m_data
.ident
, expressionStart
, expressionEnd
, tokenEnd());
2056 goto endMemberExpression
;
2059 endMemberExpression
:
2061 base
= context
.createNewExpr(base
, start
, lastTokenEnd());
2065 template <class TreeBuilder
> TreeExpression
JSParser::parseUnaryExpression(TreeBuilder
& context
)
2067 typename
TreeBuilder::UnaryExprContext
unaryExprContext(context
);
2068 AllowInOverride
allowInOverride(this);
2069 int tokenStackDepth
= 0;
2070 bool modifiesExpr
= false;
2071 bool requiresLExpr
= false;
2072 while (isUnaryOp(m_token
.m_type
)) {
2074 switch (m_token
.m_type
) {
2078 case AUTOMINUSMINUS
:
2079 failIfTrue(requiresLExpr
);
2080 modifiesExpr
= true;
2081 requiresLExpr
= true;
2084 failIfTrue(requiresLExpr
);
2085 requiresLExpr
= true;
2088 failIfTrue(requiresLExpr
);
2093 context
.appendUnaryToken(tokenStackDepth
, m_token
.m_type
, tokenStart());
2095 m_nonTrivialExpressionCount
++;
2097 int subExprStart
= tokenStart();
2098 TreeExpression expr
= parseMemberExpression(context
);
2100 bool isEvalOrArguments
= false;
2101 if (strictMode() && !m_syntaxAlreadyValidated
) {
2102 if (context
.isResolve(expr
)) {
2103 isEvalOrArguments
= *m_lastIdentifier
== m_globalData
->propertyNames
->eval
|| *m_lastIdentifier
== m_globalData
->propertyNames
->arguments
;
2106 failIfTrueIfStrict(isEvalOrArguments
&& modifiesExpr
);
2107 switch (m_token
.m_type
) {
2109 m_nonTrivialExpressionCount
++;
2111 expr
= context
.makePostfixNode(expr
, OpPlusPlus
, subExprStart
, lastTokenEnd(), tokenEnd());
2112 m_assignmentCount
++;
2113 failIfTrueIfStrict(isEvalOrArguments
);
2114 failIfTrueIfStrict(requiresLExpr
);
2118 m_nonTrivialExpressionCount
++;
2120 expr
= context
.makePostfixNode(expr
, OpMinusMinus
, subExprStart
, lastTokenEnd(), tokenEnd());
2121 m_assignmentCount
++;
2122 failIfTrueIfStrict(isEvalOrArguments
);
2123 failIfTrueIfStrict(requiresLExpr
);
2130 int end
= lastTokenEnd();
2132 if (!TreeBuilder::CreatesAST
&& (m_syntaxAlreadyValidated
|| !strictMode()))
2135 while (tokenStackDepth
) {
2136 switch (context
.unaryTokenStackLastType(tokenStackDepth
)) {
2138 expr
= context
.createLogicalNot(expr
);
2141 expr
= context
.makeBitwiseNotNode(expr
);
2144 expr
= context
.makeNegateNode(expr
);
2147 expr
= context
.createUnaryPlus(expr
);
2151 expr
= context
.makePrefixNode(expr
, OpPlusPlus
, context
.unaryTokenStackLastStart(tokenStackDepth
), subExprStart
+ 1, end
);
2152 m_assignmentCount
++;
2155 case AUTOMINUSMINUS
:
2156 expr
= context
.makePrefixNode(expr
, OpMinusMinus
, context
.unaryTokenStackLastStart(tokenStackDepth
), subExprStart
+ 1, end
);
2157 m_assignmentCount
++;
2160 expr
= context
.makeTypeOfNode(expr
);
2163 expr
= context
.createVoid(expr
);
2166 failIfTrueIfStrict(context
.isResolve(expr
));
2167 expr
= context
.makeDeleteNode(expr
, context
.unaryTokenStackLastStart(tokenStackDepth
), end
, end
);
2170 // If we get here something has gone horribly horribly wrong
2173 subExprStart
= context
.unaryTokenStackLastStart(tokenStackDepth
);
2174 context
.unaryTokenStackRemoveLast(tokenStackDepth
);
2183 template <> struct VectorTraits
<JSC::JSParser::Scope
> : SimpleClassVectorTraits
{
2184 static const bool canInitializeWithMemset
= false; // Not all Scope data members initialize to 0.