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