]> git.saurik.com Git - apple/javascriptcore.git/blame - parser/Parser.cpp
JavaScriptCore-1218.33.tar.gz
[apple/javascriptcore.git] / parser / Parser.cpp
CommitLineData
9dae56ea
A
1/*
2 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
3 * Copyright (C) 2001 Peter Kelly (pmk@post.com)
93a37866 4 * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc. All rights reserved.
9dae56ea
A
5 *
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.
10 *
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.
15 *
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.
20 *
21 */
22
23#include "config.h"
24#include "Parser.h"
25
6fe7ccc8
A
26#include "ASTBuilder.h"
27#include "CodeBlock.h"
9dae56ea 28#include "Debugger.h"
93a37866 29#include "JSCJSValueInlines.h"
9dae56ea 30#include "Lexer.h"
6fe7ccc8
A
31#include "NodeInfo.h"
32#include "SourceProvider.h"
93a37866 33#include "VM.h"
6fe7ccc8
A
34#include <utility>
35#include <wtf/HashFunctions.h>
36#include <wtf/OwnPtr.h>
37#include <wtf/WTFThreadData.h>
38
93a37866
A
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)
60
6fe7ccc8 61using namespace std;
9dae56ea
A
62
63namespace JSC {
64
6fe7ccc8 65template <typename LexerType>
93a37866
A
66Parser<LexerType>::Parser(VM* vm, const SourceCode& source, FunctionParameters* parameters, const Identifier& name, JSParserStrictness strictness, JSParserMode parserMode)
67 : m_vm(vm)
6fe7ccc8
A
68 , m_source(&source)
69 , m_stack(wtfThreadData().stack())
93a37866 70 , m_hasStackOverflow(false)
6fe7ccc8
A
71 , m_allowsIn(true)
72 , m_lastLine(0)
73 , m_lastTokenEnd(0)
74 , m_assignmentCount(0)
75 , m_nonLHSCount(0)
76 , m_syntaxAlreadyValidated(source.provider()->isValid())
77 , m_statementDepth(0)
78 , m_nonTrivialExpressionCount(0)
79 , m_lastIdentifier(0)
80 , m_sourceElements(0)
9dae56ea 81{
93a37866
A
82 m_lexer = adoptPtr(new LexerType(vm));
83 m_arena = m_vm->parserArena.get();
6fe7ccc8 84 m_lexer->setCode(source, m_arena);
93a37866
A
85 m_token.m_location.endOffset = source.startOffset();
86 m_token.m_location.lineStartOffset = source.startOffset();
9dae56ea 87
93a37866 88 m_functionCache = vm->addSourceProviderCache(source.provider());
6fe7ccc8
A
89 ScopeRef scope = pushScope();
90 if (parserMode == JSParseFunctionCode)
91 scope->setIsFunction();
92 if (strictness == JSParseStrict)
93 scope->setStrictMode();
94 if (parameters) {
95 for (unsigned i = 0; i < parameters->size(); i++)
96 scope->declareParameter(&parameters->at(i));
97 }
93a37866
A
98 if (!name.isNull())
99 scope->declareCallee(&name);
6fe7ccc8 100 next();
6fe7ccc8 101}
9dae56ea 102
6fe7ccc8
A
103template <typename LexerType>
104Parser<LexerType>::~Parser()
105{
106}
9dae56ea 107
6fe7ccc8 108template <typename LexerType>
93a37866 109String Parser<LexerType>::parseInner()
6fe7ccc8 110{
93a37866 111 String parseError = String();
6fe7ccc8 112
93a37866 113 ASTBuilder context(const_cast<VM*>(m_vm), const_cast<SourceCode*>(m_source));
6fe7ccc8
A
114 if (m_lexer->isReparsing())
115 m_statementDepth--;
116 ScopeRef scope = currentScope();
117 SourceElements* sourceElements = parseSourceElements<CheckForStrictMode>(context);
93a37866
A
118 if (!sourceElements || !consume(EOFTOK)) {
119 if (hasError())
120 parseError = m_errorMessage;
121 else
122 parseError = ASCIILiteral("Parser error");
123 }
9dae56ea 124
6fe7ccc8
A
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;
9dae56ea 132
6fe7ccc8
A
133 didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), features,
134 m_lastLine, context.numConstants(), capturedVariables);
9dae56ea 135
6fe7ccc8 136 return parseError;
9dae56ea
A
137}
138
6fe7ccc8
A
139template <typename LexerType>
140void Parser<LexerType>::didFinishParsing(SourceElements* sourceElements, ParserArenaData<DeclarationStacks::VarStack>* varStack,
14957cd0 141 ParserArenaData<DeclarationStacks::FunctionStack>* funcStack, CodeFeatures features, int lastLine, int numConstants, IdentifierSet& capturedVars)
9dae56ea
A
142{
143 m_sourceElements = sourceElements;
144 m_varDeclarations = varStack;
145 m_funcDeclarations = funcStack;
14957cd0 146 m_capturedVariables.swap(capturedVars);
9dae56ea
A
147 m_features = features;
148 m_lastLine = lastLine;
149 m_numConstants = numConstants;
150}
151
6fe7ccc8
A
152template <typename LexerType>
153bool Parser<LexerType>::allowAutomaticSemicolon()
154{
155 return match(CLOSEBRACE) || match(EOFTOK) || m_lexer->prevTerminator();
156}
157
158template <typename LexerType>
159template <SourceElementsMode mode, class TreeBuilder> TreeSourceElements Parser<LexerType>::parseSourceElements(TreeBuilder& context)
160{
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;
93a37866
A
166 unsigned startOffset = m_token.m_location.startOffset;
167 unsigned startLineStartOffset = m_token.m_location.lineStartOffset;
6fe7ccc8
A
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) {
173 if (directive) {
174 // "use strict" must be the exact literal without escape sequences or line continuation.
93a37866 175 if (!hasSetStrict && directiveLiteralLength == lengthOfUseStrictLiteral && m_vm->propertyNames->useStrictIdentifier == *directive) {
6fe7ccc8
A
176 setStrictMode();
177 hasSetStrict = true;
178 failIfFalse(isValidStrictMode());
93a37866 179 m_lexer->setOffset(startOffset, startLineStartOffset);
6fe7ccc8
A
180 next();
181 m_lexer->setLastLineNumber(oldLastLineNumber);
182 m_lexer->setLineNumber(oldLineNumber);
93a37866 183 failIfTrue(hasError());
6fe7ccc8
A
184 continue;
185 }
186 } else
187 seenNonDirective = true;
188 }
189 context.appendStatement(sourceElements, statement);
190 }
93a37866
A
191
192 failIfTrue(hasError());
6fe7ccc8
A
193 return sourceElements;
194}
195
196template <typename LexerType>
197template <class TreeBuilder> TreeStatement Parser<LexerType>::parseVarDeclaration(TreeBuilder& context)
198{
199 ASSERT(match(VAR));
93a37866 200 JSTokenLocation location(tokenLocation());
6fe7ccc8
A
201 int start = tokenLine();
202 int end = 0;
203 int scratch;
204 const Identifier* scratch1 = 0;
205 TreeExpression scratch2 = 0;
206 int scratch3 = 0;
207 TreeExpression varDecls = parseVarDeclarationList(context, scratch, scratch1, scratch2, scratch3, scratch3, scratch3);
93a37866 208 failIfTrue(hasError());
6fe7ccc8
A
209 failIfFalse(autoSemiColon());
210
93a37866 211 return context.createVarStatement(location, varDecls, start, end);
6fe7ccc8
A
212}
213
214template <typename LexerType>
215template <class TreeBuilder> TreeStatement Parser<LexerType>::parseConstDeclaration(TreeBuilder& context)
216{
217 ASSERT(match(CONSTTOKEN));
93a37866 218 JSTokenLocation location(tokenLocation());
6fe7ccc8
A
219 int start = tokenLine();
220 int end = 0;
221 TreeConstDeclList constDecls = parseConstDeclarationList(context);
93a37866 222 failIfTrue(hasError());
6fe7ccc8
A
223 failIfFalse(autoSemiColon());
224
93a37866 225 return context.createConstStatement(location, constDecls, start, end);
6fe7ccc8
A
226}
227
228template <typename LexerType>
229template <class TreeBuilder> TreeStatement Parser<LexerType>::parseDoWhileStatement(TreeBuilder& context)
230{
231 ASSERT(match(DO));
232 int startLine = tokenLine();
233 next();
234 const Identifier* unused = 0;
235 startLoop();
236 TreeStatement statement = parseStatement(context, unused);
237 endLoop();
238 failIfFalse(statement);
239 int endLine = tokenLine();
93a37866 240 JSTokenLocation location(tokenLocation());
6fe7ccc8
A
241 consumeOrFail(WHILE);
242 consumeOrFail(OPENPAREN);
243 TreeExpression expr = parseExpression(context);
244 failIfFalse(expr);
245 consumeOrFail(CLOSEPAREN);
246 if (match(SEMICOLON))
247 next(); // Always performs automatic semicolon insertion.
93a37866 248 return context.createDoWhileStatement(location, statement, expr, startLine, endLine);
6fe7ccc8
A
249}
250
251template <typename LexerType>
252template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWhileStatement(TreeBuilder& context)
253{
254 ASSERT(match(WHILE));
93a37866 255 JSTokenLocation location(tokenLocation());
6fe7ccc8
A
256 int startLine = tokenLine();
257 next();
258 consumeOrFail(OPENPAREN);
259 TreeExpression expr = parseExpression(context);
260 failIfFalse(expr);
261 int endLine = tokenLine();
262 consumeOrFail(CLOSEPAREN);
263 const Identifier* unused = 0;
264 startLoop();
265 TreeStatement statement = parseStatement(context, unused);
266 endLoop();
267 failIfFalse(statement);
93a37866 268 return context.createWhileStatement(location, expr, statement, startLine, endLine);
6fe7ccc8
A
269}
270
271template <typename LexerType>
272template <class TreeBuilder> TreeExpression Parser<LexerType>::parseVarDeclarationList(TreeBuilder& context, int& declarations, const Identifier*& lastIdent, TreeExpression& lastInitializer, int& identStart, int& initStart, int& initEnd)
273{
274 TreeExpression varDecls = 0;
275 do {
276 declarations++;
93a37866 277 JSTokenLocation location(tokenLocation());
6fe7ccc8
A
278 next();
279 matchOrFail(IDENT);
280
281 int varStart = tokenStart();
282 identStart = varStart;
283 const Identifier* name = m_token.m_data.ident;
284 lastIdent = name;
285 next();
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;
93a37866
A
291 unsigned varLine = tokenLine();
292 unsigned varLineStart = tokenLineStart();
6fe7ccc8
A
293 initStart = tokenStart();
294 next(TreeBuilder::DontBuildStrings); // consume '='
6fe7ccc8
A
295 TreeExpression initializer = parseAssignmentExpression(context);
296 initEnd = lastTokenEnd();
297 lastInitializer = initializer;
298 failIfFalse(initializer);
299
93a37866 300 TreeExpression node = context.createAssignResolve(location, *name, initializer, varStart, varDivot, lastTokenEnd(), varLine, varLineStart);
6fe7ccc8
A
301 if (!varDecls)
302 varDecls = node;
303 else
93a37866 304 varDecls = context.combineCommaNodes(location, varDecls, node);
6fe7ccc8
A
305 }
306 } while (match(COMMA));
307 return varDecls;
308}
309
310template <typename LexerType>
311template <class TreeBuilder> TreeConstDeclList Parser<LexerType>::parseConstDeclarationList(TreeBuilder& context)
312{
313 failIfTrue(strictMode());
314 TreeConstDeclList constDecls = 0;
315 TreeConstDeclList tail = 0;
316 do {
93a37866 317 JSTokenLocation location(tokenLocation());
6fe7ccc8
A
318 next();
319 matchOrFail(IDENT);
320 const Identifier* name = m_token.m_data.ident;
321 next();
322 bool hasInitializer = match(EQUAL);
323 declareVariable(name);
324 context.addVar(name, DeclarationStacks::IsConstant | (hasInitializer ? DeclarationStacks::HasInitializer : 0));
93a37866 325
6fe7ccc8
A
326 TreeExpression initializer = 0;
327 if (hasInitializer) {
328 next(TreeBuilder::DontBuildStrings); // consume '='
329 initializer = parseAssignmentExpression(context);
330 }
93a37866 331 tail = context.appendConstDecl(location, tail, name, initializer);
6fe7ccc8
A
332 if (!constDecls)
333 constDecls = tail;
334 } while (match(COMMA));
335 return constDecls;
336}
337
338template <typename LexerType>
339template <class TreeBuilder> TreeStatement Parser<LexerType>::parseForStatement(TreeBuilder& context)
340{
341 ASSERT(match(FOR));
93a37866 342 JSTokenLocation location(tokenLocation());
6fe7ccc8
A
343 int startLine = tokenLine();
344 next();
345 consumeOrFail(OPENPAREN);
346 int nonLHSCount = m_nonLHSCount;
347 int declarations = 0;
348 int declsStart = 0;
349 int declsEnd = 0;
93a37866
A
350 unsigned declsLine = 0;
351 unsigned declsLineStart = 0;
6fe7ccc8 352 TreeExpression decls = 0;
6fe7ccc8
A
353 if (match(VAR)) {
354 /*
355 for (var IDENT in expression) statement
356 for (var IDENT = expression in expression) statement
357 for (var varDeclarationList; expressionOpt; expressionOpt)
358 */
6fe7ccc8
A
359 const Identifier* forInTarget = 0;
360 TreeExpression forInInitializer = 0;
361 m_allowsIn = false;
362 int initStart = 0;
363 int initEnd = 0;
364 decls = parseVarDeclarationList(context, declarations, forInTarget, forInInitializer, declsStart, initStart, initEnd);
365 m_allowsIn = true;
93a37866
A
366 failIfTrue(hasError());
367
6fe7ccc8
A
368 // Remainder of a standard for loop is handled identically
369 if (match(SEMICOLON))
370 goto standardForLoop;
371
372 failIfFalse(declarations == 1);
373
374 // Handle for-in with var declaration
375 int inLocation = tokenStart();
93a37866
A
376 unsigned inLine = tokenLine();
377 unsigned inLineStart = tokenLineStart();
6fe7ccc8
A
378 consumeOrFail(INTOKEN);
379
380 TreeExpression expr = parseExpression(context);
381 failIfFalse(expr);
382 int exprEnd = lastTokenEnd();
383
384 int endLine = tokenLine();
385 consumeOrFail(CLOSEPAREN);
386
387 const Identifier* unused = 0;
388 startLoop();
389 TreeStatement statement = parseStatement(context, unused);
390 endLoop();
391 failIfFalse(statement);
392
93a37866 393 return context.createForInLoop(location, forInTarget, forInInitializer, expr, statement, declsStart, inLocation, exprEnd, initStart, initEnd, startLine, endLine, inLine, inLineStart);
6fe7ccc8
A
394 }
395
396 if (!match(SEMICOLON)) {
397 m_allowsIn = false;
398 declsStart = tokenStart();
399 decls = parseExpression(context);
400 declsEnd = lastTokenEnd();
93a37866
A
401 declsLine = lastTokenLine();
402 declsLineStart = lastTokenLineStart();
6fe7ccc8
A
403 m_allowsIn = true;
404 failIfFalse(decls);
405 }
406
407 if (match(SEMICOLON)) {
408 standardForLoop:
409 // Standard for loop
410 next();
411 TreeExpression condition = 0;
412
413 if (!match(SEMICOLON)) {
414 condition = parseExpression(context);
415 failIfFalse(condition);
416 }
417 consumeOrFail(SEMICOLON);
418
419 TreeExpression increment = 0;
420 if (!match(CLOSEPAREN)) {
421 increment = parseExpression(context);
422 failIfFalse(increment);
423 }
424 int endLine = tokenLine();
425 consumeOrFail(CLOSEPAREN);
426 const Identifier* unused = 0;
427 startLoop();
428 TreeStatement statement = parseStatement(context, unused);
429 endLoop();
430 failIfFalse(statement);
93a37866 431 return context.createForLoop(location, decls, condition, increment, statement, startLine, endLine);
6fe7ccc8
A
432 }
433
434 // For-in loop
435 failIfFalse(nonLHSCount == m_nonLHSCount);
436 consumeOrFail(INTOKEN);
437 TreeExpression expr = parseExpression(context);
438 failIfFalse(expr);
439 int exprEnd = lastTokenEnd();
440 int endLine = tokenLine();
441 consumeOrFail(CLOSEPAREN);
442 const Identifier* unused = 0;
443 startLoop();
444 TreeStatement statement = parseStatement(context, unused);
445 endLoop();
446 failIfFalse(statement);
447
93a37866 448 return context.createForInLoop(location, decls, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine, declsLine, declsLineStart);
6fe7ccc8
A
449}
450
451template <typename LexerType>
452template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBreakStatement(TreeBuilder& context)
453{
454 ASSERT(match(BREAK));
93a37866 455 JSTokenLocation location(tokenLocation());
6fe7ccc8
A
456 int startCol = tokenStart();
457 int endCol = tokenEnd();
458 int startLine = tokenLine();
459 int endLine = tokenLine();
93a37866 460 unsigned endLineStart = tokenLineStart();
6fe7ccc8
A
461 next();
462
463 if (autoSemiColon()) {
464 failIfFalseWithMessage(breakIsValid(), "'break' is only valid inside a switch or loop statement");
93a37866 465 return context.createBreakStatement(location, startCol, endCol, startLine, endLine, endLineStart);
6fe7ccc8
A
466 }
467 matchOrFail(IDENT);
468 const Identifier* ident = m_token.m_data.ident;
469 failIfFalseWithNameAndMessage(getLabel(ident), "Label", ident->impl(), "is not defined");
470 endCol = tokenEnd();
471 endLine = tokenLine();
93a37866 472 endLineStart = tokenLineStart();
6fe7ccc8
A
473 next();
474 failIfFalse(autoSemiColon());
93a37866 475 return context.createBreakStatement(location, ident, startCol, endCol, startLine, endLine, endLineStart);
6fe7ccc8
A
476}
477
478template <typename LexerType>
479template <class TreeBuilder> TreeStatement Parser<LexerType>::parseContinueStatement(TreeBuilder& context)
480{
481 ASSERT(match(CONTINUE));
93a37866 482 JSTokenLocation location(tokenLocation());
6fe7ccc8
A
483 int startCol = tokenStart();
484 int endCol = tokenEnd();
485 int startLine = tokenLine();
486 int endLine = tokenLine();
93a37866 487 unsigned endLineStart = tokenLineStart();
6fe7ccc8
A
488 next();
489
490 if (autoSemiColon()) {
491 failIfFalseWithMessage(continueIsValid(), "'continue' is only valid inside a loop statement");
93a37866 492 return context.createContinueStatement(location, startCol, endCol, startLine, endLine, endLineStart);
6fe7ccc8
A
493 }
494 matchOrFail(IDENT);
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");
499 endCol = tokenEnd();
500 endLine = tokenLine();
93a37866 501 endLineStart = tokenLineStart();
6fe7ccc8
A
502 next();
503 failIfFalse(autoSemiColon());
93a37866 504 return context.createContinueStatement(location, ident, startCol, endCol, startLine, endLine, endLineStart);
6fe7ccc8
A
505}
506
507template <typename LexerType>
508template <class TreeBuilder> TreeStatement Parser<LexerType>::parseReturnStatement(TreeBuilder& context)
509{
510 ASSERT(match(RETURN));
93a37866 511 JSTokenLocation location(tokenLocation());
6fe7ccc8
A
512 failIfFalse(currentScope()->isFunction());
513 int startLine = tokenLine();
514 int endLine = startLine;
515 int start = tokenStart();
516 int end = tokenEnd();
93a37866
A
517 unsigned divotLine = tokenLine();
518 unsigned divotLineStart = tokenLineStart();
6fe7ccc8
A
519 next();
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
522 // the statement
523 if (match(SEMICOLON))
524 endLine = tokenLine();
525 if (autoSemiColon())
93a37866 526 return context.createReturnStatement(location, 0, start, end, startLine, endLine, divotLine, divotLineStart);
6fe7ccc8
A
527 TreeExpression expr = parseExpression(context);
528 failIfFalse(expr);
529 end = lastTokenEnd();
93a37866
A
530 divotLine = lastTokenLine();
531 divotLineStart = lastTokenLineStart();
6fe7ccc8
A
532 if (match(SEMICOLON))
533 endLine = tokenLine();
534 failIfFalse(autoSemiColon());
93a37866 535 return context.createReturnStatement(location, expr, start, end, startLine, endLine, divotLine, divotLineStart);
6fe7ccc8
A
536}
537
538template <typename LexerType>
539template <class TreeBuilder> TreeStatement Parser<LexerType>::parseThrowStatement(TreeBuilder& context)
540{
541 ASSERT(match(THROW));
93a37866 542 JSTokenLocation location(tokenLocation());
6fe7ccc8
A
543 int eStart = tokenStart();
544 int startLine = tokenLine();
545 next();
546
547 failIfTrue(autoSemiColon());
548
549 TreeExpression expr = parseExpression(context);
550 failIfFalse(expr);
551 int eEnd = lastTokenEnd();
93a37866
A
552 unsigned divotLine = lastTokenLine();
553 unsigned divotLineStart = lastTokenLineStart();
6fe7ccc8
A
554 int endLine = tokenLine();
555 failIfFalse(autoSemiColon());
556
93a37866 557 return context.createThrowStatement(location, expr, eStart, eEnd, startLine, endLine, divotLine, divotLineStart);
6fe7ccc8
A
558}
559
560template <typename LexerType>
561template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWithStatement(TreeBuilder& context)
562{
563 ASSERT(match(WITH));
93a37866 564 JSTokenLocation location(tokenLocation());
6fe7ccc8
A
565 failIfTrueWithMessage(strictMode(), "'with' statements are not valid in strict mode");
566 currentScope()->setNeedsFullActivation();
567 int startLine = tokenLine();
568 next();
569 consumeOrFail(OPENPAREN);
570 int start = tokenStart();
571 TreeExpression expr = parseExpression(context);
572 failIfFalse(expr);
573 int end = lastTokenEnd();
93a37866
A
574 unsigned divotLine = lastTokenLine();
575 unsigned divotLineStart = lastTokenLineStart();
6fe7ccc8
A
576 int endLine = tokenLine();
577 consumeOrFail(CLOSEPAREN);
578 const Identifier* unused = 0;
579 TreeStatement statement = parseStatement(context, unused);
580 failIfFalse(statement);
581
93a37866 582 return context.createWithStatement(location, expr, statement, start, end, startLine, endLine, divotLine, divotLineStart);
6fe7ccc8
A
583}
584
585template <typename LexerType>
586template <class TreeBuilder> TreeStatement Parser<LexerType>::parseSwitchStatement(TreeBuilder& context)
587{
588 ASSERT(match(SWITCH));
93a37866 589 JSTokenLocation location(tokenLocation());
6fe7ccc8
A
590 int startLine = tokenLine();
591 next();
592 consumeOrFail(OPENPAREN);
593 TreeExpression expr = parseExpression(context);
594 failIfFalse(expr);
595 int endLine = tokenLine();
596 consumeOrFail(CLOSEPAREN);
597 consumeOrFail(OPENBRACE);
598 startSwitch();
599 TreeClauseList firstClauses = parseSwitchClauses(context);
93a37866 600 failIfTrue(hasError());
6fe7ccc8
A
601
602 TreeClause defaultClause = parseSwitchDefaultClause(context);
93a37866 603 failIfTrue(hasError());
6fe7ccc8
A
604
605 TreeClauseList secondClauses = parseSwitchClauses(context);
93a37866 606 failIfTrue(hasError());
6fe7ccc8
A
607 endSwitch();
608 consumeOrFail(CLOSEBRACE);
609
93a37866 610 return context.createSwitchStatement(location, expr, firstClauses, defaultClause, secondClauses, startLine, endLine);
6fe7ccc8
A
611
612}
613
614template <typename LexerType>
615template <class TreeBuilder> TreeClauseList Parser<LexerType>::parseSwitchClauses(TreeBuilder& context)
616{
617 if (!match(CASE))
618 return 0;
619 next();
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;
628
629 while (match(CASE)) {
630 next();
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);
638 }
639 return clauseList;
640}
641
642template <typename LexerType>
643template <class TreeBuilder> TreeClause Parser<LexerType>::parseSwitchDefaultClause(TreeBuilder& context)
644{
645 if (!match(DEFAULT))
646 return 0;
647 next();
648 consumeOrFail(COLON);
649 TreeSourceElements statements = parseSourceElements<DontCheckForStrictMode>(context);
650 failIfFalse(statements);
651 return context.createClause(0, statements);
652}
653
654template <typename LexerType>
655template <class TreeBuilder> TreeStatement Parser<LexerType>::parseTryStatement(TreeBuilder& context)
656{
657 ASSERT(match(TRY));
93a37866 658 JSTokenLocation location(tokenLocation());
6fe7ccc8 659 TreeStatement tryBlock = 0;
93a37866 660 const Identifier* ident = &m_vm->propertyNames->nullIdentifier;
6fe7ccc8
A
661 TreeStatement catchBlock = 0;
662 TreeStatement finallyBlock = 0;
663 int firstLine = tokenLine();
664 next();
665 matchOrFail(OPENBRACE);
666
667 tryBlock = parseBlockStatement(context);
668 failIfFalse(tryBlock);
669 int lastLine = m_lastLine;
670
671 if (match(CATCH)) {
672 currentScope()->setNeedsFullActivation();
673 next();
674 consumeOrFail(OPENPAREN);
675 matchOrFail(IDENT);
676 ident = m_token.m_data.ident;
677 next();
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));
686 }
687
688 if (match(FINALLY)) {
689 next();
690 matchOrFail(OPENBRACE);
691 finallyBlock = parseBlockStatement(context);
692 failIfFalse(finallyBlock);
693 }
694 failIfFalse(catchBlock || finallyBlock);
93a37866 695 return context.createTryStatement(location, tryBlock, ident, catchBlock, finallyBlock, firstLine, lastLine);
6fe7ccc8
A
696}
697
698template <typename LexerType>
699template <class TreeBuilder> TreeStatement Parser<LexerType>::parseDebuggerStatement(TreeBuilder& context)
700{
701 ASSERT(match(DEBUGGER));
93a37866 702 JSTokenLocation location(tokenLocation());
6fe7ccc8
A
703 int startLine = tokenLine();
704 int endLine = startLine;
705 next();
706 if (match(SEMICOLON))
707 startLine = tokenLine();
708 failIfFalse(autoSemiColon());
93a37866 709 return context.createDebugger(location, startLine, endLine);
6fe7ccc8
A
710}
711
712template <typename LexerType>
713template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBlockStatement(TreeBuilder& context)
714{
715 ASSERT(match(OPENBRACE));
93a37866 716 JSTokenLocation location(tokenLocation());
6fe7ccc8
A
717 int start = tokenLine();
718 next();
719 if (match(CLOSEBRACE)) {
720 next();
93a37866 721 return context.createBlockStatement(location, 0, start, m_lastLine);
6fe7ccc8
A
722 }
723 TreeSourceElements subtree = parseSourceElements<DontCheckForStrictMode>(context);
724 failIfFalse(subtree);
725 matchOrFail(CLOSEBRACE);
726 next();
93a37866 727 return context.createBlockStatement(location, subtree, start, m_lastLine);
6fe7ccc8
A
728}
729
730template <typename LexerType>
731template <class TreeBuilder> TreeStatement Parser<LexerType>::parseStatement(TreeBuilder& context, const Identifier*& directive, unsigned* directiveLiteralLength)
732{
733 DepthManager statementDepth(&m_statementDepth);
734 m_statementDepth++;
735 directive = 0;
736 int nonTrivialExpressionCount = 0;
737 failIfStackOverflow();
738 switch (m_token.m_type) {
739 case OPENBRACE:
740 return parseBlockStatement(context);
741 case VAR:
742 return parseVarDeclaration(context);
743 case CONSTTOKEN:
744 return parseConstDeclaration(context);
745 case FUNCTION:
746 failIfFalseIfStrictWithMessage(m_statementDepth == 1, "Functions cannot be declared in a nested block in strict mode");
747 return parseFunctionDeclaration(context);
93a37866
A
748 case SEMICOLON: {
749 JSTokenLocation location(tokenLocation());
6fe7ccc8 750 next();
93a37866
A
751 return context.createEmptyStatement(location);
752 }
6fe7ccc8
A
753 case IF:
754 return parseIfStatement(context);
755 case DO:
756 return parseDoWhileStatement(context);
757 case WHILE:
758 return parseWhileStatement(context);
759 case FOR:
760 return parseForStatement(context);
761 case CONTINUE:
762 return parseContinueStatement(context);
763 case BREAK:
764 return parseBreakStatement(context);
765 case RETURN:
766 return parseReturnStatement(context);
767 case WITH:
768 return parseWithStatement(context);
769 case SWITCH:
770 return parseSwitchStatement(context);
771 case THROW:
772 return parseThrowStatement(context);
773 case TRY:
774 return parseTryStatement(context);
775 case DEBUGGER:
776 return parseDebuggerStatement(context);
777 case EOFTOK:
778 case CASE:
779 case CLOSEBRACE:
780 case DEFAULT:
781 // These tokens imply the end of a set of source elements
782 return 0;
783 case IDENT:
784 return parseExpressionOrLabelStatement(context);
785 case STRING:
786 directive = m_token.m_data.ident;
787 if (directiveLiteralLength)
93a37866 788 *directiveLiteralLength = m_token.m_location.endOffset - m_token.m_location.startOffset;
6fe7ccc8
A
789 nonTrivialExpressionCount = m_nonTrivialExpressionCount;
790 default:
791 TreeStatement exprStatement = parseExpressionStatement(context);
792 if (directive && nonTrivialExpressionCount != m_nonTrivialExpressionCount)
793 directive = 0;
794 return exprStatement;
795 }
796}
797
798template <typename LexerType>
799template <class TreeBuilder> TreeFormalParameterList Parser<LexerType>::parseFormalParameters(TreeBuilder& context)
800{
801 matchOrFail(IDENT);
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;
805 next();
806 while (match(COMMA)) {
807 next();
808 matchOrFail(IDENT);
809 const Identifier* ident = m_token.m_data.ident;
810 failIfFalseIfStrictWithNameAndMessage(declareParameter(ident), "Cannot declare a parameter named", ident->impl(), "in strict mode");
811 next();
812 tail = context.createFormalParameterList(tail, *ident);
813 }
814 return list;
815}
816
817template <typename LexerType>
818template <class TreeBuilder> TreeFunctionBody Parser<LexerType>::parseFunctionBody(TreeBuilder& context)
819{
93a37866
A
820 JSTokenLocation startLocation(tokenLocation());
821 unsigned startColumn = tokenColumn();
822 next();
823
6fe7ccc8 824 if (match(CLOSEBRACE))
93a37866 825 return context.createFunctionBody(startLocation, tokenLocation(), startColumn, strictMode());
6fe7ccc8
A
826 DepthManager statementDepth(&m_statementDepth);
827 m_statementDepth = 0;
93a37866 828 typename TreeBuilder::FunctionBodyBuilder bodyBuilder(const_cast<VM*>(m_vm), m_lexer.get());
6fe7ccc8 829 failIfFalse(parseSourceElements<CheckForStrictMode>(bodyBuilder));
93a37866 830 return context.createFunctionBody(startLocation, tokenLocation(), startColumn, strictMode());
6fe7ccc8
A
831}
832
833template <typename LexerType>
93a37866 834template <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)
6fe7ccc8
A
835{
836 AutoPopScopeRef functionScope(this, pushScope());
837 functionScope->setIsFunction();
93a37866 838 int functionStart = m_token.m_location.startOffset;
6fe7ccc8
A
839 if (match(IDENT)) {
840 name = m_token.m_data.ident;
841 next();
842 if (!nameIsInContainingScope)
843 failIfFalseIfStrict(functionScope->declareVariable(name));
844 } else if (requirements == FunctionNeedsName)
845 return false;
846 consumeOrFail(OPENPAREN);
847 if (!match(CLOSEPAREN)) {
848 parameters = parseFormalParameters(context);
849 failIfFalse(parameters);
850 }
851 consumeOrFail(CLOSEPAREN);
852 matchOrFail(OPENBRACE);
853
93a37866 854 openBraceOffset = m_token.m_data.offset;
6fe7ccc8 855 bodyStartLine = tokenLine();
93a37866
A
856 bodyStartColumn = m_token.m_data.offset - m_token.m_data.lineStartOffset;
857 JSTokenLocation startLocation(tokenLocation());
6fe7ccc8
A
858
859 // If we know about this function already, we can use the cached info and skip the parser to the end of the function.
93a37866 860 if (const SourceProviderCacheItem* cachedInfo = TreeBuilder::CanUseFunctionCache ? findCachedFunctionInfo(openBraceOffset) : 0) {
6fe7ccc8
A
861 // If we're in a strict context, the cached function info must say it was strict too.
862 ASSERT(!strictMode() || cachedInfo->strictMode);
93a37866
A
863 JSTokenLocation endLocation;
864
865 endLocation.line = cachedInfo->closeBraceLine;
866 endLocation.startOffset = cachedInfo->closeBraceOffset;
867 endLocation.lineStartOffset = cachedInfo->closeBraceLineStartOffset;
868 ASSERT(endLocation.startOffset >= endLocation.lineStartOffset);
869
870 body = context.createFunctionBody(startLocation, endLocation, bodyStartColumn, cachedInfo->strictMode);
6fe7ccc8 871
93a37866 872 functionScope->restoreFromSourceProviderCache(cachedInfo);
6fe7ccc8
A
873 failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo));
874
93a37866
A
875 closeBraceOffset = cachedInfo->closeBraceOffset;
876
877 context.setFunctionStart(body, functionStart);
6fe7ccc8 878 m_token = cachedInfo->closeBraceToken();
93a37866
A
879
880 m_lexer->setOffset(m_token.m_location.endOffset, m_token.m_location.lineStartOffset);
881 m_lexer->setLineNumber(m_token.m_location.line);
6fe7ccc8
A
882
883 next();
884 return true;
885 }
886
6fe7ccc8
A
887 body = parseFunctionBody(context);
888 failIfFalse(body);
889 if (functionScope->strictMode() && name) {
93a37866
A
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");
6fe7ccc8 892 }
93a37866
A
893 closeBraceOffset = m_token.m_data.offset;
894 unsigned closeBraceLine = m_token.m_data.line;
895 unsigned closeBraceLineStartOffset = m_token.m_data.lineStartOffset;
6fe7ccc8
A
896
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.
93a37866 899 static const int minimumFunctionLengthToCache = 16;
6fe7ccc8 900 OwnPtr<SourceProviderCacheItem> newInfo;
93a37866 901 int functionLength = closeBraceOffset - openBraceOffset;
6fe7ccc8 902 if (TreeBuilder::CanUseFunctionCache && m_functionCache && functionLength > minimumFunctionLengthToCache) {
93a37866
A
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);
910
6fe7ccc8 911 }
93a37866 912 context.setFunctionStart(body, functionStart);
6fe7ccc8
A
913
914 failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo));
915 matchOrFail(CLOSEBRACE);
916
93a37866
A
917 if (newInfo)
918 m_functionCache->add(openBraceOffset, newInfo.release());
6fe7ccc8
A
919
920 next();
921 return true;
922}
923
924template <typename LexerType>
925template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDeclaration(TreeBuilder& context)
926{
927 ASSERT(match(FUNCTION));
93a37866 928 JSTokenLocation location(tokenLocation());
6fe7ccc8
A
929 next();
930 const Identifier* name = 0;
931 TreeFormalParameterList parameters = 0;
932 TreeFunctionBody body = 0;
93a37866
A
933 unsigned openBraceOffset = 0;
934 unsigned closeBraceOffset = 0;
6fe7ccc8 935 int bodyStartLine = 0;
93a37866
A
936 unsigned bodyStartColumn = 0;
937 failIfFalse((parseFunctionInfo<FunctionNeedsName, true>(context, name, parameters, body, openBraceOffset, closeBraceOffset, bodyStartLine, bodyStartColumn)));
6fe7ccc8
A
938 failIfFalse(name);
939 failIfFalseIfStrict(declareVariable(name));
93a37866 940 return context.createFuncDeclStatement(location, name, body, parameters, openBraceOffset, closeBraceOffset, bodyStartLine, m_lastLine, bodyStartColumn);
6fe7ccc8
A
941}
942
943struct LabelInfo {
93a37866 944 LabelInfo(const Identifier* ident, unsigned start, unsigned end, unsigned divotLine, unsigned divotLineStart)
6fe7ccc8
A
945 : m_ident(ident)
946 , m_start(start)
947 , m_end(end)
93a37866
A
948 , m_divotLine(divotLine)
949 , m_divotLineStart(divotLineStart)
6fe7ccc8
A
950 {
951 }
952
953 const Identifier* m_ident;
93a37866
A
954 unsigned m_start;
955 unsigned m_end;
956 unsigned m_divotLine;
957 unsigned m_divotLineStart;
6fe7ccc8
A
958};
959
960template <typename LexerType>
961template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionOrLabelStatement(TreeBuilder& context)
962{
963
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.
966 */
967 Vector<LabelInfo> labels;
93a37866 968 JSTokenLocation location;
6fe7ccc8
A
969 do {
970 int start = tokenStart();
93a37866
A
971 int startingLine = tokenLine();
972 location = tokenLocation();
6fe7ccc8
A
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());
93a37866 980 return context.createExprStatement(location, expression, startingLine, m_lastLine);
6fe7ccc8
A
981 }
982 const Identifier* ident = m_token.m_data.ident;
983 int end = tokenEnd();
93a37866
A
984 unsigned divotLine = tokenLine();
985 unsigned divotLineStart = tokenLineStart();
6fe7ccc8
A
986 next();
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));
93a37866 994 labels.append(LabelInfo(ident, start, end, divotLine, divotLineStart));
6fe7ccc8
A
995 }
996 } while (match(IDENT));
997 bool isLoop = false;
998 switch (m_token.m_type) {
999 case FOR:
1000 case WHILE:
1001 case DO:
1002 isLoop = true;
1003 break;
1004
1005 default:
1006 break;
1007 }
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);
1012 }
1013 TreeStatement statement = parseStatement(context, unused);
1014 if (!m_syntaxAlreadyValidated) {
1015 for (size_t i = 0; i < labels.size(); i++)
1016 popLabel();
1017 }
1018 failIfFalse(statement);
1019 for (size_t i = 0; i < labels.size(); i++) {
1020 const LabelInfo& info = labels[labels.size() - i - 1];
93a37866 1021 statement = context.createLabelStatement(location, info.m_ident, statement, info.m_start, info.m_end, info.m_divotLine, info.m_divotLineStart);
6fe7ccc8
A
1022 }
1023 return statement;
1024}
1025
1026template <typename LexerType>
1027template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionStatement(TreeBuilder& context)
1028{
1029 int startLine = tokenLine();
93a37866 1030 JSTokenLocation location(tokenLocation());
6fe7ccc8
A
1031 TreeExpression expression = parseExpression(context);
1032 failIfFalse(expression);
1033 failIfFalse(autoSemiColon());
93a37866 1034 return context.createExprStatement(location, expression, startLine, m_lastLine);
6fe7ccc8
A
1035}
1036
1037template <typename LexerType>
1038template <class TreeBuilder> TreeStatement Parser<LexerType>::parseIfStatement(TreeBuilder& context)
1039{
1040 ASSERT(match(IF));
93a37866 1041 JSTokenLocation ifLocation(tokenLocation());
6fe7ccc8
A
1042 int start = tokenLine();
1043 next();
93a37866 1044
6fe7ccc8 1045 consumeOrFail(OPENPAREN);
93a37866 1046
6fe7ccc8
A
1047 TreeExpression condition = parseExpression(context);
1048 failIfFalse(condition);
1049 int end = tokenLine();
1050 consumeOrFail(CLOSEPAREN);
93a37866 1051
6fe7ccc8
A
1052 const Identifier* unused = 0;
1053 TreeStatement trueBlock = parseStatement(context, unused);
1054 failIfFalse(trueBlock);
93a37866 1055
6fe7ccc8 1056 if (!match(ELSE))
93a37866
A
1057 return context.createIfStatement(ifLocation, condition, trueBlock, 0, start, end);
1058
6fe7ccc8
A
1059 Vector<TreeExpression> exprStack;
1060 Vector<pair<int, int> > posStack;
93a37866 1061 Vector<JSTokenLocation> tokenLocationStack;
6fe7ccc8
A
1062 Vector<TreeStatement> statementStack;
1063 bool trailingElse = false;
1064 do {
93a37866 1065 JSTokenLocation tempLocation = tokenLocation();
6fe7ccc8
A
1066 next();
1067 if (!match(IF)) {
1068 const Identifier* unused = 0;
1069 TreeStatement block = parseStatement(context, unused);
1070 failIfFalse(block);
1071 statementStack.append(block);
1072 trailingElse = true;
1073 break;
1074 }
1075 int innerStart = tokenLine();
1076 next();
93a37866 1077
6fe7ccc8 1078 consumeOrFail(OPENPAREN);
93a37866 1079
6fe7ccc8
A
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);
93a37866
A
1086 failIfFalse(innerTrueBlock);
1087 tokenLocationStack.append(tempLocation);
6fe7ccc8
A
1088 exprStack.append(innerCondition);
1089 posStack.append(make_pair(innerStart, innerEnd));
1090 statementStack.append(innerTrueBlock);
1091 } while (match(ELSE));
93a37866 1092
6fe7ccc8
A
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();
93a37866
A
1100 JSTokenLocation elseLocation = tokenLocationStack.last();
1101 tokenLocationStack.removeLast();
1102 statementStack.append(context.createIfStatement(elseLocation, condition, trueBlock, 0, pos.first, pos.second));
6fe7ccc8 1103 }
93a37866 1104
6fe7ccc8
A
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();
93a37866
A
1114 JSTokenLocation elseLocation = tokenLocationStack.last();
1115 tokenLocationStack.removeLast();
1116 statementStack.append(context.createIfStatement(elseLocation, condition, trueBlock, falseBlock, pos.first, pos.second));
6fe7ccc8 1117 }
93a37866
A
1118
1119 return context.createIfStatement(ifLocation, condition, trueBlock, statementStack.last(), start, end);
6fe7ccc8
A
1120}
1121
1122template <typename LexerType>
1123template <class TreeBuilder> TreeExpression Parser<LexerType>::parseExpression(TreeBuilder& context)
1124{
1125 failIfStackOverflow();
93a37866 1126 JSTokenLocation location(tokenLocation());
6fe7ccc8
A
1127 TreeExpression node = parseAssignmentExpression(context);
1128 failIfFalse(node);
1129 if (!match(COMMA))
1130 return node;
1131 next();
1132 m_nonTrivialExpressionCount++;
1133 m_nonLHSCount++;
1134 TreeExpression right = parseAssignmentExpression(context);
1135 failIfFalse(right);
93a37866 1136 typename TreeBuilder::Comma commaNode = context.createCommaExpr(location, node, right);
6fe7ccc8
A
1137 while (match(COMMA)) {
1138 next(TreeBuilder::DontBuildStrings);
1139 right = parseAssignmentExpression(context);
1140 failIfFalse(right);
1141 context.appendToComma(commaNode, right);
1142 }
1143 return commaNode;
1144}
1145
1146template <typename LexerType>
1147template <typename TreeBuilder> TreeExpression Parser<LexerType>::parseAssignmentExpression(TreeBuilder& context)
1148{
1149 failIfStackOverflow();
1150 int start = tokenStart();
93a37866
A
1151 unsigned line = tokenLine();
1152 unsigned lineStart = tokenLineStart();
1153 JSTokenLocation location(tokenLocation());
6fe7ccc8
A
1154 int initialAssignmentCount = m_assignmentCount;
1155 int initialNonLHSCount = m_nonLHSCount;
1156 TreeExpression lhs = parseConditionalExpression(context);
1157 failIfFalse(lhs);
1158 if (initialNonLHSCount != m_nonLHSCount)
1159 return lhs;
1160
1161 int assignmentStack = 0;
1162 Operator op;
1163 bool hadAssignment = false;
1164 while (true) {
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;
1178 default:
1179 goto end;
1180 }
1181 m_nonTrivialExpressionCount++;
1182 hadAssignment = true;
93a37866 1183 context.assignmentStackAppend(assignmentStack, lhs, start, tokenStart(), line, lineStart, m_assignmentCount, op);
6fe7ccc8 1184 start = tokenStart();
93a37866
A
1185 line = tokenLine();
1186 lineStart = tokenLineStart();
6fe7ccc8
A
1187 m_assignmentCount++;
1188 next(TreeBuilder::DontBuildStrings);
1189 if (strictMode() && m_lastIdentifier && context.isResolve(lhs)) {
93a37866
A
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");
6fe7ccc8
A
1192 declareWrite(m_lastIdentifier);
1193 m_lastIdentifier = 0;
1194 }
1195 lhs = parseConditionalExpression(context);
1196 failIfFalse(lhs);
1197 if (initialNonLHSCount != m_nonLHSCount)
1198 break;
1199 }
1200end:
1201 if (hadAssignment)
1202 m_nonLHSCount++;
1203
1204 if (!TreeBuilder::CreatesAST)
1205 return lhs;
1206
1207 while (assignmentStack)
93a37866 1208 lhs = context.createAssignment(location, assignmentStack, lhs, initialAssignmentCount, m_assignmentCount, lastTokenEnd());
6fe7ccc8
A
1209
1210 return lhs;
1211}
1212
1213template <typename LexerType>
1214template <class TreeBuilder> TreeExpression Parser<LexerType>::parseConditionalExpression(TreeBuilder& context)
1215{
93a37866 1216 JSTokenLocation location(tokenLocation());
6fe7ccc8
A
1217 TreeExpression cond = parseBinaryExpression(context);
1218 failIfFalse(cond);
1219 if (!match(QUESTION))
1220 return cond;
1221 m_nonTrivialExpressionCount++;
1222 m_nonLHSCount++;
1223 next(TreeBuilder::DontBuildStrings);
1224 TreeExpression lhs = parseAssignmentExpression(context);
1225 consumeOrFailWithFlags(COLON, TreeBuilder::DontBuildStrings);
1226
1227 TreeExpression rhs = parseAssignmentExpression(context);
1228 failIfFalse(rhs);
93a37866 1229 return context.createConditionalExpr(location, cond, lhs, rhs);
6fe7ccc8
A
1230}
1231
1232ALWAYS_INLINE static bool isUnaryOp(JSTokenType token)
1233{
1234 return token & UnaryOpTokenFlag;
1235}
1236
1237template <typename LexerType>
1238int Parser<LexerType>::isBinaryOperator(JSTokenType token)
1239{
1240 if (m_allowsIn)
1241 return token & (BinaryOpTokenPrecedenceMask << BinaryOpTokenAllowsInPrecedenceAdditionalShift);
1242 return token & BinaryOpTokenPrecedenceMask;
1243}
1244
1245template <typename LexerType>
1246template <class TreeBuilder> TreeExpression Parser<LexerType>::parseBinaryExpression(TreeBuilder& context)
1247{
1248
1249 int operandStackDepth = 0;
1250 int operatorStackDepth = 0;
1251 typename TreeBuilder::BinaryExprContext binaryExprContext(context);
93a37866 1252 JSTokenLocation location(tokenLocation());
6fe7ccc8
A
1253 while (true) {
1254 int exprStart = tokenStart();
1255 int initialAssignments = m_assignmentCount;
1256 TreeExpression current = parseUnaryExpression(context);
1257 failIfFalse(current);
1258
93a37866 1259 context.appendBinaryExpressionInfo(operandStackDepth, current, exprStart, lastTokenEnd(), lastTokenEnd(), lastTokenLine(), lastTokenLineStart(), initialAssignments != m_assignmentCount);
6fe7ccc8
A
1260 int precedence = isBinaryOperator(m_token.m_type);
1261 if (!precedence)
1262 break;
1263 m_nonTrivialExpressionCount++;
1264 m_nonLHSCount++;
1265 int operatorToken = m_token.m_type;
1266 next(TreeBuilder::DontBuildStrings);
1267
1268 while (operatorStackDepth && context.operatorStackHasHigherPrecedence(operatorStackDepth, precedence)) {
1269 ASSERT(operandStackDepth > 1);
1270
1271 typename TreeBuilder::BinaryOperand rhs = context.getFromOperandStack(-1);
1272 typename TreeBuilder::BinaryOperand lhs = context.getFromOperandStack(-2);
1273 context.shrinkOperandStackBy(operandStackDepth, 2);
93a37866 1274 context.appendBinaryOperation(location, operandStackDepth, operatorStackDepth, lhs, rhs);
6fe7ccc8
A
1275 context.operatorStackPop(operatorStackDepth);
1276 }
1277 context.operatorStackAppend(operatorStackDepth, operatorToken, precedence);
1278 }
1279 while (operatorStackDepth) {
1280 ASSERT(operandStackDepth > 1);
1281
1282 typename TreeBuilder::BinaryOperand rhs = context.getFromOperandStack(-1);
1283 typename TreeBuilder::BinaryOperand lhs = context.getFromOperandStack(-2);
1284 context.shrinkOperandStackBy(operandStackDepth, 2);
93a37866 1285 context.appendBinaryOperation(location, operandStackDepth, operatorStackDepth, lhs, rhs);
6fe7ccc8
A
1286 context.operatorStackPop(operatorStackDepth);
1287 }
1288 return context.popOperandStack(operandStackDepth);
1289}
1290
1291template <typename LexerType>
1292template <bool complete, class TreeBuilder> TreeProperty Parser<LexerType>::parseProperty(TreeBuilder& context)
1293{
1294 bool wasIdent = false;
1295 switch (m_token.m_type) {
1296 namedProperty:
1297 case IDENT:
1298 wasIdent = true;
1299 case STRING: {
1300 const Identifier* ident = m_token.m_data.ident;
93a37866 1301 if (complete || (wasIdent && (*ident == m_vm->propertyNames->get || *ident == m_vm->propertyNames->set)))
6fe7ccc8
A
1302 nextExpectIdentifier(LexerFlagsIgnoreReservedWords);
1303 else
1304 nextExpectIdentifier(LexerFlagsIgnoreReservedWords | TreeBuilder::DontBuildKeywords);
1305
1306 if (match(COLON)) {
1307 next();
1308 TreeExpression node = parseAssignmentExpression(context);
1309 failIfFalse(node);
1310 return context.template createProperty<complete>(ident, node, PropertyNode::Constant);
1311 }
1312 failIfFalse(wasIdent);
1313 const Identifier* accessorName = 0;
1314 TreeFormalParameterList parameters = 0;
1315 TreeFunctionBody body = 0;
93a37866
A
1316 unsigned openBraceOffset = 0;
1317 unsigned closeBraceOffset = 0;
6fe7ccc8 1318 int bodyStartLine = 0;
93a37866 1319 unsigned bodyStartColumn = 0;
6fe7ccc8 1320 PropertyNode::Type type;
93a37866 1321 if (*ident == m_vm->propertyNames->get)
6fe7ccc8 1322 type = PropertyNode::Getter;
93a37866 1323 else if (*ident == m_vm->propertyNames->set)
6fe7ccc8
A
1324 type = PropertyNode::Setter;
1325 else
1326 fail();
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;
1333 else
1334 fail();
93a37866 1335 JSTokenLocation location(tokenLocation());
6fe7ccc8 1336 next();
93a37866 1337 failIfFalse((parseFunctionInfo<FunctionNoRequirements, false>(context, accessorName, parameters, body, openBraceOffset, closeBraceOffset, bodyStartLine, bodyStartColumn)));
6fe7ccc8 1338 if (stringPropertyName)
93a37866
A
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);
6fe7ccc8
A
1341 }
1342 case NUMBER: {
1343 double propertyName = m_token.m_data.doubleValue;
1344 next();
1345 consumeOrFail(COLON);
1346 TreeExpression node = parseAssignmentExpression(context);
1347 failIfFalse(node);
93a37866 1348 return context.template createProperty<complete>(const_cast<VM*>(m_vm), propertyName, node, PropertyNode::Constant);
6fe7ccc8
A
1349 }
1350 default:
1351 failIfFalse(m_token.m_type & KeywordTokenFlag);
1352 goto namedProperty;
1353 }
1354}
1355
1356template <typename LexerType>
1357template <class TreeBuilder> TreeExpression Parser<LexerType>::parseObjectLiteral(TreeBuilder& context)
1358{
93a37866
A
1359 int startOffset = m_token.m_data.offset;
1360 unsigned oldLineStartOffset = m_lexer->currentLineStartOffset();
6fe7ccc8
A
1361 unsigned oldLastLineNumber = m_lexer->lastLineNumber();
1362 unsigned oldLineNumber = m_lexer->lineNumber();
1363 consumeOrFailWithFlags(OPENBRACE, TreeBuilder::DontBuildStrings);
93a37866
A
1364 JSTokenLocation location(tokenLocation());
1365
6fe7ccc8
A
1366 int oldNonLHSCount = m_nonLHSCount;
1367
1368 if (match(CLOSEBRACE)) {
1369 next();
93a37866 1370 return context.createObjectLiteral(location);
6fe7ccc8
A
1371 }
1372
1373 TreeProperty property = parseProperty<false>(context);
1374 failIfFalse(property);
1375 if (!m_syntaxAlreadyValidated && context.getType(property) != PropertyNode::Constant) {
93a37866 1376 m_lexer->setOffset(startOffset, oldLineStartOffset);
6fe7ccc8
A
1377 next();
1378 m_lexer->setLastLineNumber(oldLastLineNumber);
1379 m_lexer->setLineNumber(oldLineNumber);
1380 return parseStrictObjectLiteral(context);
1381 }
93a37866 1382 TreePropertyList propertyList = context.createPropertyList(location, property);
6fe7ccc8
A
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))
1388 break;
93a37866 1389 JSTokenLocation propertyLocation(tokenLocation());
6fe7ccc8
A
1390 property = parseProperty<false>(context);
1391 failIfFalse(property);
1392 if (!m_syntaxAlreadyValidated && context.getType(property) != PropertyNode::Constant) {
93a37866 1393 m_lexer->setOffset(startOffset, oldLineStartOffset);
6fe7ccc8
A
1394 next();
1395 m_lexer->setLastLineNumber(oldLastLineNumber);
1396 m_lexer->setLineNumber(oldLineNumber);
1397 return parseStrictObjectLiteral(context);
1398 }
93a37866 1399 tail = context.createPropertyList(propertyLocation, property, tail);
6fe7ccc8 1400 }
93a37866
A
1401
1402 location = tokenLocation();
6fe7ccc8
A
1403 consumeOrFail(CLOSEBRACE);
1404
1405 m_nonLHSCount = oldNonLHSCount;
1406
93a37866 1407 return context.createObjectLiteral(location, propertyList);
6fe7ccc8
A
1408}
1409
1410template <typename LexerType>
1411template <class TreeBuilder> TreeExpression Parser<LexerType>::parseStrictObjectLiteral(TreeBuilder& context)
1412{
1413 consumeOrFail(OPENBRACE);
1414
1415 int oldNonLHSCount = m_nonLHSCount;
1416
93a37866 1417 JSTokenLocation location(tokenLocation());
6fe7ccc8
A
1418 if (match(CLOSEBRACE)) {
1419 next();
93a37866 1420 return context.createObjectLiteral(location);
6fe7ccc8
A
1421 }
1422
1423 TreeProperty property = parseProperty<true>(context);
1424 failIfFalse(property);
1425
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));
1431
93a37866 1432 TreePropertyList propertyList = context.createPropertyList(location, property);
6fe7ccc8
A
1433 TreePropertyList tail = propertyList;
1434 while (match(COMMA)) {
1435 next();
1436 // allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939
1437 if (match(CLOSEBRACE))
1438 break;
93a37866 1439 JSTokenLocation propertyLocation(tokenLocation());
6fe7ccc8
A
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) {
93a37866 1445 failIfTrue(propertyEntry.iterator->value == PropertyNode::Constant);
6fe7ccc8 1446 failIfTrue(context.getType(property) == PropertyNode::Constant);
93a37866
A
1447 failIfTrue(context.getType(property) & propertyEntry.iterator->value);
1448 propertyEntry.iterator->value |= context.getType(property);
6fe7ccc8
A
1449 }
1450 }
93a37866 1451 tail = context.createPropertyList(propertyLocation, property, tail);
6fe7ccc8 1452 }
93a37866
A
1453
1454 location = tokenLocation();
6fe7ccc8
A
1455 consumeOrFail(CLOSEBRACE);
1456
1457 m_nonLHSCount = oldNonLHSCount;
1458
93a37866 1459 return context.createObjectLiteral(location, propertyList);
6fe7ccc8
A
1460}
1461
1462template <typename LexerType>
1463template <class TreeBuilder> TreeExpression Parser<LexerType>::parseArrayLiteral(TreeBuilder& context)
1464{
1465 consumeOrFailWithFlags(OPENBRACKET, TreeBuilder::DontBuildStrings);
1466
1467 int oldNonLHSCount = m_nonLHSCount;
1468
1469 int elisions = 0;
1470 while (match(COMMA)) {
1471 next(TreeBuilder::DontBuildStrings);
1472 elisions++;
1473 }
1474 if (match(CLOSEBRACKET)) {
93a37866 1475 JSTokenLocation location(tokenLocation());
6fe7ccc8 1476 next(TreeBuilder::DontBuildStrings);
93a37866 1477 return context.createArray(location, elisions);
6fe7ccc8
A
1478 }
1479
1480 TreeExpression elem = parseAssignmentExpression(context);
1481 failIfFalse(elem);
1482 typename TreeBuilder::ElementList elementList = context.createElementList(elisions, elem);
1483 typename TreeBuilder::ElementList tail = elementList;
1484 elisions = 0;
1485 while (match(COMMA)) {
1486 next(TreeBuilder::DontBuildStrings);
1487 elisions = 0;
1488
1489 while (match(COMMA)) {
1490 next();
1491 elisions++;
1492 }
1493
1494 if (match(CLOSEBRACKET)) {
93a37866 1495 JSTokenLocation location(tokenLocation());
6fe7ccc8 1496 next(TreeBuilder::DontBuildStrings);
93a37866 1497 return context.createArray(location, elisions, elementList);
6fe7ccc8
A
1498 }
1499 TreeExpression elem = parseAssignmentExpression(context);
1500 failIfFalse(elem);
1501 tail = context.createElementList(tail, elisions, elem);
1502 }
93a37866
A
1503
1504 JSTokenLocation location(tokenLocation());
6fe7ccc8
A
1505 consumeOrFail(CLOSEBRACKET);
1506
1507 m_nonLHSCount = oldNonLHSCount;
1508
93a37866 1509 return context.createArray(location, elementList);
6fe7ccc8
A
1510}
1511
1512template <typename LexerType>
1513template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePrimaryExpression(TreeBuilder& context)
1514{
1515 failIfStackOverflow();
1516 switch (m_token.m_type) {
1517 case OPENBRACE:
1518 if (strictMode())
1519 return parseStrictObjectLiteral(context);
1520 return parseObjectLiteral(context);
1521 case OPENBRACKET:
1522 return parseArrayLiteral(context);
1523 case OPENPAREN: {
1524 next();
1525 int oldNonLHSCount = m_nonLHSCount;
1526 TreeExpression result = parseExpression(context);
1527 m_nonLHSCount = oldNonLHSCount;
1528 consumeOrFail(CLOSEPAREN);
1529
1530 return result;
1531 }
1532 case THISTOKEN: {
93a37866 1533 JSTokenLocation location(tokenLocation());
6fe7ccc8 1534 next();
93a37866 1535 return context.thisExpr(location);
6fe7ccc8
A
1536 }
1537 case IDENT: {
1538 int start = tokenStart();
93a37866
A
1539 int line = tokenLine();
1540 int lineStart = tokenLineStart();
6fe7ccc8 1541 const Identifier* ident = m_token.m_data.ident;
93a37866 1542 JSTokenLocation location(tokenLocation());
6fe7ccc8 1543 next();
93a37866 1544 currentScope()->useVariable(ident, m_vm->propertyNames->eval == *ident);
6fe7ccc8 1545 m_lastIdentifier = ident;
93a37866 1546 return context.createResolve(location, ident, start, line, lineStart);
6fe7ccc8
A
1547 }
1548 case STRING: {
1549 const Identifier* ident = m_token.m_data.ident;
93a37866 1550 JSTokenLocation location(tokenLocation());
6fe7ccc8 1551 next();
93a37866 1552 return context.createString(location, ident);
6fe7ccc8
A
1553 }
1554 case NUMBER: {
1555 double d = m_token.m_data.doubleValue;
93a37866 1556 JSTokenLocation location(tokenLocation());
6fe7ccc8 1557 next();
93a37866 1558 return context.createNumberExpr(location, d);
6fe7ccc8
A
1559 }
1560 case NULLTOKEN: {
93a37866 1561 JSTokenLocation location(tokenLocation());
6fe7ccc8 1562 next();
93a37866 1563 return context.createNull(location);
6fe7ccc8
A
1564 }
1565 case TRUETOKEN: {
93a37866 1566 JSTokenLocation location(tokenLocation());
6fe7ccc8 1567 next();
93a37866 1568 return context.createBoolean(location, true);
6fe7ccc8
A
1569 }
1570 case FALSETOKEN: {
93a37866 1571 JSTokenLocation location(tokenLocation());
6fe7ccc8 1572 next();
93a37866 1573 return context.createBoolean(location, false);
6fe7ccc8
A
1574 }
1575 case DIVEQUAL:
1576 case DIVIDE: {
1577 /* regexp */
1578 const Identifier* pattern;
1579 const Identifier* flags;
1580 if (match(DIVEQUAL))
1581 failIfFalse(m_lexer->scanRegExp(pattern, flags, '='));
1582 else
1583 failIfFalse(m_lexer->scanRegExp(pattern, flags));
1584
1585 int start = tokenStart();
93a37866
A
1586 int line = tokenLine();
1587 int lineStart = tokenLineStart();
1588 JSTokenLocation location(tokenLocation());
6fe7ccc8 1589 next();
93a37866 1590 TreeExpression re = context.createRegExp(location, *pattern, *flags, start, line, lineStart);
6fe7ccc8 1591 if (!re) {
93a37866 1592 const char* yarrErrorMsg = Yarr::checkSyntax(pattern->string());
6fe7ccc8
A
1593 failWithMessage(yarrErrorMsg);
1594 }
1595 return re;
1596 }
1597 default:
1598 fail();
1599 }
1600}
1601
1602template <typename LexerType>
1603template <class TreeBuilder> TreeArguments Parser<LexerType>::parseArguments(TreeBuilder& context)
1604{
1605 consumeOrFailWithFlags(OPENPAREN, TreeBuilder::DontBuildStrings);
93a37866 1606 JSTokenLocation location(tokenLocation());
6fe7ccc8
A
1607 if (match(CLOSEPAREN)) {
1608 next(TreeBuilder::DontBuildStrings);
1609 return context.createArguments();
1610 }
1611 TreeExpression firstArg = parseAssignmentExpression(context);
1612 failIfFalse(firstArg);
1613
93a37866 1614 TreeArgumentsList argList = context.createArgumentsList(location, firstArg);
6fe7ccc8
A
1615 TreeArgumentsList tail = argList;
1616 while (match(COMMA)) {
93a37866 1617 JSTokenLocation argumentLocation(tokenLocation());
6fe7ccc8
A
1618 next(TreeBuilder::DontBuildStrings);
1619 TreeExpression arg = parseAssignmentExpression(context);
1620 failIfFalse(arg);
93a37866 1621 tail = context.createArgumentsList(argumentLocation, tail, arg);
6fe7ccc8
A
1622 }
1623 consumeOrFail(CLOSEPAREN);
1624 return context.createArguments(argList);
1625}
1626
1627template <typename LexerType>
1628template <class TreeBuilder> TreeExpression Parser<LexerType>::parseMemberExpression(TreeBuilder& context)
1629{
1630 TreeExpression base = 0;
1631 int start = tokenStart();
1632 int expressionStart = start;
93a37866
A
1633 int expressionLine = tokenLine();
1634 int expressionLineStart = tokenLineStart();
6fe7ccc8 1635 int newCount = 0;
93a37866 1636 JSTokenLocation location;
6fe7ccc8
A
1637 while (match(NEW)) {
1638 next();
1639 newCount++;
1640 }
1641
1642 if (match(FUNCTION)) {
93a37866 1643 const Identifier* name = &m_vm->propertyNames->nullIdentifier;
6fe7ccc8
A
1644 TreeFormalParameterList parameters = 0;
1645 TreeFunctionBody body = 0;
93a37866
A
1646 unsigned openBraceOffset = 0;
1647 unsigned closeBraceOffset = 0;
6fe7ccc8 1648 int bodyStartLine = 0;
93a37866
A
1649 unsigned bodyStartColumn = 0;
1650 location = tokenLocation();
6fe7ccc8 1651 next();
93a37866
A
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);
6fe7ccc8
A
1654 } else
1655 base = parsePrimaryExpression(context);
1656
1657 failIfFalse(base);
1658 while (true) {
93a37866 1659 location = tokenLocation();
6fe7ccc8
A
1660 switch (m_token.m_type) {
1661 case OPENBRACKET: {
1662 m_nonTrivialExpressionCount++;
1663 int expressionEnd = lastTokenEnd();
93a37866
A
1664 int expressionLine = lastTokenLine();
1665 int expressionLineStart = lastTokenLineStart();
6fe7ccc8
A
1666 next();
1667 int nonLHSCount = m_nonLHSCount;
1668 int initialAssignments = m_assignmentCount;
1669 TreeExpression property = parseExpression(context);
1670 failIfFalse(property);
93a37866 1671 base = context.createBracketAccess(location, base, property, initialAssignments != m_assignmentCount, expressionStart, expressionEnd, tokenEnd(), expressionLine, expressionLineStart);
6fe7ccc8
A
1672 consumeOrFail(CLOSEBRACKET);
1673 m_nonLHSCount = nonLHSCount;
1674 break;
1675 }
1676 case OPENPAREN: {
1677 m_nonTrivialExpressionCount++;
1678 int nonLHSCount = m_nonLHSCount;
1679 if (newCount) {
1680 newCount--;
1681 int exprEnd = lastTokenEnd();
93a37866
A
1682 unsigned expressionLine = lastTokenLine();
1683 unsigned expressionLineStart = lastTokenLineStart();
6fe7ccc8
A
1684 TreeArguments arguments = parseArguments(context);
1685 failIfFalse(arguments);
93a37866 1686 base = context.createNewExpr(location, base, arguments, start, exprEnd, lastTokenEnd(), expressionLine, expressionLineStart);
6fe7ccc8
A
1687 } else {
1688 int expressionEnd = lastTokenEnd();
93a37866
A
1689 unsigned expressionLine = lastTokenLine();
1690 int expressionLineStart = lastTokenLineStart();
6fe7ccc8
A
1691 TreeArguments arguments = parseArguments(context);
1692 failIfFalse(arguments);
93a37866 1693 base = context.makeFunctionCallNode(location, base, arguments, expressionStart, expressionEnd, lastTokenEnd(), expressionLine, expressionLineStart);
6fe7ccc8
A
1694 }
1695 m_nonLHSCount = nonLHSCount;
1696 break;
1697 }
1698 case DOT: {
1699 m_nonTrivialExpressionCount++;
1700 int expressionEnd = lastTokenEnd();
93a37866 1701 expressionLineStart = lastTokenLineStart();
6fe7ccc8
A
1702 nextExpectIdentifier(LexerFlagsIgnoreReservedWords | TreeBuilder::DontBuildKeywords);
1703 matchOrFail(IDENT);
93a37866 1704 base = context.createDotAccess(location, base, m_token.m_data.ident, expressionStart, expressionEnd, tokenEnd(), expressionLine, expressionLineStart);
6fe7ccc8
A
1705 next();
1706 break;
1707 }
1708 default:
1709 goto endMemberExpression;
1710 }
1711 }
1712endMemberExpression:
1713 while (newCount--)
93a37866 1714 base = context.createNewExpr(location, base, start, lastTokenEnd(), expressionLine, expressionLineStart);
6fe7ccc8
A
1715 return base;
1716}
1717
1718template <typename LexerType>
1719template <class TreeBuilder> TreeExpression Parser<LexerType>::parseUnaryExpression(TreeBuilder& context)
1720{
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)) {
1727 if (strictMode()) {
1728 switch (m_token.m_type) {
1729 case PLUSPLUS:
1730 case MINUSMINUS:
1731 case AUTOPLUSPLUS:
1732 case AUTOMINUSMINUS:
1733 failIfTrue(requiresLExpr);
1734 modifiesExpr = true;
1735 requiresLExpr = true;
1736 break;
1737 case DELETETOKEN:
1738 failIfTrue(requiresLExpr);
1739 requiresLExpr = true;
1740 break;
1741 default:
1742 failIfTrue(requiresLExpr);
1743 break;
1744 }
1745 }
1746 m_nonLHSCount++;
93a37866 1747 context.appendUnaryToken(tokenStackDepth, m_token.m_type, tokenStart(), tokenLine(), tokenLineStart());
6fe7ccc8
A
1748 next();
1749 m_nonTrivialExpressionCount++;
1750 }
1751 int subExprStart = tokenStart();
93a37866
A
1752 int subExprLine = tokenLine();
1753 int subExprLineStartPosition = tokenLineStart();
1754 ASSERT(subExprStart >= subExprLineStartPosition);
1755 JSTokenLocation location(tokenLocation());
6fe7ccc8
A
1756 TreeExpression expr = parseMemberExpression(context);
1757 failIfFalse(expr);
1758 bool isEvalOrArguments = false;
1759 if (strictMode() && !m_syntaxAlreadyValidated) {
1760 if (context.isResolve(expr))
93a37866 1761 isEvalOrArguments = *m_lastIdentifier == m_vm->propertyNames->eval || *m_lastIdentifier == m_vm->propertyNames->arguments;
6fe7ccc8
A
1762 }
1763 failIfTrueIfStrictWithNameAndMessage(isEvalOrArguments && modifiesExpr, "'", m_lastIdentifier->impl(), "' cannot be modified in strict mode");
1764 switch (m_token.m_type) {
1765 case PLUSPLUS:
1766 m_nonTrivialExpressionCount++;
1767 m_nonLHSCount++;
93a37866 1768 expr = context.makePostfixNode(location, expr, OpPlusPlus, subExprStart, lastTokenEnd(), tokenEnd(), tokenLine(), tokenLineStart());
6fe7ccc8
A
1769 m_assignmentCount++;
1770 failIfTrueIfStrictWithNameAndMessage(isEvalOrArguments, "'", m_lastIdentifier->impl(), "' cannot be modified in strict mode");
1771 failIfTrueIfStrict(requiresLExpr);
1772 next();
1773 break;
1774 case MINUSMINUS:
1775 m_nonTrivialExpressionCount++;
1776 m_nonLHSCount++;
93a37866 1777 expr = context.makePostfixNode(location, expr, OpMinusMinus, subExprStart, lastTokenEnd(), tokenEnd(), tokenLine(), tokenLineStart());
6fe7ccc8
A
1778 m_assignmentCount++;
1779 failIfTrueIfStrictWithNameAndMessage(isEvalOrArguments, "'", m_lastIdentifier->impl(), "' cannot be modified in strict mode");
1780 failIfTrueIfStrict(requiresLExpr);
1781 next();
1782 break;
1783 default:
1784 break;
1785 }
1786
1787 int end = lastTokenEnd();
93a37866
A
1788 int endLine = lastTokenLine();
1789 int endLineStartPosition = lastTokenLineStart();
1790
6fe7ccc8
A
1791 if (!TreeBuilder::CreatesAST && (m_syntaxAlreadyValidated || !strictMode()))
1792 return expr;
93a37866
A
1793
1794 location = tokenLocation();
1795 location.line = m_lexer->lastLineNumber();
6fe7ccc8
A
1796 while (tokenStackDepth) {
1797 switch (context.unaryTokenStackLastType(tokenStackDepth)) {
1798 case EXCLAMATION:
93a37866 1799 expr = context.createLogicalNot(location, expr);
6fe7ccc8
A
1800 break;
1801 case TILDE:
93a37866 1802 expr = context.makeBitwiseNotNode(location, expr);
6fe7ccc8
A
1803 break;
1804 case MINUS:
93a37866 1805 expr = context.makeNegateNode(location, expr);
6fe7ccc8
A
1806 break;
1807 case PLUS:
93a37866 1808 expr = context.createUnaryPlus(location, expr);
6fe7ccc8
A
1809 break;
1810 case PLUSPLUS:
1811 case AUTOPLUSPLUS:
93a37866 1812 expr = context.makePrefixNode(location, expr, OpPlusPlus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end, subExprLine, subExprLineStartPosition);
6fe7ccc8
A
1813 m_assignmentCount++;
1814 break;
1815 case MINUSMINUS:
1816 case AUTOMINUSMINUS:
93a37866 1817 expr = context.makePrefixNode(location, expr, OpMinusMinus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end, subExprLine, subExprLineStartPosition);
6fe7ccc8
A
1818 m_assignmentCount++;
1819 break;
1820 case TYPEOF:
93a37866 1821 expr = context.makeTypeOfNode(location, expr);
6fe7ccc8
A
1822 break;
1823 case VOIDTOKEN:
93a37866 1824 expr = context.createVoid(location, expr);
6fe7ccc8
A
1825 break;
1826 case DELETETOKEN:
1827 failIfTrueIfStrictWithNameAndMessage(context.isResolve(expr), "Cannot delete unqualified property", m_lastIdentifier->impl(), "in strict mode");
93a37866 1828 expr = context.makeDeleteNode(location, expr, context.unaryTokenStackLastStart(tokenStackDepth), end, end, endLine, endLineStartPosition);
6fe7ccc8
A
1829 break;
1830 default:
1831 // If we get here something has gone horribly horribly wrong
1832 CRASH();
1833 }
1834 subExprStart = context.unaryTokenStackLastStart(tokenStackDepth);
93a37866 1835 subExprLineStartPosition = context.unaryTokenStackLastLineStartPosition(tokenStackDepth);
6fe7ccc8
A
1836 context.unaryTokenStackRemoveLast(tokenStackDepth);
1837 }
1838 return expr;
1839}
1840
1841// Instantiate the two flavors of Parser we need instead of putting most of this file in Parser.h
1842template class Parser< Lexer<LChar> >;
1843template class Parser< Lexer<UChar> >;
1844
9dae56ea 1845} // namespace JSC