initial import
[vuplus_webkit] / Source / JavaScriptCore / parser / JSParser.cpp
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27
28 #include "JSParser.h"
29
30 using namespace JSC;
31
32 #include "CodeBlock.h"
33 #include "JSGlobalData.h"
34 #include "NodeInfo.h"
35 #include "ASTBuilder.h"
36 #include "SourceProvider.h"
37 #include "SourceProviderCacheItem.h"
38 #include <wtf/HashFunctions.h>
39 #include <wtf/OwnPtr.h>
40 #include <wtf/WTFThreadData.h>
41 #include <utility>
42
43 using namespace std;
44
45 namespace JSC {
46 #define fail() do { if (!m_error) updateErrorMessage(); return 0; } while (0)
47 #define failWithToken(tok) do { if (!m_error) updateErrorMessage(tok); return 0; } while (0)
48 #define failWithMessage(msg) do { if (!m_error) updateErrorMessage(msg); return 0; } while (0)
49 #define failWithNameAndMessage(before, name, after) do { if (!m_error) updateErrorWithNameAndMessage(before, name, after); return 0; } while (0)
50 #define failIfFalse(cond) do { if (!(cond)) fail(); } while (0)
51 #define failIfFalseWithMessage(cond, msg) do { if (!(cond)) failWithMessage(msg); } while (0)
52 #define failIfFalseWithNameAndMessage(cond, before, name, msg) do { if (!(cond)) failWithNameAndMessage(before, name, msg); } while (0)
53 #define failIfTrue(cond) do { if ((cond)) fail(); } while (0)
54 #define failIfTrueWithMessage(cond, msg) do { if ((cond)) failWithMessage(msg); } while (0)
55 #define failIfTrueWithNameAndMessage(cond, before, name, msg) do { if ((cond)) failWithNameAndMessage(before, name, msg); } while (0)
56 #define failIfTrueIfStrict(cond) do { if ((cond) && strictMode()) fail(); } while (0)
57 #define failIfTrueIfStrictWithMessage(cond, msg) do { if ((cond) && strictMode()) failWithMessage(msg); } while (0)
58 #define failIfTrueIfStrictWithNameAndMessage(cond, before, name, after) do { if ((cond) && strictMode()) failWithNameAndMessage(before, name, after); } while (0)
59 #define failIfFalseIfStrict(cond) do { if ((!(cond)) && strictMode()) fail(); } while (0)
60 #define failIfFalseIfStrictWithMessage(cond, msg) do { if ((!(cond)) && strictMode()) failWithMessage(msg); } while (0)
61 #define failIfFalseIfStrictWithNameAndMessage(cond, before, name, after) do { if ((!(cond)) && strictMode()) failWithNameAndMessage(before, name, after); } while (0)
62 #define consumeOrFail(tokenType) do { if (!consume(tokenType)) failWithToken(tokenType); } while (0)
63 #define consumeOrFailWithFlags(tokenType, flags) do { if (!consume(tokenType, flags)) failWithToken(tokenType); } while (0)
64 #define matchOrFail(tokenType) do { if (!match(tokenType)) failWithToken(tokenType); } while (0)
65 #define failIfStackOverflow() do { failIfFalseWithMessage(canRecurse(), "Code nested too deeply."); } while (0)
66
67 // Macros to make the more common TreeBuilder types a little less verbose
68 #define TreeStatement typename TreeBuilder::Statement
69 #define TreeExpression typename TreeBuilder::Expression
70 #define TreeFormalParameterList typename TreeBuilder::FormalParameterList
71 #define TreeSourceElements typename TreeBuilder::SourceElements
72 #define TreeClause typename TreeBuilder::Clause
73 #define TreeClauseList typename TreeBuilder::ClauseList
74 #define TreeConstDeclList typename TreeBuilder::ConstDeclList
75 #define TreeArguments typename TreeBuilder::Arguments
76 #define TreeArgumentsList typename TreeBuilder::ArgumentsList
77 #define TreeFunctionBody typename TreeBuilder::FunctionBody
78 #define TreeProperty typename TreeBuilder::Property
79 #define TreePropertyList typename TreeBuilder::PropertyList
80
81 COMPILE_ASSERT(LastUntaggedToken < 64, LessThan64UntaggedTokens);
82
83 class JSParser {
84 public:
85     JSParser(Lexer*, JSGlobalData*, FunctionParameters*, bool isStrictContext, bool isFunction, const SourceCode*);
86     UString parseProgram();
87 private:
88     struct AllowInOverride {
89         AllowInOverride(JSParser* parser)
90             : m_parser(parser)
91             , m_oldAllowsIn(parser->m_allowsIn)
92         {
93             parser->m_allowsIn = true;
94         }
95         ~AllowInOverride()
96         {
97             m_parser->m_allowsIn = m_oldAllowsIn;
98         }
99         JSParser* m_parser;
100         bool m_oldAllowsIn;
101     };
102     
103     struct ScopeLabelInfo {
104         ScopeLabelInfo(StringImpl* ident, bool isLoop)
105         : m_ident(ident)
106         , m_isLoop(isLoop)
107         {
108         }
109         StringImpl* m_ident;
110         bool m_isLoop;
111     };
112     
113     ALWAYS_INLINE void next(unsigned lexType = 0)
114     {
115         m_lastLine = m_token.m_info.line;
116         m_lastTokenEnd = m_token.m_info.endOffset;
117         m_lexer->setLastLineNumber(m_lastLine);
118         m_token.m_type = m_lexer->lex(&m_token.m_data, &m_token.m_info, lexType, strictMode());
119     }
120     
121     ALWAYS_INLINE void nextExpectIdentifier(unsigned lexType = 0)
122     {
123         m_lastLine = m_token.m_info.line;
124         m_lastTokenEnd = m_token.m_info.endOffset;
125         m_lexer->setLastLineNumber(m_lastLine);
126         m_token.m_type = m_lexer->lexExpectIdentifier(&m_token.m_data, &m_token.m_info, lexType, strictMode());
127     }
128     
129     ALWAYS_INLINE bool nextTokenIsColon()
130     {
131         return m_lexer->nextTokenIsColon();
132     }
133
134     ALWAYS_INLINE bool consume(JSTokenType expected, unsigned flags = 0)
135     {
136         bool result = m_token.m_type == expected;
137         if (result)
138             next(flags);
139         return result;
140     }
141
142     ALWAYS_INLINE UString getToken() {
143         SourceProvider* sourceProvider = m_source->provider();
144         return UString(sourceProvider->getRange(tokenStart(), tokenEnd()).impl());
145     }
146     
147     ALWAYS_INLINE bool match(JSTokenType expected)
148     {
149         return m_token.m_type == expected;
150     }
151
152     ALWAYS_INLINE int tokenStart()
153     {
154         return m_token.m_info.startOffset;
155     }
156
157     ALWAYS_INLINE int tokenLine()
158     {
159         return m_token.m_info.line;
160     }
161
162     ALWAYS_INLINE int tokenEnd()
163     {
164         return m_token.m_info.endOffset;
165     }
166     
167     const char* getTokenName(JSTokenType tok) 
168     {
169         switch (tok) {
170         case NULLTOKEN: 
171             return "null";
172         case TRUETOKEN:
173             return "true";
174         case FALSETOKEN: 
175             return "false";
176         case BREAK: 
177             return "break";
178         case CASE: 
179             return "case";
180         case DEFAULT: 
181             return "defualt";
182         case FOR: 
183             return "for";
184         case NEW: 
185             return "new";
186         case VAR: 
187             return "var";
188         case CONSTTOKEN: 
189             return "const";
190         case CONTINUE: 
191             return "continue";
192         case FUNCTION: 
193             return "function";
194         case IF: 
195             return "if";
196         case THISTOKEN: 
197             return "this";
198         case DO: 
199             return "do";
200         case WHILE: 
201             return "while";
202         case SWITCH: 
203             return "switch";
204         case WITH: 
205             return "with";
206         case THROW: 
207             return "throw";
208         case TRY: 
209             return "try";
210         case CATCH: 
211             return "catch";
212         case FINALLY: 
213             return "finally";
214         case DEBUGGER: 
215             return "debugger";
216         case ELSE: 
217             return "else";
218         case OPENBRACE: 
219             return "{";
220         case CLOSEBRACE: 
221             return "}";
222         case OPENPAREN: 
223             return "(";
224         case CLOSEPAREN: 
225             return ")";
226         case OPENBRACKET: 
227             return "[";
228         case CLOSEBRACKET: 
229             return "]";
230         case COMMA: 
231             return ",";
232         case QUESTION: 
233             return "?";
234         case SEMICOLON: 
235             return ";";
236         case COLON: 
237             return ":";
238         case DOT: 
239             return ".";
240         case EQUAL: 
241             return "=";
242         case PLUSEQUAL: 
243             return "+=";
244         case MINUSEQUAL: 
245             return "-=";
246         case MULTEQUAL: 
247             return "*=";
248         case DIVEQUAL: 
249             return "/=";
250         case LSHIFTEQUAL: 
251             return "<<=";
252         case RSHIFTEQUAL: 
253             return ">>=";
254         case URSHIFTEQUAL: 
255             return ">>>=";
256         case ANDEQUAL: 
257             return "&=";
258         case MODEQUAL: 
259             return "%=";
260         case XOREQUAL: 
261             return "^=";
262         case OREQUAL: 
263             return "|=";
264         case AUTOPLUSPLUS: 
265         case PLUSPLUS: 
266             return "++";
267         case AUTOMINUSMINUS: 
268         case MINUSMINUS: 
269             return "--";
270         case EXCLAMATION: 
271             return "!";
272         case TILDE: 
273             return "~";
274         case TYPEOF: 
275             return "typeof";
276         case VOIDTOKEN: 
277             return "void";
278         case DELETETOKEN: 
279             return "delete";
280         case OR: 
281             return "||";
282         case AND: 
283             return "&&";
284         case BITOR: 
285             return "|";
286         case BITXOR: 
287             return "^";
288         case BITAND: 
289             return "&";
290         case EQEQ: 
291             return "==";
292         case NE: 
293             return "!=";
294         case STREQ: 
295             return "===";
296         case STRNEQ: 
297             return "!==";
298         case LT: 
299             return "<";
300         case GT: 
301             return ">";
302         case LE: 
303             return "<=";
304         case GE: 
305             return ">=";
306         case INSTANCEOF: 
307             return "instanceof";
308         case INTOKEN: 
309             return "in";
310         case LSHIFT: 
311             return "<<";
312         case RSHIFT: 
313             return ">>";
314         case URSHIFT: 
315             return ">>>";
316         case PLUS: 
317             return "+";
318         case MINUS: 
319             return "-";
320         case TIMES: 
321             return "*";
322         case DIVIDE: 
323             return "/";
324         case MOD: 
325             return "%";
326         case RETURN: 
327         case RESERVED_IF_STRICT:
328         case RESERVED: 
329         case NUMBER:
330         case IDENT: 
331         case STRING: 
332         case ERRORTOK:
333         case EOFTOK: 
334             return 0;
335         case LastUntaggedToken: 
336             break;
337         }
338         ASSERT_NOT_REACHED();
339         return "internal error";
340     }
341     
342     ALWAYS_INLINE void updateErrorMessageSpecialCase(JSTokenType expectedToken) 
343     {
344         String errorMessage;
345         switch (expectedToken) {
346         case RESERVED_IF_STRICT:
347             errorMessage = "Use of reserved word '";
348             errorMessage += getToken().impl();
349             errorMessage += "' in strict mode";
350             m_errorMessage = errorMessage.impl();
351             return;
352         case RESERVED:
353             errorMessage = "Use of reserved word '";
354             errorMessage += getToken().impl();
355             errorMessage += "'";
356             m_errorMessage = errorMessage.impl();
357             return;
358         case NUMBER: 
359             errorMessage = "Unexpected number '";
360             errorMessage += getToken().impl();
361             errorMessage += "'";
362             m_errorMessage = errorMessage.impl();
363             return;
364         case IDENT: 
365             errorMessage = "Expected an identifier but found '";
366             errorMessage += getToken().impl();
367             errorMessage += "' instead";
368             m_errorMessage = errorMessage.impl();
369             return;
370         case STRING: 
371             errorMessage = "Unexpected string ";
372             errorMessage += getToken().impl();
373             m_errorMessage = errorMessage.impl();
374             return;
375         case ERRORTOK: 
376             errorMessage = "Unrecognized token '";
377             errorMessage += getToken().impl();
378             errorMessage += "'";
379             m_errorMessage = errorMessage.impl();
380             return;
381         case EOFTOK:  
382             m_errorMessage = "Unexpected EOF";
383             return;
384         case RETURN:
385             m_errorMessage = "Return statements are only valid inside functions";
386             return;
387         default:
388             ASSERT_NOT_REACHED();
389             m_errorMessage = "internal error";
390             return;
391         }
392     }
393         
394     NEVER_INLINE void updateErrorMessage() 
395     {
396         m_error = true;
397         const char* name = getTokenName(m_token.m_type);
398         if (!name) 
399             updateErrorMessageSpecialCase(m_token.m_type);
400         else 
401             m_errorMessage = UString(String::format("Unexpected token '%s'", name).impl());
402     }
403     
404     NEVER_INLINE void updateErrorMessage(JSTokenType expectedToken) 
405     {
406         m_error = true;
407         const char* name = getTokenName(expectedToken);
408         if (name)
409             m_errorMessage = UString(String::format("Expected token '%s'", name).impl());
410         else {
411             if (!getTokenName(m_token.m_type))
412                 updateErrorMessageSpecialCase(m_token.m_type);
413             else
414                 updateErrorMessageSpecialCase(expectedToken);
415         } 
416     }
417     
418     NEVER_INLINE void updateErrorWithNameAndMessage(const char* beforeMsg, UString name, const char* afterMsg) 
419     {
420         m_error = true;
421         String prefix(beforeMsg);
422         String postfix(afterMsg);
423         prefix += " '";
424         prefix += name.impl();
425         prefix += "' ";
426         prefix += postfix;
427         m_errorMessage = prefix.impl();
428     }
429     
430     NEVER_INLINE void updateErrorMessage(const char* msg) 
431     {   
432         m_error = true;
433         m_errorMessage = UString(msg);
434     }
435     
436     void startLoop() { currentScope()->startLoop(); }
437     void endLoop() { currentScope()->endLoop(); }
438     void startSwitch() { currentScope()->startSwitch(); }
439     void endSwitch() { currentScope()->endSwitch(); }
440     void setStrictMode() { currentScope()->setStrictMode(); }
441     bool strictMode() { return currentScope()->strictMode(); }
442     bool isValidStrictMode() { return currentScope()->isValidStrictMode(); }
443     bool declareParameter(const Identifier* ident) { return currentScope()->declareParameter(ident); }
444     bool breakIsValid()
445     {
446         ScopeRef current = currentScope();
447         while (!current->breakIsValid()) {
448             if (!current.hasContainingScope())
449                 return false;
450             current = current.containingScope();
451         }
452         return true;
453     }
454     bool continueIsValid()
455     {
456         ScopeRef current = currentScope();
457         while (!current->continueIsValid()) {
458             if (!current.hasContainingScope())
459                 return false;
460             current = current.containingScope();
461         }
462         return true;
463     }
464     void pushLabel(const Identifier* label, bool isLoop) { currentScope()->pushLabel(label, isLoop); }
465     void popLabel() { currentScope()->popLabel(); }
466     ScopeLabelInfo* getLabel(const Identifier* label)
467     {
468         ScopeRef current = currentScope();
469         ScopeLabelInfo* result = 0;
470         while (!(result = current->getLabel(label))) {
471             if (!current.hasContainingScope())
472                 return 0;
473             current = current.containingScope();
474         }
475         return result;
476     }
477
478     enum SourceElementsMode { CheckForStrictMode, DontCheckForStrictMode };
479     template <SourceElementsMode mode, class TreeBuilder> TreeSourceElements parseSourceElements(TreeBuilder&);
480     template <class TreeBuilder> TreeStatement parseStatement(TreeBuilder&, const Identifier*& directive);
481     template <class TreeBuilder> TreeStatement parseFunctionDeclaration(TreeBuilder&);
482     template <class TreeBuilder> TreeStatement parseVarDeclaration(TreeBuilder&);
483     template <class TreeBuilder> TreeStatement parseConstDeclaration(TreeBuilder&);
484     template <class TreeBuilder> TreeStatement parseDoWhileStatement(TreeBuilder&);
485     template <class TreeBuilder> TreeStatement parseWhileStatement(TreeBuilder&);
486     template <class TreeBuilder> TreeStatement parseForStatement(TreeBuilder&);
487     template <class TreeBuilder> TreeStatement parseBreakStatement(TreeBuilder&);
488     template <class TreeBuilder> TreeStatement parseContinueStatement(TreeBuilder&);
489     template <class TreeBuilder> TreeStatement parseReturnStatement(TreeBuilder&);
490     template <class TreeBuilder> TreeStatement parseThrowStatement(TreeBuilder&);
491     template <class TreeBuilder> TreeStatement parseWithStatement(TreeBuilder&);
492     template <class TreeBuilder> TreeStatement parseSwitchStatement(TreeBuilder&);
493     template <class TreeBuilder> TreeClauseList parseSwitchClauses(TreeBuilder&);
494     template <class TreeBuilder> TreeClause parseSwitchDefaultClause(TreeBuilder&);
495     template <class TreeBuilder> TreeStatement parseTryStatement(TreeBuilder&);
496     template <class TreeBuilder> TreeStatement parseDebuggerStatement(TreeBuilder&);
497     template <class TreeBuilder> TreeStatement parseExpressionStatement(TreeBuilder&);
498     template <class TreeBuilder> TreeStatement parseExpressionOrLabelStatement(TreeBuilder&);
499     template <class TreeBuilder> TreeStatement parseIfStatement(TreeBuilder&);
500     template <class TreeBuilder> ALWAYS_INLINE TreeStatement parseBlockStatement(TreeBuilder&);
501     template <class TreeBuilder> TreeExpression parseExpression(TreeBuilder&);
502     template <class TreeBuilder> TreeExpression parseAssignmentExpression(TreeBuilder&);
503     template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseConditionalExpression(TreeBuilder&);
504     template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseBinaryExpression(TreeBuilder&);
505     template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseUnaryExpression(TreeBuilder&);
506     template <class TreeBuilder> TreeExpression parseMemberExpression(TreeBuilder&);
507     template <class TreeBuilder> ALWAYS_INLINE TreeExpression parsePrimaryExpression(TreeBuilder&);
508     template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseArrayLiteral(TreeBuilder&);
509     template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseObjectLiteral(TreeBuilder&);
510     template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseStrictObjectLiteral(TreeBuilder&);
511     template <class TreeBuilder> ALWAYS_INLINE TreeArguments parseArguments(TreeBuilder&);
512     template <bool strict, class TreeBuilder> ALWAYS_INLINE TreeProperty parseProperty(TreeBuilder&);
513     template <class TreeBuilder> ALWAYS_INLINE TreeFunctionBody parseFunctionBody(TreeBuilder&);
514     template <class TreeBuilder> ALWAYS_INLINE TreeFormalParameterList parseFormalParameters(TreeBuilder&);
515     template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseVarDeclarationList(TreeBuilder&, int& declarations, const Identifier*& lastIdent, TreeExpression& lastInitializer, int& identStart, int& initStart, int& initEnd);
516     template <class TreeBuilder> ALWAYS_INLINE TreeConstDeclList parseConstDeclarationList(TreeBuilder& context);
517     enum FunctionRequirements { FunctionNoRequirements, FunctionNeedsName };
518     template <FunctionRequirements, bool nameIsInContainingScope, class TreeBuilder> bool parseFunctionInfo(TreeBuilder&, const Identifier*&, TreeFormalParameterList&, TreeFunctionBody&, int& openBrace, int& closeBrace, int& bodyStartLine);
519     ALWAYS_INLINE int isBinaryOperator(JSTokenType token);
520     bool allowAutomaticSemicolon();
521
522     bool autoSemiColon()
523     {
524         if (m_token.m_type == SEMICOLON) {
525             next();
526             return true;
527         }
528         return allowAutomaticSemicolon();
529     }
530
531     bool canRecurse()
532     {
533         return m_stack.recursionCheck();
534     }
535     
536     int lastTokenEnd() const
537     {
538         return m_lastTokenEnd;
539     }
540
541     ParserArena m_arena;
542     Lexer* m_lexer;
543     StackBounds m_stack;
544     bool m_error;
545     UString m_errorMessage;
546     JSGlobalData* m_globalData;
547     JSToken m_token;
548     bool m_allowsIn;
549     int m_lastLine;
550     int m_lastTokenEnd;
551     int m_assignmentCount;
552     int m_nonLHSCount;
553     bool m_syntaxAlreadyValidated;
554     int m_statementDepth;
555     int m_nonTrivialExpressionCount;
556     const Identifier* m_lastIdentifier;
557
558     struct DepthManager {
559         DepthManager(int* depth)
560             : m_originalDepth(*depth)
561             , m_depth(depth)
562         {
563         }
564         
565         ~DepthManager()
566         {
567             *m_depth = m_originalDepth;
568         }
569         
570     private:
571         int m_originalDepth;
572         int* m_depth;
573     };
574     
575     struct Scope {
576         Scope(JSGlobalData* globalData, bool isFunction, bool strictMode)
577             : m_globalData(globalData)
578             , m_shadowsArguments(false)
579             , m_usesEval(false)
580             , m_needsFullActivation(false)
581             , m_allowsNewDecls(true)
582             , m_strictMode(strictMode)
583             , m_isFunction(isFunction)
584             , m_isFunctionBoundary(false)
585             , m_isValidStrictMode(true)
586             , m_loopDepth(0)
587             , m_switchDepth(0)
588         {
589         }
590
591         Scope(const Scope& rhs)
592             : m_globalData(rhs.m_globalData)
593             , m_shadowsArguments(rhs.m_shadowsArguments)
594             , m_usesEval(rhs.m_usesEval)
595             , m_needsFullActivation(rhs.m_needsFullActivation)
596             , m_allowsNewDecls(rhs.m_allowsNewDecls)
597             , m_strictMode(rhs.m_strictMode)
598             , m_isFunction(rhs.m_isFunction)
599             , m_isFunctionBoundary(rhs.m_isFunctionBoundary)
600             , m_isValidStrictMode(rhs.m_isValidStrictMode)
601             , m_loopDepth(rhs.m_loopDepth)
602             , m_switchDepth(rhs.m_switchDepth)
603         {
604             if (rhs.m_labels) {
605                 m_labels = adoptPtr(new LabelStack);
606                 
607                 typedef LabelStack::const_iterator iterator;
608                 iterator end = rhs.m_labels->end();
609                 for (iterator it = rhs.m_labels->begin(); it != end; ++it)
610                     m_labels->append(ScopeLabelInfo(it->m_ident, it->m_isLoop));
611             }
612         }
613
614         void startSwitch() { m_switchDepth++; }
615         void endSwitch() { m_switchDepth--; }
616         void startLoop() { m_loopDepth++; }
617         void endLoop() { ASSERT(m_loopDepth); m_loopDepth--; }
618         bool inLoop() { return !!m_loopDepth; }
619         bool breakIsValid() { return m_loopDepth || m_switchDepth; }
620         bool continueIsValid() { return m_loopDepth; }
621
622         void pushLabel(const Identifier* label, bool isLoop)
623         {
624             if (!m_labels)
625                 m_labels = adoptPtr(new LabelStack);
626             m_labels->append(ScopeLabelInfo(label->impl(), isLoop));
627         }
628
629         void popLabel()
630         {
631             ASSERT(m_labels);
632             ASSERT(m_labels->size());
633             m_labels->removeLast();
634         }
635
636         ScopeLabelInfo* getLabel(const Identifier* label)
637         {
638             if (!m_labels)
639                 return 0;
640             for (int i = m_labels->size(); i > 0; i--) {
641                 if (m_labels->at(i - 1).m_ident == label->impl())
642                     return &m_labels->at(i - 1);
643             }
644             return 0;
645         }
646
647         void setIsFunction()
648         {
649             m_isFunction = true;
650             m_isFunctionBoundary = true;
651         }
652         bool isFunction() { return m_isFunction; }
653         bool isFunctionBoundary() { return m_isFunctionBoundary; }
654         
655         bool declareVariable(const Identifier* ident)
656         {
657             bool isValidStrictMode = m_globalData->propertyNames->eval != *ident && m_globalData->propertyNames->arguments != *ident;
658             m_isValidStrictMode = m_isValidStrictMode && isValidStrictMode;
659             m_declaredVariables.add(ident->ustring().impl());
660             return isValidStrictMode;
661         }
662         
663         void declareWrite(const Identifier* ident)
664         {
665             ASSERT(m_strictMode);
666             m_writtenVariables.add(ident->impl());
667         }
668
669         void preventNewDecls() { m_allowsNewDecls = false; }
670         bool allowsNewDecls() const { return m_allowsNewDecls; }
671
672         bool declareParameter(const Identifier* ident)
673         {
674             bool isArguments = m_globalData->propertyNames->arguments == *ident;
675             bool isValidStrictMode = m_declaredVariables.add(ident->ustring().impl()).second && m_globalData->propertyNames->eval != *ident && !isArguments;
676             m_isValidStrictMode = m_isValidStrictMode && isValidStrictMode;
677             if (isArguments)
678                 m_shadowsArguments = true;
679             return isValidStrictMode;
680         }
681         
682         void useVariable(const Identifier* ident, bool isEval)
683         {
684             m_usesEval |= isEval;
685             m_usedVariables.add(ident->ustring().impl());
686         }
687         
688         void setNeedsFullActivation() { m_needsFullActivation = true; }
689         
690         bool collectFreeVariables(Scope* nestedScope, bool shouldTrackClosedVariables)
691         {
692             if (nestedScope->m_usesEval)
693                 m_usesEval = true;
694             IdentifierSet::iterator end = nestedScope->m_usedVariables.end();
695             for (IdentifierSet::iterator ptr = nestedScope->m_usedVariables.begin(); ptr != end; ++ptr) {
696                 if (nestedScope->m_declaredVariables.contains(*ptr))
697                     continue;
698                 m_usedVariables.add(*ptr);
699                 if (shouldTrackClosedVariables)
700                     m_closedVariables.add(*ptr);
701             }
702             if (nestedScope->m_writtenVariables.size()) {
703                 IdentifierSet::iterator end = nestedScope->m_writtenVariables.end();
704                 for (IdentifierSet::iterator ptr = nestedScope->m_writtenVariables.begin(); ptr != end; ++ptr) {
705                     if (nestedScope->m_declaredVariables.contains(*ptr))
706                         continue;
707                     m_writtenVariables.add(*ptr);
708                 }
709             }
710
711             return true;
712         }
713
714         void getUncapturedWrittenVariables(IdentifierSet& writtenVariables)
715         {
716             IdentifierSet::iterator end = m_writtenVariables.end();
717             for (IdentifierSet::iterator ptr = m_writtenVariables.begin(); ptr != end; ++ptr) {
718                 if (!m_declaredVariables.contains(*ptr))
719                     writtenVariables.add(*ptr);
720             }
721         }
722
723         void getCapturedVariables(IdentifierSet& capturedVariables)
724         {
725             if (m_needsFullActivation || m_usesEval) {
726                 capturedVariables.swap(m_declaredVariables);
727                 return;
728             }
729             for (IdentifierSet::iterator ptr = m_closedVariables.begin(); ptr != m_closedVariables.end(); ++ptr) {
730                 if (!m_declaredVariables.contains(*ptr))
731                     continue;
732                 capturedVariables.add(*ptr);
733             }
734         }
735         void setStrictMode() { m_strictMode = true; }
736         bool strictMode() const { return m_strictMode; }
737         bool isValidStrictMode() const { return m_isValidStrictMode; }
738         bool shadowsArguments() const { return m_shadowsArguments; }
739         
740         void copyCapturedVariablesToVector(const IdentifierSet& capturedVariables, Vector<RefPtr<StringImpl> >& vector)
741         {
742             IdentifierSet::iterator end = capturedVariables.end();
743             for (IdentifierSet::iterator it = capturedVariables.begin(); it != end; ++it) {
744                 if (m_declaredVariables.contains(*it))
745                     continue;
746                 vector.append(*it);
747             }
748             vector.shrinkToFit();
749         }
750
751         void saveFunctionInfo(SourceProviderCacheItem* info)
752         {
753             ASSERT(m_isFunction);
754             info->usesEval = m_usesEval;
755             copyCapturedVariablesToVector(m_writtenVariables, info->writtenVariables);
756             copyCapturedVariablesToVector(m_usedVariables, info->usedVariables);
757         }
758
759         void restoreFunctionInfo(const SourceProviderCacheItem* info)
760         {
761             ASSERT(m_isFunction);
762             m_usesEval = info->usesEval;
763             unsigned size = info->usedVariables.size();
764             for (unsigned i = 0; i < size; ++i)
765                 m_usedVariables.add(info->usedVariables[i]);
766             size = info->writtenVariables.size();
767             for (unsigned i = 0; i < size; ++i)
768                 m_writtenVariables.add(info->writtenVariables[i]);
769         }
770
771     private:
772         JSGlobalData* m_globalData;
773         bool m_shadowsArguments : 1;
774         bool m_usesEval : 1;
775         bool m_needsFullActivation : 1;
776         bool m_allowsNewDecls : 1;
777         bool m_strictMode : 1;
778         bool m_isFunction : 1;
779         bool m_isFunctionBoundary : 1;
780         bool m_isValidStrictMode : 1;
781         int m_loopDepth;
782         int m_switchDepth;
783
784         typedef Vector<ScopeLabelInfo, 2> LabelStack;
785         OwnPtr<LabelStack> m_labels;
786         IdentifierSet m_declaredVariables;
787         IdentifierSet m_usedVariables;
788         IdentifierSet m_closedVariables;
789         IdentifierSet m_writtenVariables;
790     };
791
792     typedef Vector<Scope, 10> ScopeStack;
793
794     struct ScopeRef {
795         ScopeRef(ScopeStack* scopeStack, unsigned index)
796             : m_scopeStack(scopeStack)
797             , m_index(index)
798         {
799         }
800         Scope* operator->() { return &m_scopeStack->at(m_index); }
801         unsigned index() const { return m_index; }
802
803         bool hasContainingScope()
804         {
805             return m_index && !m_scopeStack->at(m_index).isFunctionBoundary();
806         }
807
808         ScopeRef containingScope()
809         {
810             ASSERT(hasContainingScope());
811             return ScopeRef(m_scopeStack, m_index - 1);
812         }
813
814     private:
815         ScopeStack* m_scopeStack;
816         unsigned m_index;
817     };
818
819     struct AutoPopScopeRef : public ScopeRef {
820         AutoPopScopeRef(JSParser* parser, ScopeRef scope)
821             : ScopeRef(scope)
822             , m_parser(parser)
823         {
824         }
825
826         ~AutoPopScopeRef()
827         {
828             if (m_parser)
829                 m_parser->popScope(*this, false);
830         }
831
832         void setPopped()
833         {
834             m_parser = 0;
835         }
836
837     private:
838         JSParser* m_parser;
839     };
840
841     ScopeRef currentScope()
842     {
843         return ScopeRef(&m_scopeStack, m_scopeStack.size() - 1);
844     }
845     
846     ScopeRef pushScope()
847     {
848         bool isFunction = false;
849         bool isStrict = false;
850         if (!m_scopeStack.isEmpty()) {
851             isStrict = m_scopeStack.last().strictMode();
852             isFunction = m_scopeStack.last().isFunction();
853         }
854         m_scopeStack.append(Scope(m_globalData, isFunction, isStrict));
855         return currentScope();
856     }
857
858     bool popScopeInternal(ScopeRef& scope, bool shouldTrackClosedVariables)
859     {
860         ASSERT_UNUSED(scope, scope.index() == m_scopeStack.size() - 1);
861         ASSERT(m_scopeStack.size() > 1);
862         bool result = m_scopeStack[m_scopeStack.size() - 2].collectFreeVariables(&m_scopeStack.last(), shouldTrackClosedVariables);
863         m_scopeStack.removeLast();
864         return result;
865     }
866
867     bool popScope(ScopeRef& scope, bool shouldTrackClosedVariables)
868     {
869         return popScopeInternal(scope, shouldTrackClosedVariables);
870     }
871
872     bool popScope(AutoPopScopeRef& scope, bool shouldTrackClosedVariables)
873     {
874         scope.setPopped();
875         return popScopeInternal(scope, shouldTrackClosedVariables);
876     }
877
878     bool declareVariable(const Identifier* ident)
879     {
880         unsigned i = m_scopeStack.size() - 1;
881         ASSERT(i < m_scopeStack.size());
882         while (!m_scopeStack[i].allowsNewDecls()) {
883             i--;
884             ASSERT(i < m_scopeStack.size());
885         }
886         return m_scopeStack[i].declareVariable(ident);
887     }
888     
889     void declareWrite(const Identifier* ident)
890     {
891         if (!m_syntaxAlreadyValidated)
892             m_scopeStack.last().declareWrite(ident);
893     }
894
895     ScopeStack m_scopeStack;
896
897     const SourceProviderCacheItem* findCachedFunctionInfo(int openBracePos) 
898     {
899         return m_functionCache ? m_functionCache->get(openBracePos) : 0;
900     }
901
902     SourceProviderCache* m_functionCache;
903     const SourceCode* m_source;
904 };
905
906 UString jsParse(JSGlobalData* globalData, FunctionParameters* parameters, JSParserStrictness strictness, JSParserMode parserMode, const SourceCode* source)
907 {
908     JSParser parser(globalData->lexer, globalData, parameters, strictness == JSParseStrict, parserMode == JSParseFunctionCode, source);
909     return parser.parseProgram();
910 }
911
912 JSParser::JSParser(Lexer* lexer, JSGlobalData* globalData, FunctionParameters* parameters, bool inStrictContext, bool isFunction, const SourceCode* source)
913     : m_lexer(lexer)
914     , m_stack(globalData->stack())
915     , m_error(false)
916     , m_errorMessage("Parse error")
917     , m_globalData(globalData)
918     , m_allowsIn(true)
919     , m_lastLine(0)
920     , m_lastTokenEnd(0)
921     , m_assignmentCount(0)
922     , m_nonLHSCount(0)
923     , m_syntaxAlreadyValidated(source->provider()->isValid())
924     , m_statementDepth(0)
925     , m_nonTrivialExpressionCount(0)
926     , m_lastIdentifier(0)
927     , m_functionCache(m_lexer->sourceProvider()->cache())
928     , m_source(source)
929 {
930     ScopeRef scope = pushScope();
931     if (isFunction)
932         scope->setIsFunction();
933     if (inStrictContext)
934         scope->setStrictMode();
935     if (parameters) {
936         for (unsigned i = 0; i < parameters->size(); i++)
937             scope->declareParameter(&parameters->at(i));
938     }
939     next();
940     m_lexer->setLastLineNumber(tokenLine());
941 }
942
943 UString JSParser::parseProgram()
944 {
945     unsigned oldFunctionCacheSize = m_functionCache ? m_functionCache->byteSize() : 0;
946     ASTBuilder context(m_globalData, m_lexer);
947     if (m_lexer->isReparsing())
948         m_statementDepth--;
949     ScopeRef scope = currentScope();
950     SourceElements* sourceElements = parseSourceElements<CheckForStrictMode>(context);
951     if (!sourceElements || !consume(EOFTOK))
952         return m_errorMessage;
953     IdentifierSet capturedVariables;
954     scope->getCapturedVariables(capturedVariables);
955     CodeFeatures features = context.features();
956     if (scope->strictMode())
957         features |= StrictModeFeature;
958     if (scope->shadowsArguments())
959         features |= ShadowsArgumentsFeature;
960     
961     unsigned functionCacheSize = m_functionCache ? m_functionCache->byteSize() : 0;
962     if (functionCacheSize != oldFunctionCacheSize)
963         m_lexer->sourceProvider()->notifyCacheSizeChanged(functionCacheSize - oldFunctionCacheSize);
964
965     m_globalData->parser->didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), features,
966                                            m_lastLine, context.numConstants(), capturedVariables);
967     return UString();
968 }
969
970 bool JSParser::allowAutomaticSemicolon()
971 {
972     return match(CLOSEBRACE) || match(EOFTOK) || m_lexer->prevTerminator();
973 }
974
975 template <JSParser::SourceElementsMode mode, class TreeBuilder> TreeSourceElements JSParser::parseSourceElements(TreeBuilder& context)
976 {
977     TreeSourceElements sourceElements = context.createSourceElements();
978     bool seenNonDirective = false;
979     const Identifier* directive = 0;
980     unsigned startOffset = m_token.m_info.startOffset;
981     unsigned oldLastLineNumber = m_lexer->lastLineNumber();
982     unsigned oldLineNumber = m_lexer->lineNumber();
983     bool hasSetStrict = false;
984     while (TreeStatement statement = parseStatement(context, directive)) {
985         if (mode == CheckForStrictMode && !seenNonDirective) {
986             if (directive) {
987                 if (!hasSetStrict && m_globalData->propertyNames->useStrictIdentifier == *directive) {
988                     setStrictMode();
989                     hasSetStrict = true;
990                     failIfFalse(isValidStrictMode());
991                     m_lexer->setOffset(startOffset);
992                     next();
993                     m_lexer->setLastLineNumber(oldLastLineNumber);
994                     m_lexer->setLineNumber(oldLineNumber);
995                     failIfTrue(m_error);
996                     continue;
997                 }
998             } else
999                 seenNonDirective = true;
1000         }
1001         context.appendStatement(sourceElements, statement);
1002     }
1003
1004     if (m_error)
1005         fail();
1006     return sourceElements;
1007 }
1008
1009 template <class TreeBuilder> TreeStatement JSParser::parseVarDeclaration(TreeBuilder& context)
1010 {
1011     ASSERT(match(VAR));
1012     int start = tokenLine();
1013     int end = 0;
1014     int scratch;
1015     const Identifier* scratch1 = 0;
1016     TreeExpression scratch2 = 0;
1017     int scratch3 = 0;
1018     TreeExpression varDecls = parseVarDeclarationList(context, scratch, scratch1, scratch2, scratch3, scratch3, scratch3);
1019     failIfTrue(m_error);
1020     failIfFalse(autoSemiColon());
1021
1022     return context.createVarStatement(varDecls, start, end);
1023 }
1024
1025 template <class TreeBuilder> TreeStatement JSParser::parseConstDeclaration(TreeBuilder& context)
1026 {
1027     ASSERT(match(CONSTTOKEN));
1028     int start = tokenLine();
1029     int end = 0;
1030     TreeConstDeclList constDecls = parseConstDeclarationList(context);
1031     failIfTrue(m_error);
1032     failIfFalse(autoSemiColon());
1033     
1034     return context.createConstStatement(constDecls, start, end);
1035 }
1036
1037 template <class TreeBuilder> TreeStatement JSParser::parseDoWhileStatement(TreeBuilder& context)
1038 {
1039     ASSERT(match(DO));
1040     int startLine = tokenLine();
1041     next();
1042     const Identifier* unused = 0;
1043     startLoop();
1044     TreeStatement statement = parseStatement(context, unused);
1045     endLoop();
1046     failIfFalse(statement);
1047     int endLine = tokenLine();
1048     consumeOrFail(WHILE);
1049     consumeOrFail(OPENPAREN);
1050     TreeExpression expr = parseExpression(context);
1051     failIfFalse(expr);
1052     consumeOrFail(CLOSEPAREN);
1053     if (match(SEMICOLON))
1054         next(); // Always performs automatic semicolon insertion.
1055     return context.createDoWhileStatement(statement, expr, startLine, endLine);
1056 }
1057
1058 template <class TreeBuilder> TreeStatement JSParser::parseWhileStatement(TreeBuilder& context)
1059 {
1060     ASSERT(match(WHILE));
1061     int startLine = tokenLine();
1062     next();
1063     consumeOrFail(OPENPAREN);
1064     TreeExpression expr = parseExpression(context);
1065     failIfFalse(expr);
1066     int endLine = tokenLine();
1067     consumeOrFail(CLOSEPAREN);
1068     const Identifier* unused = 0;
1069     startLoop();
1070     TreeStatement statement = parseStatement(context, unused);
1071     endLoop();
1072     failIfFalse(statement);
1073     return context.createWhileStatement(expr, statement, startLine, endLine);
1074 }
1075
1076 template <class TreeBuilder> TreeExpression JSParser::parseVarDeclarationList(TreeBuilder& context, int& declarations, const Identifier*& lastIdent, TreeExpression& lastInitializer, int& identStart, int& initStart, int& initEnd)
1077 {
1078     TreeExpression varDecls = 0;
1079     do {
1080         declarations++;
1081         next();
1082         matchOrFail(IDENT);
1083
1084         int varStart = tokenStart();
1085         identStart = varStart;
1086         const Identifier* name = m_token.m_data.ident;
1087         lastIdent = name;
1088         next();
1089         bool hasInitializer = match(EQUAL);
1090         failIfFalseIfStrictWithNameAndMessage(declareVariable(name), "Cannot declare a variable named", name->impl(), "in strict mode.");
1091         context.addVar(name, (hasInitializer || (!m_allowsIn && match(INTOKEN))) ? DeclarationStacks::HasInitializer : 0);
1092         if (hasInitializer) {
1093             int varDivot = tokenStart() + 1;
1094             initStart = tokenStart();
1095             next(TreeBuilder::DontBuildStrings); // consume '='
1096             int initialAssignments = m_assignmentCount;
1097             TreeExpression initializer = parseAssignmentExpression(context);
1098             initEnd = lastTokenEnd();
1099             lastInitializer = initializer;
1100             failIfFalse(initializer);
1101
1102             TreeExpression node = context.createAssignResolve(*name, initializer, initialAssignments != m_assignmentCount, varStart, varDivot, lastTokenEnd());
1103             if (!varDecls)
1104                 varDecls = node;
1105             else
1106                 varDecls = context.combineCommaNodes(varDecls, node);
1107         }
1108     } while (match(COMMA));
1109     return varDecls;
1110 }
1111
1112 template <class TreeBuilder> TreeConstDeclList JSParser::parseConstDeclarationList(TreeBuilder& context)
1113 {
1114     failIfTrue(strictMode());
1115     TreeConstDeclList constDecls = 0;
1116     TreeConstDeclList tail = 0;
1117     do {
1118         next();
1119         matchOrFail(IDENT);
1120         const Identifier* name = m_token.m_data.ident;
1121         next();
1122         bool hasInitializer = match(EQUAL);
1123         declareVariable(name);
1124         context.addVar(name, DeclarationStacks::IsConstant | (hasInitializer ? DeclarationStacks::HasInitializer : 0));
1125         TreeExpression initializer = 0;
1126         if (hasInitializer) {
1127             next(TreeBuilder::DontBuildStrings); // consume '='
1128             initializer = parseAssignmentExpression(context);
1129         }
1130         tail = context.appendConstDecl(tail, name, initializer);
1131         if (!constDecls)
1132             constDecls = tail;
1133     } while (match(COMMA));
1134     return constDecls;
1135 }
1136
1137 template <class TreeBuilder> TreeStatement JSParser::parseForStatement(TreeBuilder& context)
1138 {
1139     ASSERT(match(FOR));
1140     int startLine = tokenLine();
1141     next();
1142     consumeOrFail(OPENPAREN);
1143     int nonLHSCount = m_nonLHSCount;
1144     int declarations = 0;
1145     int declsStart = 0;
1146     int declsEnd = 0;
1147     TreeExpression decls = 0;
1148     bool hasDeclaration = false;
1149     if (match(VAR)) {
1150         /*
1151          for (var IDENT in expression) statement
1152          for (var IDENT = expression in expression) statement
1153          for (var varDeclarationList; expressionOpt; expressionOpt)
1154          */
1155         hasDeclaration = true;
1156         const Identifier* forInTarget = 0;
1157         TreeExpression forInInitializer = 0;
1158         m_allowsIn = false;
1159         int initStart = 0;
1160         int initEnd = 0;
1161         decls = parseVarDeclarationList(context, declarations, forInTarget, forInInitializer, declsStart, initStart, initEnd);
1162         m_allowsIn = true;
1163         if (m_error)
1164             fail();
1165
1166         // Remainder of a standard for loop is handled identically
1167         if (match(SEMICOLON))
1168             goto standardForLoop;
1169
1170         failIfFalse(declarations == 1);
1171
1172         // Handle for-in with var declaration
1173         int inLocation = tokenStart();
1174         consumeOrFail(INTOKEN);
1175
1176         TreeExpression expr = parseExpression(context);
1177         failIfFalse(expr);
1178         int exprEnd = lastTokenEnd();
1179
1180         int endLine = tokenLine();
1181         consumeOrFail(CLOSEPAREN);
1182
1183         const Identifier* unused = 0;
1184         startLoop();
1185         TreeStatement statement = parseStatement(context, unused);
1186         endLoop();
1187         failIfFalse(statement);
1188
1189         return context.createForInLoop(forInTarget, forInInitializer, expr, statement, declsStart, inLocation, exprEnd, initStart, initEnd, startLine, endLine);
1190     }
1191
1192     if (!match(SEMICOLON)) {
1193         m_allowsIn = false;
1194         declsStart = tokenStart();
1195         decls = parseExpression(context);
1196         declsEnd = lastTokenEnd();
1197         m_allowsIn = true;
1198         failIfFalse(decls);
1199     }
1200
1201     if (match(SEMICOLON)) {
1202     standardForLoop:
1203         // Standard for loop
1204         next();
1205         TreeExpression condition = 0;
1206
1207         if (!match(SEMICOLON)) {
1208             condition = parseExpression(context);
1209             failIfFalse(condition);
1210         }
1211         consumeOrFail(SEMICOLON);
1212
1213         TreeExpression increment = 0;
1214         if (!match(CLOSEPAREN)) {
1215             increment = parseExpression(context);
1216             failIfFalse(increment);
1217         }
1218         int endLine = tokenLine();
1219         consumeOrFail(CLOSEPAREN);
1220         const Identifier* unused = 0;
1221         startLoop();
1222         TreeStatement statement = parseStatement(context, unused);
1223         endLoop();
1224         failIfFalse(statement);
1225         return context.createForLoop(decls, condition, increment, statement, hasDeclaration, startLine, endLine);
1226     }
1227
1228     // For-in loop
1229     failIfFalse(nonLHSCount == m_nonLHSCount);
1230     consumeOrFail(INTOKEN);
1231     TreeExpression expr = parseExpression(context);
1232     failIfFalse(expr);
1233     int exprEnd = lastTokenEnd();
1234     int endLine = tokenLine();
1235     consumeOrFail(CLOSEPAREN);
1236     const Identifier* unused = 0;
1237     startLoop();
1238     TreeStatement statement = parseStatement(context, unused);
1239     endLoop();
1240     failIfFalse(statement);
1241     
1242     return context.createForInLoop(decls, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine);
1243 }
1244
1245 template <class TreeBuilder> TreeStatement JSParser::parseBreakStatement(TreeBuilder& context)
1246 {
1247     ASSERT(match(BREAK));
1248     int startCol = tokenStart();
1249     int endCol = tokenEnd();
1250     int startLine = tokenLine();
1251     int endLine = tokenLine();
1252     next();
1253
1254     if (autoSemiColon()) {
1255         failIfFalseWithMessage(breakIsValid(), "'break' is only valid inside a switch or loop statement");
1256         return context.createBreakStatement(startCol, endCol, startLine, endLine);
1257     }
1258     matchOrFail(IDENT);
1259     const Identifier* ident = m_token.m_data.ident;
1260     failIfFalseWithNameAndMessage(getLabel(ident), "Label", ident->impl(), "is not defined");
1261     endCol = tokenEnd();
1262     endLine = tokenLine();
1263     next();
1264     failIfFalse(autoSemiColon());
1265     return context.createBreakStatement(ident, startCol, endCol, startLine, endLine);
1266 }
1267
1268 template <class TreeBuilder> TreeStatement JSParser::parseContinueStatement(TreeBuilder& context)
1269 {
1270     ASSERT(match(CONTINUE));
1271     int startCol = tokenStart();
1272     int endCol = tokenEnd();
1273     int startLine = tokenLine();
1274     int endLine = tokenLine();
1275     next();
1276
1277     if (autoSemiColon()) {
1278         failIfFalseWithMessage(continueIsValid(), "'continue' is only valid inside a loop statement");
1279         return context.createContinueStatement(startCol, endCol, startLine, endLine);
1280     }
1281     matchOrFail(IDENT);
1282     const Identifier* ident = m_token.m_data.ident;
1283     ScopeLabelInfo* label = getLabel(ident);
1284     failIfFalseWithNameAndMessage(label, "Label", ident->impl(), "is not defined");
1285     failIfFalseWithMessage(label->m_isLoop, "'continue' is only valid inside a loop statement");
1286     endCol = tokenEnd();
1287     endLine = tokenLine();
1288     next();
1289     failIfFalse(autoSemiColon());
1290     return context.createContinueStatement(ident, startCol, endCol, startLine, endLine);
1291 }
1292
1293 template <class TreeBuilder> TreeStatement JSParser::parseReturnStatement(TreeBuilder& context)
1294 {
1295     ASSERT(match(RETURN));
1296     failIfFalse(currentScope()->isFunction());
1297     int startLine = tokenLine();
1298     int endLine = startLine;
1299     int start = tokenStart();
1300     int end = tokenEnd();
1301     next();
1302     // We do the auto semicolon check before attempting to parse an expression
1303     // as we need to ensure the a line break after the return correctly terminates
1304     // the statement
1305     if (match(SEMICOLON))
1306         endLine  = tokenLine();
1307     if (autoSemiColon())
1308         return context.createReturnStatement(0, start, end, startLine, endLine);
1309     TreeExpression expr = parseExpression(context);
1310     failIfFalse(expr);
1311     end = lastTokenEnd();
1312     if (match(SEMICOLON))
1313         endLine  = tokenLine();
1314     failIfFalse(autoSemiColon());
1315     return context.createReturnStatement(expr, start, end, startLine, endLine);
1316 }
1317
1318 template <class TreeBuilder> TreeStatement JSParser::parseThrowStatement(TreeBuilder& context)
1319 {
1320     ASSERT(match(THROW));
1321     int eStart = tokenStart();
1322     int startLine = tokenLine();
1323     next();
1324     
1325     failIfTrue(autoSemiColon());
1326
1327     TreeExpression expr = parseExpression(context);
1328     failIfFalse(expr);
1329     int eEnd = lastTokenEnd();
1330     int endLine = tokenLine();
1331     failIfFalse(autoSemiColon());
1332
1333     return context.createThrowStatement(expr, eStart, eEnd, startLine, endLine);
1334 }
1335
1336 template <class TreeBuilder> TreeStatement JSParser::parseWithStatement(TreeBuilder& context)
1337 {
1338     ASSERT(match(WITH));
1339     failIfTrueWithMessage(strictMode(), "'with' statements are not valid in strict mode");
1340     currentScope()->setNeedsFullActivation();
1341     int startLine = tokenLine();
1342     next();
1343     consumeOrFail(OPENPAREN);
1344     int start = tokenStart();
1345     TreeExpression expr = parseExpression(context);
1346     failIfFalse(expr);
1347     int end = lastTokenEnd();
1348
1349     int endLine = tokenLine();
1350     consumeOrFail(CLOSEPAREN);
1351     const Identifier* unused = 0;
1352     TreeStatement statement = parseStatement(context, unused);
1353     failIfFalse(statement);
1354
1355     return context.createWithStatement(expr, statement, start, end, startLine, endLine);
1356 }
1357
1358 template <class TreeBuilder> TreeStatement JSParser::parseSwitchStatement(TreeBuilder& context)
1359 {
1360     ASSERT(match(SWITCH));
1361     int startLine = tokenLine();
1362     next();
1363     consumeOrFail(OPENPAREN);
1364     TreeExpression expr = parseExpression(context);
1365     failIfFalse(expr);
1366     int endLine = tokenLine();
1367     consumeOrFail(CLOSEPAREN);
1368     consumeOrFail(OPENBRACE);
1369     startSwitch();
1370     TreeClauseList firstClauses = parseSwitchClauses(context);
1371     failIfTrue(m_error);
1372
1373     TreeClause defaultClause = parseSwitchDefaultClause(context);
1374     failIfTrue(m_error);
1375
1376     TreeClauseList secondClauses = parseSwitchClauses(context);
1377     failIfTrue(m_error);
1378     endSwitch();
1379     consumeOrFail(CLOSEBRACE);
1380
1381     return context.createSwitchStatement(expr, firstClauses, defaultClause, secondClauses, startLine, endLine);
1382
1383 }
1384
1385 template <class TreeBuilder> TreeClauseList JSParser::parseSwitchClauses(TreeBuilder& context)
1386 {
1387     if (!match(CASE))
1388         return 0;
1389     next();
1390     TreeExpression condition = parseExpression(context);
1391     failIfFalse(condition);
1392     consumeOrFail(COLON);
1393     TreeSourceElements statements = parseSourceElements<DontCheckForStrictMode>(context);
1394     failIfFalse(statements);
1395     TreeClause clause = context.createClause(condition, statements);
1396     TreeClauseList clauseList = context.createClauseList(clause);
1397     TreeClauseList tail = clauseList;
1398
1399     while (match(CASE)) {
1400         next();
1401         TreeExpression condition = parseExpression(context);
1402         failIfFalse(condition);
1403         consumeOrFail(COLON);
1404         TreeSourceElements statements = parseSourceElements<DontCheckForStrictMode>(context);
1405         failIfFalse(statements);
1406         clause = context.createClause(condition, statements);
1407         tail = context.createClauseList(tail, clause);
1408     }
1409     return clauseList;
1410 }
1411
1412 template <class TreeBuilder> TreeClause JSParser::parseSwitchDefaultClause(TreeBuilder& context)
1413 {
1414     if (!match(DEFAULT))
1415         return 0;
1416     next();
1417     consumeOrFail(COLON);
1418     TreeSourceElements statements = parseSourceElements<DontCheckForStrictMode>(context);
1419     failIfFalse(statements);
1420     return context.createClause(0, statements);
1421 }
1422
1423 template <class TreeBuilder> TreeStatement JSParser::parseTryStatement(TreeBuilder& context)
1424 {
1425     ASSERT(match(TRY));
1426     TreeStatement tryBlock = 0;
1427     const Identifier* ident = &m_globalData->propertyNames->nullIdentifier;
1428     bool catchHasEval = false;
1429     TreeStatement catchBlock = 0;
1430     TreeStatement finallyBlock = 0;
1431     int firstLine = tokenLine();
1432     next();
1433     matchOrFail(OPENBRACE);
1434
1435     tryBlock = parseBlockStatement(context);
1436     failIfFalse(tryBlock);
1437     int lastLine = m_lastLine;
1438
1439     if (match(CATCH)) {
1440         currentScope()->setNeedsFullActivation();
1441         next();
1442         consumeOrFail(OPENPAREN);
1443         matchOrFail(IDENT);
1444         ident = m_token.m_data.ident;
1445         next();
1446         AutoPopScopeRef catchScope(this, pushScope());
1447         failIfFalseIfStrictWithNameAndMessage(catchScope->declareVariable(ident), "Cannot declare a variable named", ident->impl(), "in strict mode");
1448         catchScope->preventNewDecls();
1449         consumeOrFail(CLOSEPAREN);
1450         matchOrFail(OPENBRACE);
1451         int initialEvalCount = context.evalCount();
1452         catchBlock = parseBlockStatement(context);
1453         failIfFalseWithMessage(catchBlock, "'try' must have a catch or finally block");
1454         catchHasEval = initialEvalCount != context.evalCount();
1455         failIfFalse(popScope(catchScope, TreeBuilder::NeedsFreeVariableInfo));
1456     }
1457
1458     if (match(FINALLY)) {
1459         next();
1460         matchOrFail(OPENBRACE);
1461         finallyBlock = parseBlockStatement(context);
1462         failIfFalse(finallyBlock);
1463     }
1464     failIfFalse(catchBlock || finallyBlock);
1465     return context.createTryStatement(tryBlock, ident, catchHasEval, catchBlock, finallyBlock, firstLine, lastLine);
1466 }
1467
1468 template <class TreeBuilder> TreeStatement JSParser::parseDebuggerStatement(TreeBuilder& context)
1469 {
1470     ASSERT(match(DEBUGGER));
1471     int startLine = tokenLine();
1472     int endLine = startLine;
1473     next();
1474     if (match(SEMICOLON))
1475         startLine = tokenLine();
1476     failIfFalse(autoSemiColon());
1477     return context.createDebugger(startLine, endLine);
1478 }
1479
1480 template <class TreeBuilder> TreeStatement JSParser::parseBlockStatement(TreeBuilder& context)
1481 {
1482     ASSERT(match(OPENBRACE));
1483     int start = tokenLine();
1484     next();
1485     if (match(CLOSEBRACE)) {
1486         next();
1487         return context.createBlockStatement(0, start, m_lastLine);
1488     }
1489     TreeSourceElements subtree = parseSourceElements<DontCheckForStrictMode>(context);
1490     failIfFalse(subtree);
1491     matchOrFail(CLOSEBRACE);
1492     next();
1493     return context.createBlockStatement(subtree, start, m_lastLine);
1494 }
1495
1496 template <class TreeBuilder> TreeStatement JSParser::parseStatement(TreeBuilder& context, const Identifier*& directive)
1497 {
1498     DepthManager statementDepth(&m_statementDepth);
1499     m_statementDepth++;
1500     directive = 0;
1501     int nonTrivialExpressionCount = 0;
1502     failIfStackOverflow();
1503     switch (m_token.m_type) {
1504     case OPENBRACE:
1505         return parseBlockStatement(context);
1506     case VAR:
1507         return parseVarDeclaration(context);
1508     case CONSTTOKEN:
1509         return parseConstDeclaration(context);
1510     case FUNCTION:
1511         failIfFalseIfStrictWithMessage(m_statementDepth == 1, "Functions cannot be declared in a nested block in strict mode");
1512         return parseFunctionDeclaration(context);
1513     case SEMICOLON:
1514         next();
1515         return context.createEmptyStatement();
1516     case IF:
1517         return parseIfStatement(context);
1518     case DO:
1519         return parseDoWhileStatement(context);
1520     case WHILE:
1521         return parseWhileStatement(context);
1522     case FOR:
1523         return parseForStatement(context);
1524     case CONTINUE:
1525         return parseContinueStatement(context);
1526     case BREAK:
1527         return parseBreakStatement(context);
1528     case RETURN:
1529         return parseReturnStatement(context);
1530     case WITH:
1531         return parseWithStatement(context);
1532     case SWITCH:
1533         return parseSwitchStatement(context);
1534     case THROW:
1535         return parseThrowStatement(context);
1536     case TRY:
1537         return parseTryStatement(context);
1538     case DEBUGGER:
1539         return parseDebuggerStatement(context);
1540     case EOFTOK:
1541     case CASE:
1542     case CLOSEBRACE:
1543     case DEFAULT:
1544         // These tokens imply the end of a set of source elements
1545         return 0;
1546     case IDENT:
1547         return parseExpressionOrLabelStatement(context);
1548     case STRING:
1549         directive = m_token.m_data.ident;
1550         nonTrivialExpressionCount = m_nonTrivialExpressionCount;
1551     default:
1552         TreeStatement exprStatement = parseExpressionStatement(context);
1553         if (directive && nonTrivialExpressionCount != m_nonTrivialExpressionCount)
1554             directive = 0;
1555         return exprStatement;
1556     }
1557 }
1558
1559 template <class TreeBuilder> TreeFormalParameterList JSParser::parseFormalParameters(TreeBuilder& context)
1560 {
1561     matchOrFail(IDENT);
1562     failIfFalseIfStrictWithNameAndMessage(declareParameter(m_token.m_data.ident), "Cannot declare a parameter named", m_token.m_data.ident->impl(), " in strict mode");
1563     TreeFormalParameterList list = context.createFormalParameterList(*m_token.m_data.ident);
1564     TreeFormalParameterList tail = list;
1565     next();
1566     while (match(COMMA)) {
1567         next();
1568         matchOrFail(IDENT);
1569         const Identifier* ident = m_token.m_data.ident;
1570         failIfFalseIfStrictWithNameAndMessage(declareParameter(ident), "Cannot declare a parameter named", ident->impl(), "in strict mode");
1571         next();
1572         tail = context.createFormalParameterList(tail, *ident);
1573     }
1574     return list;
1575 }
1576
1577 template <class TreeBuilder> TreeFunctionBody JSParser::parseFunctionBody(TreeBuilder& context)
1578 {
1579     if (match(CLOSEBRACE))
1580         return context.createFunctionBody(strictMode());
1581     DepthManager statementDepth(&m_statementDepth);
1582     m_statementDepth = 0;
1583     typename TreeBuilder::FunctionBodyBuilder bodyBuilder(m_globalData, m_lexer);
1584     failIfFalse(parseSourceElements<CheckForStrictMode>(bodyBuilder));
1585     return context.createFunctionBody(strictMode());
1586 }
1587
1588 template <JSParser::FunctionRequirements requirements, bool nameIsInContainingScope, class TreeBuilder> bool JSParser::parseFunctionInfo(TreeBuilder& context, const Identifier*& name, TreeFormalParameterList& parameters, TreeFunctionBody& body, int& openBracePos, int& closeBracePos, int& bodyStartLine)
1589 {
1590     AutoPopScopeRef functionScope(this, pushScope());
1591     functionScope->setIsFunction();
1592     if (match(IDENT)) {
1593         name = m_token.m_data.ident;
1594         failIfTrueWithMessage(*name == m_globalData->propertyNames->underscoreProto, "Cannot name a function __proto__");
1595         next();
1596         if (!nameIsInContainingScope)
1597             failIfFalseIfStrict(functionScope->declareVariable(name));
1598     } else if (requirements == FunctionNeedsName)
1599         return false;
1600     consumeOrFail(OPENPAREN);
1601     if (!match(CLOSEPAREN)) {
1602         parameters = parseFormalParameters(context);
1603         failIfFalse(parameters);
1604     }
1605     consumeOrFail(CLOSEPAREN);
1606     matchOrFail(OPENBRACE);
1607
1608     openBracePos = m_token.m_data.intValue;
1609     bodyStartLine = tokenLine();
1610
1611     if (const SourceProviderCacheItem* cachedInfo = TreeBuilder::CanUseFunctionCache ? findCachedFunctionInfo(openBracePos) : 0) {
1612         // If we know about this function already, we can use the cached info and skip the parser to the end of the function.
1613         body = context.createFunctionBody(strictMode());
1614
1615         functionScope->restoreFunctionInfo(cachedInfo);
1616         failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo));
1617
1618         closeBracePos = cachedInfo->closeBracePos;
1619         m_token = cachedInfo->closeBraceToken();
1620         m_lexer->setOffset(m_token.m_info.endOffset);
1621         m_lexer->setLineNumber(m_token.m_info.line);
1622
1623         next();
1624         return true;
1625     }
1626
1627     next();
1628
1629     body = parseFunctionBody(context);
1630     failIfFalse(body);
1631     if (functionScope->strictMode() && name) {
1632         failIfTrueWithNameAndMessage(m_globalData->propertyNames->arguments == *name, "Function name", name->impl(), "is not valid in strict mode");
1633         failIfTrueWithNameAndMessage(m_globalData->propertyNames->eval == *name, "Function name", name->impl(), "is not valid in strict mode");
1634     }
1635     closeBracePos = m_token.m_data.intValue;
1636     
1637     // Cache the tokenizer state and the function scope the first time the function is parsed.
1638     // Any future reparsing can then skip the function.
1639     static const int minimumFunctionLengthToCache = 64;
1640     OwnPtr<SourceProviderCacheItem> newInfo;
1641     int functionLength = closeBracePos - openBracePos;
1642     if (TreeBuilder::CanUseFunctionCache && m_functionCache && functionLength > minimumFunctionLengthToCache) {
1643         newInfo = adoptPtr(new SourceProviderCacheItem(m_token.m_info.line, closeBracePos));
1644         functionScope->saveFunctionInfo(newInfo.get());
1645     }
1646     
1647     failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo));
1648     matchOrFail(CLOSEBRACE);
1649
1650     if (newInfo) {
1651         unsigned approximateByteSize = newInfo->approximateByteSize();
1652         m_functionCache->add(openBracePos, newInfo.release(), approximateByteSize);
1653     }
1654
1655     next();
1656     return true;
1657 }
1658
1659 template <class TreeBuilder> TreeStatement JSParser::parseFunctionDeclaration(TreeBuilder& context)
1660 {
1661     ASSERT(match(FUNCTION));
1662     next();
1663     const Identifier* name = 0;
1664     TreeFormalParameterList parameters = 0;
1665     TreeFunctionBody body = 0;
1666     int openBracePos = 0;
1667     int closeBracePos = 0;
1668     int bodyStartLine = 0;
1669     failIfFalse((parseFunctionInfo<FunctionNeedsName, true>(context, name, parameters, body, openBracePos, closeBracePos, bodyStartLine)));
1670     failIfFalse(name);
1671     failIfFalseIfStrict(declareVariable(name));
1672     return context.createFuncDeclStatement(name, body, parameters, openBracePos, closeBracePos, bodyStartLine, m_lastLine);
1673 }
1674
1675 struct LabelInfo {
1676     LabelInfo(const Identifier* ident, int start, int end)
1677         : m_ident(ident)
1678         , m_start(start)
1679         , m_end(end)
1680     {
1681     }
1682
1683     const Identifier* m_ident;
1684     int m_start;
1685     int m_end;
1686 };
1687
1688 template <class TreeBuilder> TreeStatement JSParser::parseExpressionOrLabelStatement(TreeBuilder& context)
1689 {
1690
1691     /* Expression and Label statements are ambiguous at LL(1), so we have a
1692      * special case that looks for a colon as the next character in the input.
1693      */
1694     Vector<LabelInfo> labels;
1695
1696     do {
1697         int start = tokenStart();
1698         int startLine = tokenLine();
1699         if (!nextTokenIsColon()) {
1700             // If we hit this path we're making a expression statement, which
1701             // by definition can't make use of continue/break so we can just
1702             // ignore any labels we might have accumulated.
1703             TreeExpression expression = parseExpression(context);
1704             failIfFalse(expression);
1705             failIfFalse(autoSemiColon());
1706             return context.createExprStatement(expression, startLine, m_lastLine);
1707         }
1708         const Identifier* ident = m_token.m_data.ident;
1709         int end = tokenEnd();
1710         next();
1711         consumeOrFail(COLON);
1712         if (!m_syntaxAlreadyValidated) {
1713             // This is O(N^2) over the current list of consecutive labels, but I
1714             // have never seen more than one label in a row in the real world.
1715             for (size_t i = 0; i < labels.size(); i++)
1716                 failIfTrue(ident->impl() == labels[i].m_ident->impl());
1717             failIfTrue(getLabel(ident));
1718             labels.append(LabelInfo(ident, start, end));
1719         }
1720     } while (match(IDENT));
1721     bool isLoop = false;
1722     switch (m_token.m_type) {
1723     case FOR:
1724     case WHILE:
1725     case DO:
1726         isLoop = true;
1727         break;
1728
1729     default:
1730         break;
1731     }
1732     const Identifier* unused = 0;
1733     if (!m_syntaxAlreadyValidated) {
1734         for (size_t i = 0; i < labels.size(); i++)
1735             pushLabel(labels[i].m_ident, isLoop);
1736     }
1737     TreeStatement statement = parseStatement(context, unused);
1738     if (!m_syntaxAlreadyValidated) {
1739         for (size_t i = 0; i < labels.size(); i++)
1740             popLabel();
1741     }
1742     failIfFalse(statement);
1743     for (size_t i = 0; i < labels.size(); i++) {
1744         const LabelInfo& info = labels[labels.size() - i - 1];
1745         statement = context.createLabelStatement(info.m_ident, statement, info.m_start, info.m_end);
1746     }
1747     return statement;
1748 }
1749
1750 template <class TreeBuilder> TreeStatement JSParser::parseExpressionStatement(TreeBuilder& context)
1751 {
1752     int startLine = tokenLine();
1753     TreeExpression expression = parseExpression(context);
1754     failIfFalse(expression);
1755     failIfFalse(autoSemiColon());
1756     return context.createExprStatement(expression, startLine, m_lastLine);
1757 }
1758
1759 template <class TreeBuilder> TreeStatement JSParser::parseIfStatement(TreeBuilder& context)
1760 {
1761     ASSERT(match(IF));
1762
1763     int start = tokenLine();
1764     next();
1765
1766     consumeOrFail(OPENPAREN);
1767
1768     TreeExpression condition = parseExpression(context);
1769     failIfFalse(condition);
1770     int end = tokenLine();
1771     consumeOrFail(CLOSEPAREN);
1772
1773     const Identifier* unused = 0;
1774     TreeStatement trueBlock = parseStatement(context, unused);
1775     failIfFalse(trueBlock);
1776
1777     if (!match(ELSE))
1778         return context.createIfStatement(condition, trueBlock, start, end);
1779     
1780     Vector<TreeExpression> exprStack;
1781     Vector<pair<int, int> > posStack;
1782     Vector<TreeStatement> statementStack;
1783     bool trailingElse = false;
1784     do {
1785         next();
1786         if (!match(IF)) {
1787             const Identifier* unused = 0;
1788             TreeStatement block = parseStatement(context, unused);
1789             failIfFalse(block);
1790             statementStack.append(block);
1791             trailingElse = true;
1792             break;
1793         }
1794         int innerStart = tokenLine();
1795         next();
1796         
1797         consumeOrFail(OPENPAREN);
1798         
1799         TreeExpression innerCondition = parseExpression(context);
1800         failIfFalse(innerCondition);
1801         int innerEnd = tokenLine();
1802         consumeOrFail(CLOSEPAREN);
1803         const Identifier* unused = 0;
1804         TreeStatement innerTrueBlock = parseStatement(context, unused);
1805         failIfFalse(innerTrueBlock);     
1806         exprStack.append(innerCondition);
1807         posStack.append(make_pair(innerStart, innerEnd));
1808         statementStack.append(innerTrueBlock);
1809     } while (match(ELSE));
1810
1811     if (!trailingElse) {
1812         TreeExpression condition = exprStack.last();
1813         exprStack.removeLast();
1814         TreeStatement trueBlock = statementStack.last();
1815         statementStack.removeLast();
1816         pair<int, int> pos = posStack.last();
1817         posStack.removeLast();
1818         statementStack.append(context.createIfStatement(condition, trueBlock, pos.first, pos.second));
1819     }
1820
1821     while (!exprStack.isEmpty()) {
1822         TreeExpression condition = exprStack.last();
1823         exprStack.removeLast();
1824         TreeStatement falseBlock = statementStack.last();
1825         statementStack.removeLast();
1826         TreeStatement trueBlock = statementStack.last();
1827         statementStack.removeLast();
1828         pair<int, int> pos = posStack.last();
1829         posStack.removeLast();
1830         statementStack.append(context.createIfStatement(condition, trueBlock, falseBlock, pos.first, pos.second));
1831     }
1832     
1833     return context.createIfStatement(condition, trueBlock, statementStack.last(), start, end);
1834 }
1835
1836 template <class TreeBuilder> TreeExpression JSParser::parseExpression(TreeBuilder& context)
1837 {
1838     failIfStackOverflow();
1839     TreeExpression node = parseAssignmentExpression(context);
1840     failIfFalse(node);
1841     if (!match(COMMA))
1842         return node;
1843     next();
1844     m_nonTrivialExpressionCount++;
1845     m_nonLHSCount++;
1846     TreeExpression right = parseAssignmentExpression(context);
1847     failIfFalse(right);
1848     typename TreeBuilder::Comma commaNode = context.createCommaExpr(node, right);
1849     while (match(COMMA)) {
1850         next(TreeBuilder::DontBuildStrings);
1851         right = parseAssignmentExpression(context);
1852         failIfFalse(right);
1853         context.appendToComma(commaNode, right);
1854     }
1855     return commaNode;
1856 }
1857
1858
1859 template <typename TreeBuilder> TreeExpression JSParser::parseAssignmentExpression(TreeBuilder& context)
1860 {
1861     failIfStackOverflow();
1862     int start = tokenStart();
1863     int initialAssignmentCount = m_assignmentCount;
1864     int initialNonLHSCount = m_nonLHSCount;
1865     TreeExpression lhs = parseConditionalExpression(context);
1866     failIfFalse(lhs);
1867     if (initialNonLHSCount != m_nonLHSCount)
1868         return lhs;
1869
1870     int assignmentStack = 0;
1871     Operator op;
1872     bool hadAssignment = false;
1873     while (true) {
1874         switch (m_token.m_type) {
1875         case EQUAL: op = OpEqual; break;
1876         case PLUSEQUAL: op = OpPlusEq; break;
1877         case MINUSEQUAL: op = OpMinusEq; break;
1878         case MULTEQUAL: op = OpMultEq; break;
1879         case DIVEQUAL: op = OpDivEq; break;
1880         case LSHIFTEQUAL: op = OpLShift; break;
1881         case RSHIFTEQUAL: op = OpRShift; break;
1882         case URSHIFTEQUAL: op = OpURShift; break;
1883         case ANDEQUAL: op = OpAndEq; break;
1884         case XOREQUAL: op = OpXOrEq; break;
1885         case OREQUAL: op = OpOrEq; break;
1886         case MODEQUAL: op = OpModEq; break;
1887         default:
1888             goto end;
1889         }
1890         m_nonTrivialExpressionCount++;
1891         hadAssignment = true;
1892         context.assignmentStackAppend(assignmentStack, lhs, start, tokenStart(), m_assignmentCount, op);
1893         start = tokenStart();
1894         m_assignmentCount++;
1895         next(TreeBuilder::DontBuildStrings);
1896         if (strictMode() && m_lastIdentifier && context.isResolve(lhs)) {
1897             failIfTrueIfStrictWithMessage(m_globalData->propertyNames->eval == *m_lastIdentifier, "'eval' cannot be modified in strict mode");
1898             failIfTrueIfStrictWithMessage(m_globalData->propertyNames->arguments == *m_lastIdentifier, "'arguments' cannot be modified in strict mode");
1899             declareWrite(m_lastIdentifier);
1900             m_lastIdentifier = 0;
1901         }
1902         lhs = parseConditionalExpression(context);
1903         failIfFalse(lhs);
1904         if (initialNonLHSCount != m_nonLHSCount)
1905             break;
1906     }
1907 end:
1908     if (hadAssignment)
1909         m_nonLHSCount++;
1910
1911     if (!TreeBuilder::CreatesAST)
1912         return lhs;
1913
1914     while (assignmentStack)
1915         lhs = context.createAssignment(assignmentStack, lhs, initialAssignmentCount, m_assignmentCount, lastTokenEnd());
1916
1917     return lhs;
1918 }
1919
1920 template <class TreeBuilder> TreeExpression JSParser::parseConditionalExpression(TreeBuilder& context)
1921 {
1922     TreeExpression cond = parseBinaryExpression(context);
1923     failIfFalse(cond);
1924     if (!match(QUESTION))
1925         return cond;
1926     m_nonTrivialExpressionCount++;
1927     m_nonLHSCount++;
1928     next(TreeBuilder::DontBuildStrings);
1929     TreeExpression lhs = parseAssignmentExpression(context);
1930     consumeOrFailWithFlags(COLON, TreeBuilder::DontBuildStrings);
1931
1932     TreeExpression rhs = parseAssignmentExpression(context);
1933     failIfFalse(rhs);
1934     return context.createConditionalExpr(cond, lhs, rhs);
1935 }
1936
1937 ALWAYS_INLINE static bool isUnaryOp(JSTokenType token)
1938 {
1939     return token & UnaryOpTokenFlag;
1940 }
1941
1942 int JSParser::isBinaryOperator(JSTokenType token)
1943 {
1944     if (m_allowsIn)
1945         return token & (BinaryOpTokenPrecedenceMask << BinaryOpTokenAllowsInPrecedenceAdditionalShift);
1946     return token & BinaryOpTokenPrecedenceMask;
1947 }
1948
1949 template <class TreeBuilder> TreeExpression JSParser::parseBinaryExpression(TreeBuilder& context)
1950 {
1951
1952     int operandStackDepth = 0;
1953     int operatorStackDepth = 0;
1954     typename TreeBuilder::BinaryExprContext binaryExprContext(context);
1955     while (true) {
1956         int exprStart = tokenStart();
1957         int initialAssignments = m_assignmentCount;
1958         TreeExpression current = parseUnaryExpression(context);
1959         failIfFalse(current);
1960
1961         context.appendBinaryExpressionInfo(operandStackDepth, current, exprStart, lastTokenEnd(), lastTokenEnd(), initialAssignments != m_assignmentCount);
1962         int precedence = isBinaryOperator(m_token.m_type);
1963         if (!precedence)
1964             break;
1965         m_nonTrivialExpressionCount++;
1966         m_nonLHSCount++;
1967         int operatorToken = m_token.m_type;
1968         next(TreeBuilder::DontBuildStrings);
1969
1970         while (operatorStackDepth &&  context.operatorStackHasHigherPrecedence(operatorStackDepth, precedence)) {
1971             ASSERT(operandStackDepth > 1);
1972
1973             typename TreeBuilder::BinaryOperand rhs = context.getFromOperandStack(-1);
1974             typename TreeBuilder::BinaryOperand lhs = context.getFromOperandStack(-2);
1975             context.shrinkOperandStackBy(operandStackDepth, 2);
1976             context.appendBinaryOperation(operandStackDepth, operatorStackDepth, lhs, rhs);
1977             context.operatorStackPop(operatorStackDepth);
1978         }
1979         context.operatorStackAppend(operatorStackDepth, operatorToken, precedence);
1980     }
1981     while (operatorStackDepth) {
1982         ASSERT(operandStackDepth > 1);
1983
1984         typename TreeBuilder::BinaryOperand rhs = context.getFromOperandStack(-1);
1985         typename TreeBuilder::BinaryOperand lhs = context.getFromOperandStack(-2);
1986         context.shrinkOperandStackBy(operandStackDepth, 2);
1987         context.appendBinaryOperation(operandStackDepth, operatorStackDepth, lhs, rhs);
1988         context.operatorStackPop(operatorStackDepth);
1989     }
1990     return context.popOperandStack(operandStackDepth);
1991 }
1992
1993
1994 template <bool complete, class TreeBuilder> TreeProperty JSParser::parseProperty(TreeBuilder& context)
1995 {
1996     bool wasIdent = false;
1997     switch (m_token.m_type) {
1998     namedProperty:
1999     case IDENT:
2000         wasIdent = true;
2001     case STRING: {
2002         const Identifier* ident = m_token.m_data.ident;
2003         if (complete || (wasIdent && (*ident == m_globalData->propertyNames->get || *ident == m_globalData->propertyNames->set)))
2004             nextExpectIdentifier(Lexer::IgnoreReservedWords);
2005         else
2006             nextExpectIdentifier(Lexer::IgnoreReservedWords | TreeBuilder::DontBuildKeywords);
2007
2008         if (match(COLON)) {
2009             next();
2010             TreeExpression node = parseAssignmentExpression(context);
2011             failIfFalse(node);
2012             return context.template createProperty<complete>(ident, node, PropertyNode::Constant);
2013         }
2014         failIfFalse(wasIdent);
2015         matchOrFail(IDENT);
2016         const Identifier* accessorName = 0;
2017         TreeFormalParameterList parameters = 0;
2018         TreeFunctionBody body = 0;
2019         int openBracePos = 0;
2020         int closeBracePos = 0;
2021         int bodyStartLine = 0;
2022         PropertyNode::Type type;
2023         if (*ident == m_globalData->propertyNames->get)
2024             type = PropertyNode::Getter;
2025         else if (*ident == m_globalData->propertyNames->set)
2026             type = PropertyNode::Setter;
2027         else
2028             fail();
2029         failIfFalse((parseFunctionInfo<FunctionNeedsName, false>(context, accessorName, parameters, body, openBracePos, closeBracePos, bodyStartLine)));
2030         return context.template createGetterOrSetterProperty<complete>(type, accessorName, parameters, body, openBracePos, closeBracePos, bodyStartLine, m_lastLine);
2031     }
2032     case NUMBER: {
2033         double propertyName = m_token.m_data.doubleValue;
2034         next();
2035         consumeOrFail(COLON);
2036         TreeExpression node = parseAssignmentExpression(context);
2037         failIfFalse(node);
2038         return context.template createProperty<complete>(m_globalData, propertyName, node, PropertyNode::Constant);
2039     }
2040     default:
2041         failIfFalse(m_token.m_type & KeywordTokenFlag);
2042         goto namedProperty;
2043     }
2044 }
2045
2046 template <class TreeBuilder> TreeExpression JSParser::parseObjectLiteral(TreeBuilder& context)
2047 {
2048     int startOffset = m_token.m_data.intValue;
2049     consumeOrFailWithFlags(OPENBRACE, TreeBuilder::DontBuildStrings);
2050
2051     if (match(CLOSEBRACE)) {
2052         next();
2053         return context.createObjectLiteral();
2054     }
2055
2056     TreeProperty property = parseProperty<false>(context);
2057     failIfFalse(property);
2058     if (!m_syntaxAlreadyValidated && context.getType(property) != PropertyNode::Constant) {
2059         m_lexer->setOffset(startOffset);
2060         next();
2061         return parseStrictObjectLiteral(context);
2062     }
2063     TreePropertyList propertyList = context.createPropertyList(property);
2064     TreePropertyList tail = propertyList;
2065     while (match(COMMA)) {
2066         next(TreeBuilder::DontBuildStrings);
2067         // allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939
2068         if (match(CLOSEBRACE))
2069             break;
2070         property = parseProperty<false>(context);
2071         failIfFalse(property);
2072         if (!m_syntaxAlreadyValidated && context.getType(property) != PropertyNode::Constant) {
2073             m_lexer->setOffset(startOffset);
2074             next();
2075             return parseStrictObjectLiteral(context);
2076         }
2077         tail = context.createPropertyList(property, tail);
2078     }
2079
2080     consumeOrFail(CLOSEBRACE);
2081
2082     return context.createObjectLiteral(propertyList);
2083 }
2084
2085 template <class TreeBuilder> TreeExpression JSParser::parseStrictObjectLiteral(TreeBuilder& context)
2086 {
2087     consumeOrFail(OPENBRACE);
2088     
2089     if (match(CLOSEBRACE)) {
2090         next();
2091         return context.createObjectLiteral();
2092     }
2093     
2094     TreeProperty property = parseProperty<true>(context);
2095     failIfFalse(property);
2096     
2097     typedef HashMap<RefPtr<StringImpl>, unsigned, IdentifierRepHash> ObjectValidationMap;
2098     ObjectValidationMap objectValidator;
2099     // Add the first property
2100     if (!m_syntaxAlreadyValidated)
2101         objectValidator.add(context.getName(property).impl(), context.getType(property));
2102     
2103     TreePropertyList propertyList = context.createPropertyList(property);
2104     TreePropertyList tail = propertyList;
2105     while (match(COMMA)) {
2106         next();
2107         // allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939
2108         if (match(CLOSEBRACE))
2109             break;
2110         property = parseProperty<true>(context);
2111         failIfFalse(property);
2112         if (!m_syntaxAlreadyValidated) {
2113             std::pair<ObjectValidationMap::iterator, bool> propertyEntryIter = objectValidator.add(context.getName(property).impl(), context.getType(property));
2114             if (!propertyEntryIter.second) {
2115                 failIfTrue(propertyEntryIter.first->second == PropertyNode::Constant);
2116                 failIfTrue(context.getType(property) == PropertyNode::Constant);
2117                 failIfTrue(context.getType(property) & propertyEntryIter.first->second);
2118                 propertyEntryIter.first->second |= context.getType(property);
2119             }
2120         }
2121         tail = context.createPropertyList(property, tail);
2122     }
2123     
2124     consumeOrFail(CLOSEBRACE);
2125     
2126     return context.createObjectLiteral(propertyList);
2127 }
2128
2129 template <class TreeBuilder> TreeExpression JSParser::parseArrayLiteral(TreeBuilder& context)
2130 {
2131     consumeOrFailWithFlags(OPENBRACKET, TreeBuilder::DontBuildStrings);
2132
2133     int elisions = 0;
2134     while (match(COMMA)) {
2135         next(TreeBuilder::DontBuildStrings);
2136         elisions++;
2137     }
2138     if (match(CLOSEBRACKET)) {
2139         next(TreeBuilder::DontBuildStrings);
2140         return context.createArray(elisions);
2141     }
2142
2143     TreeExpression elem = parseAssignmentExpression(context);
2144     failIfFalse(elem);
2145     typename TreeBuilder::ElementList elementList = context.createElementList(elisions, elem);
2146     typename TreeBuilder::ElementList tail = elementList;
2147     elisions = 0;
2148     while (match(COMMA)) {
2149         next(TreeBuilder::DontBuildStrings);
2150         elisions = 0;
2151
2152         while (match(COMMA)) {
2153             next();
2154             elisions++;
2155         }
2156
2157         if (match(CLOSEBRACKET)) {
2158             next(TreeBuilder::DontBuildStrings);
2159             return context.createArray(elisions, elementList);
2160         }
2161         TreeExpression elem = parseAssignmentExpression(context);
2162         failIfFalse(elem);
2163         tail = context.createElementList(tail, elisions, elem);
2164     }
2165
2166     consumeOrFail(CLOSEBRACKET);
2167
2168     return context.createArray(elementList);
2169 }
2170
2171 template <class TreeBuilder> TreeExpression JSParser::parsePrimaryExpression(TreeBuilder& context)
2172 {
2173     switch (m_token.m_type) {
2174     case OPENBRACE:
2175         if (strictMode())
2176             return parseStrictObjectLiteral(context);
2177         return parseObjectLiteral(context);
2178     case OPENBRACKET:
2179         return parseArrayLiteral(context);
2180     case OPENPAREN: {
2181         next();
2182         int oldNonLHSCount = m_nonLHSCount;
2183         TreeExpression result = parseExpression(context);
2184         m_nonLHSCount = oldNonLHSCount;
2185         consumeOrFail(CLOSEPAREN);
2186
2187         return result;
2188     }
2189     case THISTOKEN: {
2190         next();
2191         return context.thisExpr();
2192     }
2193     case IDENT: {
2194         int start = tokenStart();
2195         const Identifier* ident = m_token.m_data.ident;
2196         next();
2197         currentScope()->useVariable(ident, m_globalData->propertyNames->eval == *ident);
2198         m_lastIdentifier = ident;
2199         return context.createResolve(ident, start);
2200     }
2201     case STRING: {
2202         const Identifier* ident = m_token.m_data.ident;
2203         next();
2204         return context.createString(ident);
2205     }
2206     case NUMBER: {
2207         double d = m_token.m_data.doubleValue;
2208         next();
2209         return context.createNumberExpr(d);
2210     }
2211     case NULLTOKEN: {
2212         next();
2213         return context.createNull();
2214     }
2215     case TRUETOKEN: {
2216         next();
2217         return context.createBoolean(true);
2218     }
2219     case FALSETOKEN: {
2220         next();
2221         return context.createBoolean(false);
2222     }
2223     case DIVEQUAL:
2224     case DIVIDE: {
2225         /* regexp */
2226         const Identifier* pattern;
2227         const Identifier* flags;
2228         if (match(DIVEQUAL))
2229             failIfFalse(m_lexer->scanRegExp(pattern, flags, '='));
2230         else
2231             failIfFalse(m_lexer->scanRegExp(pattern, flags));
2232
2233         int start = tokenStart();
2234         next();
2235         TreeExpression re = context.createRegExp(*pattern, *flags, start);
2236         if (!re) {
2237             const char* yarrErrorMsg = Yarr::checkSyntax(pattern->ustring());
2238             ASSERT(!m_errorMessage.isNull());
2239             failWithMessage(yarrErrorMsg);
2240         }
2241         return re;
2242     }
2243     default:
2244         fail();
2245     }
2246 }
2247
2248 template <class TreeBuilder> TreeArguments JSParser::parseArguments(TreeBuilder& context)
2249 {
2250     consumeOrFailWithFlags(OPENPAREN, TreeBuilder::DontBuildStrings);
2251     if (match(CLOSEPAREN)) {
2252         next(TreeBuilder::DontBuildStrings);
2253         return context.createArguments();
2254     }
2255     TreeExpression firstArg = parseAssignmentExpression(context);
2256     failIfFalse(firstArg);
2257
2258     TreeArgumentsList argList = context.createArgumentsList(firstArg);
2259     TreeArgumentsList tail = argList;
2260     while (match(COMMA)) {
2261         next(TreeBuilder::DontBuildStrings);
2262         TreeExpression arg = parseAssignmentExpression(context);
2263         failIfFalse(arg);
2264         tail = context.createArgumentsList(tail, arg);
2265     }
2266     consumeOrFail(CLOSEPAREN);
2267     return context.createArguments(argList);
2268 }
2269
2270 template <class TreeBuilder> TreeExpression JSParser::parseMemberExpression(TreeBuilder& context)
2271 {
2272     TreeExpression base = 0;
2273     int start = tokenStart();
2274     int expressionStart = start;
2275     int newCount = 0;
2276     while (match(NEW)) {
2277         next();
2278         newCount++;
2279     }
2280
2281     if (match(FUNCTION)) {
2282         const Identifier* name = &m_globalData->propertyNames->nullIdentifier;
2283         TreeFormalParameterList parameters = 0;
2284         TreeFunctionBody body = 0;
2285         int openBracePos = 0;
2286         int closeBracePos = 0;
2287         int bodyStartLine = 0;
2288         next();
2289         failIfFalse((parseFunctionInfo<FunctionNoRequirements, false>(context, name, parameters, body, openBracePos, closeBracePos, bodyStartLine)));
2290         base = context.createFunctionExpr(name, body, parameters, openBracePos, closeBracePos, bodyStartLine, m_lastLine);
2291     } else
2292         base = parsePrimaryExpression(context);
2293
2294     failIfFalse(base);
2295     while (true) {
2296         switch (m_token.m_type) {
2297         case OPENBRACKET: {
2298             m_nonTrivialExpressionCount++;
2299             int expressionEnd = lastTokenEnd();
2300             next();
2301             int nonLHSCount = m_nonLHSCount;
2302             int initialAssignments = m_assignmentCount;
2303             TreeExpression property = parseExpression(context);
2304             failIfFalse(property);
2305             base = context.createBracketAccess(base, property, initialAssignments != m_assignmentCount, expressionStart, expressionEnd, tokenEnd());
2306             consumeOrFail(CLOSEBRACKET);
2307             m_nonLHSCount = nonLHSCount;
2308             break;
2309         }
2310         case OPENPAREN: {
2311             m_nonTrivialExpressionCount++;
2312             if (newCount) {
2313                 newCount--;
2314                 if (match(OPENPAREN)) {
2315                     int exprEnd = lastTokenEnd();
2316                     TreeArguments arguments = parseArguments(context);
2317                     failIfFalse(arguments);
2318                     base = context.createNewExpr(base, arguments, start, exprEnd, lastTokenEnd());
2319                 } else
2320                     base = context.createNewExpr(base, start, lastTokenEnd());               
2321             } else {
2322                 int nonLHSCount = m_nonLHSCount;
2323                 int expressionEnd = lastTokenEnd();
2324                 TreeArguments arguments = parseArguments(context);
2325                 failIfFalse(arguments);
2326                 base = context.makeFunctionCallNode(base, arguments, expressionStart, expressionEnd, lastTokenEnd());
2327                 m_nonLHSCount = nonLHSCount;
2328             }
2329             break;
2330         }
2331         case DOT: {
2332             m_nonTrivialExpressionCount++;
2333             int expressionEnd = lastTokenEnd();
2334             nextExpectIdentifier(Lexer::IgnoreReservedWords | TreeBuilder::DontBuildKeywords);
2335             matchOrFail(IDENT);
2336             base = context.createDotAccess(base, m_token.m_data.ident, expressionStart, expressionEnd, tokenEnd());
2337             next();
2338             break;
2339         }
2340         default:
2341             goto endMemberExpression;
2342         }
2343     }
2344 endMemberExpression:
2345     while (newCount--)
2346         base = context.createNewExpr(base, start, lastTokenEnd());
2347     return base;
2348 }
2349
2350 template <class TreeBuilder> TreeExpression JSParser::parseUnaryExpression(TreeBuilder& context)
2351 {
2352     typename TreeBuilder::UnaryExprContext unaryExprContext(context);
2353     AllowInOverride allowInOverride(this);
2354     int tokenStackDepth = 0;
2355     bool modifiesExpr = false;
2356     bool requiresLExpr = false;
2357     while (isUnaryOp(m_token.m_type)) {
2358         if (strictMode()) {
2359             switch (m_token.m_type) {
2360             case PLUSPLUS:
2361             case MINUSMINUS:
2362             case AUTOPLUSPLUS:
2363             case AUTOMINUSMINUS:
2364                 failIfTrue(requiresLExpr);
2365                 modifiesExpr = true;
2366                 requiresLExpr = true;
2367                 break;
2368             case DELETETOKEN:
2369                 failIfTrue(requiresLExpr);
2370                 requiresLExpr = true;
2371                 break;
2372             default:
2373                 failIfTrue(requiresLExpr);
2374                 break;
2375             }
2376         }
2377         m_nonLHSCount++;
2378         context.appendUnaryToken(tokenStackDepth, m_token.m_type, tokenStart());
2379         next();
2380         m_nonTrivialExpressionCount++;
2381     }
2382     int subExprStart = tokenStart();
2383     TreeExpression expr = parseMemberExpression(context);
2384     failIfFalse(expr);
2385     bool isEvalOrArguments = false;
2386     if (strictMode() && !m_syntaxAlreadyValidated) {
2387         if (context.isResolve(expr)) {
2388             isEvalOrArguments = *m_lastIdentifier == m_globalData->propertyNames->eval || *m_lastIdentifier == m_globalData->propertyNames->arguments;
2389         }
2390     }
2391     failIfTrueIfStrictWithNameAndMessage(isEvalOrArguments && modifiesExpr, "'", m_lastIdentifier->impl(), "' cannot be modified in strict mode");
2392     switch (m_token.m_type) {
2393     case PLUSPLUS:
2394         m_nonTrivialExpressionCount++;
2395         m_nonLHSCount++;
2396         expr = context.makePostfixNode(expr, OpPlusPlus, subExprStart, lastTokenEnd(), tokenEnd());
2397         m_assignmentCount++;
2398         failIfTrueIfStrictWithNameAndMessage(isEvalOrArguments, "'", m_lastIdentifier->impl(), "' cannot be modified in strict mode");
2399         failIfTrueIfStrict(requiresLExpr);
2400         next();
2401         break;
2402     case MINUSMINUS:
2403         m_nonTrivialExpressionCount++;
2404         m_nonLHSCount++;
2405         expr = context.makePostfixNode(expr, OpMinusMinus, subExprStart, lastTokenEnd(), tokenEnd());
2406         m_assignmentCount++;
2407         failIfTrueIfStrictWithNameAndMessage(isEvalOrArguments, "'", m_lastIdentifier->impl(), "' cannot be modified in strict mode");
2408         failIfTrueIfStrict(requiresLExpr);
2409         next();
2410         break;
2411     default:
2412         break;
2413     }
2414
2415     int end = lastTokenEnd();
2416
2417     if (!TreeBuilder::CreatesAST && (m_syntaxAlreadyValidated || !strictMode()))
2418         return expr;
2419
2420     while (tokenStackDepth) {
2421         switch (context.unaryTokenStackLastType(tokenStackDepth)) {
2422         case EXCLAMATION:
2423             expr = context.createLogicalNot(expr);
2424             break;
2425         case TILDE:
2426             expr = context.makeBitwiseNotNode(expr);
2427             break;
2428         case MINUS:
2429             expr = context.makeNegateNode(expr);
2430             break;
2431         case PLUS:
2432             expr = context.createUnaryPlus(expr);
2433             break;
2434         case PLUSPLUS:
2435         case AUTOPLUSPLUS:
2436             expr = context.makePrefixNode(expr, OpPlusPlus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end);
2437             m_assignmentCount++;
2438             break;
2439         case MINUSMINUS:
2440         case AUTOMINUSMINUS:
2441             expr = context.makePrefixNode(expr, OpMinusMinus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end);
2442             m_assignmentCount++;
2443             break;
2444         case TYPEOF:
2445             expr = context.makeTypeOfNode(expr);
2446             break;
2447         case VOIDTOKEN:
2448             expr = context.createVoid(expr);
2449             break;
2450         case DELETETOKEN:
2451             failIfTrueIfStrictWithNameAndMessage(context.isResolve(expr), "Cannot delete unqualified property", m_lastIdentifier->impl(), "in strict mode");
2452             expr = context.makeDeleteNode(expr, context.unaryTokenStackLastStart(tokenStackDepth), end, end);
2453             break;
2454         default:
2455             // If we get here something has gone horribly horribly wrong
2456             CRASH();
2457         }
2458         subExprStart = context.unaryTokenStackLastStart(tokenStackDepth);
2459         context.unaryTokenStackRemoveLast(tokenStackDepth);
2460     }
2461     return expr;
2462 }
2463
2464 }
2465
2466 namespace WTF
2467 {
2468     template <> struct VectorTraits<JSC::JSParser::Scope> : SimpleClassVectorTraits {
2469         static const bool canInitializeWithMemset = false; // Not all Scope data members initialize to 0.
2470     };
2471 }