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 Apple Inc. All rights reserved.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
26 #include "ASTBuilder.h"
27 #include "CodeBlock.h"
29 #include "JSGlobalData.h"
32 #include "SourceProvider.h"
34 #include <wtf/HashFunctions.h>
35 #include <wtf/OwnPtr.h>
36 #include <wtf/WTFThreadData.h>
42 template <typename LexerType
>
43 Parser
<LexerType
>::Parser(JSGlobalData
* globalData
, const SourceCode
& source
, FunctionParameters
* parameters
, JSParserStrictness strictness
, JSParserMode parserMode
)
44 : m_globalData(globalData
)
46 , m_stack(wtfThreadData().stack())
48 , m_errorMessage("Parse error")
52 , m_assignmentCount(0)
54 , m_syntaxAlreadyValidated(source
.provider()->isValid())
56 , m_nonTrivialExpressionCount(0)
60 m_lexer
= adoptPtr(new LexerType(globalData
));
61 m_arena
= m_globalData
->parserArena
.get();
62 m_lexer
->setCode(source
, m_arena
);
64 m_functionCache
= source
.provider()->cache();
65 ScopeRef scope
= pushScope();
66 if (parserMode
== JSParseFunctionCode
)
67 scope
->setIsFunction();
68 if (strictness
== JSParseStrict
)
69 scope
->setStrictMode();
71 for (unsigned i
= 0; i
< parameters
->size(); i
++)
72 scope
->declareParameter(¶meters
->at(i
));
75 m_lexer
->setLastLineNumber(tokenLine());
78 template <typename LexerType
>
79 Parser
<LexerType
>::~Parser()
83 template <typename LexerType
>
84 UString Parser
<LexerType
>::parseInner()
86 UString parseError
= UString();
88 unsigned oldFunctionCacheSize
= m_functionCache
? m_functionCache
->byteSize() : 0;
89 ASTBuilder
context(const_cast<JSGlobalData
*>(m_globalData
), const_cast<SourceCode
*>(m_source
));
90 if (m_lexer
->isReparsing())
92 ScopeRef scope
= currentScope();
93 SourceElements
* sourceElements
= parseSourceElements
<CheckForStrictMode
>(context
);
94 if (!sourceElements
|| !consume(EOFTOK
))
95 parseError
= m_errorMessage
;
97 IdentifierSet capturedVariables
;
98 scope
->getCapturedVariables(capturedVariables
);
99 CodeFeatures features
= context
.features();
100 if (scope
->strictMode())
101 features
|= StrictModeFeature
;
102 if (scope
->shadowsArguments())
103 features
|= ShadowsArgumentsFeature
;
104 unsigned functionCacheSize
= m_functionCache
? m_functionCache
->byteSize() : 0;
105 if (functionCacheSize
!= oldFunctionCacheSize
)
106 m_lexer
->sourceProvider()->notifyCacheSizeChanged(functionCacheSize
- oldFunctionCacheSize
);
108 didFinishParsing(sourceElements
, context
.varDeclarations(), context
.funcDeclarations(), features
,
109 m_lastLine
, context
.numConstants(), capturedVariables
);
114 template <typename LexerType
>
115 void Parser
<LexerType
>::didFinishParsing(SourceElements
* sourceElements
, ParserArenaData
<DeclarationStacks::VarStack
>* varStack
,
116 ParserArenaData
<DeclarationStacks::FunctionStack
>* funcStack
, CodeFeatures features
, int lastLine
, int numConstants
, IdentifierSet
& capturedVars
)
118 m_sourceElements
= sourceElements
;
119 m_varDeclarations
= varStack
;
120 m_funcDeclarations
= funcStack
;
121 m_capturedVariables
.swap(capturedVars
);
122 m_features
= features
;
123 m_lastLine
= lastLine
;
124 m_numConstants
= numConstants
;
127 template <typename LexerType
>
128 bool Parser
<LexerType
>::allowAutomaticSemicolon()
130 return match(CLOSEBRACE
) || match(EOFTOK
) || m_lexer
->prevTerminator();
133 template <typename LexerType
>
134 template <SourceElementsMode mode
, class TreeBuilder
> TreeSourceElements Parser
<LexerType
>::parseSourceElements(TreeBuilder
& context
)
136 const unsigned lengthOfUseStrictLiteral
= 12; // "use strict".length
137 TreeSourceElements sourceElements
= context
.createSourceElements();
138 bool seenNonDirective
= false;
139 const Identifier
* directive
= 0;
140 unsigned directiveLiteralLength
= 0;
141 unsigned startOffset
= m_token
.m_info
.startOffset
;
142 unsigned oldLastLineNumber
= m_lexer
->lastLineNumber();
143 unsigned oldLineNumber
= m_lexer
->lineNumber();
144 bool hasSetStrict
= false;
145 while (TreeStatement statement
= parseStatement(context
, directive
, &directiveLiteralLength
)) {
146 if (mode
== CheckForStrictMode
&& !seenNonDirective
) {
148 // "use strict" must be the exact literal without escape sequences or line continuation.
149 if (!hasSetStrict
&& directiveLiteralLength
== lengthOfUseStrictLiteral
&& m_globalData
->propertyNames
->useStrictIdentifier
== *directive
) {
152 failIfFalse(isValidStrictMode());
153 m_lexer
->setOffset(startOffset
);
155 m_lexer
->setLastLineNumber(oldLastLineNumber
);
156 m_lexer
->setLineNumber(oldLineNumber
);
161 seenNonDirective
= true;
163 context
.appendStatement(sourceElements
, statement
);
168 return sourceElements
;
171 template <typename LexerType
>
172 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseVarDeclaration(TreeBuilder
& context
)
175 int start
= tokenLine();
178 const Identifier
* scratch1
= 0;
179 TreeExpression scratch2
= 0;
181 TreeExpression varDecls
= parseVarDeclarationList(context
, scratch
, scratch1
, scratch2
, scratch3
, scratch3
, scratch3
);
183 failIfFalse(autoSemiColon());
185 return context
.createVarStatement(m_lexer
->lastLineNumber(), varDecls
, start
, end
);
188 template <typename LexerType
>
189 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseConstDeclaration(TreeBuilder
& context
)
191 ASSERT(match(CONSTTOKEN
));
192 int start
= tokenLine();
194 TreeConstDeclList constDecls
= parseConstDeclarationList(context
);
196 failIfFalse(autoSemiColon());
198 return context
.createConstStatement(m_lexer
->lastLineNumber(), constDecls
, start
, end
);
201 template <typename LexerType
>
202 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseDoWhileStatement(TreeBuilder
& context
)
205 int startLine
= tokenLine();
207 const Identifier
* unused
= 0;
209 TreeStatement statement
= parseStatement(context
, unused
);
211 failIfFalse(statement
);
212 int endLine
= tokenLine();
213 consumeOrFail(WHILE
);
214 consumeOrFail(OPENPAREN
);
215 TreeExpression expr
= parseExpression(context
);
217 consumeOrFail(CLOSEPAREN
);
218 if (match(SEMICOLON
))
219 next(); // Always performs automatic semicolon insertion.
220 return context
.createDoWhileStatement(m_lexer
->lastLineNumber(), statement
, expr
, startLine
, endLine
);
223 template <typename LexerType
>
224 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseWhileStatement(TreeBuilder
& context
)
226 ASSERT(match(WHILE
));
227 int startLine
= tokenLine();
229 consumeOrFail(OPENPAREN
);
230 TreeExpression expr
= parseExpression(context
);
232 int endLine
= tokenLine();
233 consumeOrFail(CLOSEPAREN
);
234 const Identifier
* unused
= 0;
236 TreeStatement statement
= parseStatement(context
, unused
);
238 failIfFalse(statement
);
239 return context
.createWhileStatement(m_lexer
->lastLineNumber(), expr
, statement
, startLine
, endLine
);
242 template <typename LexerType
>
243 template <class TreeBuilder
> TreeExpression Parser
<LexerType
>::parseVarDeclarationList(TreeBuilder
& context
, int& declarations
, const Identifier
*& lastIdent
, TreeExpression
& lastInitializer
, int& identStart
, int& initStart
, int& initEnd
)
245 TreeExpression varDecls
= 0;
251 int varStart
= tokenStart();
252 identStart
= varStart
;
253 const Identifier
* name
= m_token
.m_data
.ident
;
256 bool hasInitializer
= match(EQUAL
);
257 failIfFalseIfStrictWithNameAndMessage(declareVariable(name
), "Cannot declare a variable named", name
->impl(), "in strict mode.");
258 context
.addVar(name
, (hasInitializer
|| (!m_allowsIn
&& match(INTOKEN
))) ? DeclarationStacks::HasInitializer
: 0);
259 if (hasInitializer
) {
260 int varDivot
= tokenStart() + 1;
261 initStart
= tokenStart();
262 next(TreeBuilder::DontBuildStrings
); // consume '='
263 int initialAssignments
= m_assignmentCount
;
264 TreeExpression initializer
= parseAssignmentExpression(context
);
265 initEnd
= lastTokenEnd();
266 lastInitializer
= initializer
;
267 failIfFalse(initializer
);
269 TreeExpression node
= context
.createAssignResolve(m_lexer
->lastLineNumber(), *name
, initializer
, initialAssignments
!= m_assignmentCount
, varStart
, varDivot
, lastTokenEnd());
273 varDecls
= context
.combineCommaNodes(m_lexer
->lastLineNumber(), varDecls
, node
);
275 } while (match(COMMA
));
279 template <typename LexerType
>
280 template <class TreeBuilder
> TreeConstDeclList Parser
<LexerType
>::parseConstDeclarationList(TreeBuilder
& context
)
282 failIfTrue(strictMode());
283 TreeConstDeclList constDecls
= 0;
284 TreeConstDeclList tail
= 0;
288 const Identifier
* name
= m_token
.m_data
.ident
;
290 bool hasInitializer
= match(EQUAL
);
291 declareVariable(name
);
292 context
.addVar(name
, DeclarationStacks::IsConstant
| (hasInitializer
? DeclarationStacks::HasInitializer
: 0));
293 TreeExpression initializer
= 0;
294 if (hasInitializer
) {
295 next(TreeBuilder::DontBuildStrings
); // consume '='
296 initializer
= parseAssignmentExpression(context
);
298 tail
= context
.appendConstDecl(m_lexer
->lastLineNumber(), tail
, name
, initializer
);
301 } while (match(COMMA
));
305 template <typename LexerType
>
306 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseForStatement(TreeBuilder
& context
)
309 int startLine
= tokenLine();
311 consumeOrFail(OPENPAREN
);
312 int nonLHSCount
= m_nonLHSCount
;
313 int declarations
= 0;
316 TreeExpression decls
= 0;
317 bool hasDeclaration
= false;
320 for (var IDENT in expression) statement
321 for (var IDENT = expression in expression) statement
322 for (var varDeclarationList; expressionOpt; expressionOpt)
324 hasDeclaration
= true;
325 const Identifier
* forInTarget
= 0;
326 TreeExpression forInInitializer
= 0;
330 decls
= parseVarDeclarationList(context
, declarations
, forInTarget
, forInInitializer
, declsStart
, initStart
, initEnd
);
335 // Remainder of a standard for loop is handled identically
336 if (match(SEMICOLON
))
337 goto standardForLoop
;
339 failIfFalse(declarations
== 1);
341 // Handle for-in with var declaration
342 int inLocation
= tokenStart();
343 consumeOrFail(INTOKEN
);
345 TreeExpression expr
= parseExpression(context
);
347 int exprEnd
= lastTokenEnd();
349 int endLine
= tokenLine();
350 consumeOrFail(CLOSEPAREN
);
352 const Identifier
* unused
= 0;
354 TreeStatement statement
= parseStatement(context
, unused
);
356 failIfFalse(statement
);
358 return context
.createForInLoop(m_lexer
->lastLineNumber(), forInTarget
, forInInitializer
, expr
, statement
, declsStart
, inLocation
, exprEnd
, initStart
, initEnd
, startLine
, endLine
);
361 if (!match(SEMICOLON
)) {
363 declsStart
= tokenStart();
364 decls
= parseExpression(context
);
365 declsEnd
= lastTokenEnd();
370 if (match(SEMICOLON
)) {
374 TreeExpression condition
= 0;
376 if (!match(SEMICOLON
)) {
377 condition
= parseExpression(context
);
378 failIfFalse(condition
);
380 consumeOrFail(SEMICOLON
);
382 TreeExpression increment
= 0;
383 if (!match(CLOSEPAREN
)) {
384 increment
= parseExpression(context
);
385 failIfFalse(increment
);
387 int endLine
= tokenLine();
388 consumeOrFail(CLOSEPAREN
);
389 const Identifier
* unused
= 0;
391 TreeStatement statement
= parseStatement(context
, unused
);
393 failIfFalse(statement
);
394 return context
.createForLoop(m_lexer
->lastLineNumber(), decls
, condition
, increment
, statement
, hasDeclaration
, startLine
, endLine
);
398 failIfFalse(nonLHSCount
== m_nonLHSCount
);
399 consumeOrFail(INTOKEN
);
400 TreeExpression expr
= parseExpression(context
);
402 int exprEnd
= lastTokenEnd();
403 int endLine
= tokenLine();
404 consumeOrFail(CLOSEPAREN
);
405 const Identifier
* unused
= 0;
407 TreeStatement statement
= parseStatement(context
, unused
);
409 failIfFalse(statement
);
411 return context
.createForInLoop(m_lexer
->lastLineNumber(), decls
, expr
, statement
, declsStart
, declsEnd
, exprEnd
, startLine
, endLine
);
414 template <typename LexerType
>
415 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseBreakStatement(TreeBuilder
& context
)
417 ASSERT(match(BREAK
));
418 int startCol
= tokenStart();
419 int endCol
= tokenEnd();
420 int startLine
= tokenLine();
421 int endLine
= tokenLine();
424 if (autoSemiColon()) {
425 failIfFalseWithMessage(breakIsValid(), "'break' is only valid inside a switch or loop statement");
426 return context
.createBreakStatement(m_lexer
->lastLineNumber(), startCol
, endCol
, startLine
, endLine
);
429 const Identifier
* ident
= m_token
.m_data
.ident
;
430 failIfFalseWithNameAndMessage(getLabel(ident
), "Label", ident
->impl(), "is not defined");
432 endLine
= tokenLine();
434 failIfFalse(autoSemiColon());
435 return context
.createBreakStatement(m_lexer
->lastLineNumber(), ident
, startCol
, endCol
, startLine
, endLine
);
438 template <typename LexerType
>
439 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseContinueStatement(TreeBuilder
& context
)
441 ASSERT(match(CONTINUE
));
442 int startCol
= tokenStart();
443 int endCol
= tokenEnd();
444 int startLine
= tokenLine();
445 int endLine
= tokenLine();
448 if (autoSemiColon()) {
449 failIfFalseWithMessage(continueIsValid(), "'continue' is only valid inside a loop statement");
450 return context
.createContinueStatement(m_lexer
->lastLineNumber(), startCol
, endCol
, startLine
, endLine
);
453 const Identifier
* ident
= m_token
.m_data
.ident
;
454 ScopeLabelInfo
* label
= getLabel(ident
);
455 failIfFalseWithNameAndMessage(label
, "Label", ident
->impl(), "is not defined");
456 failIfFalseWithMessage(label
->m_isLoop
, "'continue' is only valid inside a loop statement");
458 endLine
= tokenLine();
460 failIfFalse(autoSemiColon());
461 return context
.createContinueStatement(m_lexer
->lastLineNumber(), ident
, startCol
, endCol
, startLine
, endLine
);
464 template <typename LexerType
>
465 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseReturnStatement(TreeBuilder
& context
)
467 ASSERT(match(RETURN
));
468 failIfFalse(currentScope()->isFunction());
469 int startLine
= tokenLine();
470 int endLine
= startLine
;
471 int start
= tokenStart();
472 int end
= tokenEnd();
474 // We do the auto semicolon check before attempting to parse an expression
475 // as we need to ensure the a line break after the return correctly terminates
477 if (match(SEMICOLON
))
478 endLine
= tokenLine();
480 return context
.createReturnStatement(m_lexer
->lastLineNumber(), 0, start
, end
, startLine
, endLine
);
481 TreeExpression expr
= parseExpression(context
);
483 end
= lastTokenEnd();
484 if (match(SEMICOLON
))
485 endLine
= tokenLine();
486 failIfFalse(autoSemiColon());
487 return context
.createReturnStatement(m_lexer
->lastLineNumber(), expr
, start
, end
, startLine
, endLine
);
490 template <typename LexerType
>
491 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseThrowStatement(TreeBuilder
& context
)
493 ASSERT(match(THROW
));
494 int eStart
= tokenStart();
495 int startLine
= tokenLine();
498 failIfTrue(autoSemiColon());
500 TreeExpression expr
= parseExpression(context
);
502 int eEnd
= lastTokenEnd();
503 int endLine
= tokenLine();
504 failIfFalse(autoSemiColon());
506 return context
.createThrowStatement(m_lexer
->lastLineNumber(), expr
, eStart
, eEnd
, startLine
, endLine
);
509 template <typename LexerType
>
510 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseWithStatement(TreeBuilder
& context
)
513 failIfTrueWithMessage(strictMode(), "'with' statements are not valid in strict mode");
514 currentScope()->setNeedsFullActivation();
515 int startLine
= tokenLine();
517 consumeOrFail(OPENPAREN
);
518 int start
= tokenStart();
519 TreeExpression expr
= parseExpression(context
);
521 int end
= lastTokenEnd();
523 int endLine
= tokenLine();
524 consumeOrFail(CLOSEPAREN
);
525 const Identifier
* unused
= 0;
526 TreeStatement statement
= parseStatement(context
, unused
);
527 failIfFalse(statement
);
529 return context
.createWithStatement(m_lexer
->lastLineNumber(), expr
, statement
, start
, end
, startLine
, endLine
);
532 template <typename LexerType
>
533 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseSwitchStatement(TreeBuilder
& context
)
535 ASSERT(match(SWITCH
));
536 int startLine
= tokenLine();
538 consumeOrFail(OPENPAREN
);
539 TreeExpression expr
= parseExpression(context
);
541 int endLine
= tokenLine();
542 consumeOrFail(CLOSEPAREN
);
543 consumeOrFail(OPENBRACE
);
545 TreeClauseList firstClauses
= parseSwitchClauses(context
);
548 TreeClause defaultClause
= parseSwitchDefaultClause(context
);
551 TreeClauseList secondClauses
= parseSwitchClauses(context
);
554 consumeOrFail(CLOSEBRACE
);
556 return context
.createSwitchStatement(m_lexer
->lastLineNumber(), expr
, firstClauses
, defaultClause
, secondClauses
, startLine
, endLine
);
560 template <typename LexerType
>
561 template <class TreeBuilder
> TreeClauseList Parser
<LexerType
>::parseSwitchClauses(TreeBuilder
& context
)
566 TreeExpression condition
= parseExpression(context
);
567 failIfFalse(condition
);
568 consumeOrFail(COLON
);
569 TreeSourceElements statements
= parseSourceElements
<DontCheckForStrictMode
>(context
);
570 failIfFalse(statements
);
571 TreeClause clause
= context
.createClause(condition
, statements
);
572 TreeClauseList clauseList
= context
.createClauseList(clause
);
573 TreeClauseList tail
= clauseList
;
575 while (match(CASE
)) {
577 TreeExpression condition
= parseExpression(context
);
578 failIfFalse(condition
);
579 consumeOrFail(COLON
);
580 TreeSourceElements statements
= parseSourceElements
<DontCheckForStrictMode
>(context
);
581 failIfFalse(statements
);
582 clause
= context
.createClause(condition
, statements
);
583 tail
= context
.createClauseList(tail
, clause
);
588 template <typename LexerType
>
589 template <class TreeBuilder
> TreeClause Parser
<LexerType
>::parseSwitchDefaultClause(TreeBuilder
& context
)
594 consumeOrFail(COLON
);
595 TreeSourceElements statements
= parseSourceElements
<DontCheckForStrictMode
>(context
);
596 failIfFalse(statements
);
597 return context
.createClause(0, statements
);
600 template <typename LexerType
>
601 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseTryStatement(TreeBuilder
& context
)
604 TreeStatement tryBlock
= 0;
605 const Identifier
* ident
= &m_globalData
->propertyNames
->nullIdentifier
;
606 TreeStatement catchBlock
= 0;
607 TreeStatement finallyBlock
= 0;
608 int firstLine
= tokenLine();
610 matchOrFail(OPENBRACE
);
612 tryBlock
= parseBlockStatement(context
);
613 failIfFalse(tryBlock
);
614 int lastLine
= m_lastLine
;
617 currentScope()->setNeedsFullActivation();
619 consumeOrFail(OPENPAREN
);
621 ident
= m_token
.m_data
.ident
;
623 AutoPopScopeRef
catchScope(this, pushScope());
624 failIfFalseIfStrictWithNameAndMessage(declareVariable(ident
), "Cannot declare a variable named", ident
->impl(), "in strict mode");
625 catchScope
->preventNewDecls();
626 consumeOrFail(CLOSEPAREN
);
627 matchOrFail(OPENBRACE
);
628 catchBlock
= parseBlockStatement(context
);
629 failIfFalseWithMessage(catchBlock
, "'try' must have a catch or finally block");
630 failIfFalse(popScope(catchScope
, TreeBuilder::NeedsFreeVariableInfo
));
633 if (match(FINALLY
)) {
635 matchOrFail(OPENBRACE
);
636 finallyBlock
= parseBlockStatement(context
);
637 failIfFalse(finallyBlock
);
639 failIfFalse(catchBlock
|| finallyBlock
);
640 return context
.createTryStatement(m_lexer
->lastLineNumber(), tryBlock
, ident
, catchBlock
, finallyBlock
, firstLine
, lastLine
);
643 template <typename LexerType
>
644 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseDebuggerStatement(TreeBuilder
& context
)
646 ASSERT(match(DEBUGGER
));
647 int startLine
= tokenLine();
648 int endLine
= startLine
;
650 if (match(SEMICOLON
))
651 startLine
= tokenLine();
652 failIfFalse(autoSemiColon());
653 return context
.createDebugger(m_lexer
->lastLineNumber(), startLine
, endLine
);
656 template <typename LexerType
>
657 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseBlockStatement(TreeBuilder
& context
)
659 ASSERT(match(OPENBRACE
));
660 int start
= tokenLine();
662 if (match(CLOSEBRACE
)) {
664 return context
.createBlockStatement(m_lexer
->lastLineNumber(), 0, start
, m_lastLine
);
666 TreeSourceElements subtree
= parseSourceElements
<DontCheckForStrictMode
>(context
);
667 failIfFalse(subtree
);
668 matchOrFail(CLOSEBRACE
);
670 return context
.createBlockStatement(m_lexer
->lastLineNumber(), subtree
, start
, m_lastLine
);
673 template <typename LexerType
>
674 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseStatement(TreeBuilder
& context
, const Identifier
*& directive
, unsigned* directiveLiteralLength
)
676 DepthManager
statementDepth(&m_statementDepth
);
679 int nonTrivialExpressionCount
= 0;
680 failIfStackOverflow();
681 switch (m_token
.m_type
) {
683 return parseBlockStatement(context
);
685 return parseVarDeclaration(context
);
687 return parseConstDeclaration(context
);
689 failIfFalseIfStrictWithMessage(m_statementDepth
== 1, "Functions cannot be declared in a nested block in strict mode");
690 return parseFunctionDeclaration(context
);
693 return context
.createEmptyStatement(m_lexer
->lastLineNumber());
695 return parseIfStatement(context
);
697 return parseDoWhileStatement(context
);
699 return parseWhileStatement(context
);
701 return parseForStatement(context
);
703 return parseContinueStatement(context
);
705 return parseBreakStatement(context
);
707 return parseReturnStatement(context
);
709 return parseWithStatement(context
);
711 return parseSwitchStatement(context
);
713 return parseThrowStatement(context
);
715 return parseTryStatement(context
);
717 return parseDebuggerStatement(context
);
722 // These tokens imply the end of a set of source elements
725 return parseExpressionOrLabelStatement(context
);
727 directive
= m_token
.m_data
.ident
;
728 if (directiveLiteralLength
)
729 *directiveLiteralLength
= m_token
.m_info
.endOffset
- m_token
.m_info
.startOffset
;
730 nonTrivialExpressionCount
= m_nonTrivialExpressionCount
;
732 TreeStatement exprStatement
= parseExpressionStatement(context
);
733 if (directive
&& nonTrivialExpressionCount
!= m_nonTrivialExpressionCount
)
735 return exprStatement
;
739 template <typename LexerType
>
740 template <class TreeBuilder
> TreeFormalParameterList Parser
<LexerType
>::parseFormalParameters(TreeBuilder
& context
)
743 failIfFalseIfStrictWithNameAndMessage(declareParameter(m_token
.m_data
.ident
), "Cannot declare a parameter named", m_token
.m_data
.ident
->impl(), " in strict mode");
744 TreeFormalParameterList list
= context
.createFormalParameterList(*m_token
.m_data
.ident
);
745 TreeFormalParameterList tail
= list
;
747 while (match(COMMA
)) {
750 const Identifier
* ident
= m_token
.m_data
.ident
;
751 failIfFalseIfStrictWithNameAndMessage(declareParameter(ident
), "Cannot declare a parameter named", ident
->impl(), "in strict mode");
753 tail
= context
.createFormalParameterList(tail
, *ident
);
758 template <typename LexerType
>
759 template <class TreeBuilder
> TreeFunctionBody Parser
<LexerType
>::parseFunctionBody(TreeBuilder
& context
)
761 if (match(CLOSEBRACE
))
762 return context
.createFunctionBody(m_lexer
->lastLineNumber(), strictMode());
763 DepthManager
statementDepth(&m_statementDepth
);
764 m_statementDepth
= 0;
765 typename
TreeBuilder::FunctionBodyBuilder
bodyBuilder(const_cast<JSGlobalData
*>(m_globalData
), m_lexer
.get());
766 failIfFalse(parseSourceElements
<CheckForStrictMode
>(bodyBuilder
));
767 return context
.createFunctionBody(m_lexer
->lastLineNumber(), strictMode());
770 template <typename LexerType
>
771 template <FunctionRequirements requirements
, bool nameIsInContainingScope
, class TreeBuilder
> bool Parser
<LexerType
>::parseFunctionInfo(TreeBuilder
& context
, const Identifier
*& name
, TreeFormalParameterList
& parameters
, TreeFunctionBody
& body
, int& openBracePos
, int& closeBracePos
, int& bodyStartLine
)
773 AutoPopScopeRef
functionScope(this, pushScope());
774 functionScope
->setIsFunction();
776 name
= m_token
.m_data
.ident
;
778 if (!nameIsInContainingScope
)
779 failIfFalseIfStrict(functionScope
->declareVariable(name
));
780 } else if (requirements
== FunctionNeedsName
)
782 consumeOrFail(OPENPAREN
);
783 if (!match(CLOSEPAREN
)) {
784 parameters
= parseFormalParameters(context
);
785 failIfFalse(parameters
);
787 consumeOrFail(CLOSEPAREN
);
788 matchOrFail(OPENBRACE
);
790 openBracePos
= m_token
.m_data
.intValue
;
791 bodyStartLine
= tokenLine();
793 // If we know about this function already, we can use the cached info and skip the parser to the end of the function.
794 if (const SourceProviderCacheItem
* cachedInfo
= TreeBuilder::CanUseFunctionCache
? findCachedFunctionInfo(openBracePos
) : 0) {
795 // If we're in a strict context, the cached function info must say it was strict too.
796 ASSERT(!strictMode() || cachedInfo
->strictMode
);
797 body
= context
.createFunctionBody(m_lexer
->lastLineNumber(), cachedInfo
->strictMode
);
799 functionScope
->restoreFunctionInfo(cachedInfo
);
800 failIfFalse(popScope(functionScope
, TreeBuilder::NeedsFreeVariableInfo
));
802 closeBracePos
= cachedInfo
->closeBracePos
;
803 m_token
= cachedInfo
->closeBraceToken();
804 m_lexer
->setOffset(m_token
.m_info
.endOffset
);
805 m_lexer
->setLineNumber(m_token
.m_info
.line
);
813 body
= parseFunctionBody(context
);
815 if (functionScope
->strictMode() && name
) {
816 failIfTrueWithNameAndMessage(m_globalData
->propertyNames
->arguments
== *name
, "Function name", name
->impl(), "is not valid in strict mode");
817 failIfTrueWithNameAndMessage(m_globalData
->propertyNames
->eval
== *name
, "Function name", name
->impl(), "is not valid in strict mode");
819 closeBracePos
= m_token
.m_data
.intValue
;
821 // Cache the tokenizer state and the function scope the first time the function is parsed.
822 // Any future reparsing can then skip the function.
823 static const int minimumFunctionLengthToCache
= 64;
824 OwnPtr
<SourceProviderCacheItem
> newInfo
;
825 int functionLength
= closeBracePos
- openBracePos
;
826 if (TreeBuilder::CanUseFunctionCache
&& m_functionCache
&& functionLength
> minimumFunctionLengthToCache
) {
827 newInfo
= adoptPtr(new SourceProviderCacheItem(m_token
.m_info
.line
, closeBracePos
));
828 functionScope
->saveFunctionInfo(newInfo
.get());
831 failIfFalse(popScope(functionScope
, TreeBuilder::NeedsFreeVariableInfo
));
832 matchOrFail(CLOSEBRACE
);
835 unsigned approximateByteSize
= newInfo
->approximateByteSize();
836 m_functionCache
->add(openBracePos
, newInfo
.release(), approximateByteSize
);
843 template <typename LexerType
>
844 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseFunctionDeclaration(TreeBuilder
& context
)
846 ASSERT(match(FUNCTION
));
848 const Identifier
* name
= 0;
849 TreeFormalParameterList parameters
= 0;
850 TreeFunctionBody body
= 0;
851 int openBracePos
= 0;
852 int closeBracePos
= 0;
853 int bodyStartLine
= 0;
854 failIfFalse((parseFunctionInfo
<FunctionNeedsName
, true>(context
, name
, parameters
, body
, openBracePos
, closeBracePos
, bodyStartLine
)));
856 failIfFalseIfStrict(declareVariable(name
));
857 return context
.createFuncDeclStatement(m_lexer
->lastLineNumber(), name
, body
, parameters
, openBracePos
, closeBracePos
, bodyStartLine
, m_lastLine
);
861 LabelInfo(const Identifier
* ident
, int start
, int end
)
868 const Identifier
* m_ident
;
873 template <typename LexerType
>
874 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseExpressionOrLabelStatement(TreeBuilder
& context
)
877 /* Expression and Label statements are ambiguous at LL(1), so we have a
878 * special case that looks for a colon as the next character in the input.
880 Vector
<LabelInfo
> labels
;
883 int start
= tokenStart();
884 int startLine
= tokenLine();
885 if (!nextTokenIsColon()) {
886 // If we hit this path we're making a expression statement, which
887 // by definition can't make use of continue/break so we can just
888 // ignore any labels we might have accumulated.
889 TreeExpression expression
= parseExpression(context
);
890 failIfFalse(expression
);
891 failIfFalse(autoSemiColon());
892 return context
.createExprStatement(m_lexer
->lastLineNumber(), expression
, startLine
, m_lastLine
);
894 const Identifier
* ident
= m_token
.m_data
.ident
;
895 int end
= tokenEnd();
897 consumeOrFail(COLON
);
898 if (!m_syntaxAlreadyValidated
) {
899 // This is O(N^2) over the current list of consecutive labels, but I
900 // have never seen more than one label in a row in the real world.
901 for (size_t i
= 0; i
< labels
.size(); i
++)
902 failIfTrue(ident
->impl() == labels
[i
].m_ident
->impl());
903 failIfTrue(getLabel(ident
));
904 labels
.append(LabelInfo(ident
, start
, end
));
906 } while (match(IDENT
));
908 switch (m_token
.m_type
) {
918 const Identifier
* unused
= 0;
919 if (!m_syntaxAlreadyValidated
) {
920 for (size_t i
= 0; i
< labels
.size(); i
++)
921 pushLabel(labels
[i
].m_ident
, isLoop
);
923 TreeStatement statement
= parseStatement(context
, unused
);
924 if (!m_syntaxAlreadyValidated
) {
925 for (size_t i
= 0; i
< labels
.size(); i
++)
928 failIfFalse(statement
);
929 for (size_t i
= 0; i
< labels
.size(); i
++) {
930 const LabelInfo
& info
= labels
[labels
.size() - i
- 1];
931 statement
= context
.createLabelStatement(m_lexer
->lastLineNumber(), info
.m_ident
, statement
, info
.m_start
, info
.m_end
);
936 template <typename LexerType
>
937 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseExpressionStatement(TreeBuilder
& context
)
939 int startLine
= tokenLine();
940 TreeExpression expression
= parseExpression(context
);
941 failIfFalse(expression
);
942 failIfFalse(autoSemiColon());
943 return context
.createExprStatement(m_lexer
->lastLineNumber(), expression
, startLine
, m_lastLine
);
946 template <typename LexerType
>
947 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseIfStatement(TreeBuilder
& context
)
951 int start
= tokenLine();
954 consumeOrFail(OPENPAREN
);
956 TreeExpression condition
= parseExpression(context
);
957 failIfFalse(condition
);
958 int end
= tokenLine();
959 consumeOrFail(CLOSEPAREN
);
961 const Identifier
* unused
= 0;
962 TreeStatement trueBlock
= parseStatement(context
, unused
);
963 failIfFalse(trueBlock
);
966 return context
.createIfStatement(m_lexer
->lastLineNumber(), condition
, trueBlock
, start
, end
);
968 Vector
<TreeExpression
> exprStack
;
969 Vector
<pair
<int, int> > posStack
;
970 Vector
<TreeStatement
> statementStack
;
971 bool trailingElse
= false;
975 const Identifier
* unused
= 0;
976 TreeStatement block
= parseStatement(context
, unused
);
978 statementStack
.append(block
);
982 int innerStart
= tokenLine();
985 consumeOrFail(OPENPAREN
);
987 TreeExpression innerCondition
= parseExpression(context
);
988 failIfFalse(innerCondition
);
989 int innerEnd
= tokenLine();
990 consumeOrFail(CLOSEPAREN
);
991 const Identifier
* unused
= 0;
992 TreeStatement innerTrueBlock
= parseStatement(context
, unused
);
993 failIfFalse(innerTrueBlock
);
994 exprStack
.append(innerCondition
);
995 posStack
.append(make_pair(innerStart
, innerEnd
));
996 statementStack
.append(innerTrueBlock
);
997 } while (match(ELSE
));
1000 TreeExpression condition
= exprStack
.last();
1001 exprStack
.removeLast();
1002 TreeStatement trueBlock
= statementStack
.last();
1003 statementStack
.removeLast();
1004 pair
<int, int> pos
= posStack
.last();
1005 posStack
.removeLast();
1006 statementStack
.append(context
.createIfStatement(m_lexer
->lastLineNumber(), condition
, trueBlock
, pos
.first
, pos
.second
));
1009 while (!exprStack
.isEmpty()) {
1010 TreeExpression condition
= exprStack
.last();
1011 exprStack
.removeLast();
1012 TreeStatement falseBlock
= statementStack
.last();
1013 statementStack
.removeLast();
1014 TreeStatement trueBlock
= statementStack
.last();
1015 statementStack
.removeLast();
1016 pair
<int, int> pos
= posStack
.last();
1017 posStack
.removeLast();
1018 statementStack
.append(context
.createIfStatement(m_lexer
->lastLineNumber(), condition
, trueBlock
, falseBlock
, pos
.first
, pos
.second
));
1021 return context
.createIfStatement(m_lexer
->lastLineNumber(), condition
, trueBlock
, statementStack
.last(), start
, end
);
1024 template <typename LexerType
>
1025 template <class TreeBuilder
> TreeExpression Parser
<LexerType
>::parseExpression(TreeBuilder
& context
)
1027 failIfStackOverflow();
1028 TreeExpression node
= parseAssignmentExpression(context
);
1033 m_nonTrivialExpressionCount
++;
1035 TreeExpression right
= parseAssignmentExpression(context
);
1037 typename
TreeBuilder::Comma commaNode
= context
.createCommaExpr(m_lexer
->lastLineNumber(), node
, right
);
1038 while (match(COMMA
)) {
1039 next(TreeBuilder::DontBuildStrings
);
1040 right
= parseAssignmentExpression(context
);
1042 context
.appendToComma(commaNode
, right
);
1047 template <typename LexerType
>
1048 template <typename TreeBuilder
> TreeExpression Parser
<LexerType
>::parseAssignmentExpression(TreeBuilder
& context
)
1050 failIfStackOverflow();
1051 int start
= tokenStart();
1052 int initialAssignmentCount
= m_assignmentCount
;
1053 int initialNonLHSCount
= m_nonLHSCount
;
1054 TreeExpression lhs
= parseConditionalExpression(context
);
1056 if (initialNonLHSCount
!= m_nonLHSCount
)
1059 int assignmentStack
= 0;
1061 bool hadAssignment
= false;
1063 switch (m_token
.m_type
) {
1064 case EQUAL
: op
= OpEqual
; break;
1065 case PLUSEQUAL
: op
= OpPlusEq
; break;
1066 case MINUSEQUAL
: op
= OpMinusEq
; break;
1067 case MULTEQUAL
: op
= OpMultEq
; break;
1068 case DIVEQUAL
: op
= OpDivEq
; break;
1069 case LSHIFTEQUAL
: op
= OpLShift
; break;
1070 case RSHIFTEQUAL
: op
= OpRShift
; break;
1071 case URSHIFTEQUAL
: op
= OpURShift
; break;
1072 case ANDEQUAL
: op
= OpAndEq
; break;
1073 case XOREQUAL
: op
= OpXOrEq
; break;
1074 case OREQUAL
: op
= OpOrEq
; break;
1075 case MODEQUAL
: op
= OpModEq
; break;
1079 m_nonTrivialExpressionCount
++;
1080 hadAssignment
= true;
1081 context
.assignmentStackAppend(assignmentStack
, lhs
, start
, tokenStart(), m_assignmentCount
, op
);
1082 start
= tokenStart();
1083 m_assignmentCount
++;
1084 next(TreeBuilder::DontBuildStrings
);
1085 if (strictMode() && m_lastIdentifier
&& context
.isResolve(lhs
)) {
1086 failIfTrueIfStrictWithMessage(m_globalData
->propertyNames
->eval
== *m_lastIdentifier
, "'eval' cannot be modified in strict mode");
1087 failIfTrueIfStrictWithMessage(m_globalData
->propertyNames
->arguments
== *m_lastIdentifier
, "'arguments' cannot be modified in strict mode");
1088 declareWrite(m_lastIdentifier
);
1089 m_lastIdentifier
= 0;
1091 lhs
= parseConditionalExpression(context
);
1093 if (initialNonLHSCount
!= m_nonLHSCount
)
1100 if (!TreeBuilder::CreatesAST
)
1103 while (assignmentStack
)
1104 lhs
= context
.createAssignment(m_lexer
->lastLineNumber(), assignmentStack
, lhs
, initialAssignmentCount
, m_assignmentCount
, lastTokenEnd());
1109 template <typename LexerType
>
1110 template <class TreeBuilder
> TreeExpression Parser
<LexerType
>::parseConditionalExpression(TreeBuilder
& context
)
1112 TreeExpression cond
= parseBinaryExpression(context
);
1114 if (!match(QUESTION
))
1116 m_nonTrivialExpressionCount
++;
1118 next(TreeBuilder::DontBuildStrings
);
1119 TreeExpression lhs
= parseAssignmentExpression(context
);
1120 consumeOrFailWithFlags(COLON
, TreeBuilder::DontBuildStrings
);
1122 TreeExpression rhs
= parseAssignmentExpression(context
);
1124 return context
.createConditionalExpr(m_lexer
->lastLineNumber(), cond
, lhs
, rhs
);
1127 ALWAYS_INLINE
static bool isUnaryOp(JSTokenType token
)
1129 return token
& UnaryOpTokenFlag
;
1132 template <typename LexerType
>
1133 int Parser
<LexerType
>::isBinaryOperator(JSTokenType token
)
1136 return token
& (BinaryOpTokenPrecedenceMask
<< BinaryOpTokenAllowsInPrecedenceAdditionalShift
);
1137 return token
& BinaryOpTokenPrecedenceMask
;
1140 template <typename LexerType
>
1141 template <class TreeBuilder
> TreeExpression Parser
<LexerType
>::parseBinaryExpression(TreeBuilder
& context
)
1144 int operandStackDepth
= 0;
1145 int operatorStackDepth
= 0;
1146 typename
TreeBuilder::BinaryExprContext
binaryExprContext(context
);
1148 int exprStart
= tokenStart();
1149 int initialAssignments
= m_assignmentCount
;
1150 TreeExpression current
= parseUnaryExpression(context
);
1151 failIfFalse(current
);
1153 context
.appendBinaryExpressionInfo(operandStackDepth
, current
, exprStart
, lastTokenEnd(), lastTokenEnd(), initialAssignments
!= m_assignmentCount
);
1154 int precedence
= isBinaryOperator(m_token
.m_type
);
1157 m_nonTrivialExpressionCount
++;
1159 int operatorToken
= m_token
.m_type
;
1160 next(TreeBuilder::DontBuildStrings
);
1162 while (operatorStackDepth
&& context
.operatorStackHasHigherPrecedence(operatorStackDepth
, precedence
)) {
1163 ASSERT(operandStackDepth
> 1);
1165 typename
TreeBuilder::BinaryOperand rhs
= context
.getFromOperandStack(-1);
1166 typename
TreeBuilder::BinaryOperand lhs
= context
.getFromOperandStack(-2);
1167 context
.shrinkOperandStackBy(operandStackDepth
, 2);
1168 context
.appendBinaryOperation(m_lexer
->lastLineNumber(), operandStackDepth
, operatorStackDepth
, lhs
, rhs
);
1169 context
.operatorStackPop(operatorStackDepth
);
1171 context
.operatorStackAppend(operatorStackDepth
, operatorToken
, precedence
);
1173 while (operatorStackDepth
) {
1174 ASSERT(operandStackDepth
> 1);
1176 typename
TreeBuilder::BinaryOperand rhs
= context
.getFromOperandStack(-1);
1177 typename
TreeBuilder::BinaryOperand lhs
= context
.getFromOperandStack(-2);
1178 context
.shrinkOperandStackBy(operandStackDepth
, 2);
1179 context
.appendBinaryOperation(m_lexer
->lastLineNumber(), operandStackDepth
, operatorStackDepth
, lhs
, rhs
);
1180 context
.operatorStackPop(operatorStackDepth
);
1182 return context
.popOperandStack(operandStackDepth
);
1185 template <typename LexerType
>
1186 template <bool complete
, class TreeBuilder
> TreeProperty Parser
<LexerType
>::parseProperty(TreeBuilder
& context
)
1188 bool wasIdent
= false;
1189 switch (m_token
.m_type
) {
1194 const Identifier
* ident
= m_token
.m_data
.ident
;
1195 if (complete
|| (wasIdent
&& (*ident
== m_globalData
->propertyNames
->get
|| *ident
== m_globalData
->propertyNames
->set
)))
1196 nextExpectIdentifier(LexerFlagsIgnoreReservedWords
);
1198 nextExpectIdentifier(LexerFlagsIgnoreReservedWords
| TreeBuilder::DontBuildKeywords
);
1202 TreeExpression node
= parseAssignmentExpression(context
);
1204 return context
.template createProperty
<complete
>(ident
, node
, PropertyNode::Constant
);
1206 failIfFalse(wasIdent
);
1207 const Identifier
* accessorName
= 0;
1208 TreeFormalParameterList parameters
= 0;
1209 TreeFunctionBody body
= 0;
1210 int openBracePos
= 0;
1211 int closeBracePos
= 0;
1212 int bodyStartLine
= 0;
1213 PropertyNode::Type type
;
1214 if (*ident
== m_globalData
->propertyNames
->get
)
1215 type
= PropertyNode::Getter
;
1216 else if (*ident
== m_globalData
->propertyNames
->set
)
1217 type
= PropertyNode::Setter
;
1220 const Identifier
* stringPropertyName
= 0;
1221 double numericPropertyName
= 0;
1222 if (m_token
.m_type
== IDENT
|| m_token
.m_type
== STRING
)
1223 stringPropertyName
= m_token
.m_data
.ident
;
1224 else if (m_token
.m_type
== NUMBER
)
1225 numericPropertyName
= m_token
.m_data
.doubleValue
;
1229 failIfFalse((parseFunctionInfo
<FunctionNoRequirements
, false>(context
, accessorName
, parameters
, body
, openBracePos
, closeBracePos
, bodyStartLine
)));
1230 if (stringPropertyName
)
1231 return context
.template createGetterOrSetterProperty
<complete
>(m_lexer
->lastLineNumber(), type
, stringPropertyName
, parameters
, body
, openBracePos
, closeBracePos
, bodyStartLine
, m_lastLine
);
1232 return context
.template createGetterOrSetterProperty
<complete
>(const_cast<JSGlobalData
*>(m_globalData
), m_lexer
->lastLineNumber(), type
, numericPropertyName
, parameters
, body
, openBracePos
, closeBracePos
, bodyStartLine
, m_lastLine
);
1235 double propertyName
= m_token
.m_data
.doubleValue
;
1237 consumeOrFail(COLON
);
1238 TreeExpression node
= parseAssignmentExpression(context
);
1240 return context
.template createProperty
<complete
>(const_cast<JSGlobalData
*>(m_globalData
), propertyName
, node
, PropertyNode::Constant
);
1243 failIfFalse(m_token
.m_type
& KeywordTokenFlag
);
1248 template <typename LexerType
>
1249 template <class TreeBuilder
> TreeExpression Parser
<LexerType
>::parseObjectLiteral(TreeBuilder
& context
)
1251 int startOffset
= m_token
.m_data
.intValue
;
1252 unsigned oldLastLineNumber
= m_lexer
->lastLineNumber();
1253 unsigned oldLineNumber
= m_lexer
->lineNumber();
1254 consumeOrFailWithFlags(OPENBRACE
, TreeBuilder::DontBuildStrings
);
1256 int oldNonLHSCount
= m_nonLHSCount
;
1258 if (match(CLOSEBRACE
)) {
1260 return context
.createObjectLiteral(m_lexer
->lastLineNumber());
1263 TreeProperty property
= parseProperty
<false>(context
);
1264 failIfFalse(property
);
1265 if (!m_syntaxAlreadyValidated
&& context
.getType(property
) != PropertyNode::Constant
) {
1266 m_lexer
->setOffset(startOffset
);
1268 m_lexer
->setLastLineNumber(oldLastLineNumber
);
1269 m_lexer
->setLineNumber(oldLineNumber
);
1270 return parseStrictObjectLiteral(context
);
1272 TreePropertyList propertyList
= context
.createPropertyList(m_lexer
->lastLineNumber(), property
);
1273 TreePropertyList tail
= propertyList
;
1274 while (match(COMMA
)) {
1275 next(TreeBuilder::DontBuildStrings
);
1276 // allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939
1277 if (match(CLOSEBRACE
))
1279 property
= parseProperty
<false>(context
);
1280 failIfFalse(property
);
1281 if (!m_syntaxAlreadyValidated
&& context
.getType(property
) != PropertyNode::Constant
) {
1282 m_lexer
->setOffset(startOffset
);
1284 m_lexer
->setLastLineNumber(oldLastLineNumber
);
1285 m_lexer
->setLineNumber(oldLineNumber
);
1286 return parseStrictObjectLiteral(context
);
1288 tail
= context
.createPropertyList(m_lexer
->lastLineNumber(), property
, tail
);
1291 consumeOrFail(CLOSEBRACE
);
1293 m_nonLHSCount
= oldNonLHSCount
;
1295 return context
.createObjectLiteral(m_lexer
->lastLineNumber(), propertyList
);
1298 template <typename LexerType
>
1299 template <class TreeBuilder
> TreeExpression Parser
<LexerType
>::parseStrictObjectLiteral(TreeBuilder
& context
)
1301 consumeOrFail(OPENBRACE
);
1303 int oldNonLHSCount
= m_nonLHSCount
;
1305 if (match(CLOSEBRACE
)) {
1307 return context
.createObjectLiteral(m_lexer
->lastLineNumber());
1310 TreeProperty property
= parseProperty
<true>(context
);
1311 failIfFalse(property
);
1313 typedef HashMap
<RefPtr
<StringImpl
>, unsigned, IdentifierRepHash
> ObjectValidationMap
;
1314 ObjectValidationMap objectValidator
;
1315 // Add the first property
1316 if (!m_syntaxAlreadyValidated
)
1317 objectValidator
.add(context
.getName(property
).impl(), context
.getType(property
));
1319 TreePropertyList propertyList
= context
.createPropertyList(m_lexer
->lastLineNumber(), property
);
1320 TreePropertyList tail
= propertyList
;
1321 while (match(COMMA
)) {
1323 // allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939
1324 if (match(CLOSEBRACE
))
1326 property
= parseProperty
<true>(context
);
1327 failIfFalse(property
);
1328 if (!m_syntaxAlreadyValidated
) {
1329 ObjectValidationMap::AddResult propertyEntry
= objectValidator
.add(context
.getName(property
).impl(), context
.getType(property
));
1330 if (!propertyEntry
.isNewEntry
) {
1331 failIfTrue(propertyEntry
.iterator
->second
== PropertyNode::Constant
);
1332 failIfTrue(context
.getType(property
) == PropertyNode::Constant
);
1333 failIfTrue(context
.getType(property
) & propertyEntry
.iterator
->second
);
1334 propertyEntry
.iterator
->second
|= context
.getType(property
);
1337 tail
= context
.createPropertyList(m_lexer
->lastLineNumber(), property
, tail
);
1340 consumeOrFail(CLOSEBRACE
);
1342 m_nonLHSCount
= oldNonLHSCount
;
1344 return context
.createObjectLiteral(m_lexer
->lastLineNumber(), propertyList
);
1347 template <typename LexerType
>
1348 template <class TreeBuilder
> TreeExpression Parser
<LexerType
>::parseArrayLiteral(TreeBuilder
& context
)
1350 consumeOrFailWithFlags(OPENBRACKET
, TreeBuilder::DontBuildStrings
);
1352 int oldNonLHSCount
= m_nonLHSCount
;
1355 while (match(COMMA
)) {
1356 next(TreeBuilder::DontBuildStrings
);
1359 if (match(CLOSEBRACKET
)) {
1360 next(TreeBuilder::DontBuildStrings
);
1361 return context
.createArray(m_lexer
->lastLineNumber(), elisions
);
1364 TreeExpression elem
= parseAssignmentExpression(context
);
1366 typename
TreeBuilder::ElementList elementList
= context
.createElementList(elisions
, elem
);
1367 typename
TreeBuilder::ElementList tail
= elementList
;
1369 while (match(COMMA
)) {
1370 next(TreeBuilder::DontBuildStrings
);
1373 while (match(COMMA
)) {
1378 if (match(CLOSEBRACKET
)) {
1379 next(TreeBuilder::DontBuildStrings
);
1380 return context
.createArray(m_lexer
->lastLineNumber(), elisions
, elementList
);
1382 TreeExpression elem
= parseAssignmentExpression(context
);
1384 tail
= context
.createElementList(tail
, elisions
, elem
);
1387 consumeOrFail(CLOSEBRACKET
);
1389 m_nonLHSCount
= oldNonLHSCount
;
1391 return context
.createArray(m_lexer
->lastLineNumber(), elementList
);
1394 template <typename LexerType
>
1395 template <class TreeBuilder
> TreeExpression Parser
<LexerType
>::parsePrimaryExpression(TreeBuilder
& context
)
1397 failIfStackOverflow();
1398 switch (m_token
.m_type
) {
1401 return parseStrictObjectLiteral(context
);
1402 return parseObjectLiteral(context
);
1404 return parseArrayLiteral(context
);
1407 int oldNonLHSCount
= m_nonLHSCount
;
1408 TreeExpression result
= parseExpression(context
);
1409 m_nonLHSCount
= oldNonLHSCount
;
1410 consumeOrFail(CLOSEPAREN
);
1416 return context
.thisExpr(m_lexer
->lastLineNumber());
1419 int start
= tokenStart();
1420 const Identifier
* ident
= m_token
.m_data
.ident
;
1422 currentScope()->useVariable(ident
, m_globalData
->propertyNames
->eval
== *ident
);
1423 m_lastIdentifier
= ident
;
1424 return context
.createResolve(m_lexer
->lastLineNumber(), ident
, start
);
1427 const Identifier
* ident
= m_token
.m_data
.ident
;
1429 return context
.createString(m_lexer
->lastLineNumber(), ident
);
1432 double d
= m_token
.m_data
.doubleValue
;
1434 return context
.createNumberExpr(m_lexer
->lastLineNumber(), d
);
1438 return context
.createNull(m_lexer
->lastLineNumber());
1442 return context
.createBoolean(m_lexer
->lastLineNumber(), true);
1446 return context
.createBoolean(m_lexer
->lastLineNumber(), false);
1451 const Identifier
* pattern
;
1452 const Identifier
* flags
;
1453 if (match(DIVEQUAL
))
1454 failIfFalse(m_lexer
->scanRegExp(pattern
, flags
, '='));
1456 failIfFalse(m_lexer
->scanRegExp(pattern
, flags
));
1458 int start
= tokenStart();
1460 TreeExpression re
= context
.createRegExp(m_lexer
->lastLineNumber(), *pattern
, *flags
, start
);
1462 const char* yarrErrorMsg
= Yarr::checkSyntax(pattern
->ustring());
1463 ASSERT(!m_errorMessage
.isNull());
1464 failWithMessage(yarrErrorMsg
);
1473 template <typename LexerType
>
1474 template <class TreeBuilder
> TreeArguments Parser
<LexerType
>::parseArguments(TreeBuilder
& context
)
1476 consumeOrFailWithFlags(OPENPAREN
, TreeBuilder::DontBuildStrings
);
1477 if (match(CLOSEPAREN
)) {
1478 next(TreeBuilder::DontBuildStrings
);
1479 return context
.createArguments();
1481 TreeExpression firstArg
= parseAssignmentExpression(context
);
1482 failIfFalse(firstArg
);
1484 TreeArgumentsList argList
= context
.createArgumentsList(m_lexer
->lastLineNumber(), firstArg
);
1485 TreeArgumentsList tail
= argList
;
1486 while (match(COMMA
)) {
1487 next(TreeBuilder::DontBuildStrings
);
1488 TreeExpression arg
= parseAssignmentExpression(context
);
1490 tail
= context
.createArgumentsList(m_lexer
->lastLineNumber(), tail
, arg
);
1492 consumeOrFail(CLOSEPAREN
);
1493 return context
.createArguments(argList
);
1496 template <typename LexerType
>
1497 template <class TreeBuilder
> TreeExpression Parser
<LexerType
>::parseMemberExpression(TreeBuilder
& context
)
1499 TreeExpression base
= 0;
1500 int start
= tokenStart();
1501 int expressionStart
= start
;
1503 while (match(NEW
)) {
1508 if (match(FUNCTION
)) {
1509 const Identifier
* name
= &m_globalData
->propertyNames
->nullIdentifier
;
1510 TreeFormalParameterList parameters
= 0;
1511 TreeFunctionBody body
= 0;
1512 int openBracePos
= 0;
1513 int closeBracePos
= 0;
1514 int bodyStartLine
= 0;
1516 failIfFalse((parseFunctionInfo
<FunctionNoRequirements
, false>(context
, name
, parameters
, body
, openBracePos
, closeBracePos
, bodyStartLine
)));
1517 base
= context
.createFunctionExpr(m_lexer
->lastLineNumber(), name
, body
, parameters
, openBracePos
, closeBracePos
, bodyStartLine
, m_lastLine
);
1519 base
= parsePrimaryExpression(context
);
1523 switch (m_token
.m_type
) {
1525 m_nonTrivialExpressionCount
++;
1526 int expressionEnd
= lastTokenEnd();
1528 int nonLHSCount
= m_nonLHSCount
;
1529 int initialAssignments
= m_assignmentCount
;
1530 TreeExpression property
= parseExpression(context
);
1531 failIfFalse(property
);
1532 base
= context
.createBracketAccess(m_lexer
->lastLineNumber(), base
, property
, initialAssignments
!= m_assignmentCount
, expressionStart
, expressionEnd
, tokenEnd());
1533 consumeOrFail(CLOSEBRACKET
);
1534 m_nonLHSCount
= nonLHSCount
;
1538 m_nonTrivialExpressionCount
++;
1539 int nonLHSCount
= m_nonLHSCount
;
1542 int exprEnd
= lastTokenEnd();
1543 TreeArguments arguments
= parseArguments(context
);
1544 failIfFalse(arguments
);
1545 base
= context
.createNewExpr(m_lexer
->lastLineNumber(), base
, arguments
, start
, exprEnd
, lastTokenEnd());
1547 int expressionEnd
= lastTokenEnd();
1548 TreeArguments arguments
= parseArguments(context
);
1549 failIfFalse(arguments
);
1550 base
= context
.makeFunctionCallNode(m_lexer
->lastLineNumber(), base
, arguments
, expressionStart
, expressionEnd
, lastTokenEnd());
1552 m_nonLHSCount
= nonLHSCount
;
1556 m_nonTrivialExpressionCount
++;
1557 int expressionEnd
= lastTokenEnd();
1558 nextExpectIdentifier(LexerFlagsIgnoreReservedWords
| TreeBuilder::DontBuildKeywords
);
1560 base
= context
.createDotAccess(m_lexer
->lastLineNumber(), base
, m_token
.m_data
.ident
, expressionStart
, expressionEnd
, tokenEnd());
1565 goto endMemberExpression
;
1568 endMemberExpression
:
1570 base
= context
.createNewExpr(m_lexer
->lastLineNumber(), base
, start
, lastTokenEnd());
1574 template <typename LexerType
>
1575 template <class TreeBuilder
> TreeExpression Parser
<LexerType
>::parseUnaryExpression(TreeBuilder
& context
)
1577 typename
TreeBuilder::UnaryExprContext
unaryExprContext(context
);
1578 AllowInOverride
allowInOverride(this);
1579 int tokenStackDepth
= 0;
1580 bool modifiesExpr
= false;
1581 bool requiresLExpr
= false;
1582 while (isUnaryOp(m_token
.m_type
)) {
1584 switch (m_token
.m_type
) {
1588 case AUTOMINUSMINUS
:
1589 failIfTrue(requiresLExpr
);
1590 modifiesExpr
= true;
1591 requiresLExpr
= true;
1594 failIfTrue(requiresLExpr
);
1595 requiresLExpr
= true;
1598 failIfTrue(requiresLExpr
);
1603 context
.appendUnaryToken(tokenStackDepth
, m_token
.m_type
, tokenStart());
1605 m_nonTrivialExpressionCount
++;
1607 int subExprStart
= tokenStart();
1608 TreeExpression expr
= parseMemberExpression(context
);
1610 bool isEvalOrArguments
= false;
1611 if (strictMode() && !m_syntaxAlreadyValidated
) {
1612 if (context
.isResolve(expr
))
1613 isEvalOrArguments
= *m_lastIdentifier
== m_globalData
->propertyNames
->eval
|| *m_lastIdentifier
== m_globalData
->propertyNames
->arguments
;
1615 failIfTrueIfStrictWithNameAndMessage(isEvalOrArguments
&& modifiesExpr
, "'", m_lastIdentifier
->impl(), "' cannot be modified in strict mode");
1616 switch (m_token
.m_type
) {
1618 m_nonTrivialExpressionCount
++;
1620 expr
= context
.makePostfixNode(m_lexer
->lastLineNumber(), expr
, OpPlusPlus
, subExprStart
, lastTokenEnd(), tokenEnd());
1621 m_assignmentCount
++;
1622 failIfTrueIfStrictWithNameAndMessage(isEvalOrArguments
, "'", m_lastIdentifier
->impl(), "' cannot be modified in strict mode");
1623 failIfTrueIfStrict(requiresLExpr
);
1627 m_nonTrivialExpressionCount
++;
1629 expr
= context
.makePostfixNode(m_lexer
->lastLineNumber(), expr
, OpMinusMinus
, subExprStart
, lastTokenEnd(), tokenEnd());
1630 m_assignmentCount
++;
1631 failIfTrueIfStrictWithNameAndMessage(isEvalOrArguments
, "'", m_lastIdentifier
->impl(), "' cannot be modified in strict mode");
1632 failIfTrueIfStrict(requiresLExpr
);
1639 int end
= lastTokenEnd();
1641 if (!TreeBuilder::CreatesAST
&& (m_syntaxAlreadyValidated
|| !strictMode()))
1644 while (tokenStackDepth
) {
1645 switch (context
.unaryTokenStackLastType(tokenStackDepth
)) {
1647 expr
= context
.createLogicalNot(m_lexer
->lastLineNumber(), expr
);
1650 expr
= context
.makeBitwiseNotNode(m_lexer
->lastLineNumber(), expr
);
1653 expr
= context
.makeNegateNode(m_lexer
->lastLineNumber(), expr
);
1656 expr
= context
.createUnaryPlus(m_lexer
->lastLineNumber(), expr
);
1660 expr
= context
.makePrefixNode(m_lexer
->lastLineNumber(), expr
, OpPlusPlus
, context
.unaryTokenStackLastStart(tokenStackDepth
), subExprStart
+ 1, end
);
1661 m_assignmentCount
++;
1664 case AUTOMINUSMINUS
:
1665 expr
= context
.makePrefixNode(m_lexer
->lastLineNumber(), expr
, OpMinusMinus
, context
.unaryTokenStackLastStart(tokenStackDepth
), subExprStart
+ 1, end
);
1666 m_assignmentCount
++;
1669 expr
= context
.makeTypeOfNode(m_lexer
->lastLineNumber(), expr
);
1672 expr
= context
.createVoid(m_lexer
->lastLineNumber(), expr
);
1675 failIfTrueIfStrictWithNameAndMessage(context
.isResolve(expr
), "Cannot delete unqualified property", m_lastIdentifier
->impl(), "in strict mode");
1676 expr
= context
.makeDeleteNode(m_lexer
->lastLineNumber(), expr
, context
.unaryTokenStackLastStart(tokenStackDepth
), end
, end
);
1679 // If we get here something has gone horribly horribly wrong
1682 subExprStart
= context
.unaryTokenStackLastStart(tokenStackDepth
);
1683 context
.unaryTokenStackRemoveLast(tokenStackDepth
);
1688 // Instantiate the two flavors of Parser we need instead of putting most of this file in Parser.h
1689 template class Parser
< Lexer
<LChar
> >;
1690 template class Parser
< Lexer
<UChar
> >;