~ubuntu-branches/ubuntu/raring/qtwebkit-source/raring-proposed

« back to all changes in this revision

Viewing changes to Source/JavaScriptCore/parser/Parser.cpp

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2013-02-18 14:24:18 UTC
  • Revision ID: package-import@ubuntu.com-20130218142418-eon0jmjg3nj438uy
Tags: upstream-2.3
ImportĀ upstreamĀ versionĀ 2.3

Show diffs side-by-side

added added

removed removed

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