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, 2011, 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.
27 #include "ExceptionHelpers.h"
28 #include "Executable.h"
29 #include "JSGlobalObject.h"
32 #include "ParserArena.h"
33 #include "ParserError.h"
34 #include "ParserTokens.h"
35 #include "SourceProvider.h"
36 #include "SourceProviderCache.h"
37 #include "SourceProviderCacheItem.h"
38 #include <wtf/Forward.h>
39 #include <wtf/Noncopyable.h>
40 #include <wtf/OwnPtr.h>
41 #include <wtf/RefPtr.h>
47 template <> struct VectorTraits
<JSC::Scope
> : SimpleClassVectorTraits
{
48 static const bool canInitializeWithMemset
= false; // Not all Scope data members initialize to 0.
55 class FunctionBodyNode
;
56 class FunctionParameters
;
62 // Macros to make the more common TreeBuilder types a little less verbose
63 #define TreeStatement typename TreeBuilder::Statement
64 #define TreeExpression typename TreeBuilder::Expression
65 #define TreeFormalParameterList typename TreeBuilder::FormalParameterList
66 #define TreeSourceElements typename TreeBuilder::SourceElements
67 #define TreeClause typename TreeBuilder::Clause
68 #define TreeClauseList typename TreeBuilder::ClauseList
69 #define TreeConstDeclList typename TreeBuilder::ConstDeclList
70 #define TreeArguments typename TreeBuilder::Arguments
71 #define TreeArgumentsList typename TreeBuilder::ArgumentsList
72 #define TreeFunctionBody typename TreeBuilder::FunctionBody
73 #define TreeProperty typename TreeBuilder::Property
74 #define TreePropertyList typename TreeBuilder::PropertyList
76 COMPILE_ASSERT(LastUntaggedToken
< 64, LessThan64UntaggedTokens
);
78 enum SourceElementsMode
{ CheckForStrictMode
, DontCheckForStrictMode
};
79 enum FunctionRequirements
{ FunctionNoRequirements
, FunctionNeedsName
};
81 template <typename T
> inline bool isEvalNode() { return false; }
82 template <> inline bool isEvalNode
<EvalNode
>() { return true; }
85 DepthManager(int* depth
)
86 : m_originalDepth(*depth
)
93 *m_depth
= m_originalDepth
;
101 struct ScopeLabelInfo
{
102 ScopeLabelInfo(StringImpl
* ident
, bool isLoop
)
113 Scope(const VM
* vm
, bool isFunction
, bool strictMode
)
115 , m_shadowsArguments(false)
117 , m_needsFullActivation(false)
118 , m_allowsNewDecls(true)
119 , m_strictMode(strictMode
)
120 , m_isFunction(isFunction
)
121 , m_isFunctionBoundary(false)
122 , m_isValidStrictMode(true)
128 Scope(const Scope
& rhs
)
130 , m_shadowsArguments(rhs
.m_shadowsArguments
)
131 , m_usesEval(rhs
.m_usesEval
)
132 , m_needsFullActivation(rhs
.m_needsFullActivation
)
133 , m_allowsNewDecls(rhs
.m_allowsNewDecls
)
134 , m_strictMode(rhs
.m_strictMode
)
135 , m_isFunction(rhs
.m_isFunction
)
136 , m_isFunctionBoundary(rhs
.m_isFunctionBoundary
)
137 , m_isValidStrictMode(rhs
.m_isValidStrictMode
)
138 , m_loopDepth(rhs
.m_loopDepth
)
139 , m_switchDepth(rhs
.m_switchDepth
)
142 m_labels
= adoptPtr(new LabelStack
);
144 typedef LabelStack::const_iterator iterator
;
145 iterator end
= rhs
.m_labels
->end();
146 for (iterator it
= rhs
.m_labels
->begin(); it
!= end
; ++it
)
147 m_labels
->append(ScopeLabelInfo(it
->m_ident
, it
->m_isLoop
));
151 void startSwitch() { m_switchDepth
++; }
152 void endSwitch() { m_switchDepth
--; }
153 void startLoop() { m_loopDepth
++; }
154 void endLoop() { ASSERT(m_loopDepth
); m_loopDepth
--; }
155 bool inLoop() { return !!m_loopDepth
; }
156 bool breakIsValid() { return m_loopDepth
|| m_switchDepth
; }
157 bool continueIsValid() { return m_loopDepth
; }
159 void pushLabel(const Identifier
* label
, bool isLoop
)
162 m_labels
= adoptPtr(new LabelStack
);
163 m_labels
->append(ScopeLabelInfo(label
->impl(), isLoop
));
169 ASSERT(m_labels
->size());
170 m_labels
->removeLast();
173 ScopeLabelInfo
* getLabel(const Identifier
* label
)
177 for (int i
= m_labels
->size(); i
> 0; i
--) {
178 if (m_labels
->at(i
- 1).m_ident
== label
->impl())
179 return &m_labels
->at(i
- 1);
187 m_isFunctionBoundary
= true;
189 bool isFunction() { return m_isFunction
; }
190 bool isFunctionBoundary() { return m_isFunctionBoundary
; }
192 void declareCallee(const Identifier
* ident
)
194 m_declaredVariables
.add(ident
->string().impl());
197 bool declareVariable(const Identifier
* ident
)
199 bool isValidStrictMode
= m_vm
->propertyNames
->eval
!= *ident
&& m_vm
->propertyNames
->arguments
!= *ident
;
200 m_isValidStrictMode
= m_isValidStrictMode
&& isValidStrictMode
;
201 m_declaredVariables
.add(ident
->string().impl());
202 return isValidStrictMode
;
205 void declareWrite(const Identifier
* ident
)
207 ASSERT(m_strictMode
);
208 m_writtenVariables
.add(ident
->impl());
211 void preventNewDecls() { m_allowsNewDecls
= false; }
212 bool allowsNewDecls() const { return m_allowsNewDecls
; }
214 bool declareParameter(const Identifier
* ident
)
216 bool isArguments
= m_vm
->propertyNames
->arguments
== *ident
;
217 bool isValidStrictMode
= m_declaredVariables
.add(ident
->string().impl()).isNewEntry
&& m_vm
->propertyNames
->eval
!= *ident
&& !isArguments
;
218 m_isValidStrictMode
= m_isValidStrictMode
&& isValidStrictMode
;
220 m_shadowsArguments
= true;
221 return isValidStrictMode
;
224 void useVariable(const Identifier
* ident
, bool isEval
)
226 m_usesEval
|= isEval
;
227 m_usedVariables
.add(ident
->string().impl());
230 void setNeedsFullActivation() { m_needsFullActivation
= true; }
232 bool collectFreeVariables(Scope
* nestedScope
, bool shouldTrackClosedVariables
)
234 if (nestedScope
->m_usesEval
)
236 IdentifierSet::iterator end
= nestedScope
->m_usedVariables
.end();
237 for (IdentifierSet::iterator ptr
= nestedScope
->m_usedVariables
.begin(); ptr
!= end
; ++ptr
) {
238 if (nestedScope
->m_declaredVariables
.contains(*ptr
))
240 m_usedVariables
.add(*ptr
);
241 if (shouldTrackClosedVariables
)
242 m_closedVariables
.add(*ptr
);
244 if (nestedScope
->m_writtenVariables
.size()) {
245 IdentifierSet::iterator end
= nestedScope
->m_writtenVariables
.end();
246 for (IdentifierSet::iterator ptr
= nestedScope
->m_writtenVariables
.begin(); ptr
!= end
; ++ptr
) {
247 if (nestedScope
->m_declaredVariables
.contains(*ptr
))
249 m_writtenVariables
.add(*ptr
);
256 void getUncapturedWrittenVariables(IdentifierSet
& writtenVariables
)
258 IdentifierSet::iterator end
= m_writtenVariables
.end();
259 for (IdentifierSet::iterator ptr
= m_writtenVariables
.begin(); ptr
!= end
; ++ptr
) {
260 if (!m_declaredVariables
.contains(*ptr
))
261 writtenVariables
.add(*ptr
);
265 void getCapturedVariables(IdentifierSet
& capturedVariables
)
267 if (m_needsFullActivation
|| m_usesEval
) {
268 capturedVariables
.swap(m_declaredVariables
);
271 for (IdentifierSet::iterator ptr
= m_closedVariables
.begin(); ptr
!= m_closedVariables
.end(); ++ptr
) {
272 if (!m_declaredVariables
.contains(*ptr
))
274 capturedVariables
.add(*ptr
);
277 void setStrictMode() { m_strictMode
= true; }
278 bool strictMode() const { return m_strictMode
; }
279 bool isValidStrictMode() const { return m_isValidStrictMode
; }
280 bool shadowsArguments() const { return m_shadowsArguments
; }
282 void copyCapturedVariablesToVector(const IdentifierSet
& capturedVariables
, Vector
<RefPtr
<StringImpl
> >& vector
)
284 IdentifierSet::iterator end
= capturedVariables
.end();
285 for (IdentifierSet::iterator it
= capturedVariables
.begin(); it
!= end
; ++it
) {
286 if (m_declaredVariables
.contains(*it
))
292 void fillParametersForSourceProviderCache(SourceProviderCacheItemCreationParameters
& parameters
)
294 ASSERT(m_isFunction
);
295 parameters
.usesEval
= m_usesEval
;
296 parameters
.strictMode
= m_strictMode
;
297 parameters
.needsFullActivation
= m_needsFullActivation
;
298 copyCapturedVariablesToVector(m_writtenVariables
, parameters
.writtenVariables
);
299 copyCapturedVariablesToVector(m_usedVariables
, parameters
.usedVariables
);
302 void restoreFromSourceProviderCache(const SourceProviderCacheItem
* info
)
304 ASSERT(m_isFunction
);
305 m_usesEval
= info
->usesEval
;
306 m_strictMode
= info
->strictMode
;
307 m_needsFullActivation
= info
->needsFullActivation
;
308 for (unsigned i
= 0; i
< info
->usedVariablesCount
; ++i
)
309 m_usedVariables
.add(info
->usedVariables()[i
]);
310 for (unsigned i
= 0; i
< info
->writtenVariablesCount
; ++i
)
311 m_writtenVariables
.add(info
->writtenVariables()[i
]);
316 bool m_shadowsArguments
: 1;
318 bool m_needsFullActivation
: 1;
319 bool m_allowsNewDecls
: 1;
320 bool m_strictMode
: 1;
321 bool m_isFunction
: 1;
322 bool m_isFunctionBoundary
: 1;
323 bool m_isValidStrictMode
: 1;
327 typedef Vector
<ScopeLabelInfo
, 2> LabelStack
;
328 OwnPtr
<LabelStack
> m_labels
;
329 IdentifierSet m_declaredVariables
;
330 IdentifierSet m_usedVariables
;
331 IdentifierSet m_closedVariables
;
332 IdentifierSet m_writtenVariables
;
335 typedef Vector
<Scope
, 10> ScopeStack
;
338 ScopeRef(ScopeStack
* scopeStack
, unsigned index
)
339 : m_scopeStack(scopeStack
)
343 Scope
* operator->() { return &m_scopeStack
->at(m_index
); }
344 unsigned index() const { return m_index
; }
346 bool hasContainingScope()
348 return m_index
&& !m_scopeStack
->at(m_index
).isFunctionBoundary();
351 ScopeRef
containingScope()
353 ASSERT(hasContainingScope());
354 return ScopeRef(m_scopeStack
, m_index
- 1);
358 ScopeStack
* m_scopeStack
;
362 template <typename LexerType
>
364 WTF_MAKE_NONCOPYABLE(Parser
);
365 WTF_MAKE_FAST_ALLOCATED
;
368 Parser(VM
*, const SourceCode
&, FunctionParameters
*, const Identifier
&, JSParserStrictness
, JSParserMode
);
371 template <class ParsedNode
>
372 PassRefPtr
<ParsedNode
> parse(ParserError
&);
375 struct AllowInOverride
{
376 AllowInOverride(Parser
* parser
)
378 , m_oldAllowsIn(parser
->m_allowsIn
)
380 parser
->m_allowsIn
= true;
384 m_parser
->m_allowsIn
= m_oldAllowsIn
;
390 struct AutoPopScopeRef
: public ScopeRef
{
391 AutoPopScopeRef(Parser
* parser
, ScopeRef scope
)
400 m_parser
->popScope(*this, false);
412 ScopeRef
currentScope()
414 return ScopeRef(&m_scopeStack
, m_scopeStack
.size() - 1);
419 bool isFunction
= false;
420 bool isStrict
= false;
421 if (!m_scopeStack
.isEmpty()) {
422 isStrict
= m_scopeStack
.last().strictMode();
423 isFunction
= m_scopeStack
.last().isFunction();
425 m_scopeStack
.append(Scope(m_vm
, isFunction
, isStrict
));
426 return currentScope();
429 bool popScopeInternal(ScopeRef
& scope
, bool shouldTrackClosedVariables
)
431 ASSERT_UNUSED(scope
, scope
.index() == m_scopeStack
.size() - 1);
432 ASSERT(m_scopeStack
.size() > 1);
433 bool result
= m_scopeStack
[m_scopeStack
.size() - 2].collectFreeVariables(&m_scopeStack
.last(), shouldTrackClosedVariables
);
434 m_scopeStack
.removeLast();
438 bool popScope(ScopeRef
& scope
, bool shouldTrackClosedVariables
)
440 return popScopeInternal(scope
, shouldTrackClosedVariables
);
443 bool popScope(AutoPopScopeRef
& scope
, bool shouldTrackClosedVariables
)
446 return popScopeInternal(scope
, shouldTrackClosedVariables
);
449 bool declareVariable(const Identifier
* ident
)
451 unsigned i
= m_scopeStack
.size() - 1;
452 ASSERT(i
< m_scopeStack
.size());
453 while (!m_scopeStack
[i
].allowsNewDecls()) {
455 ASSERT(i
< m_scopeStack
.size());
457 return m_scopeStack
[i
].declareVariable(ident
);
460 void declareWrite(const Identifier
* ident
)
462 if (!m_syntaxAlreadyValidated
)
463 m_scopeStack
.last().declareWrite(ident
);
466 ScopeStack m_scopeStack
;
468 const SourceProviderCacheItem
* findCachedFunctionInfo(int openBracePos
)
470 return m_functionCache
? m_functionCache
->get(openBracePos
) : 0;
476 void didFinishParsing(SourceElements
*, ParserArenaData
<DeclarationStacks::VarStack
>*,
477 ParserArenaData
<DeclarationStacks::FunctionStack
>*, CodeFeatures
,
478 int, int, IdentifierSet
&);
480 // Used to determine type of error to report.
481 bool isFunctionBodyNode(ScopeNode
*) { return false; }
482 bool isFunctionBodyNode(FunctionBodyNode
*) { return true; }
484 ALWAYS_INLINE
void next(unsigned lexerFlags
= 0)
486 m_lastLine
= m_token
.m_location
.line
;
487 m_lastTokenEnd
= m_token
.m_location
.endOffset
;
488 m_lastTokenLineStart
= m_token
.m_location
.lineStartOffset
;
489 m_lexer
->setLastLineNumber(m_lastLine
);
490 m_token
.m_type
= m_lexer
->lex(&m_token
.m_data
, &m_token
.m_location
, lexerFlags
, strictMode());
493 ALWAYS_INLINE
void nextExpectIdentifier(unsigned lexerFlags
= 0)
495 m_lastLine
= m_token
.m_location
.line
;
496 m_lastTokenEnd
= m_token
.m_location
.endOffset
;
497 m_lastTokenLineStart
= m_token
.m_location
.lineStartOffset
;
498 m_lexer
->setLastLineNumber(m_lastLine
);
499 m_token
.m_type
= m_lexer
->lexExpectIdentifier(&m_token
.m_data
, &m_token
.m_location
, lexerFlags
, strictMode());
502 ALWAYS_INLINE
bool nextTokenIsColon()
504 return m_lexer
->nextTokenIsColon();
507 ALWAYS_INLINE
bool consume(JSTokenType expected
, unsigned flags
= 0)
509 bool result
= m_token
.m_type
== expected
;
515 ALWAYS_INLINE String
getToken() {
516 SourceProvider
* sourceProvider
= m_source
->provider();
517 return sourceProvider
->getRange(tokenStart(), tokenEnd());
520 ALWAYS_INLINE
bool match(JSTokenType expected
)
522 return m_token
.m_type
== expected
;
525 ALWAYS_INLINE
unsigned tokenStart()
527 return m_token
.m_location
.startOffset
;
530 ALWAYS_INLINE
int tokenLine()
532 return m_token
.m_location
.line
;
535 ALWAYS_INLINE
int tokenColumn()
537 return tokenStart() - tokenLineStart();
540 ALWAYS_INLINE
unsigned tokenEnd()
542 return m_token
.m_location
.endOffset
;
545 ALWAYS_INLINE
unsigned tokenLineStart()
547 return m_token
.m_location
.lineStartOffset
;
550 ALWAYS_INLINE
const JSTokenLocation
& tokenLocation()
552 return m_token
.m_location
;
555 const char* getTokenName(JSTokenType tok
)
715 case RESERVED_IF_STRICT
:
720 case UNTERMINATED_IDENTIFIER_ESCAPE_ERRORTOK
:
721 case UNTERMINATED_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK
:
722 case UNTERMINATED_MULTILINE_COMMENT_ERRORTOK
:
723 case UNTERMINATED_NUMERIC_LITERAL_ERRORTOK
:
724 case UNTERMINATED_STRING_LITERAL_ERRORTOK
:
725 case INVALID_IDENTIFIER_ESCAPE_ERRORTOK
:
726 case INVALID_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK
:
727 case INVALID_NUMERIC_LITERAL_ERRORTOK
:
728 case INVALID_OCTAL_NUMBER_ERRORTOK
:
729 case INVALID_STRING_LITERAL_ERRORTOK
:
733 case LastUntaggedToken
:
736 RELEASE_ASSERT_NOT_REACHED();
737 return "internal error";
740 ALWAYS_INLINE
void updateErrorMessageSpecialCase(JSTokenType expectedToken
)
742 switch (expectedToken
) {
743 case RESERVED_IF_STRICT
:
744 m_errorMessage
= "Use of reserved word '" + getToken() + "' in strict mode";
747 m_errorMessage
= "Use of reserved word '" + getToken() + '\'';
750 m_errorMessage
= "Unexpected number '" + getToken() + '\'';
753 m_errorMessage
= "Expected an identifier but found '" + getToken() + "' instead";
756 m_errorMessage
= "Unexpected string " + getToken();
759 case UNTERMINATED_IDENTIFIER_ESCAPE_ERRORTOK
:
760 case UNTERMINATED_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK
:
761 m_errorMessage
= "Incomplete unicode escape in identifier: '" + getToken() + '\'';
763 case UNTERMINATED_MULTILINE_COMMENT_ERRORTOK
:
764 m_errorMessage
= "Unterminated multiline comment";
766 case UNTERMINATED_NUMERIC_LITERAL_ERRORTOK
:
767 m_errorMessage
= "Unterminated numeric literal '" + getToken() + '\'';
769 case UNTERMINATED_STRING_LITERAL_ERRORTOK
:
770 m_errorMessage
= "Unterminated string literal '" + getToken() + '\'';
772 case INVALID_IDENTIFIER_ESCAPE_ERRORTOK
:
773 m_errorMessage
= "Invalid escape in identifier: '" + getToken() + '\'';
775 case INVALID_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK
:
776 m_errorMessage
= "Invalid unicode escape in identifier: '" + getToken() + '\'';
778 case INVALID_NUMERIC_LITERAL_ERRORTOK
:
779 m_errorMessage
= "Invalid numeric literal: '" + getToken() + '\'';
781 case INVALID_OCTAL_NUMBER_ERRORTOK
:
782 m_errorMessage
= "Invalid use of octal: '" + getToken() + '\'';
784 case INVALID_STRING_LITERAL_ERRORTOK
:
785 m_errorMessage
= "Invalid string literal: '" + getToken() + '\'';
788 m_errorMessage
= "Unrecognized token '" + getToken() + '\'';
791 m_errorMessage
= ASCIILiteral("Unexpected EOF");
794 m_errorMessage
= ASCIILiteral("Return statements are only valid inside functions");
797 RELEASE_ASSERT_NOT_REACHED();
798 m_errorMessage
= ASCIILiteral("internal error");
803 NEVER_INLINE
void updateErrorMessage()
805 const char* name
= getTokenName(m_token
.m_type
);
807 updateErrorMessageSpecialCase(m_token
.m_type
);
809 m_errorMessage
= String::format("Unexpected token '%s'", name
);
810 ASSERT(!m_errorMessage
.isNull());
813 NEVER_INLINE
void updateErrorMessage(JSTokenType expectedToken
)
815 const char* name
= getTokenName(expectedToken
);
817 m_errorMessage
= String::format("Expected token '%s'", name
);
819 if (!getTokenName(m_token
.m_type
))
820 updateErrorMessageSpecialCase(m_token
.m_type
);
822 updateErrorMessageSpecialCase(expectedToken
);
824 ASSERT(!m_errorMessage
.isNull());
827 NEVER_INLINE
void updateErrorWithNameAndMessage(const char* beforeMsg
, String name
, const char* afterMsg
)
829 m_errorMessage
= makeString(beforeMsg
, " '", name
, "' ", afterMsg
);
832 NEVER_INLINE
void updateErrorMessage(const char* msg
)
835 m_errorMessage
= String(msg
);
836 ASSERT(!m_errorMessage
.isNull());
839 void startLoop() { currentScope()->startLoop(); }
840 void endLoop() { currentScope()->endLoop(); }
841 void startSwitch() { currentScope()->startSwitch(); }
842 void endSwitch() { currentScope()->endSwitch(); }
843 void setStrictMode() { currentScope()->setStrictMode(); }
844 bool strictMode() { return currentScope()->strictMode(); }
845 bool isValidStrictMode() { return currentScope()->isValidStrictMode(); }
846 bool declareParameter(const Identifier
* ident
) { return currentScope()->declareParameter(ident
); }
849 ScopeRef current
= currentScope();
850 while (!current
->breakIsValid()) {
851 if (!current
.hasContainingScope())
853 current
= current
.containingScope();
857 bool continueIsValid()
859 ScopeRef current
= currentScope();
860 while (!current
->continueIsValid()) {
861 if (!current
.hasContainingScope())
863 current
= current
.containingScope();
867 void pushLabel(const Identifier
* label
, bool isLoop
) { currentScope()->pushLabel(label
, isLoop
); }
868 void popLabel() { currentScope()->popLabel(); }
869 ScopeLabelInfo
* getLabel(const Identifier
* label
)
871 ScopeRef current
= currentScope();
872 ScopeLabelInfo
* result
= 0;
873 while (!(result
= current
->getLabel(label
))) {
874 if (!current
.hasContainingScope())
876 current
= current
.containingScope();
881 template <SourceElementsMode mode
, class TreeBuilder
> TreeSourceElements
parseSourceElements(TreeBuilder
&);
882 template <class TreeBuilder
> TreeStatement
parseStatement(TreeBuilder
&, const Identifier
*& directive
, unsigned* directiveLiteralLength
= 0);
883 template <class TreeBuilder
> TreeStatement
parseFunctionDeclaration(TreeBuilder
&);
884 template <class TreeBuilder
> TreeStatement
parseVarDeclaration(TreeBuilder
&);
885 template <class TreeBuilder
> TreeStatement
parseConstDeclaration(TreeBuilder
&);
886 template <class TreeBuilder
> TreeStatement
parseDoWhileStatement(TreeBuilder
&);
887 template <class TreeBuilder
> TreeStatement
parseWhileStatement(TreeBuilder
&);
888 template <class TreeBuilder
> TreeStatement
parseForStatement(TreeBuilder
&);
889 template <class TreeBuilder
> TreeStatement
parseBreakStatement(TreeBuilder
&);
890 template <class TreeBuilder
> TreeStatement
parseContinueStatement(TreeBuilder
&);
891 template <class TreeBuilder
> TreeStatement
parseReturnStatement(TreeBuilder
&);
892 template <class TreeBuilder
> TreeStatement
parseThrowStatement(TreeBuilder
&);
893 template <class TreeBuilder
> TreeStatement
parseWithStatement(TreeBuilder
&);
894 template <class TreeBuilder
> TreeStatement
parseSwitchStatement(TreeBuilder
&);
895 template <class TreeBuilder
> TreeClauseList
parseSwitchClauses(TreeBuilder
&);
896 template <class TreeBuilder
> TreeClause
parseSwitchDefaultClause(TreeBuilder
&);
897 template <class TreeBuilder
> TreeStatement
parseTryStatement(TreeBuilder
&);
898 template <class TreeBuilder
> TreeStatement
parseDebuggerStatement(TreeBuilder
&);
899 template <class TreeBuilder
> TreeStatement
parseExpressionStatement(TreeBuilder
&);
900 template <class TreeBuilder
> TreeStatement
parseExpressionOrLabelStatement(TreeBuilder
&);
901 template <class TreeBuilder
> TreeStatement
parseIfStatement(TreeBuilder
&);
902 template <class TreeBuilder
> ALWAYS_INLINE TreeStatement
parseBlockStatement(TreeBuilder
&);
903 template <class TreeBuilder
> TreeExpression
parseExpression(TreeBuilder
&);
904 template <class TreeBuilder
> TreeExpression
parseAssignmentExpression(TreeBuilder
&);
905 template <class TreeBuilder
> ALWAYS_INLINE TreeExpression
parseConditionalExpression(TreeBuilder
&);
906 template <class TreeBuilder
> ALWAYS_INLINE TreeExpression
parseBinaryExpression(TreeBuilder
&);
907 template <class TreeBuilder
> ALWAYS_INLINE TreeExpression
parseUnaryExpression(TreeBuilder
&);
908 template <class TreeBuilder
> TreeExpression
parseMemberExpression(TreeBuilder
&);
909 template <class TreeBuilder
> ALWAYS_INLINE TreeExpression
parsePrimaryExpression(TreeBuilder
&);
910 template <class TreeBuilder
> ALWAYS_INLINE TreeExpression
parseArrayLiteral(TreeBuilder
&);
911 template <class TreeBuilder
> ALWAYS_INLINE TreeExpression
parseObjectLiteral(TreeBuilder
&);
912 template <class TreeBuilder
> ALWAYS_INLINE TreeExpression
parseStrictObjectLiteral(TreeBuilder
&);
913 template <class TreeBuilder
> ALWAYS_INLINE TreeArguments
parseArguments(TreeBuilder
&);
914 template <bool strict
, class TreeBuilder
> ALWAYS_INLINE TreeProperty
parseProperty(TreeBuilder
&);
915 template <class TreeBuilder
> ALWAYS_INLINE TreeFunctionBody
parseFunctionBody(TreeBuilder
&);
916 template <class TreeBuilder
> ALWAYS_INLINE TreeFormalParameterList
parseFormalParameters(TreeBuilder
&);
917 template <class TreeBuilder
> ALWAYS_INLINE TreeExpression
parseVarDeclarationList(TreeBuilder
&, int& declarations
, const Identifier
*& lastIdent
, TreeExpression
& lastInitializer
, int& identStart
, int& initStart
, int& initEnd
);
918 template <class TreeBuilder
> ALWAYS_INLINE TreeConstDeclList
parseConstDeclarationList(TreeBuilder
& context
);
919 template <FunctionRequirements
, bool nameIsInContainingScope
, class TreeBuilder
> bool parseFunctionInfo(TreeBuilder
&, const Identifier
*&, TreeFormalParameterList
&, TreeFunctionBody
&, unsigned& openBraceOffset
, unsigned& closeBraceOffset
, int& bodyStartLine
, unsigned& bodyStartColumn
);
920 ALWAYS_INLINE
int isBinaryOperator(JSTokenType
);
921 bool allowAutomaticSemicolon();
925 if (m_token
.m_type
== SEMICOLON
) {
929 return allowAutomaticSemicolon();
934 return m_stack
.isSafeToRecurse();
937 int lastTokenEnd() const
939 return m_lastTokenEnd
;
942 unsigned lastTokenLine() const
947 unsigned lastTokenLineStart() const
949 return m_lastTokenLineStart
;
952 bool hasError() const
954 return !m_errorMessage
.isNull();
958 const SourceCode
* m_source
;
959 ParserArena
* m_arena
;
960 OwnPtr
<LexerType
> m_lexer
;
963 bool m_hasStackOverflow
;
964 String m_errorMessage
;
969 unsigned m_lastTokenLine
;
970 unsigned m_lastTokenLineStart
;
971 int m_assignmentCount
;
973 bool m_syntaxAlreadyValidated
;
974 int m_statementDepth
;
975 int m_nonTrivialExpressionCount
;
976 const Identifier
* m_lastIdentifier
;
977 RefPtr
<SourceProviderCache
> m_functionCache
;
978 SourceElements
* m_sourceElements
;
979 ParserArenaData
<DeclarationStacks::VarStack
>* m_varDeclarations
;
980 ParserArenaData
<DeclarationStacks::FunctionStack
>* m_funcDeclarations
;
981 IdentifierSet m_capturedVariables
;
982 CodeFeatures m_features
;
985 struct DepthManager
{
986 DepthManager(int* depth
)
987 : m_originalDepth(*depth
)
994 *m_depth
= m_originalDepth
;
1004 template <typename LexerType
>
1005 template <class ParsedNode
>
1006 PassRefPtr
<ParsedNode
> Parser
<LexerType
>::parse(ParserError
& error
)
1011 if (ParsedNode::scopeIsFunction
)
1012 m_lexer
->setIsReparsing();
1014 m_sourceElements
= 0;
1019 JSTokenLocation
startLocation(tokenLocation());
1020 unsigned startColumn
= m_source
->startColumn();
1022 String parseError
= parseInner();
1024 int lineNumber
= m_lexer
->lineNumber();
1025 bool lexError
= m_lexer
->sawError();
1026 String lexErrorMessage
= lexError
? m_lexer
->getErrorMessage() : String();
1027 ASSERT(lexErrorMessage
.isNull() != lexError
);
1030 if (!parseError
.isNull() || lexError
) {
1031 errLine
= lineNumber
;
1032 errMsg
= !lexErrorMessage
.isNull() ? lexErrorMessage
: parseError
;
1033 m_sourceElements
= 0;
1036 RefPtr
<ParsedNode
> result
;
1037 if (m_sourceElements
) {
1038 JSTokenLocation endLocation
;
1039 endLocation
.line
= m_lexer
->lastLineNumber();
1040 endLocation
.lineStartOffset
= m_lexer
->currentLineStartOffset();
1041 endLocation
.startOffset
= m_lexer
->currentOffset();
1042 result
= ParsedNode::create(m_vm
,
1047 m_varDeclarations
? &m_varDeclarations
->data
: 0,
1048 m_funcDeclarations
? &m_funcDeclarations
->data
: 0,
1049 m_capturedVariables
,
1053 result
->setLoc(m_source
->firstLine(), m_lastLine
, m_lexer
->currentOffset(), m_lexer
->currentLineStartOffset());
1055 // We can never see a syntax error when reparsing a function, since we should have
1056 // reported the error when parsing the containing program or eval code. So if we're
1057 // parsing a function body node, we assume that what actually happened here is that
1058 // we ran out of stack while parsing. If we see an error while parsing eval or program
1059 // code we assume that it was a syntax error since running out of stack is much less
1060 // likely, and we are currently unable to distinguish between the two cases.
1061 if (isFunctionBodyNode(static_cast<ParsedNode
*>(0)) || m_hasStackOverflow
)
1062 error
= ParserError(ParserError::StackOverflow
, ParserError::SyntaxErrorNone
, m_token
);
1064 ParserError::SyntaxErrorType errorType
= ParserError::SyntaxErrorIrrecoverable
;
1065 if (m_token
.m_type
== EOFTOK
)
1066 errorType
= ParserError::SyntaxErrorRecoverable
;
1067 else if (m_token
.m_type
& UnterminatedErrorTokenFlag
)
1068 errorType
= ParserError::SyntaxErrorUnterminatedLiteral
;
1070 if (isEvalNode
<ParsedNode
>())
1071 error
= ParserError(ParserError::EvalError
, errorType
, m_token
, errMsg
, errLine
);
1073 error
= ParserError(ParserError::SyntaxError
, errorType
, m_token
, errMsg
, errLine
);
1079 return result
.release();
1082 template <class ParsedNode
>
1083 PassRefPtr
<ParsedNode
> parse(VM
* vm
, const SourceCode
& source
, FunctionParameters
* parameters
, const Identifier
& name
, JSParserStrictness strictness
, JSParserMode parserMode
, ParserError
& error
)
1085 SamplingRegion
samplingRegion("Parsing");
1087 ASSERT(!source
.provider()->source().isNull());
1088 if (source
.provider()->source().is8Bit()) {
1089 Parser
< Lexer
<LChar
> > parser(vm
, source
, parameters
, name
, strictness
, parserMode
);
1090 return parser
.parse
<ParsedNode
>(error
);
1092 Parser
< Lexer
<UChar
> > parser(vm
, source
, parameters
, name
, strictness
, parserMode
);
1093 return parser
.parse
<ParsedNode
>(error
);