2 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
3 * Copyright (C) 2001 Peter Kelly (pmk@post.com)
4 * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc. All rights reserved.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
26 #include "ASTBuilder.h"
27 #include "CodeBlock.h"
29 #include "JSCJSValueInlines.h"
32 #include "SourceProvider.h"
35 #include <wtf/HashFunctions.h>
36 #include <wtf/OwnPtr.h>
37 #include <wtf/WTFThreadData.h>
39 #define fail() do { if (!hasError()) updateErrorMessage(); return 0; } while (0)
40 #define failWithToken(tok) do { if (!hasError()) updateErrorMessage(tok); return 0; } while (0)
41 #define failWithMessage(msg) do { if (!hasError()) updateErrorMessage(msg); return 0; } while (0)
42 #define failWithNameAndMessage(before, name, after) do { if (!hasError()) updateErrorWithNameAndMessage(before, name, after); return 0; } while (0)
43 #define failWithStackOverflow() do { updateErrorMessage("Stack exhausted"); m_hasStackOverflow = true; return 0; } while (0)
44 #define failIfFalse(cond) do { if (!(cond)) fail(); } while (0)
45 #define failIfFalseWithMessage(cond, msg) do { if (!(cond)) failWithMessage(msg); } while (0)
46 #define failIfFalseWithNameAndMessage(cond, before, name, msg) do { if (!(cond)) failWithNameAndMessage(before, name, msg); } while (0)
47 #define failIfTrue(cond) do { if ((cond)) fail(); } while (0)
48 #define failIfTrueWithMessage(cond, msg) do { if ((cond)) failWithMessage(msg); } while (0)
49 #define failIfTrueWithNameAndMessage(cond, before, name, msg) do { if ((cond)) failWithNameAndMessage(before, name, msg); } while (0)
50 #define failIfTrueIfStrict(cond) do { if ((cond) && strictMode()) fail(); } while (0)
51 #define failIfTrueIfStrictWithMessage(cond, msg) do { if ((cond) && strictMode()) failWithMessage(msg); } while (0)
52 #define failIfTrueIfStrictWithNameAndMessage(cond, before, name, after) do { if ((cond) && strictMode()) failWithNameAndMessage(before, name, after); } while (0)
53 #define failIfFalseIfStrict(cond) do { if ((!(cond)) && strictMode()) fail(); } while (0)
54 #define failIfFalseIfStrictWithMessage(cond, msg) do { if ((!(cond)) && strictMode()) failWithMessage(msg); } while (0)
55 #define failIfFalseIfStrictWithNameAndMessage(cond, before, name, after) do { if ((!(cond)) && strictMode()) failWithNameAndMessage(before, name, after); } while (0)
56 #define consumeOrFail(tokenType) do { if (!consume(tokenType)) failWithToken(tokenType); } while (0)
57 #define consumeOrFailWithFlags(tokenType, flags) do { if (!consume(tokenType, flags)) failWithToken(tokenType); } while (0)
58 #define matchOrFail(tokenType) do { if (!match(tokenType)) failWithToken(tokenType); } while (0)
59 #define failIfStackOverflow() do { if (!canRecurse()) failWithStackOverflow(); } while (0)
65 template <typename LexerType
>
66 Parser
<LexerType
>::Parser(VM
* vm
, const SourceCode
& source
, FunctionParameters
* parameters
, const Identifier
& name
, JSParserStrictness strictness
, JSParserMode parserMode
)
69 , m_stack(wtfThreadData().stack())
70 , m_hasStackOverflow(false)
74 , m_assignmentCount(0)
76 , m_syntaxAlreadyValidated(source
.provider()->isValid())
78 , m_nonTrivialExpressionCount(0)
82 m_lexer
= adoptPtr(new LexerType(vm
));
83 m_arena
= m_vm
->parserArena
.get();
84 m_lexer
->setCode(source
, m_arena
);
85 m_token
.m_location
.endOffset
= source
.startOffset();
86 m_token
.m_location
.lineStartOffset
= source
.startOffset();
88 m_functionCache
= vm
->addSourceProviderCache(source
.provider());
89 ScopeRef scope
= pushScope();
90 if (parserMode
== JSParseFunctionCode
)
91 scope
->setIsFunction();
92 if (strictness
== JSParseStrict
)
93 scope
->setStrictMode();
95 for (unsigned i
= 0; i
< parameters
->size(); i
++)
96 scope
->declareParameter(¶meters
->at(i
));
99 scope
->declareCallee(&name
);
103 template <typename LexerType
>
104 Parser
<LexerType
>::~Parser()
108 template <typename LexerType
>
109 String Parser
<LexerType
>::parseInner()
111 String parseError
= String();
113 ASTBuilder
context(const_cast<VM
*>(m_vm
), const_cast<SourceCode
*>(m_source
));
114 if (m_lexer
->isReparsing())
116 ScopeRef scope
= currentScope();
117 SourceElements
* sourceElements
= parseSourceElements
<CheckForStrictMode
>(context
);
118 if (!sourceElements
|| !consume(EOFTOK
)) {
120 parseError
= m_errorMessage
;
122 parseError
= ASCIILiteral("Parser error");
125 IdentifierSet capturedVariables
;
126 scope
->getCapturedVariables(capturedVariables
);
127 CodeFeatures features
= context
.features();
128 if (scope
->strictMode())
129 features
|= StrictModeFeature
;
130 if (scope
->shadowsArguments())
131 features
|= ShadowsArgumentsFeature
;
133 didFinishParsing(sourceElements
, context
.varDeclarations(), context
.funcDeclarations(), features
,
134 m_lastLine
, context
.numConstants(), capturedVariables
);
139 template <typename LexerType
>
140 void Parser
<LexerType
>::didFinishParsing(SourceElements
* sourceElements
, ParserArenaData
<DeclarationStacks::VarStack
>* varStack
,
141 ParserArenaData
<DeclarationStacks::FunctionStack
>* funcStack
, CodeFeatures features
, int lastLine
, int numConstants
, IdentifierSet
& capturedVars
)
143 m_sourceElements
= sourceElements
;
144 m_varDeclarations
= varStack
;
145 m_funcDeclarations
= funcStack
;
146 m_capturedVariables
.swap(capturedVars
);
147 m_features
= features
;
148 m_lastLine
= lastLine
;
149 m_numConstants
= numConstants
;
152 template <typename LexerType
>
153 bool Parser
<LexerType
>::allowAutomaticSemicolon()
155 return match(CLOSEBRACE
) || match(EOFTOK
) || m_lexer
->prevTerminator();
158 template <typename LexerType
>
159 template <SourceElementsMode mode
, class TreeBuilder
> TreeSourceElements Parser
<LexerType
>::parseSourceElements(TreeBuilder
& context
)
161 const unsigned lengthOfUseStrictLiteral
= 12; // "use strict".length
162 TreeSourceElements sourceElements
= context
.createSourceElements();
163 bool seenNonDirective
= false;
164 const Identifier
* directive
= 0;
165 unsigned directiveLiteralLength
= 0;
166 unsigned startOffset
= m_token
.m_location
.startOffset
;
167 unsigned startLineStartOffset
= m_token
.m_location
.lineStartOffset
;
168 unsigned oldLastLineNumber
= m_lexer
->lastLineNumber();
169 unsigned oldLineNumber
= m_lexer
->lineNumber();
170 bool hasSetStrict
= false;
171 while (TreeStatement statement
= parseStatement(context
, directive
, &directiveLiteralLength
)) {
172 if (mode
== CheckForStrictMode
&& !seenNonDirective
) {
174 // "use strict" must be the exact literal without escape sequences or line continuation.
175 if (!hasSetStrict
&& directiveLiteralLength
== lengthOfUseStrictLiteral
&& m_vm
->propertyNames
->useStrictIdentifier
== *directive
) {
178 failIfFalse(isValidStrictMode());
179 m_lexer
->setOffset(startOffset
, startLineStartOffset
);
181 m_lexer
->setLastLineNumber(oldLastLineNumber
);
182 m_lexer
->setLineNumber(oldLineNumber
);
183 failIfTrue(hasError());
187 seenNonDirective
= true;
189 context
.appendStatement(sourceElements
, statement
);
192 failIfTrue(hasError());
193 return sourceElements
;
196 template <typename LexerType
>
197 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseVarDeclaration(TreeBuilder
& context
)
200 JSTokenLocation
location(tokenLocation());
201 int start
= tokenLine();
204 const Identifier
* scratch1
= 0;
205 TreeExpression scratch2
= 0;
207 TreeExpression varDecls
= parseVarDeclarationList(context
, scratch
, scratch1
, scratch2
, scratch3
, scratch3
, scratch3
);
208 failIfTrue(hasError());
209 failIfFalse(autoSemiColon());
211 return context
.createVarStatement(location
, varDecls
, start
, end
);
214 template <typename LexerType
>
215 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseConstDeclaration(TreeBuilder
& context
)
217 ASSERT(match(CONSTTOKEN
));
218 JSTokenLocation
location(tokenLocation());
219 int start
= tokenLine();
221 TreeConstDeclList constDecls
= parseConstDeclarationList(context
);
222 failIfTrue(hasError());
223 failIfFalse(autoSemiColon());
225 return context
.createConstStatement(location
, constDecls
, start
, end
);
228 template <typename LexerType
>
229 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseDoWhileStatement(TreeBuilder
& context
)
232 int startLine
= tokenLine();
234 const Identifier
* unused
= 0;
236 TreeStatement statement
= parseStatement(context
, unused
);
238 failIfFalse(statement
);
239 int endLine
= tokenLine();
240 JSTokenLocation
location(tokenLocation());
241 consumeOrFail(WHILE
);
242 consumeOrFail(OPENPAREN
);
243 TreeExpression expr
= parseExpression(context
);
245 consumeOrFail(CLOSEPAREN
);
246 if (match(SEMICOLON
))
247 next(); // Always performs automatic semicolon insertion.
248 return context
.createDoWhileStatement(location
, statement
, expr
, startLine
, endLine
);
251 template <typename LexerType
>
252 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseWhileStatement(TreeBuilder
& context
)
254 ASSERT(match(WHILE
));
255 JSTokenLocation
location(tokenLocation());
256 int startLine
= tokenLine();
258 consumeOrFail(OPENPAREN
);
259 TreeExpression expr
= parseExpression(context
);
261 int endLine
= tokenLine();
262 consumeOrFail(CLOSEPAREN
);
263 const Identifier
* unused
= 0;
265 TreeStatement statement
= parseStatement(context
, unused
);
267 failIfFalse(statement
);
268 return context
.createWhileStatement(location
, expr
, statement
, startLine
, endLine
);
271 template <typename LexerType
>
272 template <class TreeBuilder
> TreeExpression Parser
<LexerType
>::parseVarDeclarationList(TreeBuilder
& context
, int& declarations
, const Identifier
*& lastIdent
, TreeExpression
& lastInitializer
, int& identStart
, int& initStart
, int& initEnd
)
274 TreeExpression varDecls
= 0;
277 JSTokenLocation
location(tokenLocation());
281 int varStart
= tokenStart();
282 identStart
= varStart
;
283 const Identifier
* name
= m_token
.m_data
.ident
;
286 bool hasInitializer
= match(EQUAL
);
287 failIfFalseIfStrictWithNameAndMessage(declareVariable(name
), "Cannot declare a variable named", name
->impl(), "in strict mode.");
288 context
.addVar(name
, (hasInitializer
|| (!m_allowsIn
&& match(INTOKEN
))) ? DeclarationStacks::HasInitializer
: 0);
289 if (hasInitializer
) {
290 int varDivot
= tokenStart() + 1;
291 unsigned varLine
= tokenLine();
292 unsigned varLineStart
= tokenLineStart();
293 initStart
= tokenStart();
294 next(TreeBuilder::DontBuildStrings
); // consume '='
295 TreeExpression initializer
= parseAssignmentExpression(context
);
296 initEnd
= lastTokenEnd();
297 lastInitializer
= initializer
;
298 failIfFalse(initializer
);
300 TreeExpression node
= context
.createAssignResolve(location
, *name
, initializer
, varStart
, varDivot
, lastTokenEnd(), varLine
, varLineStart
);
304 varDecls
= context
.combineCommaNodes(location
, varDecls
, node
);
306 } while (match(COMMA
));
310 template <typename LexerType
>
311 template <class TreeBuilder
> TreeConstDeclList Parser
<LexerType
>::parseConstDeclarationList(TreeBuilder
& context
)
313 failIfTrue(strictMode());
314 TreeConstDeclList constDecls
= 0;
315 TreeConstDeclList tail
= 0;
317 JSTokenLocation
location(tokenLocation());
320 const Identifier
* name
= m_token
.m_data
.ident
;
322 bool hasInitializer
= match(EQUAL
);
323 declareVariable(name
);
324 context
.addVar(name
, DeclarationStacks::IsConstant
| (hasInitializer
? DeclarationStacks::HasInitializer
: 0));
326 TreeExpression initializer
= 0;
327 if (hasInitializer
) {
328 next(TreeBuilder::DontBuildStrings
); // consume '='
329 initializer
= parseAssignmentExpression(context
);
331 tail
= context
.appendConstDecl(location
, tail
, name
, initializer
);
334 } while (match(COMMA
));
338 template <typename LexerType
>
339 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseForStatement(TreeBuilder
& context
)
342 JSTokenLocation
location(tokenLocation());
343 int startLine
= tokenLine();
345 consumeOrFail(OPENPAREN
);
346 int nonLHSCount
= m_nonLHSCount
;
347 int declarations
= 0;
350 unsigned declsLine
= 0;
351 unsigned declsLineStart
= 0;
352 TreeExpression decls
= 0;
355 for (var IDENT in expression) statement
356 for (var IDENT = expression in expression) statement
357 for (var varDeclarationList; expressionOpt; expressionOpt)
359 const Identifier
* forInTarget
= 0;
360 TreeExpression forInInitializer
= 0;
364 decls
= parseVarDeclarationList(context
, declarations
, forInTarget
, forInInitializer
, declsStart
, initStart
, initEnd
);
366 failIfTrue(hasError());
368 // Remainder of a standard for loop is handled identically
369 if (match(SEMICOLON
))
370 goto standardForLoop
;
372 failIfFalse(declarations
== 1);
374 // Handle for-in with var declaration
375 int inLocation
= tokenStart();
376 unsigned inLine
= tokenLine();
377 unsigned inLineStart
= tokenLineStart();
378 consumeOrFail(INTOKEN
);
380 TreeExpression expr
= parseExpression(context
);
382 int exprEnd
= lastTokenEnd();
384 int endLine
= tokenLine();
385 consumeOrFail(CLOSEPAREN
);
387 const Identifier
* unused
= 0;
389 TreeStatement statement
= parseStatement(context
, unused
);
391 failIfFalse(statement
);
393 return context
.createForInLoop(location
, forInTarget
, forInInitializer
, expr
, statement
, declsStart
, inLocation
, exprEnd
, initStart
, initEnd
, startLine
, endLine
, inLine
, inLineStart
);
396 if (!match(SEMICOLON
)) {
398 declsStart
= tokenStart();
399 decls
= parseExpression(context
);
400 declsEnd
= lastTokenEnd();
401 declsLine
= lastTokenLine();
402 declsLineStart
= lastTokenLineStart();
407 if (match(SEMICOLON
)) {
411 TreeExpression condition
= 0;
413 if (!match(SEMICOLON
)) {
414 condition
= parseExpression(context
);
415 failIfFalse(condition
);
417 consumeOrFail(SEMICOLON
);
419 TreeExpression increment
= 0;
420 if (!match(CLOSEPAREN
)) {
421 increment
= parseExpression(context
);
422 failIfFalse(increment
);
424 int endLine
= tokenLine();
425 consumeOrFail(CLOSEPAREN
);
426 const Identifier
* unused
= 0;
428 TreeStatement statement
= parseStatement(context
, unused
);
430 failIfFalse(statement
);
431 return context
.createForLoop(location
, decls
, condition
, increment
, statement
, startLine
, endLine
);
435 failIfFalse(nonLHSCount
== m_nonLHSCount
);
436 consumeOrFail(INTOKEN
);
437 TreeExpression expr
= parseExpression(context
);
439 int exprEnd
= lastTokenEnd();
440 int endLine
= tokenLine();
441 consumeOrFail(CLOSEPAREN
);
442 const Identifier
* unused
= 0;
444 TreeStatement statement
= parseStatement(context
, unused
);
446 failIfFalse(statement
);
448 return context
.createForInLoop(location
, decls
, expr
, statement
, declsStart
, declsEnd
, exprEnd
, startLine
, endLine
, declsLine
, declsLineStart
);
451 template <typename LexerType
>
452 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseBreakStatement(TreeBuilder
& context
)
454 ASSERT(match(BREAK
));
455 JSTokenLocation
location(tokenLocation());
456 int startCol
= tokenStart();
457 int endCol
= tokenEnd();
458 int startLine
= tokenLine();
459 int endLine
= tokenLine();
460 unsigned endLineStart
= tokenLineStart();
463 if (autoSemiColon()) {
464 failIfFalseWithMessage(breakIsValid(), "'break' is only valid inside a switch or loop statement");
465 return context
.createBreakStatement(location
, startCol
, endCol
, startLine
, endLine
, endLineStart
);
468 const Identifier
* ident
= m_token
.m_data
.ident
;
469 failIfFalseWithNameAndMessage(getLabel(ident
), "Label", ident
->impl(), "is not defined");
471 endLine
= tokenLine();
472 endLineStart
= tokenLineStart();
474 failIfFalse(autoSemiColon());
475 return context
.createBreakStatement(location
, ident
, startCol
, endCol
, startLine
, endLine
, endLineStart
);
478 template <typename LexerType
>
479 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseContinueStatement(TreeBuilder
& context
)
481 ASSERT(match(CONTINUE
));
482 JSTokenLocation
location(tokenLocation());
483 int startCol
= tokenStart();
484 int endCol
= tokenEnd();
485 int startLine
= tokenLine();
486 int endLine
= tokenLine();
487 unsigned endLineStart
= tokenLineStart();
490 if (autoSemiColon()) {
491 failIfFalseWithMessage(continueIsValid(), "'continue' is only valid inside a loop statement");
492 return context
.createContinueStatement(location
, startCol
, endCol
, startLine
, endLine
, endLineStart
);
495 const Identifier
* ident
= m_token
.m_data
.ident
;
496 ScopeLabelInfo
* label
= getLabel(ident
);
497 failIfFalseWithNameAndMessage(label
, "Label", ident
->impl(), "is not defined");
498 failIfFalseWithMessage(label
->m_isLoop
, "'continue' is only valid inside a loop statement");
500 endLine
= tokenLine();
501 endLineStart
= tokenLineStart();
503 failIfFalse(autoSemiColon());
504 return context
.createContinueStatement(location
, ident
, startCol
, endCol
, startLine
, endLine
, endLineStart
);
507 template <typename LexerType
>
508 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseReturnStatement(TreeBuilder
& context
)
510 ASSERT(match(RETURN
));
511 JSTokenLocation
location(tokenLocation());
512 failIfFalse(currentScope()->isFunction());
513 int startLine
= tokenLine();
514 int endLine
= startLine
;
515 int start
= tokenStart();
516 int end
= tokenEnd();
517 unsigned divotLine
= tokenLine();
518 unsigned divotLineStart
= tokenLineStart();
520 // We do the auto semicolon check before attempting to parse an expression
521 // as we need to ensure the a line break after the return correctly terminates
523 if (match(SEMICOLON
))
524 endLine
= tokenLine();
526 return context
.createReturnStatement(location
, 0, start
, end
, startLine
, endLine
, divotLine
, divotLineStart
);
527 TreeExpression expr
= parseExpression(context
);
529 end
= lastTokenEnd();
530 divotLine
= lastTokenLine();
531 divotLineStart
= lastTokenLineStart();
532 if (match(SEMICOLON
))
533 endLine
= tokenLine();
534 failIfFalse(autoSemiColon());
535 return context
.createReturnStatement(location
, expr
, start
, end
, startLine
, endLine
, divotLine
, divotLineStart
);
538 template <typename LexerType
>
539 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseThrowStatement(TreeBuilder
& context
)
541 ASSERT(match(THROW
));
542 JSTokenLocation
location(tokenLocation());
543 int eStart
= tokenStart();
544 int startLine
= tokenLine();
547 failIfTrue(autoSemiColon());
549 TreeExpression expr
= parseExpression(context
);
551 int eEnd
= lastTokenEnd();
552 unsigned divotLine
= lastTokenLine();
553 unsigned divotLineStart
= lastTokenLineStart();
554 int endLine
= tokenLine();
555 failIfFalse(autoSemiColon());
557 return context
.createThrowStatement(location
, expr
, eStart
, eEnd
, startLine
, endLine
, divotLine
, divotLineStart
);
560 template <typename LexerType
>
561 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseWithStatement(TreeBuilder
& context
)
564 JSTokenLocation
location(tokenLocation());
565 failIfTrueWithMessage(strictMode(), "'with' statements are not valid in strict mode");
566 currentScope()->setNeedsFullActivation();
567 int startLine
= tokenLine();
569 consumeOrFail(OPENPAREN
);
570 int start
= tokenStart();
571 TreeExpression expr
= parseExpression(context
);
573 int end
= lastTokenEnd();
574 unsigned divotLine
= lastTokenLine();
575 unsigned divotLineStart
= lastTokenLineStart();
576 int endLine
= tokenLine();
577 consumeOrFail(CLOSEPAREN
);
578 const Identifier
* unused
= 0;
579 TreeStatement statement
= parseStatement(context
, unused
);
580 failIfFalse(statement
);
582 return context
.createWithStatement(location
, expr
, statement
, start
, end
, startLine
, endLine
, divotLine
, divotLineStart
);
585 template <typename LexerType
>
586 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseSwitchStatement(TreeBuilder
& context
)
588 ASSERT(match(SWITCH
));
589 JSTokenLocation
location(tokenLocation());
590 int startLine
= tokenLine();
592 consumeOrFail(OPENPAREN
);
593 TreeExpression expr
= parseExpression(context
);
595 int endLine
= tokenLine();
596 consumeOrFail(CLOSEPAREN
);
597 consumeOrFail(OPENBRACE
);
599 TreeClauseList firstClauses
= parseSwitchClauses(context
);
600 failIfTrue(hasError());
602 TreeClause defaultClause
= parseSwitchDefaultClause(context
);
603 failIfTrue(hasError());
605 TreeClauseList secondClauses
= parseSwitchClauses(context
);
606 failIfTrue(hasError());
608 consumeOrFail(CLOSEBRACE
);
610 return context
.createSwitchStatement(location
, expr
, firstClauses
, defaultClause
, secondClauses
, startLine
, endLine
);
614 template <typename LexerType
>
615 template <class TreeBuilder
> TreeClauseList Parser
<LexerType
>::parseSwitchClauses(TreeBuilder
& context
)
620 TreeExpression condition
= parseExpression(context
);
621 failIfFalse(condition
);
622 consumeOrFail(COLON
);
623 TreeSourceElements statements
= parseSourceElements
<DontCheckForStrictMode
>(context
);
624 failIfFalse(statements
);
625 TreeClause clause
= context
.createClause(condition
, statements
);
626 TreeClauseList clauseList
= context
.createClauseList(clause
);
627 TreeClauseList tail
= clauseList
;
629 while (match(CASE
)) {
631 TreeExpression condition
= parseExpression(context
);
632 failIfFalse(condition
);
633 consumeOrFail(COLON
);
634 TreeSourceElements statements
= parseSourceElements
<DontCheckForStrictMode
>(context
);
635 failIfFalse(statements
);
636 clause
= context
.createClause(condition
, statements
);
637 tail
= context
.createClauseList(tail
, clause
);
642 template <typename LexerType
>
643 template <class TreeBuilder
> TreeClause Parser
<LexerType
>::parseSwitchDefaultClause(TreeBuilder
& context
)
648 consumeOrFail(COLON
);
649 TreeSourceElements statements
= parseSourceElements
<DontCheckForStrictMode
>(context
);
650 failIfFalse(statements
);
651 return context
.createClause(0, statements
);
654 template <typename LexerType
>
655 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseTryStatement(TreeBuilder
& context
)
658 JSTokenLocation
location(tokenLocation());
659 TreeStatement tryBlock
= 0;
660 const Identifier
* ident
= &m_vm
->propertyNames
->nullIdentifier
;
661 TreeStatement catchBlock
= 0;
662 TreeStatement finallyBlock
= 0;
663 int firstLine
= tokenLine();
665 matchOrFail(OPENBRACE
);
667 tryBlock
= parseBlockStatement(context
);
668 failIfFalse(tryBlock
);
669 int lastLine
= m_lastLine
;
672 currentScope()->setNeedsFullActivation();
674 consumeOrFail(OPENPAREN
);
676 ident
= m_token
.m_data
.ident
;
678 AutoPopScopeRef
catchScope(this, pushScope());
679 failIfFalseIfStrictWithNameAndMessage(declareVariable(ident
), "Cannot declare a variable named", ident
->impl(), "in strict mode");
680 catchScope
->preventNewDecls();
681 consumeOrFail(CLOSEPAREN
);
682 matchOrFail(OPENBRACE
);
683 catchBlock
= parseBlockStatement(context
);
684 failIfFalseWithMessage(catchBlock
, "'try' must have a catch or finally block");
685 failIfFalse(popScope(catchScope
, TreeBuilder::NeedsFreeVariableInfo
));
688 if (match(FINALLY
)) {
690 matchOrFail(OPENBRACE
);
691 finallyBlock
= parseBlockStatement(context
);
692 failIfFalse(finallyBlock
);
694 failIfFalse(catchBlock
|| finallyBlock
);
695 return context
.createTryStatement(location
, tryBlock
, ident
, catchBlock
, finallyBlock
, firstLine
, lastLine
);
698 template <typename LexerType
>
699 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseDebuggerStatement(TreeBuilder
& context
)
701 ASSERT(match(DEBUGGER
));
702 JSTokenLocation
location(tokenLocation());
703 int startLine
= tokenLine();
704 int endLine
= startLine
;
706 if (match(SEMICOLON
))
707 startLine
= tokenLine();
708 failIfFalse(autoSemiColon());
709 return context
.createDebugger(location
, startLine
, endLine
);
712 template <typename LexerType
>
713 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseBlockStatement(TreeBuilder
& context
)
715 ASSERT(match(OPENBRACE
));
716 JSTokenLocation
location(tokenLocation());
717 int start
= tokenLine();
719 if (match(CLOSEBRACE
)) {
721 return context
.createBlockStatement(location
, 0, start
, m_lastLine
);
723 TreeSourceElements subtree
= parseSourceElements
<DontCheckForStrictMode
>(context
);
724 failIfFalse(subtree
);
725 matchOrFail(CLOSEBRACE
);
727 return context
.createBlockStatement(location
, subtree
, start
, m_lastLine
);
730 template <typename LexerType
>
731 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseStatement(TreeBuilder
& context
, const Identifier
*& directive
, unsigned* directiveLiteralLength
)
733 DepthManager
statementDepth(&m_statementDepth
);
736 int nonTrivialExpressionCount
= 0;
737 failIfStackOverflow();
738 switch (m_token
.m_type
) {
740 return parseBlockStatement(context
);
742 return parseVarDeclaration(context
);
744 return parseConstDeclaration(context
);
746 failIfFalseIfStrictWithMessage(m_statementDepth
== 1, "Functions cannot be declared in a nested block in strict mode");
747 return parseFunctionDeclaration(context
);
749 JSTokenLocation
location(tokenLocation());
751 return context
.createEmptyStatement(location
);
754 return parseIfStatement(context
);
756 return parseDoWhileStatement(context
);
758 return parseWhileStatement(context
);
760 return parseForStatement(context
);
762 return parseContinueStatement(context
);
764 return parseBreakStatement(context
);
766 return parseReturnStatement(context
);
768 return parseWithStatement(context
);
770 return parseSwitchStatement(context
);
772 return parseThrowStatement(context
);
774 return parseTryStatement(context
);
776 return parseDebuggerStatement(context
);
781 // These tokens imply the end of a set of source elements
784 return parseExpressionOrLabelStatement(context
);
786 directive
= m_token
.m_data
.ident
;
787 if (directiveLiteralLength
)
788 *directiveLiteralLength
= m_token
.m_location
.endOffset
- m_token
.m_location
.startOffset
;
789 nonTrivialExpressionCount
= m_nonTrivialExpressionCount
;
791 TreeStatement exprStatement
= parseExpressionStatement(context
);
792 if (directive
&& nonTrivialExpressionCount
!= m_nonTrivialExpressionCount
)
794 return exprStatement
;
798 template <typename LexerType
>
799 template <class TreeBuilder
> TreeFormalParameterList Parser
<LexerType
>::parseFormalParameters(TreeBuilder
& context
)
802 failIfFalseIfStrictWithNameAndMessage(declareParameter(m_token
.m_data
.ident
), "Cannot declare a parameter named", m_token
.m_data
.ident
->impl(), " in strict mode");
803 TreeFormalParameterList list
= context
.createFormalParameterList(*m_token
.m_data
.ident
);
804 TreeFormalParameterList tail
= list
;
806 while (match(COMMA
)) {
809 const Identifier
* ident
= m_token
.m_data
.ident
;
810 failIfFalseIfStrictWithNameAndMessage(declareParameter(ident
), "Cannot declare a parameter named", ident
->impl(), "in strict mode");
812 tail
= context
.createFormalParameterList(tail
, *ident
);
817 template <typename LexerType
>
818 template <class TreeBuilder
> TreeFunctionBody Parser
<LexerType
>::parseFunctionBody(TreeBuilder
& context
)
820 JSTokenLocation
startLocation(tokenLocation());
821 unsigned startColumn
= tokenColumn();
824 if (match(CLOSEBRACE
))
825 return context
.createFunctionBody(startLocation
, tokenLocation(), startColumn
, strictMode());
826 DepthManager
statementDepth(&m_statementDepth
);
827 m_statementDepth
= 0;
828 typename
TreeBuilder::FunctionBodyBuilder
bodyBuilder(const_cast<VM
*>(m_vm
), m_lexer
.get());
829 failIfFalse(parseSourceElements
<CheckForStrictMode
>(bodyBuilder
));
830 return context
.createFunctionBody(startLocation
, tokenLocation(), startColumn
, strictMode());
833 template <typename LexerType
>
834 template <FunctionRequirements requirements
, bool nameIsInContainingScope
, class TreeBuilder
> bool Parser
<LexerType
>::parseFunctionInfo(TreeBuilder
& context
, const Identifier
*& name
, TreeFormalParameterList
& parameters
, TreeFunctionBody
& body
, unsigned& openBraceOffset
, unsigned& closeBraceOffset
, int& bodyStartLine
, unsigned& bodyStartColumn
)
836 AutoPopScopeRef
functionScope(this, pushScope());
837 functionScope
->setIsFunction();
838 int functionStart
= m_token
.m_location
.startOffset
;
840 name
= m_token
.m_data
.ident
;
842 if (!nameIsInContainingScope
)
843 failIfFalseIfStrict(functionScope
->declareVariable(name
));
844 } else if (requirements
== FunctionNeedsName
)
846 consumeOrFail(OPENPAREN
);
847 if (!match(CLOSEPAREN
)) {
848 parameters
= parseFormalParameters(context
);
849 failIfFalse(parameters
);
851 consumeOrFail(CLOSEPAREN
);
852 matchOrFail(OPENBRACE
);
854 openBraceOffset
= m_token
.m_data
.offset
;
855 bodyStartLine
= tokenLine();
856 bodyStartColumn
= m_token
.m_data
.offset
- m_token
.m_data
.lineStartOffset
;
857 JSTokenLocation
startLocation(tokenLocation());
859 // If we know about this function already, we can use the cached info and skip the parser to the end of the function.
860 if (const SourceProviderCacheItem
* cachedInfo
= TreeBuilder::CanUseFunctionCache
? findCachedFunctionInfo(openBraceOffset
) : 0) {
861 // If we're in a strict context, the cached function info must say it was strict too.
862 ASSERT(!strictMode() || cachedInfo
->strictMode
);
863 JSTokenLocation endLocation
;
865 endLocation
.line
= cachedInfo
->closeBraceLine
;
866 endLocation
.startOffset
= cachedInfo
->closeBraceOffset
;
867 endLocation
.lineStartOffset
= cachedInfo
->closeBraceLineStartOffset
;
868 ASSERT(endLocation
.startOffset
>= endLocation
.lineStartOffset
);
870 body
= context
.createFunctionBody(startLocation
, endLocation
, bodyStartColumn
, cachedInfo
->strictMode
);
872 functionScope
->restoreFromSourceProviderCache(cachedInfo
);
873 failIfFalse(popScope(functionScope
, TreeBuilder::NeedsFreeVariableInfo
));
875 closeBraceOffset
= cachedInfo
->closeBraceOffset
;
877 context
.setFunctionStart(body
, functionStart
);
878 m_token
= cachedInfo
->closeBraceToken();
880 m_lexer
->setOffset(m_token
.m_location
.endOffset
, m_token
.m_location
.lineStartOffset
);
881 m_lexer
->setLineNumber(m_token
.m_location
.line
);
887 body
= parseFunctionBody(context
);
889 if (functionScope
->strictMode() && name
) {
890 failIfTrueWithNameAndMessage(m_vm
->propertyNames
->arguments
== *name
, "Function name", name
->impl(), "is not valid in strict mode");
891 failIfTrueWithNameAndMessage(m_vm
->propertyNames
->eval
== *name
, "Function name", name
->impl(), "is not valid in strict mode");
893 closeBraceOffset
= m_token
.m_data
.offset
;
894 unsigned closeBraceLine
= m_token
.m_data
.line
;
895 unsigned closeBraceLineStartOffset
= m_token
.m_data
.lineStartOffset
;
897 // Cache the tokenizer state and the function scope the first time the function is parsed.
898 // Any future reparsing can then skip the function.
899 static const int minimumFunctionLengthToCache
= 16;
900 OwnPtr
<SourceProviderCacheItem
> newInfo
;
901 int functionLength
= closeBraceOffset
- openBraceOffset
;
902 if (TreeBuilder::CanUseFunctionCache
&& m_functionCache
&& functionLength
> minimumFunctionLengthToCache
) {
903 SourceProviderCacheItemCreationParameters parameters
;
904 parameters
.functionStart
= functionStart
;
905 parameters
.closeBraceLine
= closeBraceLine
;
906 parameters
.closeBraceOffset
= closeBraceOffset
;
907 parameters
.closeBraceLineStartOffset
= closeBraceLineStartOffset
;
908 functionScope
->fillParametersForSourceProviderCache(parameters
);
909 newInfo
= SourceProviderCacheItem::create(parameters
);
912 context
.setFunctionStart(body
, functionStart
);
914 failIfFalse(popScope(functionScope
, TreeBuilder::NeedsFreeVariableInfo
));
915 matchOrFail(CLOSEBRACE
);
918 m_functionCache
->add(openBraceOffset
, newInfo
.release());
924 template <typename LexerType
>
925 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseFunctionDeclaration(TreeBuilder
& context
)
927 ASSERT(match(FUNCTION
));
928 JSTokenLocation
location(tokenLocation());
930 const Identifier
* name
= 0;
931 TreeFormalParameterList parameters
= 0;
932 TreeFunctionBody body
= 0;
933 unsigned openBraceOffset
= 0;
934 unsigned closeBraceOffset
= 0;
935 int bodyStartLine
= 0;
936 unsigned bodyStartColumn
= 0;
937 failIfFalse((parseFunctionInfo
<FunctionNeedsName
, true>(context
, name
, parameters
, body
, openBraceOffset
, closeBraceOffset
, bodyStartLine
, bodyStartColumn
)));
939 failIfFalseIfStrict(declareVariable(name
));
940 return context
.createFuncDeclStatement(location
, name
, body
, parameters
, openBraceOffset
, closeBraceOffset
, bodyStartLine
, m_lastLine
, bodyStartColumn
);
944 LabelInfo(const Identifier
* ident
, unsigned start
, unsigned end
, unsigned divotLine
, unsigned divotLineStart
)
948 , m_divotLine(divotLine
)
949 , m_divotLineStart(divotLineStart
)
953 const Identifier
* m_ident
;
956 unsigned m_divotLine
;
957 unsigned m_divotLineStart
;
960 template <typename LexerType
>
961 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseExpressionOrLabelStatement(TreeBuilder
& context
)
964 /* Expression and Label statements are ambiguous at LL(1), so we have a
965 * special case that looks for a colon as the next character in the input.
967 Vector
<LabelInfo
> labels
;
968 JSTokenLocation location
;
970 int start
= tokenStart();
971 int startingLine
= tokenLine();
972 location
= tokenLocation();
973 if (!nextTokenIsColon()) {
974 // If we hit this path we're making a expression statement, which
975 // by definition can't make use of continue/break so we can just
976 // ignore any labels we might have accumulated.
977 TreeExpression expression
= parseExpression(context
);
978 failIfFalse(expression
);
979 failIfFalse(autoSemiColon());
980 return context
.createExprStatement(location
, expression
, startingLine
, m_lastLine
);
982 const Identifier
* ident
= m_token
.m_data
.ident
;
983 int end
= tokenEnd();
984 unsigned divotLine
= tokenLine();
985 unsigned divotLineStart
= tokenLineStart();
987 consumeOrFail(COLON
);
988 if (!m_syntaxAlreadyValidated
) {
989 // This is O(N^2) over the current list of consecutive labels, but I
990 // have never seen more than one label in a row in the real world.
991 for (size_t i
= 0; i
< labels
.size(); i
++)
992 failIfTrue(ident
->impl() == labels
[i
].m_ident
->impl());
993 failIfTrue(getLabel(ident
));
994 labels
.append(LabelInfo(ident
, start
, end
, divotLine
, divotLineStart
));
996 } while (match(IDENT
));
998 switch (m_token
.m_type
) {
1008 const Identifier
* unused
= 0;
1009 if (!m_syntaxAlreadyValidated
) {
1010 for (size_t i
= 0; i
< labels
.size(); i
++)
1011 pushLabel(labels
[i
].m_ident
, isLoop
);
1013 TreeStatement statement
= parseStatement(context
, unused
);
1014 if (!m_syntaxAlreadyValidated
) {
1015 for (size_t i
= 0; i
< labels
.size(); i
++)
1018 failIfFalse(statement
);
1019 for (size_t i
= 0; i
< labels
.size(); i
++) {
1020 const LabelInfo
& info
= labels
[labels
.size() - i
- 1];
1021 statement
= context
.createLabelStatement(location
, info
.m_ident
, statement
, info
.m_start
, info
.m_end
, info
.m_divotLine
, info
.m_divotLineStart
);
1026 template <typename LexerType
>
1027 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseExpressionStatement(TreeBuilder
& context
)
1029 int startLine
= tokenLine();
1030 JSTokenLocation
location(tokenLocation());
1031 TreeExpression expression
= parseExpression(context
);
1032 failIfFalse(expression
);
1033 failIfFalse(autoSemiColon());
1034 return context
.createExprStatement(location
, expression
, startLine
, m_lastLine
);
1037 template <typename LexerType
>
1038 template <class TreeBuilder
> TreeStatement Parser
<LexerType
>::parseIfStatement(TreeBuilder
& context
)
1041 JSTokenLocation
ifLocation(tokenLocation());
1042 int start
= tokenLine();
1045 consumeOrFail(OPENPAREN
);
1047 TreeExpression condition
= parseExpression(context
);
1048 failIfFalse(condition
);
1049 int end
= tokenLine();
1050 consumeOrFail(CLOSEPAREN
);
1052 const Identifier
* unused
= 0;
1053 TreeStatement trueBlock
= parseStatement(context
, unused
);
1054 failIfFalse(trueBlock
);
1057 return context
.createIfStatement(ifLocation
, condition
, trueBlock
, 0, start
, end
);
1059 Vector
<TreeExpression
> exprStack
;
1060 Vector
<pair
<int, int> > posStack
;
1061 Vector
<JSTokenLocation
> tokenLocationStack
;
1062 Vector
<TreeStatement
> statementStack
;
1063 bool trailingElse
= false;
1065 JSTokenLocation tempLocation
= tokenLocation();
1068 const Identifier
* unused
= 0;
1069 TreeStatement block
= parseStatement(context
, unused
);
1071 statementStack
.append(block
);
1072 trailingElse
= true;
1075 int innerStart
= tokenLine();
1078 consumeOrFail(OPENPAREN
);
1080 TreeExpression innerCondition
= parseExpression(context
);
1081 failIfFalse(innerCondition
);
1082 int innerEnd
= tokenLine();
1083 consumeOrFail(CLOSEPAREN
);
1084 const Identifier
* unused
= 0;
1085 TreeStatement innerTrueBlock
= parseStatement(context
, unused
);
1086 failIfFalse(innerTrueBlock
);
1087 tokenLocationStack
.append(tempLocation
);
1088 exprStack
.append(innerCondition
);
1089 posStack
.append(make_pair(innerStart
, innerEnd
));
1090 statementStack
.append(innerTrueBlock
);
1091 } while (match(ELSE
));
1093 if (!trailingElse
) {
1094 TreeExpression condition
= exprStack
.last();
1095 exprStack
.removeLast();
1096 TreeStatement trueBlock
= statementStack
.last();
1097 statementStack
.removeLast();
1098 pair
<int, int> pos
= posStack
.last();
1099 posStack
.removeLast();
1100 JSTokenLocation elseLocation
= tokenLocationStack
.last();
1101 tokenLocationStack
.removeLast();
1102 statementStack
.append(context
.createIfStatement(elseLocation
, condition
, trueBlock
, 0, pos
.first
, pos
.second
));
1105 while (!exprStack
.isEmpty()) {
1106 TreeExpression condition
= exprStack
.last();
1107 exprStack
.removeLast();
1108 TreeStatement falseBlock
= statementStack
.last();
1109 statementStack
.removeLast();
1110 TreeStatement trueBlock
= statementStack
.last();
1111 statementStack
.removeLast();
1112 pair
<int, int> pos
= posStack
.last();
1113 posStack
.removeLast();
1114 JSTokenLocation elseLocation
= tokenLocationStack
.last();
1115 tokenLocationStack
.removeLast();
1116 statementStack
.append(context
.createIfStatement(elseLocation
, condition
, trueBlock
, falseBlock
, pos
.first
, pos
.second
));
1119 return context
.createIfStatement(ifLocation
, condition
, trueBlock
, statementStack
.last(), start
, end
);
1122 template <typename LexerType
>
1123 template <class TreeBuilder
> TreeExpression Parser
<LexerType
>::parseExpression(TreeBuilder
& context
)
1125 failIfStackOverflow();
1126 JSTokenLocation
location(tokenLocation());
1127 TreeExpression node
= parseAssignmentExpression(context
);
1132 m_nonTrivialExpressionCount
++;
1134 TreeExpression right
= parseAssignmentExpression(context
);
1136 typename
TreeBuilder::Comma commaNode
= context
.createCommaExpr(location
, node
, right
);
1137 while (match(COMMA
)) {
1138 next(TreeBuilder::DontBuildStrings
);
1139 right
= parseAssignmentExpression(context
);
1141 context
.appendToComma(commaNode
, right
);
1146 template <typename LexerType
>
1147 template <typename TreeBuilder
> TreeExpression Parser
<LexerType
>::parseAssignmentExpression(TreeBuilder
& context
)
1149 failIfStackOverflow();
1150 int start
= tokenStart();
1151 unsigned line
= tokenLine();
1152 unsigned lineStart
= tokenLineStart();
1153 JSTokenLocation
location(tokenLocation());
1154 int initialAssignmentCount
= m_assignmentCount
;
1155 int initialNonLHSCount
= m_nonLHSCount
;
1156 TreeExpression lhs
= parseConditionalExpression(context
);
1158 if (initialNonLHSCount
!= m_nonLHSCount
)
1161 int assignmentStack
= 0;
1163 bool hadAssignment
= false;
1165 switch (m_token
.m_type
) {
1166 case EQUAL
: op
= OpEqual
; break;
1167 case PLUSEQUAL
: op
= OpPlusEq
; break;
1168 case MINUSEQUAL
: op
= OpMinusEq
; break;
1169 case MULTEQUAL
: op
= OpMultEq
; break;
1170 case DIVEQUAL
: op
= OpDivEq
; break;
1171 case LSHIFTEQUAL
: op
= OpLShift
; break;
1172 case RSHIFTEQUAL
: op
= OpRShift
; break;
1173 case URSHIFTEQUAL
: op
= OpURShift
; break;
1174 case ANDEQUAL
: op
= OpAndEq
; break;
1175 case XOREQUAL
: op
= OpXOrEq
; break;
1176 case OREQUAL
: op
= OpOrEq
; break;
1177 case MODEQUAL
: op
= OpModEq
; break;
1181 m_nonTrivialExpressionCount
++;
1182 hadAssignment
= true;
1183 context
.assignmentStackAppend(assignmentStack
, lhs
, start
, tokenStart(), line
, lineStart
, m_assignmentCount
, op
);
1184 start
= tokenStart();
1186 lineStart
= tokenLineStart();
1187 m_assignmentCount
++;
1188 next(TreeBuilder::DontBuildStrings
);
1189 if (strictMode() && m_lastIdentifier
&& context
.isResolve(lhs
)) {
1190 failIfTrueIfStrictWithMessage(m_vm
->propertyNames
->eval
== *m_lastIdentifier
, "'eval' cannot be modified in strict mode");
1191 failIfTrueIfStrictWithMessage(m_vm
->propertyNames
->arguments
== *m_lastIdentifier
, "'arguments' cannot be modified in strict mode");
1192 declareWrite(m_lastIdentifier
);
1193 m_lastIdentifier
= 0;
1195 lhs
= parseConditionalExpression(context
);
1197 if (initialNonLHSCount
!= m_nonLHSCount
)
1204 if (!TreeBuilder::CreatesAST
)
1207 while (assignmentStack
)
1208 lhs
= context
.createAssignment(location
, assignmentStack
, lhs
, initialAssignmentCount
, m_assignmentCount
, lastTokenEnd());
1213 template <typename LexerType
>
1214 template <class TreeBuilder
> TreeExpression Parser
<LexerType
>::parseConditionalExpression(TreeBuilder
& context
)
1216 JSTokenLocation
location(tokenLocation());
1217 TreeExpression cond
= parseBinaryExpression(context
);
1219 if (!match(QUESTION
))
1221 m_nonTrivialExpressionCount
++;
1223 next(TreeBuilder::DontBuildStrings
);
1224 TreeExpression lhs
= parseAssignmentExpression(context
);
1225 consumeOrFailWithFlags(COLON
, TreeBuilder::DontBuildStrings
);
1227 TreeExpression rhs
= parseAssignmentExpression(context
);
1229 return context
.createConditionalExpr(location
, cond
, lhs
, rhs
);
1232 ALWAYS_INLINE
static bool isUnaryOp(JSTokenType token
)
1234 return token
& UnaryOpTokenFlag
;
1237 template <typename LexerType
>
1238 int Parser
<LexerType
>::isBinaryOperator(JSTokenType token
)
1241 return token
& (BinaryOpTokenPrecedenceMask
<< BinaryOpTokenAllowsInPrecedenceAdditionalShift
);
1242 return token
& BinaryOpTokenPrecedenceMask
;
1245 template <typename LexerType
>
1246 template <class TreeBuilder
> TreeExpression Parser
<LexerType
>::parseBinaryExpression(TreeBuilder
& context
)
1249 int operandStackDepth
= 0;
1250 int operatorStackDepth
= 0;
1251 typename
TreeBuilder::BinaryExprContext
binaryExprContext(context
);
1252 JSTokenLocation
location(tokenLocation());
1254 int exprStart
= tokenStart();
1255 int initialAssignments
= m_assignmentCount
;
1256 TreeExpression current
= parseUnaryExpression(context
);
1257 failIfFalse(current
);
1259 context
.appendBinaryExpressionInfo(operandStackDepth
, current
, exprStart
, lastTokenEnd(), lastTokenEnd(), lastTokenLine(), lastTokenLineStart(), initialAssignments
!= m_assignmentCount
);
1260 int precedence
= isBinaryOperator(m_token
.m_type
);
1263 m_nonTrivialExpressionCount
++;
1265 int operatorToken
= m_token
.m_type
;
1266 next(TreeBuilder::DontBuildStrings
);
1268 while (operatorStackDepth
&& context
.operatorStackHasHigherPrecedence(operatorStackDepth
, precedence
)) {
1269 ASSERT(operandStackDepth
> 1);
1271 typename
TreeBuilder::BinaryOperand rhs
= context
.getFromOperandStack(-1);
1272 typename
TreeBuilder::BinaryOperand lhs
= context
.getFromOperandStack(-2);
1273 context
.shrinkOperandStackBy(operandStackDepth
, 2);
1274 context
.appendBinaryOperation(location
, operandStackDepth
, operatorStackDepth
, lhs
, rhs
);
1275 context
.operatorStackPop(operatorStackDepth
);
1277 context
.operatorStackAppend(operatorStackDepth
, operatorToken
, precedence
);
1279 while (operatorStackDepth
) {
1280 ASSERT(operandStackDepth
> 1);
1282 typename
TreeBuilder::BinaryOperand rhs
= context
.getFromOperandStack(-1);
1283 typename
TreeBuilder::BinaryOperand lhs
= context
.getFromOperandStack(-2);
1284 context
.shrinkOperandStackBy(operandStackDepth
, 2);
1285 context
.appendBinaryOperation(location
, operandStackDepth
, operatorStackDepth
, lhs
, rhs
);
1286 context
.operatorStackPop(operatorStackDepth
);
1288 return context
.popOperandStack(operandStackDepth
);
1291 template <typename LexerType
>
1292 template <bool complete
, class TreeBuilder
> TreeProperty Parser
<LexerType
>::parseProperty(TreeBuilder
& context
)
1294 bool wasIdent
= false;
1295 switch (m_token
.m_type
) {
1300 const Identifier
* ident
= m_token
.m_data
.ident
;
1301 if (complete
|| (wasIdent
&& (*ident
== m_vm
->propertyNames
->get
|| *ident
== m_vm
->propertyNames
->set
)))
1302 nextExpectIdentifier(LexerFlagsIgnoreReservedWords
);
1304 nextExpectIdentifier(LexerFlagsIgnoreReservedWords
| TreeBuilder::DontBuildKeywords
);
1308 TreeExpression node
= parseAssignmentExpression(context
);
1310 return context
.template createProperty
<complete
>(ident
, node
, PropertyNode::Constant
);
1312 failIfFalse(wasIdent
);
1313 const Identifier
* accessorName
= 0;
1314 TreeFormalParameterList parameters
= 0;
1315 TreeFunctionBody body
= 0;
1316 unsigned openBraceOffset
= 0;
1317 unsigned closeBraceOffset
= 0;
1318 int bodyStartLine
= 0;
1319 unsigned bodyStartColumn
= 0;
1320 PropertyNode::Type type
;
1321 if (*ident
== m_vm
->propertyNames
->get
)
1322 type
= PropertyNode::Getter
;
1323 else if (*ident
== m_vm
->propertyNames
->set
)
1324 type
= PropertyNode::Setter
;
1327 const Identifier
* stringPropertyName
= 0;
1328 double numericPropertyName
= 0;
1329 if (m_token
.m_type
== IDENT
|| m_token
.m_type
== STRING
)
1330 stringPropertyName
= m_token
.m_data
.ident
;
1331 else if (m_token
.m_type
== NUMBER
)
1332 numericPropertyName
= m_token
.m_data
.doubleValue
;
1335 JSTokenLocation
location(tokenLocation());
1337 failIfFalse((parseFunctionInfo
<FunctionNoRequirements
, false>(context
, accessorName
, parameters
, body
, openBraceOffset
, closeBraceOffset
, bodyStartLine
, bodyStartColumn
)));
1338 if (stringPropertyName
)
1339 return context
.template createGetterOrSetterProperty
<complete
>(location
, type
, stringPropertyName
, parameters
, body
, openBraceOffset
, closeBraceOffset
, bodyStartLine
, m_lastLine
, bodyStartColumn
);
1340 return context
.template createGetterOrSetterProperty
<complete
>(const_cast<VM
*>(m_vm
), location
, type
, numericPropertyName
, parameters
, body
, openBraceOffset
, closeBraceOffset
, bodyStartLine
, m_lastLine
, bodyStartColumn
);
1343 double propertyName
= m_token
.m_data
.doubleValue
;
1345 consumeOrFail(COLON
);
1346 TreeExpression node
= parseAssignmentExpression(context
);
1348 return context
.template createProperty
<complete
>(const_cast<VM
*>(m_vm
), propertyName
, node
, PropertyNode::Constant
);
1351 failIfFalse(m_token
.m_type
& KeywordTokenFlag
);
1356 template <typename LexerType
>
1357 template <class TreeBuilder
> TreeExpression Parser
<LexerType
>::parseObjectLiteral(TreeBuilder
& context
)
1359 int startOffset
= m_token
.m_data
.offset
;
1360 unsigned oldLineStartOffset
= m_lexer
->currentLineStartOffset();
1361 unsigned oldLastLineNumber
= m_lexer
->lastLineNumber();
1362 unsigned oldLineNumber
= m_lexer
->lineNumber();
1363 consumeOrFailWithFlags(OPENBRACE
, TreeBuilder::DontBuildStrings
);
1364 JSTokenLocation
location(tokenLocation());
1366 int oldNonLHSCount
= m_nonLHSCount
;
1368 if (match(CLOSEBRACE
)) {
1370 return context
.createObjectLiteral(location
);
1373 TreeProperty property
= parseProperty
<false>(context
);
1374 failIfFalse(property
);
1375 if (!m_syntaxAlreadyValidated
&& context
.getType(property
) != PropertyNode::Constant
) {
1376 m_lexer
->setOffset(startOffset
, oldLineStartOffset
);
1378 m_lexer
->setLastLineNumber(oldLastLineNumber
);
1379 m_lexer
->setLineNumber(oldLineNumber
);
1380 return parseStrictObjectLiteral(context
);
1382 TreePropertyList propertyList
= context
.createPropertyList(location
, property
);
1383 TreePropertyList tail
= propertyList
;
1384 while (match(COMMA
)) {
1385 next(TreeBuilder::DontBuildStrings
);
1386 // allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939
1387 if (match(CLOSEBRACE
))
1389 JSTokenLocation
propertyLocation(tokenLocation());
1390 property
= parseProperty
<false>(context
);
1391 failIfFalse(property
);
1392 if (!m_syntaxAlreadyValidated
&& context
.getType(property
) != PropertyNode::Constant
) {
1393 m_lexer
->setOffset(startOffset
, oldLineStartOffset
);
1395 m_lexer
->setLastLineNumber(oldLastLineNumber
);
1396 m_lexer
->setLineNumber(oldLineNumber
);
1397 return parseStrictObjectLiteral(context
);
1399 tail
= context
.createPropertyList(propertyLocation
, property
, tail
);
1402 location
= tokenLocation();
1403 consumeOrFail(CLOSEBRACE
);
1405 m_nonLHSCount
= oldNonLHSCount
;
1407 return context
.createObjectLiteral(location
, propertyList
);
1410 template <typename LexerType
>
1411 template <class TreeBuilder
> TreeExpression Parser
<LexerType
>::parseStrictObjectLiteral(TreeBuilder
& context
)
1413 consumeOrFail(OPENBRACE
);
1415 int oldNonLHSCount
= m_nonLHSCount
;
1417 JSTokenLocation
location(tokenLocation());
1418 if (match(CLOSEBRACE
)) {
1420 return context
.createObjectLiteral(location
);
1423 TreeProperty property
= parseProperty
<true>(context
);
1424 failIfFalse(property
);
1426 typedef HashMap
<RefPtr
<StringImpl
>, unsigned, IdentifierRepHash
> ObjectValidationMap
;
1427 ObjectValidationMap objectValidator
;
1428 // Add the first property
1429 if (!m_syntaxAlreadyValidated
)
1430 objectValidator
.add(context
.getName(property
).impl(), context
.getType(property
));
1432 TreePropertyList propertyList
= context
.createPropertyList(location
, property
);
1433 TreePropertyList tail
= propertyList
;
1434 while (match(COMMA
)) {
1436 // allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939
1437 if (match(CLOSEBRACE
))
1439 JSTokenLocation
propertyLocation(tokenLocation());
1440 property
= parseProperty
<true>(context
);
1441 failIfFalse(property
);
1442 if (!m_syntaxAlreadyValidated
) {
1443 ObjectValidationMap::AddResult propertyEntry
= objectValidator
.add(context
.getName(property
).impl(), context
.getType(property
));
1444 if (!propertyEntry
.isNewEntry
) {
1445 failIfTrue(propertyEntry
.iterator
->value
== PropertyNode::Constant
);
1446 failIfTrue(context
.getType(property
) == PropertyNode::Constant
);
1447 failIfTrue(context
.getType(property
) & propertyEntry
.iterator
->value
);
1448 propertyEntry
.iterator
->value
|= context
.getType(property
);
1451 tail
= context
.createPropertyList(propertyLocation
, property
, tail
);
1454 location
= tokenLocation();
1455 consumeOrFail(CLOSEBRACE
);
1457 m_nonLHSCount
= oldNonLHSCount
;
1459 return context
.createObjectLiteral(location
, propertyList
);
1462 template <typename LexerType
>
1463 template <class TreeBuilder
> TreeExpression Parser
<LexerType
>::parseArrayLiteral(TreeBuilder
& context
)
1465 consumeOrFailWithFlags(OPENBRACKET
, TreeBuilder::DontBuildStrings
);
1467 int oldNonLHSCount
= m_nonLHSCount
;
1470 while (match(COMMA
)) {
1471 next(TreeBuilder::DontBuildStrings
);
1474 if (match(CLOSEBRACKET
)) {
1475 JSTokenLocation
location(tokenLocation());
1476 next(TreeBuilder::DontBuildStrings
);
1477 return context
.createArray(location
, elisions
);
1480 TreeExpression elem
= parseAssignmentExpression(context
);
1482 typename
TreeBuilder::ElementList elementList
= context
.createElementList(elisions
, elem
);
1483 typename
TreeBuilder::ElementList tail
= elementList
;
1485 while (match(COMMA
)) {
1486 next(TreeBuilder::DontBuildStrings
);
1489 while (match(COMMA
)) {
1494 if (match(CLOSEBRACKET
)) {
1495 JSTokenLocation
location(tokenLocation());
1496 next(TreeBuilder::DontBuildStrings
);
1497 return context
.createArray(location
, elisions
, elementList
);
1499 TreeExpression elem
= parseAssignmentExpression(context
);
1501 tail
= context
.createElementList(tail
, elisions
, elem
);
1504 JSTokenLocation
location(tokenLocation());
1505 consumeOrFail(CLOSEBRACKET
);
1507 m_nonLHSCount
= oldNonLHSCount
;
1509 return context
.createArray(location
, elementList
);
1512 template <typename LexerType
>
1513 template <class TreeBuilder
> TreeExpression Parser
<LexerType
>::parsePrimaryExpression(TreeBuilder
& context
)
1515 failIfStackOverflow();
1516 switch (m_token
.m_type
) {
1519 return parseStrictObjectLiteral(context
);
1520 return parseObjectLiteral(context
);
1522 return parseArrayLiteral(context
);
1525 int oldNonLHSCount
= m_nonLHSCount
;
1526 TreeExpression result
= parseExpression(context
);
1527 m_nonLHSCount
= oldNonLHSCount
;
1528 consumeOrFail(CLOSEPAREN
);
1533 JSTokenLocation
location(tokenLocation());
1535 return context
.thisExpr(location
);
1538 int start
= tokenStart();
1539 int line
= tokenLine();
1540 int lineStart
= tokenLineStart();
1541 const Identifier
* ident
= m_token
.m_data
.ident
;
1542 JSTokenLocation
location(tokenLocation());
1544 currentScope()->useVariable(ident
, m_vm
->propertyNames
->eval
== *ident
);
1545 m_lastIdentifier
= ident
;
1546 return context
.createResolve(location
, ident
, start
, line
, lineStart
);
1549 const Identifier
* ident
= m_token
.m_data
.ident
;
1550 JSTokenLocation
location(tokenLocation());
1552 return context
.createString(location
, ident
);
1555 double d
= m_token
.m_data
.doubleValue
;
1556 JSTokenLocation
location(tokenLocation());
1558 return context
.createNumberExpr(location
, d
);
1561 JSTokenLocation
location(tokenLocation());
1563 return context
.createNull(location
);
1566 JSTokenLocation
location(tokenLocation());
1568 return context
.createBoolean(location
, true);
1571 JSTokenLocation
location(tokenLocation());
1573 return context
.createBoolean(location
, false);
1578 const Identifier
* pattern
;
1579 const Identifier
* flags
;
1580 if (match(DIVEQUAL
))
1581 failIfFalse(m_lexer
->scanRegExp(pattern
, flags
, '='));
1583 failIfFalse(m_lexer
->scanRegExp(pattern
, flags
));
1585 int start
= tokenStart();
1586 int line
= tokenLine();
1587 int lineStart
= tokenLineStart();
1588 JSTokenLocation
location(tokenLocation());
1590 TreeExpression re
= context
.createRegExp(location
, *pattern
, *flags
, start
, line
, lineStart
);
1592 const char* yarrErrorMsg
= Yarr::checkSyntax(pattern
->string());
1593 failWithMessage(yarrErrorMsg
);
1602 template <typename LexerType
>
1603 template <class TreeBuilder
> TreeArguments Parser
<LexerType
>::parseArguments(TreeBuilder
& context
)
1605 consumeOrFailWithFlags(OPENPAREN
, TreeBuilder::DontBuildStrings
);
1606 JSTokenLocation
location(tokenLocation());
1607 if (match(CLOSEPAREN
)) {
1608 next(TreeBuilder::DontBuildStrings
);
1609 return context
.createArguments();
1611 TreeExpression firstArg
= parseAssignmentExpression(context
);
1612 failIfFalse(firstArg
);
1614 TreeArgumentsList argList
= context
.createArgumentsList(location
, firstArg
);
1615 TreeArgumentsList tail
= argList
;
1616 while (match(COMMA
)) {
1617 JSTokenLocation
argumentLocation(tokenLocation());
1618 next(TreeBuilder::DontBuildStrings
);
1619 TreeExpression arg
= parseAssignmentExpression(context
);
1621 tail
= context
.createArgumentsList(argumentLocation
, tail
, arg
);
1623 consumeOrFail(CLOSEPAREN
);
1624 return context
.createArguments(argList
);
1627 template <typename LexerType
>
1628 template <class TreeBuilder
> TreeExpression Parser
<LexerType
>::parseMemberExpression(TreeBuilder
& context
)
1630 TreeExpression base
= 0;
1631 int start
= tokenStart();
1632 int expressionStart
= start
;
1633 int expressionLine
= tokenLine();
1634 int expressionLineStart
= tokenLineStart();
1636 JSTokenLocation location
;
1637 while (match(NEW
)) {
1642 if (match(FUNCTION
)) {
1643 const Identifier
* name
= &m_vm
->propertyNames
->nullIdentifier
;
1644 TreeFormalParameterList parameters
= 0;
1645 TreeFunctionBody body
= 0;
1646 unsigned openBraceOffset
= 0;
1647 unsigned closeBraceOffset
= 0;
1648 int bodyStartLine
= 0;
1649 unsigned bodyStartColumn
= 0;
1650 location
= tokenLocation();
1652 failIfFalse((parseFunctionInfo
<FunctionNoRequirements
, false>(context
, name
, parameters
, body
, openBraceOffset
, closeBraceOffset
, bodyStartLine
, bodyStartColumn
)));
1653 base
= context
.createFunctionExpr(location
, name
, body
, parameters
, openBraceOffset
, closeBraceOffset
, bodyStartLine
, m_lastLine
, bodyStartColumn
);
1655 base
= parsePrimaryExpression(context
);
1659 location
= tokenLocation();
1660 switch (m_token
.m_type
) {
1662 m_nonTrivialExpressionCount
++;
1663 int expressionEnd
= lastTokenEnd();
1664 int expressionLine
= lastTokenLine();
1665 int expressionLineStart
= lastTokenLineStart();
1667 int nonLHSCount
= m_nonLHSCount
;
1668 int initialAssignments
= m_assignmentCount
;
1669 TreeExpression property
= parseExpression(context
);
1670 failIfFalse(property
);
1671 base
= context
.createBracketAccess(location
, base
, property
, initialAssignments
!= m_assignmentCount
, expressionStart
, expressionEnd
, tokenEnd(), expressionLine
, expressionLineStart
);
1672 consumeOrFail(CLOSEBRACKET
);
1673 m_nonLHSCount
= nonLHSCount
;
1677 m_nonTrivialExpressionCount
++;
1678 int nonLHSCount
= m_nonLHSCount
;
1681 int exprEnd
= lastTokenEnd();
1682 unsigned expressionLine
= lastTokenLine();
1683 unsigned expressionLineStart
= lastTokenLineStart();
1684 TreeArguments arguments
= parseArguments(context
);
1685 failIfFalse(arguments
);
1686 base
= context
.createNewExpr(location
, base
, arguments
, start
, exprEnd
, lastTokenEnd(), expressionLine
, expressionLineStart
);
1688 int expressionEnd
= lastTokenEnd();
1689 unsigned expressionLine
= lastTokenLine();
1690 int expressionLineStart
= lastTokenLineStart();
1691 TreeArguments arguments
= parseArguments(context
);
1692 failIfFalse(arguments
);
1693 base
= context
.makeFunctionCallNode(location
, base
, arguments
, expressionStart
, expressionEnd
, lastTokenEnd(), expressionLine
, expressionLineStart
);
1695 m_nonLHSCount
= nonLHSCount
;
1699 m_nonTrivialExpressionCount
++;
1700 int expressionEnd
= lastTokenEnd();
1701 expressionLineStart
= lastTokenLineStart();
1702 nextExpectIdentifier(LexerFlagsIgnoreReservedWords
| TreeBuilder::DontBuildKeywords
);
1704 base
= context
.createDotAccess(location
, base
, m_token
.m_data
.ident
, expressionStart
, expressionEnd
, tokenEnd(), expressionLine
, expressionLineStart
);
1709 goto endMemberExpression
;
1712 endMemberExpression
:
1714 base
= context
.createNewExpr(location
, base
, start
, lastTokenEnd(), expressionLine
, expressionLineStart
);
1718 template <typename LexerType
>
1719 template <class TreeBuilder
> TreeExpression Parser
<LexerType
>::parseUnaryExpression(TreeBuilder
& context
)
1721 typename
TreeBuilder::UnaryExprContext
unaryExprContext(context
);
1722 AllowInOverride
allowInOverride(this);
1723 int tokenStackDepth
= 0;
1724 bool modifiesExpr
= false;
1725 bool requiresLExpr
= false;
1726 while (isUnaryOp(m_token
.m_type
)) {
1728 switch (m_token
.m_type
) {
1732 case AUTOMINUSMINUS
:
1733 failIfTrue(requiresLExpr
);
1734 modifiesExpr
= true;
1735 requiresLExpr
= true;
1738 failIfTrue(requiresLExpr
);
1739 requiresLExpr
= true;
1742 failIfTrue(requiresLExpr
);
1747 context
.appendUnaryToken(tokenStackDepth
, m_token
.m_type
, tokenStart(), tokenLine(), tokenLineStart());
1749 m_nonTrivialExpressionCount
++;
1751 int subExprStart
= tokenStart();
1752 int subExprLine
= tokenLine();
1753 int subExprLineStartPosition
= tokenLineStart();
1754 ASSERT(subExprStart
>= subExprLineStartPosition
);
1755 JSTokenLocation
location(tokenLocation());
1756 TreeExpression expr
= parseMemberExpression(context
);
1758 bool isEvalOrArguments
= false;
1759 if (strictMode() && !m_syntaxAlreadyValidated
) {
1760 if (context
.isResolve(expr
))
1761 isEvalOrArguments
= *m_lastIdentifier
== m_vm
->propertyNames
->eval
|| *m_lastIdentifier
== m_vm
->propertyNames
->arguments
;
1763 failIfTrueIfStrictWithNameAndMessage(isEvalOrArguments
&& modifiesExpr
, "'", m_lastIdentifier
->impl(), "' cannot be modified in strict mode");
1764 switch (m_token
.m_type
) {
1766 m_nonTrivialExpressionCount
++;
1768 expr
= context
.makePostfixNode(location
, expr
, OpPlusPlus
, subExprStart
, lastTokenEnd(), tokenEnd(), tokenLine(), tokenLineStart());
1769 m_assignmentCount
++;
1770 failIfTrueIfStrictWithNameAndMessage(isEvalOrArguments
, "'", m_lastIdentifier
->impl(), "' cannot be modified in strict mode");
1771 failIfTrueIfStrict(requiresLExpr
);
1775 m_nonTrivialExpressionCount
++;
1777 expr
= context
.makePostfixNode(location
, expr
, OpMinusMinus
, subExprStart
, lastTokenEnd(), tokenEnd(), tokenLine(), tokenLineStart());
1778 m_assignmentCount
++;
1779 failIfTrueIfStrictWithNameAndMessage(isEvalOrArguments
, "'", m_lastIdentifier
->impl(), "' cannot be modified in strict mode");
1780 failIfTrueIfStrict(requiresLExpr
);
1787 int end
= lastTokenEnd();
1788 int endLine
= lastTokenLine();
1789 int endLineStartPosition
= lastTokenLineStart();
1791 if (!TreeBuilder::CreatesAST
&& (m_syntaxAlreadyValidated
|| !strictMode()))
1794 location
= tokenLocation();
1795 location
.line
= m_lexer
->lastLineNumber();
1796 while (tokenStackDepth
) {
1797 switch (context
.unaryTokenStackLastType(tokenStackDepth
)) {
1799 expr
= context
.createLogicalNot(location
, expr
);
1802 expr
= context
.makeBitwiseNotNode(location
, expr
);
1805 expr
= context
.makeNegateNode(location
, expr
);
1808 expr
= context
.createUnaryPlus(location
, expr
);
1812 expr
= context
.makePrefixNode(location
, expr
, OpPlusPlus
, context
.unaryTokenStackLastStart(tokenStackDepth
), subExprStart
+ 1, end
, subExprLine
, subExprLineStartPosition
);
1813 m_assignmentCount
++;
1816 case AUTOMINUSMINUS
:
1817 expr
= context
.makePrefixNode(location
, expr
, OpMinusMinus
, context
.unaryTokenStackLastStart(tokenStackDepth
), subExprStart
+ 1, end
, subExprLine
, subExprLineStartPosition
);
1818 m_assignmentCount
++;
1821 expr
= context
.makeTypeOfNode(location
, expr
);
1824 expr
= context
.createVoid(location
, expr
);
1827 failIfTrueIfStrictWithNameAndMessage(context
.isResolve(expr
), "Cannot delete unqualified property", m_lastIdentifier
->impl(), "in strict mode");
1828 expr
= context
.makeDeleteNode(location
, expr
, context
.unaryTokenStackLastStart(tokenStackDepth
), end
, end
, endLine
, endLineStartPosition
);
1831 // If we get here something has gone horribly horribly wrong
1834 subExprStart
= context
.unaryTokenStackLastStart(tokenStackDepth
);
1835 subExprLineStartPosition
= context
.unaryTokenStackLastLineStartPosition(tokenStackDepth
);
1836 context
.unaryTokenStackRemoveLast(tokenStackDepth
);
1841 // Instantiate the two flavors of Parser we need instead of putting most of this file in Parser.h
1842 template class Parser
< Lexer
<LChar
> >;
1843 template class Parser
< Lexer
<UChar
> >;