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>
38
#define fail() do { if (!m_error) updateErrorMessage(); return 0; } while (0)
39
#define failWithToken(tok) do { if (!m_error) updateErrorMessage(tok); return 0; } while (0)
40
#define failWithMessage(msg) do { if (!m_error) updateErrorMessage(msg); return 0; } while (0)
41
#define failWithNameAndMessage(before, name, after) do { if (!m_error) updateErrorWithNameAndMessage(before, name, after); return 0; } while (0)
42
#define failWithStackOverflow() do { m_error = true; m_hasStackOverflow = true; return 0; } while (0)
43
#define failIfFalse(cond) do { if (!(cond)) fail(); } while (0)
44
#define failIfFalseWithMessage(cond, msg) do { if (!(cond)) failWithMessage(msg); } while (0)
45
#define failIfFalseWithNameAndMessage(cond, before, name, msg) do { if (!(cond)) failWithNameAndMessage(before, name, msg); } while (0)
46
#define failIfTrue(cond) do { if ((cond)) fail(); } while (0)
47
#define failIfTrueWithMessage(cond, msg) do { if ((cond)) failWithMessage(msg); } while (0)
48
#define failIfTrueWithNameAndMessage(cond, before, name, msg) do { if ((cond)) failWithNameAndMessage(before, name, msg); } while (0)
49
#define failIfTrueIfStrict(cond) do { if ((cond) && strictMode()) fail(); } while (0)
50
#define failIfTrueIfStrictWithMessage(cond, msg) do { if ((cond) && strictMode()) failWithMessage(msg); } while (0)
51
#define failIfTrueIfStrictWithNameAndMessage(cond, before, name, after) do { if ((cond) && strictMode()) failWithNameAndMessage(before, name, after); } while (0)
52
#define failIfFalseIfStrict(cond) do { if ((!(cond)) && strictMode()) fail(); } while (0)
53
#define failIfFalseIfStrictWithMessage(cond, msg) do { if ((!(cond)) && strictMode()) failWithMessage(msg); } while (0)
54
#define failIfFalseIfStrictWithNameAndMessage(cond, before, name, after) do { if ((!(cond)) && strictMode()) failWithNameAndMessage(before, name, after); } while (0)
55
#define consumeOrFail(tokenType) do { if (!consume(tokenType)) failWithToken(tokenType); } while (0)
56
#define consumeOrFailWithFlags(tokenType, flags) do { if (!consume(tokenType, flags)) failWithToken(tokenType); } while (0)
57
#define matchOrFail(tokenType) do { if (!match(tokenType)) failWithToken(tokenType); } while (0)
58
#define failIfStackOverflow() do { if (!canRecurse()) failWithStackOverflow(); } while (0)
64
template <typename LexerType>
65
Parser<LexerType>::Parser(JSGlobalData* globalData, const SourceCode& source, FunctionParameters* parameters, const Identifier& name, JSParserStrictness strictness, JSParserMode parserMode)
66
: m_globalData(globalData)
68
, m_stack(wtfThreadData().stack())
69
, m_hasStackOverflow(false)
71
, m_errorMessage("Parse error")
75
, m_assignmentCount(0)
77
, m_syntaxAlreadyValidated(source.provider()->isValid())
79
, m_nonTrivialExpressionCount(0)
83
m_lexer = adoptPtr(new LexerType(globalData));
84
m_arena = m_globalData->parserArena.get();
85
m_lexer->setCode(source, m_arena);
87
m_functionCache = source.provider()->cache();
88
ScopeRef scope = pushScope();
89
if (parserMode == JSParseFunctionCode)
90
scope->setIsFunction();
91
if (strictness == JSParseStrict)
92
scope->setStrictMode();
94
for (unsigned i = 0; i < parameters->size(); i++)
95
scope->declareParameter(¶meters->at(i));
98
scope->declareCallee(&name);
100
m_lexer->setLastLineNumber(tokenLine());
103
template <typename LexerType>
104
Parser<LexerType>::~Parser()
108
template <typename LexerType>
109
String Parser<LexerType>::parseInner()
111
String parseError = String();
113
unsigned oldFunctionCacheSize = m_functionCache ? m_functionCache->byteSize() : 0;
114
ASTBuilder context(const_cast<JSGlobalData*>(m_globalData), const_cast<SourceCode*>(m_source));
115
if (m_lexer->isReparsing())
117
ScopeRef scope = currentScope();
118
SourceElements* sourceElements = parseSourceElements<CheckForStrictMode>(context);
119
if (!sourceElements || !consume(EOFTOK))
120
parseError = m_errorMessage;
122
IdentifierSet capturedVariables;
123
scope->getCapturedVariables(capturedVariables);
124
CodeFeatures features = context.features();
125
if (scope->strictMode())
126
features |= StrictModeFeature;
127
if (scope->shadowsArguments())
128
features |= ShadowsArgumentsFeature;
129
unsigned functionCacheSize = m_functionCache ? m_functionCache->byteSize() : 0;
130
if (functionCacheSize != oldFunctionCacheSize)
131
m_lexer->sourceProvider()->notifyCacheSizeChanged(functionCacheSize - oldFunctionCacheSize);
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 oldLastLineNumber = m_lexer->lastLineNumber();
168
unsigned oldLineNumber = m_lexer->lineNumber();
169
bool hasSetStrict = false;
170
while (TreeStatement statement = parseStatement(context, directive, &directiveLiteralLength)) {
171
if (mode == CheckForStrictMode && !seenNonDirective) {
173
// "use strict" must be the exact literal without escape sequences or line continuation.
174
if (!hasSetStrict && directiveLiteralLength == lengthOfUseStrictLiteral && m_globalData->propertyNames->useStrictIdentifier == *directive) {
177
failIfFalse(isValidStrictMode());
178
m_lexer->setOffset(startOffset);
180
m_lexer->setLastLineNumber(oldLastLineNumber);
181
m_lexer->setLineNumber(oldLineNumber);
186
seenNonDirective = true;
188
context.appendStatement(sourceElements, statement);
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);
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);
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
initStart = tokenStart();
292
next(TreeBuilder::DontBuildStrings); // consume '='
293
TreeExpression initializer = parseAssignmentExpression(context);
294
initEnd = lastTokenEnd();
295
lastInitializer = initializer;
296
failIfFalse(initializer);
298
TreeExpression node = context.createAssignResolve(location, *name, initializer, varStart, varDivot, lastTokenEnd());
302
varDecls = context.combineCommaNodes(location, varDecls, node);
304
} while (match(COMMA));
308
template <typename LexerType>
309
template <class TreeBuilder> TreeConstDeclList Parser<LexerType>::parseConstDeclarationList(TreeBuilder& context)
311
failIfTrue(strictMode());
312
TreeConstDeclList constDecls = 0;
313
TreeConstDeclList tail = 0;
315
JSTokenLocation location(tokenLocation());
318
const Identifier* name = m_token.m_data.ident;
320
bool hasInitializer = match(EQUAL);
321
declareVariable(name);
322
context.addVar(name, DeclarationStacks::IsConstant | (hasInitializer ? DeclarationStacks::HasInitializer : 0));
323
TreeExpression initializer = 0;
324
if (hasInitializer) {
325
next(TreeBuilder::DontBuildStrings); // consume '='
326
initializer = parseAssignmentExpression(context);
328
tail = context.appendConstDecl(location, tail, name, initializer);
331
} while (match(COMMA));
335
template <typename LexerType>
336
template <class TreeBuilder> TreeStatement Parser<LexerType>::parseForStatement(TreeBuilder& context)
339
JSTokenLocation location(tokenLocation());
340
int startLine = tokenLine();
342
consumeOrFail(OPENPAREN);
343
int nonLHSCount = m_nonLHSCount;
344
int declarations = 0;
347
TreeExpression decls = 0;
350
for (var IDENT in expression) statement
351
for (var IDENT = expression in expression) statement
352
for (var varDeclarationList; expressionOpt; expressionOpt)
354
const Identifier* forInTarget = 0;
355
TreeExpression forInInitializer = 0;
359
decls = parseVarDeclarationList(context, declarations, forInTarget, forInInitializer, declsStart, initStart, initEnd);
364
// Remainder of a standard for loop is handled identically
365
if (match(SEMICOLON))
366
goto standardForLoop;
368
failIfFalse(declarations == 1);
370
// Handle for-in with var declaration
371
int inLocation = tokenStart();
372
consumeOrFail(INTOKEN);
374
TreeExpression expr = parseExpression(context);
376
int exprEnd = lastTokenEnd();
378
int endLine = tokenLine();
379
consumeOrFail(CLOSEPAREN);
381
const Identifier* unused = 0;
383
TreeStatement statement = parseStatement(context, unused);
385
failIfFalse(statement);
387
return context.createForInLoop(location, forInTarget, forInInitializer, expr, statement, declsStart, inLocation, exprEnd, initStart, initEnd, startLine, endLine);
390
if (!match(SEMICOLON)) {
392
declsStart = tokenStart();
393
decls = parseExpression(context);
394
declsEnd = lastTokenEnd();
399
if (match(SEMICOLON)) {
403
TreeExpression condition = 0;
405
if (!match(SEMICOLON)) {
406
condition = parseExpression(context);
407
failIfFalse(condition);
409
consumeOrFail(SEMICOLON);
411
TreeExpression increment = 0;
412
if (!match(CLOSEPAREN)) {
413
increment = parseExpression(context);
414
failIfFalse(increment);
416
int endLine = tokenLine();
417
consumeOrFail(CLOSEPAREN);
418
const Identifier* unused = 0;
420
TreeStatement statement = parseStatement(context, unused);
422
failIfFalse(statement);
423
return context.createForLoop(location, decls, condition, increment, statement, startLine, endLine);
427
failIfFalse(nonLHSCount == m_nonLHSCount);
428
consumeOrFail(INTOKEN);
429
TreeExpression expr = parseExpression(context);
431
int exprEnd = lastTokenEnd();
432
int endLine = tokenLine();
433
consumeOrFail(CLOSEPAREN);
434
const Identifier* unused = 0;
436
TreeStatement statement = parseStatement(context, unused);
438
failIfFalse(statement);
440
return context.createForInLoop(location, decls, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine);
443
template <typename LexerType>
444
template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBreakStatement(TreeBuilder& context)
446
ASSERT(match(BREAK));
447
JSTokenLocation location(tokenLocation());
448
int startCol = tokenStart();
449
int endCol = tokenEnd();
450
int startLine = tokenLine();
451
int endLine = tokenLine();
454
if (autoSemiColon()) {
455
failIfFalseWithMessage(breakIsValid(), "'break' is only valid inside a switch or loop statement");
456
return context.createBreakStatement(location, startCol, endCol, startLine, endLine);
459
const Identifier* ident = m_token.m_data.ident;
460
failIfFalseWithNameAndMessage(getLabel(ident), "Label", ident->impl(), "is not defined");
462
endLine = tokenLine();
464
failIfFalse(autoSemiColon());
465
return context.createBreakStatement(location, ident, startCol, endCol, startLine, endLine);
468
template <typename LexerType>
469
template <class TreeBuilder> TreeStatement Parser<LexerType>::parseContinueStatement(TreeBuilder& context)
471
ASSERT(match(CONTINUE));
472
JSTokenLocation location(tokenLocation());
473
int startCol = tokenStart();
474
int endCol = tokenEnd();
475
int startLine = tokenLine();
476
int endLine = tokenLine();
479
if (autoSemiColon()) {
480
failIfFalseWithMessage(continueIsValid(), "'continue' is only valid inside a loop statement");
481
return context.createContinueStatement(location, startCol, endCol, startLine, endLine);
484
const Identifier* ident = m_token.m_data.ident;
485
ScopeLabelInfo* label = getLabel(ident);
486
failIfFalseWithNameAndMessage(label, "Label", ident->impl(), "is not defined");
487
failIfFalseWithMessage(label->m_isLoop, "'continue' is only valid inside a loop statement");
489
endLine = tokenLine();
491
failIfFalse(autoSemiColon());
492
return context.createContinueStatement(location, ident, startCol, endCol, startLine, endLine);
495
template <typename LexerType>
496
template <class TreeBuilder> TreeStatement Parser<LexerType>::parseReturnStatement(TreeBuilder& context)
498
ASSERT(match(RETURN));
499
JSTokenLocation location(tokenLocation());
500
failIfFalse(currentScope()->isFunction());
501
int startLine = tokenLine();
502
int endLine = startLine;
503
int start = tokenStart();
504
int end = tokenEnd();
506
// We do the auto semicolon check before attempting to parse an expression
507
// as we need to ensure the a line break after the return correctly terminates
509
if (match(SEMICOLON))
510
endLine = tokenLine();
512
return context.createReturnStatement(location, 0, start, end, startLine, endLine);
513
TreeExpression expr = parseExpression(context);
515
end = lastTokenEnd();
516
if (match(SEMICOLON))
517
endLine = tokenLine();
518
failIfFalse(autoSemiColon());
519
return context.createReturnStatement(location, expr, start, end, startLine, endLine);
522
template <typename LexerType>
523
template <class TreeBuilder> TreeStatement Parser<LexerType>::parseThrowStatement(TreeBuilder& context)
525
ASSERT(match(THROW));
526
JSTokenLocation location(tokenLocation());
527
int eStart = tokenStart();
528
int startLine = tokenLine();
531
failIfTrue(autoSemiColon());
533
TreeExpression expr = parseExpression(context);
535
int eEnd = lastTokenEnd();
536
int endLine = tokenLine();
537
failIfFalse(autoSemiColon());
539
return context.createThrowStatement(location, expr, eStart, eEnd, startLine, endLine);
542
template <typename LexerType>
543
template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWithStatement(TreeBuilder& context)
546
JSTokenLocation location(tokenLocation());
547
failIfTrueWithMessage(strictMode(), "'with' statements are not valid in strict mode");
548
currentScope()->setNeedsFullActivation();
549
int startLine = tokenLine();
551
consumeOrFail(OPENPAREN);
552
int start = tokenStart();
553
TreeExpression expr = parseExpression(context);
555
int end = lastTokenEnd();
557
int endLine = tokenLine();
558
consumeOrFail(CLOSEPAREN);
559
const Identifier* unused = 0;
560
TreeStatement statement = parseStatement(context, unused);
561
failIfFalse(statement);
563
return context.createWithStatement(location, expr, statement, start, end, startLine, endLine);
566
template <typename LexerType>
567
template <class TreeBuilder> TreeStatement Parser<LexerType>::parseSwitchStatement(TreeBuilder& context)
569
ASSERT(match(SWITCH));
570
JSTokenLocation location(tokenLocation());
571
int startLine = tokenLine();
573
consumeOrFail(OPENPAREN);
574
TreeExpression expr = parseExpression(context);
576
int endLine = tokenLine();
577
consumeOrFail(CLOSEPAREN);
578
consumeOrFail(OPENBRACE);
580
TreeClauseList firstClauses = parseSwitchClauses(context);
583
TreeClause defaultClause = parseSwitchDefaultClause(context);
586
TreeClauseList secondClauses = parseSwitchClauses(context);
589
consumeOrFail(CLOSEBRACE);
591
return context.createSwitchStatement(location, expr, firstClauses, defaultClause, secondClauses, startLine, endLine);
595
template <typename LexerType>
596
template <class TreeBuilder> TreeClauseList Parser<LexerType>::parseSwitchClauses(TreeBuilder& context)
601
TreeExpression condition = parseExpression(context);
602
failIfFalse(condition);
603
consumeOrFail(COLON);
604
TreeSourceElements statements = parseSourceElements<DontCheckForStrictMode>(context);
605
failIfFalse(statements);
606
TreeClause clause = context.createClause(condition, statements);
607
TreeClauseList clauseList = context.createClauseList(clause);
608
TreeClauseList tail = clauseList;
610
while (match(CASE)) {
612
TreeExpression condition = parseExpression(context);
613
failIfFalse(condition);
614
consumeOrFail(COLON);
615
TreeSourceElements statements = parseSourceElements<DontCheckForStrictMode>(context);
616
failIfFalse(statements);
617
clause = context.createClause(condition, statements);
618
tail = context.createClauseList(tail, clause);
623
template <typename LexerType>
624
template <class TreeBuilder> TreeClause Parser<LexerType>::parseSwitchDefaultClause(TreeBuilder& context)
629
consumeOrFail(COLON);
630
TreeSourceElements statements = parseSourceElements<DontCheckForStrictMode>(context);
631
failIfFalse(statements);
632
return context.createClause(0, statements);
635
template <typename LexerType>
636
template <class TreeBuilder> TreeStatement Parser<LexerType>::parseTryStatement(TreeBuilder& context)
639
JSTokenLocation location(tokenLocation());
640
TreeStatement tryBlock = 0;
641
const Identifier* ident = &m_globalData->propertyNames->nullIdentifier;
642
TreeStatement catchBlock = 0;
643
TreeStatement finallyBlock = 0;
644
int firstLine = tokenLine();
646
matchOrFail(OPENBRACE);
648
tryBlock = parseBlockStatement(context);
649
failIfFalse(tryBlock);
650
int lastLine = m_lastLine;
653
currentScope()->setNeedsFullActivation();
655
consumeOrFail(OPENPAREN);
657
ident = m_token.m_data.ident;
659
AutoPopScopeRef catchScope(this, pushScope());
660
failIfFalseIfStrictWithNameAndMessage(declareVariable(ident), "Cannot declare a variable named", ident->impl(), "in strict mode");
661
catchScope->preventNewDecls();
662
consumeOrFail(CLOSEPAREN);
663
matchOrFail(OPENBRACE);
664
catchBlock = parseBlockStatement(context);
665
failIfFalseWithMessage(catchBlock, "'try' must have a catch or finally block");
666
failIfFalse(popScope(catchScope, TreeBuilder::NeedsFreeVariableInfo));
669
if (match(FINALLY)) {
671
matchOrFail(OPENBRACE);
672
finallyBlock = parseBlockStatement(context);
673
failIfFalse(finallyBlock);
675
failIfFalse(catchBlock || finallyBlock);
676
return context.createTryStatement(location, tryBlock, ident, catchBlock, finallyBlock, firstLine, lastLine);
679
template <typename LexerType>
680
template <class TreeBuilder> TreeStatement Parser<LexerType>::parseDebuggerStatement(TreeBuilder& context)
682
ASSERT(match(DEBUGGER));
683
JSTokenLocation location(tokenLocation());
684
int startLine = tokenLine();
685
int endLine = startLine;
687
if (match(SEMICOLON))
688
startLine = tokenLine();
689
failIfFalse(autoSemiColon());
690
return context.createDebugger(location, startLine, endLine);
693
template <typename LexerType>
694
template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBlockStatement(TreeBuilder& context)
696
ASSERT(match(OPENBRACE));
697
JSTokenLocation location(tokenLocation());
698
int start = tokenLine();
700
if (match(CLOSEBRACE)) {
702
return context.createBlockStatement(location, 0, start, m_lastLine);
704
TreeSourceElements subtree = parseSourceElements<DontCheckForStrictMode>(context);
705
failIfFalse(subtree);
706
matchOrFail(CLOSEBRACE);
708
return context.createBlockStatement(location, subtree, start, m_lastLine);
711
template <typename LexerType>
712
template <class TreeBuilder> TreeStatement Parser<LexerType>::parseStatement(TreeBuilder& context, const Identifier*& directive, unsigned* directiveLiteralLength)
714
DepthManager statementDepth(&m_statementDepth);
717
int nonTrivialExpressionCount = 0;
718
failIfStackOverflow();
719
switch (m_token.m_type) {
721
return parseBlockStatement(context);
723
return parseVarDeclaration(context);
725
return parseConstDeclaration(context);
727
failIfFalseIfStrictWithMessage(m_statementDepth == 1, "Functions cannot be declared in a nested block in strict mode");
728
return parseFunctionDeclaration(context);
730
JSTokenLocation location(tokenLocation());
732
return context.createEmptyStatement(location);
735
return parseIfStatement(context);
737
return parseDoWhileStatement(context);
739
return parseWhileStatement(context);
741
return parseForStatement(context);
743
return parseContinueStatement(context);
745
return parseBreakStatement(context);
747
return parseReturnStatement(context);
749
return parseWithStatement(context);
751
return parseSwitchStatement(context);
753
return parseThrowStatement(context);
755
return parseTryStatement(context);
757
return parseDebuggerStatement(context);
762
// These tokens imply the end of a set of source elements
765
return parseExpressionOrLabelStatement(context);
767
directive = m_token.m_data.ident;
768
if (directiveLiteralLength)
769
*directiveLiteralLength = m_token.m_location.endOffset - m_token.m_location.startOffset;
770
nonTrivialExpressionCount = m_nonTrivialExpressionCount;
772
TreeStatement exprStatement = parseExpressionStatement(context);
773
if (directive && nonTrivialExpressionCount != m_nonTrivialExpressionCount)
775
return exprStatement;
779
template <typename LexerType>
780
template <class TreeBuilder> TreeFormalParameterList Parser<LexerType>::parseFormalParameters(TreeBuilder& context)
783
failIfFalseIfStrictWithNameAndMessage(declareParameter(m_token.m_data.ident), "Cannot declare a parameter named", m_token.m_data.ident->impl(), " in strict mode");
784
TreeFormalParameterList list = context.createFormalParameterList(*m_token.m_data.ident);
785
TreeFormalParameterList tail = list;
787
while (match(COMMA)) {
790
const Identifier* ident = m_token.m_data.ident;
791
failIfFalseIfStrictWithNameAndMessage(declareParameter(ident), "Cannot declare a parameter named", ident->impl(), "in strict mode");
793
tail = context.createFormalParameterList(tail, *ident);
798
template <typename LexerType>
799
template <class TreeBuilder> TreeFunctionBody Parser<LexerType>::parseFunctionBody(TreeBuilder& context)
801
if (match(CLOSEBRACE))
802
return context.createFunctionBody(tokenLocation(), strictMode());
803
DepthManager statementDepth(&m_statementDepth);
804
m_statementDepth = 0;
805
typename TreeBuilder::FunctionBodyBuilder bodyBuilder(const_cast<JSGlobalData*>(m_globalData), m_lexer.get());
806
failIfFalse(parseSourceElements<CheckForStrictMode>(bodyBuilder));
807
return context.createFunctionBody(tokenLocation(), strictMode());
810
template <typename LexerType>
811
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)
813
AutoPopScopeRef functionScope(this, pushScope());
814
functionScope->setIsFunction();
815
int functionStart = m_token.m_location.startOffset;
817
name = m_token.m_data.ident;
819
if (!nameIsInContainingScope)
820
failIfFalseIfStrict(functionScope->declareVariable(name));
821
} else if (requirements == FunctionNeedsName)
823
consumeOrFail(OPENPAREN);
824
if (!match(CLOSEPAREN)) {
825
parameters = parseFormalParameters(context);
826
failIfFalse(parameters);
828
consumeOrFail(CLOSEPAREN);
829
matchOrFail(OPENBRACE);
831
openBracePos = m_token.m_data.intValue;
832
bodyStartLine = tokenLine();
833
JSTokenLocation location(tokenLocation());
835
// If we know about this function already, we can use the cached info and skip the parser to the end of the function.
836
if (const SourceProviderCacheItem* cachedInfo = TreeBuilder::CanUseFunctionCache ? findCachedFunctionInfo(openBracePos) : 0) {
837
// If we're in a strict context, the cached function info must say it was strict too.
838
ASSERT(!strictMode() || cachedInfo->strictMode);
839
body = context.createFunctionBody(location, cachedInfo->strictMode);
841
functionScope->restoreFunctionInfo(cachedInfo);
842
failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo));
844
closeBracePos = cachedInfo->closeBracePos;
845
m_token = cachedInfo->closeBraceToken();
846
m_lexer->setOffset(m_token.m_location.endOffset);
847
m_lexer->setLineNumber(m_token.m_location.line);
855
body = parseFunctionBody(context);
857
if (functionScope->strictMode() && name) {
858
failIfTrueWithNameAndMessage(m_globalData->propertyNames->arguments == *name, "Function name", name->impl(), "is not valid in strict mode");
859
failIfTrueWithNameAndMessage(m_globalData->propertyNames->eval == *name, "Function name", name->impl(), "is not valid in strict mode");
861
closeBracePos = m_token.m_data.intValue;
863
// Cache the tokenizer state and the function scope the first time the function is parsed.
864
// Any future reparsing can then skip the function.
865
static const int minimumFunctionLengthToCache = 64;
866
OwnPtr<SourceProviderCacheItem> newInfo;
867
int functionLength = closeBracePos - openBracePos;
868
if (TreeBuilder::CanUseFunctionCache && m_functionCache && functionLength > minimumFunctionLengthToCache) {
869
newInfo = adoptPtr(new SourceProviderCacheItem(functionStart, m_token.m_location.line, closeBracePos));
870
functionScope->saveFunctionInfo(newInfo.get());
873
failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo));
874
matchOrFail(CLOSEBRACE);
877
unsigned approximateByteSize = newInfo->approximateByteSize();
878
m_functionCache->add(openBracePos, newInfo.release(), approximateByteSize);
885
template <typename LexerType>
886
template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDeclaration(TreeBuilder& context)
888
ASSERT(match(FUNCTION));
889
JSTokenLocation location(tokenLocation());
891
const Identifier* name = 0;
892
TreeFormalParameterList parameters = 0;
893
TreeFunctionBody body = 0;
894
int openBracePos = 0;
895
int closeBracePos = 0;
896
int bodyStartLine = 0;
897
failIfFalse((parseFunctionInfo<FunctionNeedsName, true>(context, name, parameters, body, openBracePos, closeBracePos, bodyStartLine)));
899
failIfFalseIfStrict(declareVariable(name));
900
return context.createFuncDeclStatement(location, name, body, parameters, openBracePos, closeBracePos, bodyStartLine, m_lastLine);
904
LabelInfo(const Identifier* ident, int start, int end)
911
const Identifier* m_ident;
916
template <typename LexerType>
917
template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionOrLabelStatement(TreeBuilder& context)
920
/* Expression and Label statements are ambiguous at LL(1), so we have a
921
* special case that looks for a colon as the next character in the input.
923
Vector<LabelInfo> labels;
924
JSTokenLocation location;
926
int start = tokenStart();
927
int startLine = tokenLine();
928
location = tokenLocation();
929
if (!nextTokenIsColon()) {
930
// If we hit this path we're making a expression statement, which
931
// by definition can't make use of continue/break so we can just
932
// ignore any labels we might have accumulated.
933
TreeExpression expression = parseExpression(context);
934
failIfFalse(expression);
935
failIfFalse(autoSemiColon());
936
return context.createExprStatement(location, expression, startLine, m_lastLine);
938
const Identifier* ident = m_token.m_data.ident;
939
int end = tokenEnd();
941
consumeOrFail(COLON);
942
if (!m_syntaxAlreadyValidated) {
943
// This is O(N^2) over the current list of consecutive labels, but I
944
// have never seen more than one label in a row in the real world.
945
for (size_t i = 0; i < labels.size(); i++)
946
failIfTrue(ident->impl() == labels[i].m_ident->impl());
947
failIfTrue(getLabel(ident));
948
labels.append(LabelInfo(ident, start, end));
950
} while (match(IDENT));
952
switch (m_token.m_type) {
962
const Identifier* unused = 0;
963
if (!m_syntaxAlreadyValidated) {
964
for (size_t i = 0; i < labels.size(); i++)
965
pushLabel(labels[i].m_ident, isLoop);
967
TreeStatement statement = parseStatement(context, unused);
968
if (!m_syntaxAlreadyValidated) {
969
for (size_t i = 0; i < labels.size(); i++)
972
failIfFalse(statement);
973
for (size_t i = 0; i < labels.size(); i++) {
974
const LabelInfo& info = labels[labels.size() - i - 1];
975
statement = context.createLabelStatement(location, info.m_ident, statement, info.m_start, info.m_end);
980
template <typename LexerType>
981
template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionStatement(TreeBuilder& context)
983
int startLine = tokenLine();
984
JSTokenLocation location(tokenLocation());
985
TreeExpression expression = parseExpression(context);
986
failIfFalse(expression);
987
failIfFalse(autoSemiColon());
988
return context.createExprStatement(location, expression, startLine, m_lastLine);
991
template <typename LexerType>
992
template <class TreeBuilder> TreeStatement Parser<LexerType>::parseIfStatement(TreeBuilder& context)
995
JSTokenLocation ifLocation(tokenLocation());
996
int start = tokenLine();
999
consumeOrFail(OPENPAREN);
1001
TreeExpression condition = parseExpression(context);
1002
failIfFalse(condition);
1003
int end = tokenLine();
1004
consumeOrFail(CLOSEPAREN);
1006
const Identifier* unused = 0;
1007
TreeStatement trueBlock = parseStatement(context, unused);
1008
failIfFalse(trueBlock);
1011
return context.createIfStatement(ifLocation, condition, trueBlock, start, end);
1013
Vector<TreeExpression> exprStack;
1014
Vector<pair<int, int> > posStack;
1015
Vector<JSTokenLocation> tokenLocationStack;
1016
Vector<TreeStatement> statementStack;
1017
bool trailingElse = false;
1019
JSTokenLocation tempLocation = tokenLocation();
1022
const Identifier* unused = 0;
1023
TreeStatement block = parseStatement(context, unused);
1025
statementStack.append(block);
1026
trailingElse = true;
1029
int innerStart = tokenLine();
1032
consumeOrFail(OPENPAREN);
1034
TreeExpression innerCondition = parseExpression(context);
1035
failIfFalse(innerCondition);
1036
int innerEnd = tokenLine();
1037
consumeOrFail(CLOSEPAREN);
1038
const Identifier* unused = 0;
1039
TreeStatement innerTrueBlock = parseStatement(context, unused);
1040
failIfFalse(innerTrueBlock);
1041
tokenLocationStack.append(tempLocation);
1042
exprStack.append(innerCondition);
1043
posStack.append(make_pair(innerStart, innerEnd));
1044
statementStack.append(innerTrueBlock);
1045
} while (match(ELSE));
1047
if (!trailingElse) {
1048
TreeExpression condition = exprStack.last();
1049
exprStack.removeLast();
1050
TreeStatement trueBlock = statementStack.last();
1051
statementStack.removeLast();
1052
pair<int, int> pos = posStack.last();
1053
posStack.removeLast();
1054
JSTokenLocation elseLocation = tokenLocationStack.last();
1055
tokenLocationStack.removeLast();
1056
statementStack.append(context.createIfStatement(elseLocation, condition, trueBlock, pos.first, pos.second));
1059
while (!exprStack.isEmpty()) {
1060
TreeExpression condition = exprStack.last();
1061
exprStack.removeLast();
1062
TreeStatement falseBlock = statementStack.last();
1063
statementStack.removeLast();
1064
TreeStatement trueBlock = statementStack.last();
1065
statementStack.removeLast();
1066
pair<int, int> pos = posStack.last();
1067
posStack.removeLast();
1068
JSTokenLocation elseLocation = tokenLocationStack.last();
1069
tokenLocationStack.removeLast();
1070
statementStack.append(context.createIfStatement(elseLocation, condition, trueBlock, falseBlock, pos.first, pos.second));
1073
return context.createIfStatement(ifLocation, condition, trueBlock, statementStack.last(), start, end);
1076
template <typename LexerType>
1077
template <class TreeBuilder> TreeExpression Parser<LexerType>::parseExpression(TreeBuilder& context)
1079
failIfStackOverflow();
1080
JSTokenLocation location(tokenLocation());
1081
TreeExpression node = parseAssignmentExpression(context);
1086
m_nonTrivialExpressionCount++;
1088
TreeExpression right = parseAssignmentExpression(context);
1090
typename TreeBuilder::Comma commaNode = context.createCommaExpr(location, node, right);
1091
while (match(COMMA)) {
1092
next(TreeBuilder::DontBuildStrings);
1093
right = parseAssignmentExpression(context);
1095
context.appendToComma(commaNode, right);
1100
template <typename LexerType>
1101
template <typename TreeBuilder> TreeExpression Parser<LexerType>::parseAssignmentExpression(TreeBuilder& context)
1103
failIfStackOverflow();
1104
int start = tokenStart();
1105
JSTokenLocation location(tokenLocation());
1106
int initialAssignmentCount = m_assignmentCount;
1107
int initialNonLHSCount = m_nonLHSCount;
1108
TreeExpression lhs = parseConditionalExpression(context);
1110
if (initialNonLHSCount != m_nonLHSCount)
1113
int assignmentStack = 0;
1115
bool hadAssignment = false;
1117
switch (m_token.m_type) {
1118
case EQUAL: op = OpEqual; break;
1119
case PLUSEQUAL: op = OpPlusEq; break;
1120
case MINUSEQUAL: op = OpMinusEq; break;
1121
case MULTEQUAL: op = OpMultEq; break;
1122
case DIVEQUAL: op = OpDivEq; break;
1123
case LSHIFTEQUAL: op = OpLShift; break;
1124
case RSHIFTEQUAL: op = OpRShift; break;
1125
case URSHIFTEQUAL: op = OpURShift; break;
1126
case ANDEQUAL: op = OpAndEq; break;
1127
case XOREQUAL: op = OpXOrEq; break;
1128
case OREQUAL: op = OpOrEq; break;
1129
case MODEQUAL: op = OpModEq; break;
1133
m_nonTrivialExpressionCount++;
1134
hadAssignment = true;
1135
context.assignmentStackAppend(assignmentStack, lhs, start, tokenStart(), m_assignmentCount, op);
1136
start = tokenStart();
1137
m_assignmentCount++;
1138
next(TreeBuilder::DontBuildStrings);
1139
if (strictMode() && m_lastIdentifier && context.isResolve(lhs)) {
1140
failIfTrueIfStrictWithMessage(m_globalData->propertyNames->eval == *m_lastIdentifier, "'eval' cannot be modified in strict mode");
1141
failIfTrueIfStrictWithMessage(m_globalData->propertyNames->arguments == *m_lastIdentifier, "'arguments' cannot be modified in strict mode");
1142
declareWrite(m_lastIdentifier);
1143
m_lastIdentifier = 0;
1145
lhs = parseConditionalExpression(context);
1147
if (initialNonLHSCount != m_nonLHSCount)
1154
if (!TreeBuilder::CreatesAST)
1157
while (assignmentStack)
1158
lhs = context.createAssignment(location, assignmentStack, lhs, initialAssignmentCount, m_assignmentCount, lastTokenEnd());
1163
template <typename LexerType>
1164
template <class TreeBuilder> TreeExpression Parser<LexerType>::parseConditionalExpression(TreeBuilder& context)
1166
JSTokenLocation location(tokenLocation());
1167
TreeExpression cond = parseBinaryExpression(context);
1169
if (!match(QUESTION))
1171
m_nonTrivialExpressionCount++;
1173
next(TreeBuilder::DontBuildStrings);
1174
TreeExpression lhs = parseAssignmentExpression(context);
1175
consumeOrFailWithFlags(COLON, TreeBuilder::DontBuildStrings);
1177
TreeExpression rhs = parseAssignmentExpression(context);
1179
return context.createConditionalExpr(location, cond, lhs, rhs);
1182
ALWAYS_INLINE static bool isUnaryOp(JSTokenType token)
1184
return token & UnaryOpTokenFlag;
1187
template <typename LexerType>
1188
int Parser<LexerType>::isBinaryOperator(JSTokenType token)
1191
return token & (BinaryOpTokenPrecedenceMask << BinaryOpTokenAllowsInPrecedenceAdditionalShift);
1192
return token & BinaryOpTokenPrecedenceMask;
1195
template <typename LexerType>
1196
template <class TreeBuilder> TreeExpression Parser<LexerType>::parseBinaryExpression(TreeBuilder& context)
1199
int operandStackDepth = 0;
1200
int operatorStackDepth = 0;
1201
typename TreeBuilder::BinaryExprContext binaryExprContext(context);
1202
JSTokenLocation location(tokenLocation());
1204
int exprStart = tokenStart();
1205
int initialAssignments = m_assignmentCount;
1206
TreeExpression current = parseUnaryExpression(context);
1207
failIfFalse(current);
1209
context.appendBinaryExpressionInfo(operandStackDepth, current, exprStart, lastTokenEnd(), lastTokenEnd(), initialAssignments != m_assignmentCount);
1210
int precedence = isBinaryOperator(m_token.m_type);
1213
m_nonTrivialExpressionCount++;
1215
int operatorToken = m_token.m_type;
1216
next(TreeBuilder::DontBuildStrings);
1218
while (operatorStackDepth && context.operatorStackHasHigherPrecedence(operatorStackDepth, precedence)) {
1219
ASSERT(operandStackDepth > 1);
1221
typename TreeBuilder::BinaryOperand rhs = context.getFromOperandStack(-1);
1222
typename TreeBuilder::BinaryOperand lhs = context.getFromOperandStack(-2);
1223
context.shrinkOperandStackBy(operandStackDepth, 2);
1224
context.appendBinaryOperation(location, operandStackDepth, operatorStackDepth, lhs, rhs);
1225
context.operatorStackPop(operatorStackDepth);
1227
context.operatorStackAppend(operatorStackDepth, operatorToken, precedence);
1229
while (operatorStackDepth) {
1230
ASSERT(operandStackDepth > 1);
1232
typename TreeBuilder::BinaryOperand rhs = context.getFromOperandStack(-1);
1233
typename TreeBuilder::BinaryOperand lhs = context.getFromOperandStack(-2);
1234
context.shrinkOperandStackBy(operandStackDepth, 2);
1235
context.appendBinaryOperation(location, operandStackDepth, operatorStackDepth, lhs, rhs);
1236
context.operatorStackPop(operatorStackDepth);
1238
return context.popOperandStack(operandStackDepth);
1241
template <typename LexerType>
1242
template <bool complete, class TreeBuilder> TreeProperty Parser<LexerType>::parseProperty(TreeBuilder& context)
1244
bool wasIdent = false;
1245
switch (m_token.m_type) {
1250
const Identifier* ident = m_token.m_data.ident;
1251
if (complete || (wasIdent && (*ident == m_globalData->propertyNames->get || *ident == m_globalData->propertyNames->set)))
1252
nextExpectIdentifier(LexerFlagsIgnoreReservedWords);
1254
nextExpectIdentifier(LexerFlagsIgnoreReservedWords | TreeBuilder::DontBuildKeywords);
1258
TreeExpression node = parseAssignmentExpression(context);
1260
return context.template createProperty<complete>(ident, node, PropertyNode::Constant);
1262
failIfFalse(wasIdent);
1263
const Identifier* accessorName = 0;
1264
TreeFormalParameterList parameters = 0;
1265
TreeFunctionBody body = 0;
1266
int openBracePos = 0;
1267
int closeBracePos = 0;
1268
int bodyStartLine = 0;
1269
PropertyNode::Type type;
1270
if (*ident == m_globalData->propertyNames->get)
1271
type = PropertyNode::Getter;
1272
else if (*ident == m_globalData->propertyNames->set)
1273
type = PropertyNode::Setter;
1276
const Identifier* stringPropertyName = 0;
1277
double numericPropertyName = 0;
1278
if (m_token.m_type == IDENT || m_token.m_type == STRING)
1279
stringPropertyName = m_token.m_data.ident;
1280
else if (m_token.m_type == NUMBER)
1281
numericPropertyName = m_token.m_data.doubleValue;
1284
JSTokenLocation location(tokenLocation());
1286
failIfFalse((parseFunctionInfo<FunctionNoRequirements, false>(context, accessorName, parameters, body, openBracePos, closeBracePos, bodyStartLine)));
1287
if (stringPropertyName)
1288
return context.template createGetterOrSetterProperty<complete>(location, type, stringPropertyName, parameters, body, openBracePos, closeBracePos, bodyStartLine, m_lastLine);
1289
return context.template createGetterOrSetterProperty<complete>(const_cast<JSGlobalData*>(m_globalData), location, type, numericPropertyName, parameters, body, openBracePos, closeBracePos, bodyStartLine, m_lastLine);
1292
double propertyName = m_token.m_data.doubleValue;
1294
consumeOrFail(COLON);
1295
TreeExpression node = parseAssignmentExpression(context);
1297
return context.template createProperty<complete>(const_cast<JSGlobalData*>(m_globalData), propertyName, node, PropertyNode::Constant);
1300
failIfFalse(m_token.m_type & KeywordTokenFlag);
1305
template <typename LexerType>
1306
template <class TreeBuilder> TreeExpression Parser<LexerType>::parseObjectLiteral(TreeBuilder& context)
1308
int startOffset = m_token.m_data.intValue;
1309
unsigned oldLastLineNumber = m_lexer->lastLineNumber();
1310
unsigned oldLineNumber = m_lexer->lineNumber();
1311
consumeOrFailWithFlags(OPENBRACE, TreeBuilder::DontBuildStrings);
1312
JSTokenLocation location(tokenLocation());
1314
int oldNonLHSCount = m_nonLHSCount;
1316
if (match(CLOSEBRACE)) {
1318
return context.createObjectLiteral(location);
1321
TreeProperty property = parseProperty<false>(context);
1322
failIfFalse(property);
1323
if (!m_syntaxAlreadyValidated && context.getType(property) != PropertyNode::Constant) {
1324
m_lexer->setOffset(startOffset);
1326
m_lexer->setLastLineNumber(oldLastLineNumber);
1327
m_lexer->setLineNumber(oldLineNumber);
1328
return parseStrictObjectLiteral(context);
1330
TreePropertyList propertyList = context.createPropertyList(location, property);
1331
TreePropertyList tail = propertyList;
1332
while (match(COMMA)) {
1333
next(TreeBuilder::DontBuildStrings);
1334
// allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939
1335
if (match(CLOSEBRACE))
1337
JSTokenLocation propertyLocation(tokenLocation());
1338
property = parseProperty<false>(context);
1339
failIfFalse(property);
1340
if (!m_syntaxAlreadyValidated && context.getType(property) != PropertyNode::Constant) {
1341
m_lexer->setOffset(startOffset);
1343
m_lexer->setLastLineNumber(oldLastLineNumber);
1344
m_lexer->setLineNumber(oldLineNumber);
1345
return parseStrictObjectLiteral(context);
1347
tail = context.createPropertyList(propertyLocation, property, tail);
1350
location = tokenLocation();
1351
consumeOrFail(CLOSEBRACE);
1353
m_nonLHSCount = oldNonLHSCount;
1355
return context.createObjectLiteral(location, propertyList);
1358
template <typename LexerType>
1359
template <class TreeBuilder> TreeExpression Parser<LexerType>::parseStrictObjectLiteral(TreeBuilder& context)
1361
consumeOrFail(OPENBRACE);
1363
int oldNonLHSCount = m_nonLHSCount;
1365
JSTokenLocation location(tokenLocation());
1366
if (match(CLOSEBRACE)) {
1368
return context.createObjectLiteral(location);
1371
TreeProperty property = parseProperty<true>(context);
1372
failIfFalse(property);
1374
typedef HashMap<RefPtr<StringImpl>, unsigned, IdentifierRepHash> ObjectValidationMap;
1375
ObjectValidationMap objectValidator;
1376
// Add the first property
1377
if (!m_syntaxAlreadyValidated)
1378
objectValidator.add(context.getName(property).impl(), context.getType(property));
1380
TreePropertyList propertyList = context.createPropertyList(location, property);
1381
TreePropertyList tail = propertyList;
1382
while (match(COMMA)) {
1384
// allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939
1385
if (match(CLOSEBRACE))
1387
JSTokenLocation propertyLocation(tokenLocation());
1388
property = parseProperty<true>(context);
1389
failIfFalse(property);
1390
if (!m_syntaxAlreadyValidated) {
1391
ObjectValidationMap::AddResult propertyEntry = objectValidator.add(context.getName(property).impl(), context.getType(property));
1392
if (!propertyEntry.isNewEntry) {
1393
failIfTrue(propertyEntry.iterator->value == PropertyNode::Constant);
1394
failIfTrue(context.getType(property) == PropertyNode::Constant);
1395
failIfTrue(context.getType(property) & propertyEntry.iterator->value);
1396
propertyEntry.iterator->value |= context.getType(property);
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>::parseArrayLiteral(TreeBuilder& context)
1413
consumeOrFailWithFlags(OPENBRACKET, TreeBuilder::DontBuildStrings);
1415
int oldNonLHSCount = m_nonLHSCount;
1418
while (match(COMMA)) {
1419
next(TreeBuilder::DontBuildStrings);
1422
if (match(CLOSEBRACKET)) {
1423
JSTokenLocation location(tokenLocation());
1424
next(TreeBuilder::DontBuildStrings);
1425
return context.createArray(location, elisions);
1428
TreeExpression elem = parseAssignmentExpression(context);
1430
typename TreeBuilder::ElementList elementList = context.createElementList(elisions, elem);
1431
typename TreeBuilder::ElementList tail = elementList;
1433
while (match(COMMA)) {
1434
next(TreeBuilder::DontBuildStrings);
1437
while (match(COMMA)) {
1442
if (match(CLOSEBRACKET)) {
1443
JSTokenLocation location(tokenLocation());
1444
next(TreeBuilder::DontBuildStrings);
1445
return context.createArray(location, elisions, elementList);
1447
TreeExpression elem = parseAssignmentExpression(context);
1449
tail = context.createElementList(tail, elisions, elem);
1452
JSTokenLocation location(tokenLocation());
1453
consumeOrFail(CLOSEBRACKET);
1455
m_nonLHSCount = oldNonLHSCount;
1457
return context.createArray(location, elementList);
1460
template <typename LexerType>
1461
template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePrimaryExpression(TreeBuilder& context)
1463
failIfStackOverflow();
1464
switch (m_token.m_type) {
1467
return parseStrictObjectLiteral(context);
1468
return parseObjectLiteral(context);
1470
return parseArrayLiteral(context);
1473
int oldNonLHSCount = m_nonLHSCount;
1474
TreeExpression result = parseExpression(context);
1475
m_nonLHSCount = oldNonLHSCount;
1476
consumeOrFail(CLOSEPAREN);
1481
JSTokenLocation location(tokenLocation());
1483
return context.thisExpr(location);
1486
int start = tokenStart();
1487
const Identifier* ident = m_token.m_data.ident;
1488
JSTokenLocation location(tokenLocation());
1490
currentScope()->useVariable(ident, m_globalData->propertyNames->eval == *ident);
1491
m_lastIdentifier = ident;
1492
return context.createResolve(location, ident, start);
1495
const Identifier* ident = m_token.m_data.ident;
1496
JSTokenLocation location(tokenLocation());
1498
return context.createString(location, ident);
1501
double d = m_token.m_data.doubleValue;
1502
JSTokenLocation location(tokenLocation());
1504
return context.createNumberExpr(location, d);
1507
JSTokenLocation location(tokenLocation());
1509
return context.createNull(location);
1512
JSTokenLocation location(tokenLocation());
1514
return context.createBoolean(location, true);
1517
JSTokenLocation location(tokenLocation());
1519
return context.createBoolean(location, false);
1524
const Identifier* pattern;
1525
const Identifier* flags;
1526
if (match(DIVEQUAL))
1527
failIfFalse(m_lexer->scanRegExp(pattern, flags, '='));
1529
failIfFalse(m_lexer->scanRegExp(pattern, flags));
1531
int start = tokenStart();
1532
JSTokenLocation location(tokenLocation());
1534
TreeExpression re = context.createRegExp(location, *pattern, *flags, start);
1536
const char* yarrErrorMsg = Yarr::checkSyntax(pattern->string());
1537
ASSERT(!m_errorMessage.isNull());
1538
failWithMessage(yarrErrorMsg);
1547
template <typename LexerType>
1548
template <class TreeBuilder> TreeArguments Parser<LexerType>::parseArguments(TreeBuilder& context)
1550
consumeOrFailWithFlags(OPENPAREN, TreeBuilder::DontBuildStrings);
1551
JSTokenLocation location(tokenLocation());
1552
if (match(CLOSEPAREN)) {
1553
next(TreeBuilder::DontBuildStrings);
1554
return context.createArguments();
1556
TreeExpression firstArg = parseAssignmentExpression(context);
1557
failIfFalse(firstArg);
1559
TreeArgumentsList argList = context.createArgumentsList(location, firstArg);
1560
TreeArgumentsList tail = argList;
1561
while (match(COMMA)) {
1562
JSTokenLocation argumentLocation(tokenLocation());
1563
next(TreeBuilder::DontBuildStrings);
1564
TreeExpression arg = parseAssignmentExpression(context);
1566
tail = context.createArgumentsList(argumentLocation, tail, arg);
1568
consumeOrFail(CLOSEPAREN);
1569
return context.createArguments(argList);
1572
template <typename LexerType>
1573
template <class TreeBuilder> TreeExpression Parser<LexerType>::parseMemberExpression(TreeBuilder& context)
1575
TreeExpression base = 0;
1576
int start = tokenStart();
1577
int expressionStart = start;
1579
JSTokenLocation location;
1580
while (match(NEW)) {
1585
if (match(FUNCTION)) {
1586
const Identifier* name = &m_globalData->propertyNames->nullIdentifier;
1587
TreeFormalParameterList parameters = 0;
1588
TreeFunctionBody body = 0;
1589
int openBracePos = 0;
1590
int closeBracePos = 0;
1591
int bodyStartLine = 0;
1592
location = tokenLocation();
1594
failIfFalse((parseFunctionInfo<FunctionNoRequirements, false>(context, name, parameters, body, openBracePos, closeBracePos, bodyStartLine)));
1595
base = context.createFunctionExpr(location, name, body, parameters, openBracePos, closeBracePos, bodyStartLine, m_lastLine);
1597
base = parsePrimaryExpression(context);
1601
location = tokenLocation();
1602
switch (m_token.m_type) {
1604
m_nonTrivialExpressionCount++;
1605
int expressionEnd = lastTokenEnd();
1607
int nonLHSCount = m_nonLHSCount;
1608
int initialAssignments = m_assignmentCount;
1609
TreeExpression property = parseExpression(context);
1610
failIfFalse(property);
1611
base = context.createBracketAccess(location, base, property, initialAssignments != m_assignmentCount, expressionStart, expressionEnd, tokenEnd());
1612
consumeOrFail(CLOSEBRACKET);
1613
m_nonLHSCount = nonLHSCount;
1617
m_nonTrivialExpressionCount++;
1618
int nonLHSCount = m_nonLHSCount;
1621
int exprEnd = lastTokenEnd();
1622
TreeArguments arguments = parseArguments(context);
1623
failIfFalse(arguments);
1624
base = context.createNewExpr(location, base, arguments, start, exprEnd, lastTokenEnd());
1626
int expressionEnd = lastTokenEnd();
1627
TreeArguments arguments = parseArguments(context);
1628
failIfFalse(arguments);
1629
base = context.makeFunctionCallNode(location, base, arguments, expressionStart, expressionEnd, lastTokenEnd());
1631
m_nonLHSCount = nonLHSCount;
1635
m_nonTrivialExpressionCount++;
1636
int expressionEnd = lastTokenEnd();
1637
nextExpectIdentifier(LexerFlagsIgnoreReservedWords | TreeBuilder::DontBuildKeywords);
1639
base = context.createDotAccess(location, base, m_token.m_data.ident, expressionStart, expressionEnd, tokenEnd());
1644
goto endMemberExpression;
1647
endMemberExpression:
1649
base = context.createNewExpr(location, base, start, lastTokenEnd());
1653
template <typename LexerType>
1654
template <class TreeBuilder> TreeExpression Parser<LexerType>::parseUnaryExpression(TreeBuilder& context)
1656
typename TreeBuilder::UnaryExprContext unaryExprContext(context);
1657
AllowInOverride allowInOverride(this);
1658
int tokenStackDepth = 0;
1659
bool modifiesExpr = false;
1660
bool requiresLExpr = false;
1661
while (isUnaryOp(m_token.m_type)) {
1663
switch (m_token.m_type) {
1667
case AUTOMINUSMINUS:
1668
failIfTrue(requiresLExpr);
1669
modifiesExpr = true;
1670
requiresLExpr = true;
1673
failIfTrue(requiresLExpr);
1674
requiresLExpr = true;
1677
failIfTrue(requiresLExpr);
1682
context.appendUnaryToken(tokenStackDepth, m_token.m_type, tokenStart());
1684
m_nonTrivialExpressionCount++;
1686
int subExprStart = tokenStart();
1687
JSTokenLocation location(tokenLocation());
1688
TreeExpression expr = parseMemberExpression(context);
1690
bool isEvalOrArguments = false;
1691
if (strictMode() && !m_syntaxAlreadyValidated) {
1692
if (context.isResolve(expr))
1693
isEvalOrArguments = *m_lastIdentifier == m_globalData->propertyNames->eval || *m_lastIdentifier == m_globalData->propertyNames->arguments;
1695
failIfTrueIfStrictWithNameAndMessage(isEvalOrArguments && modifiesExpr, "'", m_lastIdentifier->impl(), "' cannot be modified in strict mode");
1696
switch (m_token.m_type) {
1698
m_nonTrivialExpressionCount++;
1700
expr = context.makePostfixNode(location, expr, OpPlusPlus, subExprStart, lastTokenEnd(), tokenEnd());
1701
m_assignmentCount++;
1702
failIfTrueIfStrictWithNameAndMessage(isEvalOrArguments, "'", m_lastIdentifier->impl(), "' cannot be modified in strict mode");
1703
failIfTrueIfStrict(requiresLExpr);
1707
m_nonTrivialExpressionCount++;
1709
expr = context.makePostfixNode(location, expr, OpMinusMinus, subExprStart, lastTokenEnd(), tokenEnd());
1710
m_assignmentCount++;
1711
failIfTrueIfStrictWithNameAndMessage(isEvalOrArguments, "'", m_lastIdentifier->impl(), "' cannot be modified in strict mode");
1712
failIfTrueIfStrict(requiresLExpr);
1719
int end = lastTokenEnd();
1721
if (!TreeBuilder::CreatesAST && (m_syntaxAlreadyValidated || !strictMode()))
1724
location = tokenLocation();
1725
location.line = m_lexer->lastLineNumber();
1726
while (tokenStackDepth) {
1727
switch (context.unaryTokenStackLastType(tokenStackDepth)) {
1729
expr = context.createLogicalNot(location, expr);
1732
expr = context.makeBitwiseNotNode(location, expr);
1735
expr = context.makeNegateNode(location, expr);
1738
expr = context.createUnaryPlus(location, expr);
1742
expr = context.makePrefixNode(location, expr, OpPlusPlus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end);
1743
m_assignmentCount++;
1746
case AUTOMINUSMINUS:
1747
expr = context.makePrefixNode(location, expr, OpMinusMinus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end);
1748
m_assignmentCount++;
1751
expr = context.makeTypeOfNode(location, expr);
1754
expr = context.createVoid(location, expr);
1757
failIfTrueIfStrictWithNameAndMessage(context.isResolve(expr), "Cannot delete unqualified property", m_lastIdentifier->impl(), "in strict mode");
1758
expr = context.makeDeleteNode(location, expr, context.unaryTokenStackLastStart(tokenStackDepth), end, end);
1761
// If we get here something has gone horribly horribly wrong
1764
subExprStart = context.unaryTokenStackLastStart(tokenStackDepth);
1765
context.unaryTokenStackRemoveLast(tokenStackDepth);
1770
// Instantiate the two flavors of Parser we need instead of putting most of this file in Parser.h
1771
template class Parser< Lexer<LChar> >;
1772
template class Parser< Lexer<UChar> >;