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