]> git.saurik.com Git - apple/javascriptcore.git/blob - parser/Parser.cpp
JavaScriptCore-1218.34.tar.gz
[apple/javascriptcore.git] / parser / Parser.cpp
1 /*
2 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
3 * Copyright (C) 2001 Peter Kelly (pmk@post.com)
4 * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc. All rights reserved.
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
26 #include "ASTBuilder.h"
27 #include "CodeBlock.h"
28 #include "Debugger.h"
29 #include "JSCJSValueInlines.h"
30 #include "Lexer.h"
31 #include "NodeInfo.h"
32 #include "SourceProvider.h"
33 #include "VM.h"
34 #include <utility>
35 #include <wtf/HashFunctions.h>
36 #include <wtf/OwnPtr.h>
37 #include <wtf/WTFThreadData.h>
38
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
61 using namespace std;
62
63 namespace JSC {
64
65 template <typename LexerType>
66 Parser<LexerType>::Parser(VM* vm, const SourceCode& source, FunctionParameters* parameters, const Identifier& name, JSParserStrictness strictness, JSParserMode parserMode)
67 : m_vm(vm)
68 , m_source(&source)
69 , m_stack(wtfThreadData().stack())
70 , m_hasStackOverflow(false)
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)
81 {
82 m_lexer = adoptPtr(new LexerType(vm));
83 m_arena = m_vm->parserArena.get();
84 m_lexer->setCode(source, m_arena);
85 m_token.m_location.endOffset = source.startOffset();
86 m_token.m_location.lineStartOffset = source.startOffset();
87
88 m_functionCache = vm->addSourceProviderCache(source.provider());
89 ScopeRef scope = pushScope();
90 if (parserMode == JSParseFunctionCode)
91 scope->setIsFunction();
92 if (strictness == JSParseStrict)
93 scope->setStrictMode();
94 if (parameters) {
95 for (unsigned i = 0; i < parameters->size(); i++)
96 scope->declareParameter(&parameters->at(i));
97 }
98 if (!name.isNull())
99 scope->declareCallee(&name);
100 next();
101 }
102
103 template <typename LexerType>
104 Parser<LexerType>::~Parser()
105 {
106 }
107
108 template <typename LexerType>
109 String Parser<LexerType>::parseInner()
110 {
111 String parseError = String();
112
113 ASTBuilder context(const_cast<VM*>(m_vm), const_cast<SourceCode*>(m_source));
114 if (m_lexer->isReparsing())
115 m_statementDepth--;
116 ScopeRef scope = currentScope();
117 SourceElements* sourceElements = parseSourceElements<CheckForStrictMode>(context);
118 if (!sourceElements || !consume(EOFTOK)) {
119 if (hasError())
120 parseError = m_errorMessage;
121 else
122 parseError = ASCIILiteral("Parser error");
123 }
124
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;
132
133 didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), features,
134 m_lastLine, context.numConstants(), capturedVariables);
135
136 return parseError;
137 }
138
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)
142 {
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;
150 }
151
152 template <typename LexerType>
153 bool Parser<LexerType>::allowAutomaticSemicolon()
154 {
155 return match(CLOSEBRACE) || match(EOFTOK) || m_lexer->prevTerminator();
156 }
157
158 template <typename LexerType>
159 template <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;
166 unsigned startOffset = m_token.m_location.startOffset;
167 unsigned startLineStartOffset = m_token.m_location.lineStartOffset;
168 unsigned oldLastLineNumber = m_lexer->lastLineNumber();
169 unsigned oldLineNumber = m_lexer->lineNumber();
170 bool hasSetStrict = false;
171 while (TreeStatement statement = parseStatement(context, directive, &directiveLiteralLength)) {
172 if (mode == CheckForStrictMode && !seenNonDirective) {
173 if (directive) {
174 // "use strict" must be the exact literal without escape sequences or line continuation.
175 if (!hasSetStrict && directiveLiteralLength == lengthOfUseStrictLiteral && m_vm->propertyNames->useStrictIdentifier == *directive) {
176 setStrictMode();
177 hasSetStrict = true;
178 failIfFalse(isValidStrictMode());
179 m_lexer->setOffset(startOffset, startLineStartOffset);
180 next();
181 m_lexer->setLastLineNumber(oldLastLineNumber);
182 m_lexer->setLineNumber(oldLineNumber);
183 failIfTrue(hasError());
184 continue;
185 }
186 } else
187 seenNonDirective = true;
188 }
189 context.appendStatement(sourceElements, statement);
190 }
191
192 failIfTrue(hasError());
193 return sourceElements;
194 }
195
196 template <typename LexerType>
197 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseVarDeclaration(TreeBuilder& context)
198 {
199 ASSERT(match(VAR));
200 JSTokenLocation location(tokenLocation());
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);
208 failIfTrue(hasError());
209 failIfFalse(autoSemiColon());
210
211 return context.createVarStatement(location, varDecls, start, end);
212 }
213
214 template <typename LexerType>
215 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseConstDeclaration(TreeBuilder& context)
216 {
217 ASSERT(match(CONSTTOKEN));
218 JSTokenLocation location(tokenLocation());
219 int start = tokenLine();
220 int end = 0;
221 TreeConstDeclList constDecls = parseConstDeclarationList(context);
222 failIfTrue(hasError());
223 failIfFalse(autoSemiColon());
224
225 return context.createConstStatement(location, constDecls, start, end);
226 }
227
228 template <typename LexerType>
229 template <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();
240 JSTokenLocation location(tokenLocation());
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.
248 return context.createDoWhileStatement(location, statement, expr, startLine, endLine);
249 }
250
251 template <typename LexerType>
252 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWhileStatement(TreeBuilder& context)
253 {
254 ASSERT(match(WHILE));
255 JSTokenLocation location(tokenLocation());
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);
268 return context.createWhileStatement(location, expr, statement, startLine, endLine);
269 }
270
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)
273 {
274 TreeExpression varDecls = 0;
275 do {
276 declarations++;
277 JSTokenLocation location(tokenLocation());
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;
291 unsigned varLine = tokenLine();
292 unsigned varLineStart = tokenLineStart();
293 initStart = tokenStart();
294 next(TreeBuilder::DontBuildStrings); // consume '='
295 TreeExpression initializer = parseAssignmentExpression(context);
296 initEnd = lastTokenEnd();
297 lastInitializer = initializer;
298 failIfFalse(initializer);
299
300 TreeExpression node = context.createAssignResolve(location, *name, initializer, varStart, varDivot, lastTokenEnd(), varLine, varLineStart);
301 if (!varDecls)
302 varDecls = node;
303 else
304 varDecls = context.combineCommaNodes(location, varDecls, node);
305 }
306 } while (match(COMMA));
307 return varDecls;
308 }
309
310 template <typename LexerType>
311 template <class TreeBuilder> TreeConstDeclList Parser<LexerType>::parseConstDeclarationList(TreeBuilder& context)
312 {
313 failIfTrue(strictMode());
314 TreeConstDeclList constDecls = 0;
315 TreeConstDeclList tail = 0;
316 do {
317 JSTokenLocation location(tokenLocation());
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));
325
326 TreeExpression initializer = 0;
327 if (hasInitializer) {
328 next(TreeBuilder::DontBuildStrings); // consume '='
329 initializer = parseAssignmentExpression(context);
330 }
331 tail = context.appendConstDecl(location, tail, name, initializer);
332 if (!constDecls)
333 constDecls = tail;
334 } while (match(COMMA));
335 return constDecls;
336 }
337
338 template <typename LexerType>
339 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseForStatement(TreeBuilder& context)
340 {
341 ASSERT(match(FOR));
342 JSTokenLocation location(tokenLocation());
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;
350 unsigned declsLine = 0;
351 unsigned declsLineStart = 0;
352 TreeExpression decls = 0;
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 */
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;
366 failIfTrue(hasError());
367
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();
376 unsigned inLine = tokenLine();
377 unsigned inLineStart = tokenLineStart();
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
393 return context.createForInLoop(location, forInTarget, forInInitializer, expr, statement, declsStart, inLocation, exprEnd, initStart, initEnd, startLine, endLine, inLine, inLineStart);
394 }
395
396 if (!match(SEMICOLON)) {
397 m_allowsIn = false;
398 declsStart = tokenStart();
399 decls = parseExpression(context);
400 declsEnd = lastTokenEnd();
401 declsLine = lastTokenLine();
402 declsLineStart = lastTokenLineStart();
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);
431 return context.createForLoop(location, decls, condition, increment, statement, startLine, endLine);
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
448 return context.createForInLoop(location, decls, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine, declsLine, declsLineStart);
449 }
450
451 template <typename LexerType>
452 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBreakStatement(TreeBuilder& context)
453 {
454 ASSERT(match(BREAK));
455 JSTokenLocation location(tokenLocation());
456 int startCol = tokenStart();
457 int endCol = tokenEnd();
458 int startLine = tokenLine();
459 int endLine = tokenLine();
460 unsigned endLineStart = tokenLineStart();
461 next();
462
463 if (autoSemiColon()) {
464 failIfFalseWithMessage(breakIsValid(), "'break' is only valid inside a switch or loop statement");
465 return context.createBreakStatement(location, startCol, endCol, startLine, endLine, endLineStart);
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();
472 endLineStart = tokenLineStart();
473 next();
474 failIfFalse(autoSemiColon());
475 return context.createBreakStatement(location, ident, startCol, endCol, startLine, endLine, endLineStart);
476 }
477
478 template <typename LexerType>
479 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseContinueStatement(TreeBuilder& context)
480 {
481 ASSERT(match(CONTINUE));
482 JSTokenLocation location(tokenLocation());
483 int startCol = tokenStart();
484 int endCol = tokenEnd();
485 int startLine = tokenLine();
486 int endLine = tokenLine();
487 unsigned endLineStart = tokenLineStart();
488 next();
489
490 if (autoSemiColon()) {
491 failIfFalseWithMessage(continueIsValid(), "'continue' is only valid inside a loop statement");
492 return context.createContinueStatement(location, startCol, endCol, startLine, endLine, endLineStart);
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();
501 endLineStart = tokenLineStart();
502 next();
503 failIfFalse(autoSemiColon());
504 return context.createContinueStatement(location, ident, startCol, endCol, startLine, endLine, endLineStart);
505 }
506
507 template <typename LexerType>
508 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseReturnStatement(TreeBuilder& context)
509 {
510 ASSERT(match(RETURN));
511 JSTokenLocation location(tokenLocation());
512 failIfFalse(currentScope()->isFunction());
513 int startLine = tokenLine();
514 int endLine = startLine;
515 int start = tokenStart();
516 int end = tokenEnd();
517 unsigned divotLine = tokenLine();
518 unsigned divotLineStart = tokenLineStart();
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())
526 return context.createReturnStatement(location, 0, start, end, startLine, endLine, divotLine, divotLineStart);
527 TreeExpression expr = parseExpression(context);
528 failIfFalse(expr);
529 end = lastTokenEnd();
530 divotLine = lastTokenLine();
531 divotLineStart = lastTokenLineStart();
532 if (match(SEMICOLON))
533 endLine = tokenLine();
534 failIfFalse(autoSemiColon());
535 return context.createReturnStatement(location, expr, start, end, startLine, endLine, divotLine, divotLineStart);
536 }
537
538 template <typename LexerType>
539 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseThrowStatement(TreeBuilder& context)
540 {
541 ASSERT(match(THROW));
542 JSTokenLocation location(tokenLocation());
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();
552 unsigned divotLine = lastTokenLine();
553 unsigned divotLineStart = lastTokenLineStart();
554 int endLine = tokenLine();
555 failIfFalse(autoSemiColon());
556
557 return context.createThrowStatement(location, expr, eStart, eEnd, startLine, endLine, divotLine, divotLineStart);
558 }
559
560 template <typename LexerType>
561 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWithStatement(TreeBuilder& context)
562 {
563 ASSERT(match(WITH));
564 JSTokenLocation location(tokenLocation());
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();
574 unsigned divotLine = lastTokenLine();
575 unsigned divotLineStart = lastTokenLineStart();
576 int endLine = tokenLine();
577 consumeOrFail(CLOSEPAREN);
578 const Identifier* unused = 0;
579 TreeStatement statement = parseStatement(context, unused);
580 failIfFalse(statement);
581
582 return context.createWithStatement(location, expr, statement, start, end, startLine, endLine, divotLine, divotLineStart);
583 }
584
585 template <typename LexerType>
586 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseSwitchStatement(TreeBuilder& context)
587 {
588 ASSERT(match(SWITCH));
589 JSTokenLocation location(tokenLocation());
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);
600 failIfTrue(hasError());
601
602 TreeClause defaultClause = parseSwitchDefaultClause(context);
603 failIfTrue(hasError());
604
605 TreeClauseList secondClauses = parseSwitchClauses(context);
606 failIfTrue(hasError());
607 endSwitch();
608 consumeOrFail(CLOSEBRACE);
609
610 return context.createSwitchStatement(location, expr, firstClauses, defaultClause, secondClauses, startLine, endLine);
611
612 }
613
614 template <typename LexerType>
615 template <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
642 template <typename LexerType>
643 template <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
654 template <typename LexerType>
655 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseTryStatement(TreeBuilder& context)
656 {
657 ASSERT(match(TRY));
658 JSTokenLocation location(tokenLocation());
659 TreeStatement tryBlock = 0;
660 const Identifier* ident = &m_vm->propertyNames->nullIdentifier;
661 TreeStatement catchBlock = 0;
662 TreeStatement finallyBlock = 0;
663 int firstLine = tokenLine();
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);
695 return context.createTryStatement(location, tryBlock, ident, catchBlock, finallyBlock, firstLine, lastLine);
696 }
697
698 template <typename LexerType>
699 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseDebuggerStatement(TreeBuilder& context)
700 {
701 ASSERT(match(DEBUGGER));
702 JSTokenLocation location(tokenLocation());
703 int startLine = tokenLine();
704 int endLine = startLine;
705 next();
706 if (match(SEMICOLON))
707 startLine = tokenLine();
708 failIfFalse(autoSemiColon());
709 return context.createDebugger(location, startLine, endLine);
710 }
711
712 template <typename LexerType>
713 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBlockStatement(TreeBuilder& context)
714 {
715 ASSERT(match(OPENBRACE));
716 JSTokenLocation location(tokenLocation());
717 int start = tokenLine();
718 next();
719 if (match(CLOSEBRACE)) {
720 next();
721 return context.createBlockStatement(location, 0, start, m_lastLine);
722 }
723 TreeSourceElements subtree = parseSourceElements<DontCheckForStrictMode>(context);
724 failIfFalse(subtree);
725 matchOrFail(CLOSEBRACE);
726 next();
727 return context.createBlockStatement(location, subtree, start, m_lastLine);
728 }
729
730 template <typename LexerType>
731 template <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);
748 case SEMICOLON: {
749 JSTokenLocation location(tokenLocation());
750 next();
751 return context.createEmptyStatement(location);
752 }
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)
788 *directiveLiteralLength = m_token.m_location.endOffset - m_token.m_location.startOffset;
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
798 template <typename LexerType>
799 template <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
817 template <typename LexerType>
818 template <class TreeBuilder> TreeFunctionBody Parser<LexerType>::parseFunctionBody(TreeBuilder& context)
819 {
820 JSTokenLocation startLocation(tokenLocation());
821 unsigned startColumn = tokenColumn();
822 next();
823
824 if (match(CLOSEBRACE))
825 return context.createFunctionBody(startLocation, tokenLocation(), startColumn, strictMode());
826 DepthManager statementDepth(&m_statementDepth);
827 m_statementDepth = 0;
828 typename TreeBuilder::FunctionBodyBuilder bodyBuilder(const_cast<VM*>(m_vm), m_lexer.get());
829 failIfFalse(parseSourceElements<CheckForStrictMode>(bodyBuilder));
830 return context.createFunctionBody(startLocation, tokenLocation(), startColumn, strictMode());
831 }
832
833 template <typename LexerType>
834 template <FunctionRequirements requirements, bool nameIsInContainingScope, class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuilder& context, const Identifier*& name, TreeFormalParameterList& parameters, TreeFunctionBody& body, unsigned& openBraceOffset, unsigned& closeBraceOffset, int& bodyStartLine, unsigned& bodyStartColumn)
835 {
836 AutoPopScopeRef functionScope(this, pushScope());
837 functionScope->setIsFunction();
838 int functionStart = m_token.m_location.startOffset;
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
854 openBraceOffset = m_token.m_data.offset;
855 bodyStartLine = tokenLine();
856 bodyStartColumn = m_token.m_data.offset - m_token.m_data.lineStartOffset;
857 JSTokenLocation startLocation(tokenLocation());
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.
860 if (const SourceProviderCacheItem* cachedInfo = TreeBuilder::CanUseFunctionCache ? findCachedFunctionInfo(openBraceOffset) : 0) {
861 // If we're in a strict context, the cached function info must say it was strict too.
862 ASSERT(!strictMode() || cachedInfo->strictMode);
863 JSTokenLocation endLocation;
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);
871
872 functionScope->restoreFromSourceProviderCache(cachedInfo);
873 failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo));
874
875 closeBraceOffset = cachedInfo->closeBraceOffset;
876
877 context.setFunctionStart(body, functionStart);
878 m_token = cachedInfo->closeBraceToken();
879
880 m_lexer->setOffset(m_token.m_location.endOffset, m_token.m_location.lineStartOffset);
881 m_lexer->setLineNumber(m_token.m_location.line);
882
883 next();
884 return true;
885 }
886
887 body = parseFunctionBody(context);
888 failIfFalse(body);
889 if (functionScope->strictMode() && name) {
890 failIfTrueWithNameAndMessage(m_vm->propertyNames->arguments == *name, "Function name", name->impl(), "is not valid in strict mode");
891 failIfTrueWithNameAndMessage(m_vm->propertyNames->eval == *name, "Function name", name->impl(), "is not valid in strict mode");
892 }
893 closeBraceOffset = m_token.m_data.offset;
894 unsigned closeBraceLine = m_token.m_data.line;
895 unsigned closeBraceLineStartOffset = m_token.m_data.lineStartOffset;
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.
899 static const int minimumFunctionLengthToCache = 16;
900 OwnPtr<SourceProviderCacheItem> newInfo;
901 int functionLength = closeBraceOffset - openBraceOffset;
902 if (TreeBuilder::CanUseFunctionCache && m_functionCache && functionLength > minimumFunctionLengthToCache) {
903 SourceProviderCacheItemCreationParameters parameters;
904 parameters.functionStart = functionStart;
905 parameters.closeBraceLine = closeBraceLine;
906 parameters.closeBraceOffset = closeBraceOffset;
907 parameters.closeBraceLineStartOffset = closeBraceLineStartOffset;
908 functionScope->fillParametersForSourceProviderCache(parameters);
909 newInfo = SourceProviderCacheItem::create(parameters);
910
911 }
912 context.setFunctionStart(body, functionStart);
913
914 failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo));
915 matchOrFail(CLOSEBRACE);
916
917 if (newInfo)
918 m_functionCache->add(openBraceOffset, newInfo.release());
919
920 next();
921 return true;
922 }
923
924 template <typename LexerType>
925 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDeclaration(TreeBuilder& context)
926 {
927 ASSERT(match(FUNCTION));
928 JSTokenLocation location(tokenLocation());
929 next();
930 const Identifier* name = 0;
931 TreeFormalParameterList parameters = 0;
932 TreeFunctionBody body = 0;
933 unsigned openBraceOffset = 0;
934 unsigned closeBraceOffset = 0;
935 int bodyStartLine = 0;
936 unsigned bodyStartColumn = 0;
937 failIfFalse((parseFunctionInfo<FunctionNeedsName, true>(context, name, parameters, body, openBraceOffset, closeBraceOffset, bodyStartLine, bodyStartColumn)));
938 failIfFalse(name);
939 failIfFalseIfStrict(declareVariable(name));
940 return context.createFuncDeclStatement(location, name, body, parameters, openBraceOffset, closeBraceOffset, bodyStartLine, m_lastLine, bodyStartColumn);
941 }
942
943 struct LabelInfo {
944 LabelInfo(const Identifier* ident, unsigned start, unsigned end, unsigned divotLine, unsigned divotLineStart)
945 : m_ident(ident)
946 , m_start(start)
947 , m_end(end)
948 , m_divotLine(divotLine)
949 , m_divotLineStart(divotLineStart)
950 {
951 }
952
953 const Identifier* m_ident;
954 unsigned m_start;
955 unsigned m_end;
956 unsigned m_divotLine;
957 unsigned m_divotLineStart;
958 };
959
960 template <typename LexerType>
961 template <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;
968 JSTokenLocation location;
969 do {
970 int start = tokenStart();
971 int startingLine = tokenLine();
972 location = tokenLocation();
973 if (!nextTokenIsColon()) {
974 // If we hit this path we're making a expression statement, which
975 // by definition can't make use of continue/break so we can just
976 // ignore any labels we might have accumulated.
977 TreeExpression expression = parseExpression(context);
978 failIfFalse(expression);
979 failIfFalse(autoSemiColon());
980 return context.createExprStatement(location, expression, startingLine, m_lastLine);
981 }
982 const Identifier* ident = m_token.m_data.ident;
983 int end = tokenEnd();
984 unsigned divotLine = tokenLine();
985 unsigned divotLineStart = tokenLineStart();
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));
994 labels.append(LabelInfo(ident, start, end, divotLine, divotLineStart));
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];
1021 statement = context.createLabelStatement(location, info.m_ident, statement, info.m_start, info.m_end, info.m_divotLine, info.m_divotLineStart);
1022 }
1023 return statement;
1024 }
1025
1026 template <typename LexerType>
1027 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionStatement(TreeBuilder& context)
1028 {
1029 int startLine = tokenLine();
1030 JSTokenLocation location(tokenLocation());
1031 TreeExpression expression = parseExpression(context);
1032 failIfFalse(expression);
1033 failIfFalse(autoSemiColon());
1034 return context.createExprStatement(location, expression, startLine, m_lastLine);
1035 }
1036
1037 template <typename LexerType>
1038 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseIfStatement(TreeBuilder& context)
1039 {
1040 ASSERT(match(IF));
1041 JSTokenLocation ifLocation(tokenLocation());
1042 int start = tokenLine();
1043 next();
1044
1045 consumeOrFail(OPENPAREN);
1046
1047 TreeExpression condition = parseExpression(context);
1048 failIfFalse(condition);
1049 int end = tokenLine();
1050 consumeOrFail(CLOSEPAREN);
1051
1052 const Identifier* unused = 0;
1053 TreeStatement trueBlock = parseStatement(context, unused);
1054 failIfFalse(trueBlock);
1055
1056 if (!match(ELSE))
1057 return context.createIfStatement(ifLocation, condition, trueBlock, 0, start, end);
1058
1059 Vector<TreeExpression> exprStack;
1060 Vector<pair<int, int> > posStack;
1061 Vector<JSTokenLocation> tokenLocationStack;
1062 Vector<TreeStatement> statementStack;
1063 bool trailingElse = false;
1064 do {
1065 JSTokenLocation tempLocation = tokenLocation();
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();
1077
1078 consumeOrFail(OPENPAREN);
1079
1080 TreeExpression innerCondition = parseExpression(context);
1081 failIfFalse(innerCondition);
1082 int innerEnd = tokenLine();
1083 consumeOrFail(CLOSEPAREN);
1084 const Identifier* unused = 0;
1085 TreeStatement innerTrueBlock = parseStatement(context, unused);
1086 failIfFalse(innerTrueBlock);
1087 tokenLocationStack.append(tempLocation);
1088 exprStack.append(innerCondition);
1089 posStack.append(make_pair(innerStart, innerEnd));
1090 statementStack.append(innerTrueBlock);
1091 } while (match(ELSE));
1092
1093 if (!trailingElse) {
1094 TreeExpression condition = exprStack.last();
1095 exprStack.removeLast();
1096 TreeStatement trueBlock = statementStack.last();
1097 statementStack.removeLast();
1098 pair<int, int> pos = posStack.last();
1099 posStack.removeLast();
1100 JSTokenLocation elseLocation = tokenLocationStack.last();
1101 tokenLocationStack.removeLast();
1102 statementStack.append(context.createIfStatement(elseLocation, condition, trueBlock, 0, pos.first, pos.second));
1103 }
1104
1105 while (!exprStack.isEmpty()) {
1106 TreeExpression condition = exprStack.last();
1107 exprStack.removeLast();
1108 TreeStatement falseBlock = statementStack.last();
1109 statementStack.removeLast();
1110 TreeStatement trueBlock = statementStack.last();
1111 statementStack.removeLast();
1112 pair<int, int> pos = posStack.last();
1113 posStack.removeLast();
1114 JSTokenLocation elseLocation = tokenLocationStack.last();
1115 tokenLocationStack.removeLast();
1116 statementStack.append(context.createIfStatement(elseLocation, condition, trueBlock, falseBlock, pos.first, pos.second));
1117 }
1118
1119 return context.createIfStatement(ifLocation, condition, trueBlock, statementStack.last(), start, end);
1120 }
1121
1122 template <typename LexerType>
1123 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseExpression(TreeBuilder& context)
1124 {
1125 failIfStackOverflow();
1126 JSTokenLocation location(tokenLocation());
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);
1136 typename TreeBuilder::Comma commaNode = context.createCommaExpr(location, node, right);
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
1146 template <typename LexerType>
1147 template <typename TreeBuilder> TreeExpression Parser<LexerType>::parseAssignmentExpression(TreeBuilder& context)
1148 {
1149 failIfStackOverflow();
1150 int start = tokenStart();
1151 unsigned line = tokenLine();
1152 unsigned lineStart = tokenLineStart();
1153 JSTokenLocation location(tokenLocation());
1154 int initialAssignmentCount = m_assignmentCount;
1155 int initialNonLHSCount = m_nonLHSCount;
1156 TreeExpression lhs = parseConditionalExpression(context);
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;
1183 context.assignmentStackAppend(assignmentStack, lhs, start, tokenStart(), line, lineStart, m_assignmentCount, op);
1184 start = tokenStart();
1185 line = tokenLine();
1186 lineStart = tokenLineStart();
1187 m_assignmentCount++;
1188 next(TreeBuilder::DontBuildStrings);
1189 if (strictMode() && m_lastIdentifier && context.isResolve(lhs)) {
1190 failIfTrueIfStrictWithMessage(m_vm->propertyNames->eval == *m_lastIdentifier, "'eval' cannot be modified in strict mode");
1191 failIfTrueIfStrictWithMessage(m_vm->propertyNames->arguments == *m_lastIdentifier, "'arguments' cannot be modified in strict mode");
1192 declareWrite(m_lastIdentifier);
1193 m_lastIdentifier = 0;
1194 }
1195 lhs = parseConditionalExpression(context);
1196 failIfFalse(lhs);
1197 if (initialNonLHSCount != m_nonLHSCount)
1198 break;
1199 }
1200 end:
1201 if (hadAssignment)
1202 m_nonLHSCount++;
1203
1204 if (!TreeBuilder::CreatesAST)
1205 return lhs;
1206
1207 while (assignmentStack)
1208 lhs = context.createAssignment(location, assignmentStack, lhs, initialAssignmentCount, m_assignmentCount, lastTokenEnd());
1209
1210 return lhs;
1211 }
1212
1213 template <typename LexerType>
1214 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseConditionalExpression(TreeBuilder& context)
1215 {
1216 JSTokenLocation location(tokenLocation());
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);
1229 return context.createConditionalExpr(location, cond, lhs, rhs);
1230 }
1231
1232 ALWAYS_INLINE static bool isUnaryOp(JSTokenType token)
1233 {
1234 return token & UnaryOpTokenFlag;
1235 }
1236
1237 template <typename LexerType>
1238 int Parser<LexerType>::isBinaryOperator(JSTokenType token)
1239 {
1240 if (m_allowsIn)
1241 return token & (BinaryOpTokenPrecedenceMask << BinaryOpTokenAllowsInPrecedenceAdditionalShift);
1242 return token & BinaryOpTokenPrecedenceMask;
1243 }
1244
1245 template <typename LexerType>
1246 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseBinaryExpression(TreeBuilder& context)
1247 {
1248
1249 int operandStackDepth = 0;
1250 int operatorStackDepth = 0;
1251 typename TreeBuilder::BinaryExprContext binaryExprContext(context);
1252 JSTokenLocation location(tokenLocation());
1253 while (true) {
1254 int exprStart = tokenStart();
1255 int initialAssignments = m_assignmentCount;
1256 TreeExpression current = parseUnaryExpression(context);
1257 failIfFalse(current);
1258
1259 context.appendBinaryExpressionInfo(operandStackDepth, current, exprStart, lastTokenEnd(), lastTokenEnd(), lastTokenLine(), lastTokenLineStart(), initialAssignments != m_assignmentCount);
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);
1274 context.appendBinaryOperation(location, operandStackDepth, operatorStackDepth, lhs, rhs);
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);
1285 context.appendBinaryOperation(location, operandStackDepth, operatorStackDepth, lhs, rhs);
1286 context.operatorStackPop(operatorStackDepth);
1287 }
1288 return context.popOperandStack(operandStackDepth);
1289 }
1290
1291 template <typename LexerType>
1292 template <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;
1301 if (complete || (wasIdent && (*ident == m_vm->propertyNames->get || *ident == m_vm->propertyNames->set)))
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;
1316 unsigned openBraceOffset = 0;
1317 unsigned closeBraceOffset = 0;
1318 int bodyStartLine = 0;
1319 unsigned bodyStartColumn = 0;
1320 PropertyNode::Type type;
1321 if (*ident == m_vm->propertyNames->get)
1322 type = PropertyNode::Getter;
1323 else if (*ident == m_vm->propertyNames->set)
1324 type = PropertyNode::Setter;
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();
1335 JSTokenLocation location(tokenLocation());
1336 next();
1337 failIfFalse((parseFunctionInfo<FunctionNoRequirements, false>(context, accessorName, parameters, body, openBraceOffset, closeBraceOffset, bodyStartLine, bodyStartColumn)));
1338 if (stringPropertyName)
1339 return context.template createGetterOrSetterProperty<complete>(location, type, stringPropertyName, parameters, body, openBraceOffset, closeBraceOffset, bodyStartLine, m_lastLine, bodyStartColumn);
1340 return context.template createGetterOrSetterProperty<complete>(const_cast<VM*>(m_vm), location, type, numericPropertyName, parameters, body, openBraceOffset, closeBraceOffset, bodyStartLine, m_lastLine, bodyStartColumn);
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);
1348 return context.template createProperty<complete>(const_cast<VM*>(m_vm), propertyName, node, PropertyNode::Constant);
1349 }
1350 default:
1351 failIfFalse(m_token.m_type & KeywordTokenFlag);
1352 goto namedProperty;
1353 }
1354 }
1355
1356 template <typename LexerType>
1357 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseObjectLiteral(TreeBuilder& context)
1358 {
1359 int startOffset = m_token.m_data.offset;
1360 unsigned oldLineStartOffset = m_lexer->currentLineStartOffset();
1361 unsigned oldLastLineNumber = m_lexer->lastLineNumber();
1362 unsigned oldLineNumber = m_lexer->lineNumber();
1363 consumeOrFailWithFlags(OPENBRACE, TreeBuilder::DontBuildStrings);
1364 JSTokenLocation location(tokenLocation());
1365
1366 int oldNonLHSCount = m_nonLHSCount;
1367
1368 if (match(CLOSEBRACE)) {
1369 next();
1370 return context.createObjectLiteral(location);
1371 }
1372
1373 TreeProperty property = parseProperty<false>(context);
1374 failIfFalse(property);
1375 if (!m_syntaxAlreadyValidated && context.getType(property) != PropertyNode::Constant) {
1376 m_lexer->setOffset(startOffset, oldLineStartOffset);
1377 next();
1378 m_lexer->setLastLineNumber(oldLastLineNumber);
1379 m_lexer->setLineNumber(oldLineNumber);
1380 return parseStrictObjectLiteral(context);
1381 }
1382 TreePropertyList propertyList = context.createPropertyList(location, property);
1383 TreePropertyList tail = propertyList;
1384 while (match(COMMA)) {
1385 next(TreeBuilder::DontBuildStrings);
1386 // allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939
1387 if (match(CLOSEBRACE))
1388 break;
1389 JSTokenLocation propertyLocation(tokenLocation());
1390 property = parseProperty<false>(context);
1391 failIfFalse(property);
1392 if (!m_syntaxAlreadyValidated && context.getType(property) != PropertyNode::Constant) {
1393 m_lexer->setOffset(startOffset, oldLineStartOffset);
1394 next();
1395 m_lexer->setLastLineNumber(oldLastLineNumber);
1396 m_lexer->setLineNumber(oldLineNumber);
1397 return parseStrictObjectLiteral(context);
1398 }
1399 tail = context.createPropertyList(propertyLocation, property, tail);
1400 }
1401
1402 location = tokenLocation();
1403 consumeOrFail(CLOSEBRACE);
1404
1405 m_nonLHSCount = oldNonLHSCount;
1406
1407 return context.createObjectLiteral(location, propertyList);
1408 }
1409
1410 template <typename LexerType>
1411 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseStrictObjectLiteral(TreeBuilder& context)
1412 {
1413 consumeOrFail(OPENBRACE);
1414
1415 int oldNonLHSCount = m_nonLHSCount;
1416
1417 JSTokenLocation location(tokenLocation());
1418 if (match(CLOSEBRACE)) {
1419 next();
1420 return context.createObjectLiteral(location);
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
1432 TreePropertyList propertyList = context.createPropertyList(location, property);
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;
1439 JSTokenLocation propertyLocation(tokenLocation());
1440 property = parseProperty<true>(context);
1441 failIfFalse(property);
1442 if (!m_syntaxAlreadyValidated) {
1443 ObjectValidationMap::AddResult propertyEntry = objectValidator.add(context.getName(property).impl(), context.getType(property));
1444 if (!propertyEntry.isNewEntry) {
1445 failIfTrue(propertyEntry.iterator->value == PropertyNode::Constant);
1446 failIfTrue(context.getType(property) == PropertyNode::Constant);
1447 failIfTrue(context.getType(property) & propertyEntry.iterator->value);
1448 propertyEntry.iterator->value |= context.getType(property);
1449 }
1450 }
1451 tail = context.createPropertyList(propertyLocation, property, tail);
1452 }
1453
1454 location = tokenLocation();
1455 consumeOrFail(CLOSEBRACE);
1456
1457 m_nonLHSCount = oldNonLHSCount;
1458
1459 return context.createObjectLiteral(location, propertyList);
1460 }
1461
1462 template <typename LexerType>
1463 template <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)) {
1475 JSTokenLocation location(tokenLocation());
1476 next(TreeBuilder::DontBuildStrings);
1477 return context.createArray(location, elisions);
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)) {
1495 JSTokenLocation location(tokenLocation());
1496 next(TreeBuilder::DontBuildStrings);
1497 return context.createArray(location, elisions, elementList);
1498 }
1499 TreeExpression elem = parseAssignmentExpression(context);
1500 failIfFalse(elem);
1501 tail = context.createElementList(tail, elisions, elem);
1502 }
1503
1504 JSTokenLocation location(tokenLocation());
1505 consumeOrFail(CLOSEBRACKET);
1506
1507 m_nonLHSCount = oldNonLHSCount;
1508
1509 return context.createArray(location, elementList);
1510 }
1511
1512 template <typename LexerType>
1513 template <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: {
1533 JSTokenLocation location(tokenLocation());
1534 next();
1535 return context.thisExpr(location);
1536 }
1537 case IDENT: {
1538 int start = tokenStart();
1539 int line = tokenLine();
1540 int lineStart = tokenLineStart();
1541 const Identifier* ident = m_token.m_data.ident;
1542 JSTokenLocation location(tokenLocation());
1543 next();
1544 currentScope()->useVariable(ident, m_vm->propertyNames->eval == *ident);
1545 m_lastIdentifier = ident;
1546 return context.createResolve(location, ident, start, line, lineStart);
1547 }
1548 case STRING: {
1549 const Identifier* ident = m_token.m_data.ident;
1550 JSTokenLocation location(tokenLocation());
1551 next();
1552 return context.createString(location, ident);
1553 }
1554 case NUMBER: {
1555 double d = m_token.m_data.doubleValue;
1556 JSTokenLocation location(tokenLocation());
1557 next();
1558 return context.createNumberExpr(location, d);
1559 }
1560 case NULLTOKEN: {
1561 JSTokenLocation location(tokenLocation());
1562 next();
1563 return context.createNull(location);
1564 }
1565 case TRUETOKEN: {
1566 JSTokenLocation location(tokenLocation());
1567 next();
1568 return context.createBoolean(location, true);
1569 }
1570 case FALSETOKEN: {
1571 JSTokenLocation location(tokenLocation());
1572 next();
1573 return context.createBoolean(location, false);
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();
1586 int line = tokenLine();
1587 int lineStart = tokenLineStart();
1588 JSTokenLocation location(tokenLocation());
1589 next();
1590 TreeExpression re = context.createRegExp(location, *pattern, *flags, start, line, lineStart);
1591 if (!re) {
1592 const char* yarrErrorMsg = Yarr::checkSyntax(pattern->string());
1593 failWithMessage(yarrErrorMsg);
1594 }
1595 return re;
1596 }
1597 default:
1598 fail();
1599 }
1600 }
1601
1602 template <typename LexerType>
1603 template <class TreeBuilder> TreeArguments Parser<LexerType>::parseArguments(TreeBuilder& context)
1604 {
1605 consumeOrFailWithFlags(OPENPAREN, TreeBuilder::DontBuildStrings);
1606 JSTokenLocation location(tokenLocation());
1607 if (match(CLOSEPAREN)) {
1608 next(TreeBuilder::DontBuildStrings);
1609 return context.createArguments();
1610 }
1611 TreeExpression firstArg = parseAssignmentExpression(context);
1612 failIfFalse(firstArg);
1613
1614 TreeArgumentsList argList = context.createArgumentsList(location, firstArg);
1615 TreeArgumentsList tail = argList;
1616 while (match(COMMA)) {
1617 JSTokenLocation argumentLocation(tokenLocation());
1618 next(TreeBuilder::DontBuildStrings);
1619 TreeExpression arg = parseAssignmentExpression(context);
1620 failIfFalse(arg);
1621 tail = context.createArgumentsList(argumentLocation, tail, arg);
1622 }
1623 consumeOrFail(CLOSEPAREN);
1624 return context.createArguments(argList);
1625 }
1626
1627 template <typename LexerType>
1628 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseMemberExpression(TreeBuilder& context)
1629 {
1630 TreeExpression base = 0;
1631 int start = tokenStart();
1632 int expressionStart = start;
1633 int expressionLine = tokenLine();
1634 int expressionLineStart = tokenLineStart();
1635 int newCount = 0;
1636 JSTokenLocation location;
1637 while (match(NEW)) {
1638 next();
1639 newCount++;
1640 }
1641
1642 if (match(FUNCTION)) {
1643 const Identifier* name = &m_vm->propertyNames->nullIdentifier;
1644 TreeFormalParameterList parameters = 0;
1645 TreeFunctionBody body = 0;
1646 unsigned openBraceOffset = 0;
1647 unsigned closeBraceOffset = 0;
1648 int bodyStartLine = 0;
1649 unsigned bodyStartColumn = 0;
1650 location = tokenLocation();
1651 next();
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);
1654 } else
1655 base = parsePrimaryExpression(context);
1656
1657 failIfFalse(base);
1658 while (true) {
1659 location = tokenLocation();
1660 switch (m_token.m_type) {
1661 case OPENBRACKET: {
1662 m_nonTrivialExpressionCount++;
1663 int expressionEnd = lastTokenEnd();
1664 int expressionLine = lastTokenLine();
1665 int expressionLineStart = lastTokenLineStart();
1666 next();
1667 int nonLHSCount = m_nonLHSCount;
1668 int initialAssignments = m_assignmentCount;
1669 TreeExpression property = parseExpression(context);
1670 failIfFalse(property);
1671 base = context.createBracketAccess(location, base, property, initialAssignments != m_assignmentCount, expressionStart, expressionEnd, tokenEnd(), expressionLine, expressionLineStart);
1672 consumeOrFail(CLOSEBRACKET);
1673 m_nonLHSCount = nonLHSCount;
1674 break;
1675 }
1676 case OPENPAREN: {
1677 m_nonTrivialExpressionCount++;
1678 int nonLHSCount = m_nonLHSCount;
1679 if (newCount) {
1680 newCount--;
1681 int exprEnd = lastTokenEnd();
1682 unsigned expressionLine = lastTokenLine();
1683 unsigned expressionLineStart = lastTokenLineStart();
1684 TreeArguments arguments = parseArguments(context);
1685 failIfFalse(arguments);
1686 base = context.createNewExpr(location, base, arguments, start, exprEnd, lastTokenEnd(), expressionLine, expressionLineStart);
1687 } else {
1688 int expressionEnd = lastTokenEnd();
1689 unsigned expressionLine = lastTokenLine();
1690 int expressionLineStart = lastTokenLineStart();
1691 TreeArguments arguments = parseArguments(context);
1692 failIfFalse(arguments);
1693 base = context.makeFunctionCallNode(location, base, arguments, expressionStart, expressionEnd, lastTokenEnd(), expressionLine, expressionLineStart);
1694 }
1695 m_nonLHSCount = nonLHSCount;
1696 break;
1697 }
1698 case DOT: {
1699 m_nonTrivialExpressionCount++;
1700 int expressionEnd = lastTokenEnd();
1701 expressionLineStart = lastTokenLineStart();
1702 nextExpectIdentifier(LexerFlagsIgnoreReservedWords | TreeBuilder::DontBuildKeywords);
1703 matchOrFail(IDENT);
1704 base = context.createDotAccess(location, base, m_token.m_data.ident, expressionStart, expressionEnd, tokenEnd(), expressionLine, expressionLineStart);
1705 next();
1706 break;
1707 }
1708 default:
1709 goto endMemberExpression;
1710 }
1711 }
1712 endMemberExpression:
1713 while (newCount--)
1714 base = context.createNewExpr(location, base, start, lastTokenEnd(), expressionLine, expressionLineStart);
1715 return base;
1716 }
1717
1718 template <typename LexerType>
1719 template <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++;
1747 context.appendUnaryToken(tokenStackDepth, m_token.m_type, tokenStart(), tokenLine(), tokenLineStart());
1748 next();
1749 m_nonTrivialExpressionCount++;
1750 }
1751 int subExprStart = tokenStart();
1752 int subExprLine = tokenLine();
1753 int subExprLineStartPosition = tokenLineStart();
1754 ASSERT(subExprStart >= subExprLineStartPosition);
1755 JSTokenLocation location(tokenLocation());
1756 TreeExpression expr = parseMemberExpression(context);
1757 failIfFalse(expr);
1758 bool isEvalOrArguments = false;
1759 if (strictMode() && !m_syntaxAlreadyValidated) {
1760 if (context.isResolve(expr))
1761 isEvalOrArguments = *m_lastIdentifier == m_vm->propertyNames->eval || *m_lastIdentifier == m_vm->propertyNames->arguments;
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++;
1768 expr = context.makePostfixNode(location, expr, OpPlusPlus, subExprStart, lastTokenEnd(), tokenEnd(), tokenLine(), tokenLineStart());
1769 m_assignmentCount++;
1770 failIfTrueIfStrictWithNameAndMessage(isEvalOrArguments, "'", m_lastIdentifier->impl(), "' cannot be modified in strict mode");
1771 failIfTrueIfStrict(requiresLExpr);
1772 next();
1773 break;
1774 case MINUSMINUS:
1775 m_nonTrivialExpressionCount++;
1776 m_nonLHSCount++;
1777 expr = context.makePostfixNode(location, expr, OpMinusMinus, subExprStart, lastTokenEnd(), tokenEnd(), tokenLine(), tokenLineStart());
1778 m_assignmentCount++;
1779 failIfTrueIfStrictWithNameAndMessage(isEvalOrArguments, "'", m_lastIdentifier->impl(), "' cannot be modified in strict mode");
1780 failIfTrueIfStrict(requiresLExpr);
1781 next();
1782 break;
1783 default:
1784 break;
1785 }
1786
1787 int end = lastTokenEnd();
1788 int endLine = lastTokenLine();
1789 int endLineStartPosition = lastTokenLineStart();
1790
1791 if (!TreeBuilder::CreatesAST && (m_syntaxAlreadyValidated || !strictMode()))
1792 return expr;
1793
1794 location = tokenLocation();
1795 location.line = m_lexer->lastLineNumber();
1796 while (tokenStackDepth) {
1797 switch (context.unaryTokenStackLastType(tokenStackDepth)) {
1798 case EXCLAMATION:
1799 expr = context.createLogicalNot(location, expr);
1800 break;
1801 case TILDE:
1802 expr = context.makeBitwiseNotNode(location, expr);
1803 break;
1804 case MINUS:
1805 expr = context.makeNegateNode(location, expr);
1806 break;
1807 case PLUS:
1808 expr = context.createUnaryPlus(location, expr);
1809 break;
1810 case PLUSPLUS:
1811 case AUTOPLUSPLUS:
1812 expr = context.makePrefixNode(location, expr, OpPlusPlus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end, subExprLine, subExprLineStartPosition);
1813 m_assignmentCount++;
1814 break;
1815 case MINUSMINUS:
1816 case AUTOMINUSMINUS:
1817 expr = context.makePrefixNode(location, expr, OpMinusMinus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end, subExprLine, subExprLineStartPosition);
1818 m_assignmentCount++;
1819 break;
1820 case TYPEOF:
1821 expr = context.makeTypeOfNode(location, expr);
1822 break;
1823 case VOIDTOKEN:
1824 expr = context.createVoid(location, expr);
1825 break;
1826 case DELETETOKEN:
1827 failIfTrueIfStrictWithNameAndMessage(context.isResolve(expr), "Cannot delete unqualified property", m_lastIdentifier->impl(), "in strict mode");
1828 expr = context.makeDeleteNode(location, expr, context.unaryTokenStackLastStart(tokenStackDepth), end, end, endLine, endLineStartPosition);
1829 break;
1830 default:
1831 // If we get here something has gone horribly horribly wrong
1832 CRASH();
1833 }
1834 subExprStart = context.unaryTokenStackLastStart(tokenStackDepth);
1835 subExprLineStartPosition = context.unaryTokenStackLastLineStartPosition(tokenStackDepth);
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
1842 template class Parser< Lexer<LChar> >;
1843 template class Parser< Lexer<UChar> >;
1844
1845 } // namespace JSC