d9cacc722c6034f6654704c4fb6777ff592673af
[WebKit-https.git] / JavaScriptCore / parser / JSParser.cpp
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27
28 #include "JSParser.h"
29
30 using namespace JSC;
31
32 #include "JSGlobalData.h"
33 #include "NodeInfo.h"
34 #include "ASTBuilder.h"
35 #include <utility>
36
37 using namespace std;
38
39 namespace JSC {
40 #define fail() do { m_error = true; return 0; } while (0)
41 #define failIfFalse(cond) do { if (!(cond)) fail(); } while (0)
42 #define failIfTrue(cond) do { if ((cond)) fail(); } while (0)
43 #define consumeOrFail(tokenType) do { if (!consume(tokenType)) fail(); } while (0)
44 #define matchOrFail(tokenType) do { if (!match(tokenType)) fail(); } while (0)
45 #define failIfStackOverflow() do { failIfFalse(canRecurse()); } while (0)
46
47 // Macros to make the more common TreeBuilder types a little less verbose
48 #define TreeStatement typename TreeBuilder::Statement
49 #define TreeExpression typename TreeBuilder::Expression
50 #define TreeFormalParameterList typename TreeBuilder::FormalParameterList
51 #define TreeSourceElements typename TreeBuilder::SourceElements
52 #define TreeClause typename TreeBuilder::Clause
53 #define TreeClauseList typename TreeBuilder::ClauseList
54 #define TreeConstDeclList typename TreeBuilder::ConstDeclList
55 #define TreeArguments typename TreeBuilder::Arguments
56 #define TreeArgumentsList typename TreeBuilder::ArgumentsList
57 #define TreeFunctionBody typename TreeBuilder::FunctionBody
58 #define TreeProperty typename TreeBuilder::Property
59 #define TreePropertyList typename TreeBuilder::PropertyList
60
61 // This matches v8
62 static const ptrdiff_t kMaxParserStackUsage = 128 * sizeof(void*) * 1024;
63
64 class JSParser {
65 public:
66     JSParser(Lexer*, JSGlobalData*);
67     bool parseProgram();
68 private:
69     struct AllowInOverride {
70         AllowInOverride(JSParser* parser)
71             : m_parser(parser)
72             , m_oldAllowsIn(parser->m_allowsIn)
73         {
74             parser->m_allowsIn = true;
75         }
76         ~AllowInOverride()
77         {
78             m_parser->m_allowsIn = m_oldAllowsIn;
79         }
80         JSParser* m_parser;
81         bool m_oldAllowsIn;
82     };
83
84     const JSToken& token() { return m_token; }
85     void next()
86     {
87         m_lastLine = token().m_info.last_line;
88         m_lastTokenEnd = token().m_info.last_column;
89         m_lexer->setLastLineNumber(m_lastLine);
90         m_token.m_type = m_lexer->lex(&m_token.m_data, &m_token.m_info);
91         m_tokenCount++;
92     }
93
94     bool consume(int expected)
95     {
96         bool result = m_token.m_type == expected;
97         failIfFalse(result);
98         next();
99         return result;
100     }
101
102     bool match(int expected)
103     {
104         return m_token.m_type == expected;
105     }
106
107     int tokenStart()
108     {
109         return token().m_info.first_column;
110     }
111
112     int tokenLine()
113     {
114         return token().m_info.first_line;
115     }
116
117     int tokenEnd()
118     {
119         return token().m_info.last_column;
120     }
121
122     template <class TreeBuilder> TreeSourceElements parseSourceElements(TreeBuilder&);
123     template <class TreeBuilder> TreeStatement parseStatement(TreeBuilder&);
124     template <class TreeBuilder> TreeStatement parseFunctionDeclaration(TreeBuilder&);
125     template <class TreeBuilder> TreeStatement parseVarDeclaration(TreeBuilder&);
126     template <class TreeBuilder> TreeStatement parseConstDeclaration(TreeBuilder&);
127     template <class TreeBuilder> TreeStatement parseDoWhileStatement(TreeBuilder&);
128     template <class TreeBuilder> TreeStatement parseWhileStatement(TreeBuilder&);
129     template <class TreeBuilder> TreeStatement parseForStatement(TreeBuilder&);
130     template <class TreeBuilder> TreeStatement parseBreakStatement(TreeBuilder&);
131     template <class TreeBuilder> TreeStatement parseContinueStatement(TreeBuilder&);
132     template <class TreeBuilder> TreeStatement parseReturnStatement(TreeBuilder&);
133     template <class TreeBuilder> TreeStatement parseThrowStatement(TreeBuilder&);
134     template <class TreeBuilder> TreeStatement parseWithStatement(TreeBuilder&);
135     template <class TreeBuilder> TreeStatement parseSwitchStatement(TreeBuilder&);
136     template <class TreeBuilder> TreeClauseList parseSwitchClauses(TreeBuilder&);
137     template <class TreeBuilder> TreeClause parseSwitchDefaultClause(TreeBuilder&);
138     template <class TreeBuilder> TreeStatement parseTryStatement(TreeBuilder&);
139     template <class TreeBuilder> TreeStatement parseDebuggerStatement(TreeBuilder&);
140     template <class TreeBuilder> TreeStatement parseExpressionStatement(TreeBuilder&);
141     template <class TreeBuilder> TreeStatement parseExpressionOrLabelStatement(TreeBuilder&);
142     template <class TreeBuilder> TreeStatement parseIfStatement(TreeBuilder&);
143     template <class TreeBuilder> ALWAYS_INLINE TreeStatement parseBlockStatement(TreeBuilder&);
144     template <class TreeBuilder> TreeExpression parseExpression(TreeBuilder&);
145     template <class TreeBuilder> TreeExpression parseAssignmentExpression(TreeBuilder&);
146     template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseConditionalExpression(TreeBuilder&);
147     template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseBinaryExpression(TreeBuilder&);
148     template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseUnaryExpression(TreeBuilder&);
149     template <class TreeBuilder> TreeExpression parseMemberExpression(TreeBuilder&);
150     template <class TreeBuilder> ALWAYS_INLINE TreeExpression parsePrimaryExpression(TreeBuilder&);
151     template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseArrayLiteral(TreeBuilder&);
152     template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseObjectLiteral(TreeBuilder&);
153     template <class TreeBuilder> ALWAYS_INLINE TreeArguments parseArguments(TreeBuilder&);
154     template <class TreeBuilder> ALWAYS_INLINE TreeProperty parseProperty(TreeBuilder&);
155     template <class TreeBuilder> ALWAYS_INLINE TreeFunctionBody parseFunctionBody(TreeBuilder&);
156     template <class TreeBuilder> ALWAYS_INLINE TreeFormalParameterList parseFormalParameters(TreeBuilder&, bool& usesArguments);
157     template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseVarDeclarationList(TreeBuilder&, int& declarations, const Identifier*& lastIdent, TreeExpression& lastInitializer, int& identStart, int& initStart, int& initEnd);
158     template <class TreeBuilder> ALWAYS_INLINE TreeConstDeclList parseConstDeclarationList(TreeBuilder& context);
159     enum FunctionRequirements { FunctionNoRequirements, FunctionNeedsName };
160     template <FunctionRequirements, class TreeBuilder> bool parseFunctionInfo(TreeBuilder&, const Identifier*&, TreeFormalParameterList&, TreeFunctionBody&, int& openBrace, int& closeBrace, int& bodyStartLine);
161     int isBinaryOperator(int token);
162     bool allowAutomaticSemicolon();
163
164     bool autoSemiColon()
165     {
166         if (token().m_type == ';') {
167             next();
168             return true;
169         }
170         return allowAutomaticSemicolon();
171     }
172
173     bool canRecurse()
174     {
175         char sample = 0;
176         ASSERT(m_endAddress);
177         return &sample > m_endAddress;
178     }
179     
180     int lastTokenEnd() const
181     {
182         return m_lastTokenEnd;
183     }
184
185     ParserArena m_arena;
186     Lexer* m_lexer;
187     char* m_endAddress;
188     bool m_error;
189     JSGlobalData* m_globalData;
190     JSToken m_token;
191     bool m_allowsIn;
192     int m_tokenCount;
193     int m_lastLine;
194     int m_lastTokenEnd;
195     int m_assignmentCount;
196     int m_nonLHSCount;
197 };
198
199 int jsParse(JSGlobalData* globalData)
200 {
201     JSParser parser(globalData->lexer, globalData);
202     return parser.parseProgram();
203 }
204
205 JSParser::JSParser(Lexer* lexer, JSGlobalData* globalData)
206     : m_lexer(lexer)
207     , m_endAddress(0)
208     , m_error(false)
209     , m_globalData(globalData)
210     , m_allowsIn(true)
211     , m_tokenCount(0)
212     , m_lastLine(0)
213     , m_lastTokenEnd(0)
214     , m_assignmentCount(0)
215     , m_nonLHSCount(0)
216 {
217     m_endAddress = *(globalData->stackGuards);
218     if (!m_endAddress) {
219         char sample = 0;
220         m_endAddress = &sample - kMaxParserStackUsage;
221         *(globalData->stackGuards) = m_endAddress;
222     }
223     next();
224     m_lexer->setLastLineNumber(tokenLine());
225 }
226
227 bool JSParser::parseProgram()
228 {
229     ASTBuilder context(m_globalData, m_lexer);
230     SourceElements* sourceElements = parseSourceElements<ASTBuilder>(context);
231     if (!sourceElements || !consume(0))
232         return true;
233     m_globalData->parser->didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), context.features(),
234                                           m_lastLine, context.numConstants());
235     return false;
236 }
237
238 bool JSParser::allowAutomaticSemicolon()
239 {
240     return match(CLOSEBRACE) || match(0) || m_lexer->prevTerminator();
241 }
242
243 template <class TreeBuilder> TreeSourceElements JSParser::parseSourceElements(TreeBuilder& context)
244 {
245     TreeSourceElements sourceElements = context.createSourceElements();
246     while (TreeStatement statement = parseStatement(context))
247         context.appendStatement(sourceElements, statement);
248
249     if (m_error)
250         fail();
251     return sourceElements;
252 }
253
254 template <class TreeBuilder> TreeStatement JSParser::parseVarDeclaration(TreeBuilder& context)
255 {
256     ASSERT(match(VAR));
257     int start = tokenLine();
258     int end = 0;
259     int scratch;
260     const Identifier* scratch1 = 0;
261     TreeExpression scratch2 = 0;
262     int scratch3 = 0;
263     TreeExpression varDecls = parseVarDeclarationList(context, scratch, scratch1, scratch2, scratch3, scratch3, scratch3);
264     failIfTrue(m_error);
265     failIfFalse(autoSemiColon());
266
267     return context.createVarStatement(varDecls, start, end);
268 }
269
270 template <class TreeBuilder> TreeStatement JSParser::parseConstDeclaration(TreeBuilder& context)
271 {
272     ASSERT(match(CONSTTOKEN));
273     int start = tokenLine();
274     int end = 0;
275     TreeConstDeclList constDecls = parseConstDeclarationList(context);
276     failIfTrue(m_error);
277     failIfFalse(autoSemiColon());
278     
279     return context.createConstStatement(constDecls, start, end);
280 }
281
282 template <class TreeBuilder> TreeStatement JSParser::parseDoWhileStatement(TreeBuilder& context)
283 {
284     ASSERT(match(DO));
285     int startLine = tokenLine();
286     next();
287     TreeStatement statement = parseStatement(context);
288     failIfFalse(statement);
289     int endLine = tokenLine();
290     consumeOrFail(WHILE);
291     consumeOrFail('(');
292     TreeExpression expr = parseExpression(context);
293     failIfFalse(expr);
294     consumeOrFail(')');
295     if (match(';'))
296         next(); // Always performs automatic semicolon insertion.
297     return context.createDoWhileStatement(statement, expr, startLine, endLine);
298 }
299
300 template <class TreeBuilder> TreeStatement JSParser::parseWhileStatement(TreeBuilder& context)
301 {
302     ASSERT(match(WHILE));
303     int startLine = tokenLine();
304     next();
305     consumeOrFail('(');
306     TreeExpression expr = parseExpression(context);
307     failIfFalse(expr);
308     int endLine = tokenLine();
309     consumeOrFail(')');
310     TreeStatement statement = parseStatement(context);
311     failIfFalse(statement);
312     return context.createWhileStatement(expr, statement, startLine, endLine);
313 }
314
315 template <class TreeBuilder> TreeExpression JSParser::parseVarDeclarationList(TreeBuilder& context, int& declarations, const Identifier*& lastIdent, TreeExpression& lastInitializer, int& identStart, int& initStart, int& initEnd)
316 {
317     TreeExpression varDecls = 0;
318     do {
319         declarations++;
320         next();
321         matchOrFail(IDENT);
322
323         int varStart = tokenStart();
324         identStart = varStart;
325         const Identifier* name = token().m_data.ident;
326         lastIdent = name;
327         next();
328         bool hasInitializer = match('=');
329         context.addVar(name, (hasInitializer || (!m_allowsIn && match(INTOKEN))) ? DeclarationStacks::HasInitializer : 0);
330         if (hasInitializer) {
331             int varDivot = tokenStart() + 1;
332             initStart = tokenStart();
333             next(); // consume '='
334             int initialAssignments = m_assignmentCount;
335             TreeExpression initializer = parseAssignmentExpression(context);
336             initEnd = lastTokenEnd();
337             lastInitializer = initializer;
338             failIfFalse(initializer);
339
340             TreeExpression node = context.createAssignResolve(*name, initializer, initialAssignments != m_assignmentCount, varStart, varDivot, lastTokenEnd());
341             if (!varDecls)
342                 varDecls = node;
343             else
344                 varDecls = context.combineCommaNodes(varDecls, node);
345         }
346     } while (match(','));
347     return varDecls;
348 }
349
350 template <class TreeBuilder> TreeConstDeclList JSParser::parseConstDeclarationList(TreeBuilder& context)
351 {
352     TreeConstDeclList constDecls = 0;
353     TreeConstDeclList tail = 0;
354     do {
355         next();
356         matchOrFail(IDENT);
357         const Identifier* name = token().m_data.ident;
358         next();
359         bool hasInitializer = match('=');
360         context.addVar(name, DeclarationStacks::IsConstant | (hasInitializer ? DeclarationStacks::HasInitializer : 0));
361         TreeExpression initializer = 0;
362         if (hasInitializer) {
363             next(); // consume '='
364             initializer = parseAssignmentExpression(context);
365         }
366         tail = context.appendConstDecl(tail, name, initializer);
367         if (!constDecls)
368             constDecls = tail;
369     } while (match(','));
370     return constDecls;
371 }
372
373 template <class TreeBuilder> TreeStatement JSParser::parseForStatement(TreeBuilder& context)
374 {
375     ASSERT(match(FOR));
376     int startLine = tokenLine();
377     next();
378     consumeOrFail('(');
379     int nonLHSCount = m_nonLHSCount;
380     int declarations = 0;
381     int declsStart = 0;
382     int declsEnd = 0;
383     TreeExpression decls = 0;
384     bool hasDeclaration = false;
385     if (match(VAR)) {
386         /*
387          for (var IDENT in expression) statement
388          for (var IDENT = expression in expression) statement
389          for (var varDeclarationList; expressionOpt; expressionOpt)
390          */
391         hasDeclaration = true;
392         const Identifier* forInTarget = 0;
393         TreeExpression forInInitializer = 0;
394         m_allowsIn = false;
395         int initStart = 0;
396         int initEnd = 0;
397         decls = parseVarDeclarationList(context, declarations, forInTarget, forInInitializer, declsStart, initStart, initEnd);
398         m_allowsIn = true;
399         if (m_error)
400             fail();
401
402         // Remainder of a standard for loop is handled identically
403         if (declarations > 1 || match(';'))
404             goto standardForLoop;
405
406         // Handle for-in with var declaration
407         int inLocation = tokenStart();
408         if (!consume(INTOKEN))
409             fail();
410
411         TreeExpression expr = parseExpression(context);
412         failIfFalse(expr);
413         int exprEnd = lastTokenEnd();
414
415         int endLine = tokenLine();
416         consumeOrFail(')');
417
418         TreeStatement statement = parseStatement(context);
419         failIfFalse(statement);
420
421         return context.createForInLoop(forInTarget, forInInitializer, expr, statement, declsStart, inLocation, exprEnd, initStart, initEnd, startLine, endLine);
422     }
423
424     if (!match(';')) {
425         m_allowsIn = false;
426         declsStart = tokenStart();
427         decls = parseExpression(context);
428         declsEnd = lastTokenEnd();
429         m_allowsIn = true;
430         failIfFalse(decls);
431     }
432
433     if (match(';')) {
434     standardForLoop:
435         // Standard for loop
436         next();
437         TreeExpression condition = 0;
438
439         if (!match(';')) {
440             condition = parseExpression(context);
441             failIfFalse(condition);
442         }
443         consumeOrFail(';');
444
445         TreeExpression increment = 0;
446         if (!match(')')) {
447             increment = parseExpression(context);
448             failIfFalse(increment);
449         }
450         int endLine = tokenLine();
451         consumeOrFail(')');
452         TreeStatement statement = parseStatement(context);
453         failIfFalse(statement);
454         return context.createForLoop(decls, condition, increment, statement, hasDeclaration, startLine, endLine);
455     }
456
457     // For-in loop
458     failIfFalse(nonLHSCount == m_nonLHSCount);
459     consumeOrFail(INTOKEN);
460     TreeExpression expr = parseExpression(context);
461     failIfFalse(expr);
462     int exprEnd = lastTokenEnd();
463     int endLine = tokenLine();
464     consumeOrFail(')');
465     TreeStatement statement = parseStatement(context);
466     failIfFalse(statement);
467     
468     return context.createForInLoop(decls, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine);
469 }
470
471 template <class TreeBuilder> TreeStatement JSParser::parseBreakStatement(TreeBuilder& context)
472 {
473     ASSERT(match(BREAK));
474     int startCol = tokenStart();
475     int endCol = tokenEnd();
476     int startLine = tokenLine();
477     int endLine = tokenLine();
478     next();
479
480     if (autoSemiColon())
481         return context.createBreakStatement(startCol, endCol, startLine, endLine);
482     matchOrFail(IDENT);
483     const Identifier* ident = token().m_data.ident;
484     endCol = tokenEnd();
485     endLine = tokenLine();
486     next();
487     failIfFalse(autoSemiColon());
488     return context.createBreakStatement(ident, startCol, endCol, startLine, endLine);
489 }
490
491 template <class TreeBuilder> TreeStatement JSParser::parseContinueStatement(TreeBuilder& context)
492 {
493     ASSERT(match(CONTINUE));
494     int startCol = tokenStart();
495     int endCol = tokenEnd();
496     int startLine = tokenLine();
497     int endLine = tokenLine();
498     next();
499
500     if (autoSemiColon())
501         return context.createContinueStatement(startCol, endCol, startLine, endLine);
502     matchOrFail(IDENT);
503     const Identifier* ident = token().m_data.ident;
504     endCol = tokenEnd();
505     endLine = tokenLine();
506     next();
507     failIfFalse(autoSemiColon());
508     return context.createContinueStatement(ident, startCol, endCol, startLine, endLine);
509 }
510
511 template <class TreeBuilder> TreeStatement JSParser::parseReturnStatement(TreeBuilder& context)
512 {
513     ASSERT(match(RETURN));
514     int startLine = tokenLine();
515     int endLine = startLine;
516     int start = tokenStart();
517     int end = tokenEnd();
518     next();
519     // We do the auto semicolon check before attempting to parse an expression
520     // as we need to ensure the a line break after the return correctly terminates
521     // the statement
522     if (match(';'))
523         endLine  = tokenLine();
524     if (autoSemiColon())
525         return context.createReturnStatement(0, start, end, startLine, endLine);
526     TreeExpression expr = parseExpression(context);
527     failIfFalse(expr);
528     end = lastTokenEnd();
529     if (match(';'))
530         endLine  = tokenLine();
531     failIfFalse(autoSemiColon());
532     return context.createReturnStatement(expr, start, end, startLine, endLine);
533 }
534
535 template <class TreeBuilder> TreeStatement JSParser::parseThrowStatement(TreeBuilder& context)
536 {
537     ASSERT(match(THROW));
538     int eStart = tokenStart();
539     int startLine = tokenLine();
540     next();
541
542     TreeExpression expr = parseExpression(context);
543     failIfFalse(expr);
544     int eEnd = lastTokenEnd();
545     int endLine = tokenLine();
546     failIfFalse(autoSemiColon());
547
548     return context.createThrowStatement(expr, eStart, eEnd, startLine, endLine);
549 }
550
551 template <class TreeBuilder> TreeStatement JSParser::parseWithStatement(TreeBuilder& context)
552 {
553     ASSERT(match(WITH));
554     int startLine = tokenLine();
555     next();
556     consumeOrFail('(');
557     int start = tokenStart();
558     TreeExpression expr = parseExpression(context);
559     failIfFalse(expr);
560     int end = lastTokenEnd();
561
562     int endLine = tokenLine();
563     consumeOrFail(')');
564     
565     TreeStatement statement = parseStatement(context);
566     failIfFalse(statement);
567
568     return context.createWithStatement(expr, statement, start, end, startLine, endLine);
569 }
570
571 template <class TreeBuilder> TreeStatement JSParser::parseSwitchStatement(TreeBuilder& context)
572 {
573     ASSERT(match(SWITCH));
574     int startLine = tokenLine();
575     next();
576     consumeOrFail('(');
577     TreeExpression expr = parseExpression(context);
578     failIfFalse(expr);
579     int endLine = tokenLine();
580     consumeOrFail(')');
581     consumeOrFail(OPENBRACE);
582
583     TreeClauseList firstClauses = parseSwitchClauses(context);
584     failIfTrue(m_error);
585
586     TreeClause defaultClause = parseSwitchDefaultClause(context);
587     failIfTrue(m_error);
588
589     TreeClauseList secondClauses = parseSwitchClauses(context);
590     failIfTrue(m_error);
591     consumeOrFail(CLOSEBRACE);
592
593     return context.createSwitchStatement(expr, firstClauses, defaultClause, secondClauses, startLine, endLine);
594
595 }
596
597 template <class TreeBuilder> TreeClauseList JSParser::parseSwitchClauses(TreeBuilder& context)
598 {
599     if (!match(CASE))
600         return 0;
601     next();
602     TreeExpression condition = parseExpression(context);
603     failIfFalse(condition);
604     consumeOrFail(':');
605     TreeSourceElements statements = parseSourceElements(context);
606     failIfFalse(statements);
607     TreeClause clause = context.createClause(condition, statements);
608     TreeClauseList clauseList = context.createClauseList(clause);
609     TreeClauseList tail = clauseList;
610
611     while (match(CASE)) {
612         next();
613         TreeExpression condition = parseExpression(context);
614         failIfFalse(condition);
615         consumeOrFail(':');
616         TreeSourceElements statements = parseSourceElements(context);
617         failIfFalse(statements);
618         clause = context.createClause(condition, statements);
619         tail = context.createClauseList(tail, clause);
620     }
621     return clauseList;
622 }
623
624 template <class TreeBuilder> TreeClause JSParser::parseSwitchDefaultClause(TreeBuilder& context)
625 {
626     if (!match(DEFAULT))
627         return 0;
628     next();
629     consumeOrFail(':');
630     TreeSourceElements statements = parseSourceElements(context);
631     failIfFalse(statements);
632     return context.createClause(0, statements);
633 }
634
635 template <class TreeBuilder> TreeStatement JSParser::parseTryStatement(TreeBuilder& context)
636 {
637     ASSERT(match(TRY));
638     TreeStatement tryBlock = 0;
639     const Identifier* ident = &m_globalData->propertyNames->nullIdentifier;
640     bool catchHasEval = false;
641     TreeStatement catchBlock = 0;
642     TreeStatement finallyBlock = 0;
643     int firstLine = tokenLine();
644     next();
645     matchOrFail(OPENBRACE);
646
647     tryBlock = parseBlockStatement(context);
648     failIfFalse(tryBlock);
649     int lastLine = m_lastLine;
650
651     if (match(CATCH)) {
652         next();
653         consumeOrFail('(');
654         matchOrFail(IDENT);
655         ident = token().m_data.ident;
656         next();
657         consumeOrFail(')');
658         matchOrFail(OPENBRACE);
659         int initialEvalCount = context.evalCount();
660         catchBlock = parseBlockStatement(context);
661         failIfFalse(catchBlock);
662         catchHasEval = initialEvalCount != context.evalCount();
663     }
664
665     if (match(FINALLY)) {
666         next();
667         matchOrFail(OPENBRACE);
668         finallyBlock = parseBlockStatement(context);
669         failIfFalse(finallyBlock);
670     }
671     failIfFalse(catchBlock || finallyBlock);
672     return context.createTryStatement(tryBlock, ident, catchHasEval, catchBlock, finallyBlock, firstLine, lastLine);
673 }
674
675 template <class TreeBuilder> TreeStatement JSParser::parseDebuggerStatement(TreeBuilder& context)
676 {
677     ASSERT(match(DEBUGGER));
678     int startLine = tokenLine();
679     int endLine = startLine;
680     next();
681     if (match(';'))
682         startLine = tokenLine();
683     failIfFalse(autoSemiColon());
684     return context.createDebugger(startLine, endLine);
685 }
686
687 template <class TreeBuilder> TreeStatement JSParser::parseBlockStatement(TreeBuilder& context)
688 {
689     ASSERT(match(OPENBRACE));
690     int start = tokenLine();
691     next();
692     if (match(CLOSEBRACE)) {
693         next();
694         return context.createBlockStatement(0, start, m_lastLine);
695     }
696     TreeSourceElements subtree = parseSourceElements(context);
697     failIfFalse(subtree);
698     matchOrFail(CLOSEBRACE);
699     next();
700     return context.createBlockStatement(subtree, start, m_lastLine);
701 }
702
703 template <class TreeBuilder> TreeStatement JSParser::parseStatement(TreeBuilder& context)
704 {
705     failIfStackOverflow();
706     switch (token().m_type) {
707     case OPENBRACE:
708         return parseBlockStatement(context);
709     case VAR:
710         return parseVarDeclaration(context);
711     case CONSTTOKEN:
712         return parseConstDeclaration(context);
713     case FUNCTION:
714         return parseFunctionDeclaration(context);
715     case ';':
716         next();
717         return context.createEmptyStatement();
718     case IF:
719         return parseIfStatement(context);
720     case DO:
721         return parseDoWhileStatement(context);
722     case WHILE:
723         return parseWhileStatement(context);
724     case FOR:
725         return parseForStatement(context);
726     case CONTINUE:
727         return parseContinueStatement(context);
728     case BREAK:
729         return parseBreakStatement(context);
730     case RETURN:
731         return parseReturnStatement(context);
732     case WITH:
733         return parseWithStatement(context);
734     case SWITCH:
735         return parseSwitchStatement(context);
736     case THROW:
737         return parseThrowStatement(context);
738     case TRY:
739         return parseTryStatement(context);
740     case DEBUGGER:
741         return parseDebuggerStatement(context);
742     case 0:
743     case CASE:
744     case CLOSEBRACE:
745     case DEFAULT:
746         // These tokens imply the end of a set of source elements
747         return 0;
748     case IDENT:
749         return parseExpressionOrLabelStatement(context);
750     default:
751         return parseExpressionStatement(context);
752     }
753 }
754
755 template <class TreeBuilder> TreeFormalParameterList JSParser::parseFormalParameters(TreeBuilder& context, bool& usesArguments)
756 {
757     matchOrFail(IDENT);
758     usesArguments = m_globalData->propertyNames->arguments == *token().m_data.ident;
759     TreeFormalParameterList list = context.createFormalParameterList(*token().m_data.ident);
760     TreeFormalParameterList tail = list;
761     next();
762     while (match(',')) {
763         next();
764         matchOrFail(IDENT);
765         const Identifier* ident = token().m_data.ident;
766         next();
767         usesArguments = usesArguments || m_globalData->propertyNames->arguments == *ident;
768         tail = context.createFormalParameterList(tail, *ident);
769     }
770     return list;
771 }
772
773 template <class TreeBuilder> TreeFunctionBody JSParser::parseFunctionBody(TreeBuilder& context)
774 {
775     if (match(CLOSEBRACE))
776         return context.createFunctionBody();
777     typename TreeBuilder::FunctionBodyBuilder bodyBuilder(m_globalData, m_lexer);
778     failIfFalse(parseSourceElements(bodyBuilder));
779     return context.createFunctionBody();
780 }
781
782 template <JSParser::FunctionRequirements requirements, class TreeBuilder> bool JSParser::parseFunctionInfo(TreeBuilder& context, const Identifier*& name, TreeFormalParameterList& parameters, TreeFunctionBody& body, int& openBracePos, int& closeBracePos, int& bodyStartLine)
783 {
784     if (match(IDENT)) {
785         name = token().m_data.ident;
786         next();
787     } else if (requirements == FunctionNeedsName)
788         return false;
789     consumeOrFail('(');
790     bool usesArguments = false;
791     if (!match(')')) {
792         parameters = parseFormalParameters(context, usesArguments);
793         failIfFalse(parameters);
794     }
795     consumeOrFail(')');
796     matchOrFail(OPENBRACE);
797
798     openBracePos = token().m_data.intValue;
799     bodyStartLine = tokenLine();
800     next();
801
802     body = parseFunctionBody(context);
803     failIfFalse(body);
804     if (usesArguments)
805         context.setUsesArguments(body);
806
807     matchOrFail(CLOSEBRACE);
808     closeBracePos = token().m_data.intValue;
809     next();
810     return true;
811 }
812
813 template <class TreeBuilder> TreeStatement JSParser::parseFunctionDeclaration(TreeBuilder& context)
814 {
815     ASSERT(match(FUNCTION));
816     next();
817     const Identifier* name = 0;
818     TreeFormalParameterList parameters = 0;
819     TreeFunctionBody body = 0;
820     int openBracePos = 0;
821     int closeBracePos = 0;
822     int bodyStartLine = 0;
823     failIfFalse(parseFunctionInfo<FunctionNeedsName>(context, name, parameters, body, openBracePos, closeBracePos, bodyStartLine));
824     failIfFalse(name);
825     return context.createFuncDeclStatement(name, body, parameters, openBracePos, closeBracePos, bodyStartLine, m_lastLine);
826 }
827
828 template <class TreeBuilder> TreeStatement JSParser::parseExpressionOrLabelStatement(TreeBuilder& context)
829 {
830
831     /* Expression and Label statements are ambiguous at LL(1), to avoid
832      * the cost of having a token buffer to support LL(2) we simply assume
833      * we have an expression statement, and then only look for a label if that
834      * parse fails.
835      */
836     int start = tokenStart();
837     int startLine = tokenLine();
838     const Identifier* ident = token().m_data.ident;
839     int currentToken = m_tokenCount;
840     TreeExpression expression = parseExpression(context);
841     failIfFalse(expression);
842     if (autoSemiColon())
843         return context.createExprStatement(expression, startLine, m_lastLine);
844     failIfFalse(currentToken + 1 == m_tokenCount);
845     int end = tokenEnd();
846     consumeOrFail(':');
847     TreeStatement statement = parseStatement(context);
848     failIfFalse(statement);
849     return context.createLabelStatement(ident, statement, start, end);
850 }
851
852 template <class TreeBuilder> TreeStatement JSParser::parseExpressionStatement(TreeBuilder& context)
853 {
854     int startLine = tokenLine();
855     TreeExpression expression = parseExpression(context);
856     failIfFalse(expression);
857     failIfFalse(autoSemiColon());
858     return context.createExprStatement(expression, startLine, m_lastLine);
859 }
860
861 template <class TreeBuilder> TreeStatement JSParser::parseIfStatement(TreeBuilder& context)
862 {
863     ASSERT(match(IF));
864
865     int start = tokenLine();
866     next();
867
868     consumeOrFail('(');
869
870     TreeExpression condition = parseExpression(context);
871     failIfFalse(condition);
872     int end = tokenLine();
873     consumeOrFail(')');
874
875     TreeStatement trueBlock = parseStatement(context);
876     failIfFalse(trueBlock);
877
878     if (!match(ELSE))
879         return context.createIfStatement(condition, trueBlock, start, end);
880     
881     Vector<TreeExpression> exprStack;
882     Vector<pair<int, int> > posStack;
883     Vector<TreeStatement> statementStack;
884     bool trailingElse = false;
885     do {
886         next();
887         if (!match(IF)) {
888             TreeStatement block = parseStatement(context);
889             failIfFalse(block);
890             statementStack.append(block);
891             trailingElse = true;
892             break;
893         }
894         int innerStart = tokenLine();
895         next();
896         
897         consumeOrFail('(');
898         
899         TreeExpression innerCondition = parseExpression(context);
900         failIfFalse(innerCondition);
901         int innerEnd = tokenLine();
902         consumeOrFail(')');
903         
904         TreeStatement innerTrueBlock = parseStatement(context);
905         failIfFalse(innerTrueBlock);     
906         exprStack.append(innerCondition);
907         posStack.append(make_pair(innerStart, innerEnd));
908         statementStack.append(innerTrueBlock);
909     } while (match(ELSE));
910
911     if (!trailingElse) {
912         TreeExpression condition = exprStack.last();
913         exprStack.removeLast();
914         TreeStatement trueBlock = statementStack.last();
915         statementStack.removeLast();
916         pair<int, int> pos = posStack.last();
917         posStack.removeLast();
918         statementStack.append(context.createIfStatement(condition, trueBlock, pos.first, pos.second));
919     }
920
921     while (!exprStack.isEmpty()) {
922         TreeExpression condition = exprStack.last();
923         exprStack.removeLast();
924         TreeStatement falseBlock = statementStack.last();
925         statementStack.removeLast();
926         TreeStatement trueBlock = statementStack.last();
927         statementStack.removeLast();
928         pair<int, int> pos = posStack.last();
929         posStack.removeLast();
930         statementStack.append(context.createIfStatement(condition, trueBlock, falseBlock, pos.first, pos.second));
931     }
932     
933     return context.createIfStatement(condition, trueBlock, statementStack.last(), start, end);
934 }
935
936 template <class TreeBuilder> TreeExpression JSParser::parseExpression(TreeBuilder& context)
937 {
938     failIfStackOverflow();
939     TreeExpression node = parseAssignmentExpression(context);
940     failIfFalse(node);
941     if (!match(','))
942         return node;
943     next();
944     m_nonLHSCount++;
945     TreeExpression right = parseAssignmentExpression(context);
946     failIfFalse(right);
947     typename TreeBuilder::Comma commaNode = context.createCommaExpr(node, right);
948     while (match(',')) {
949         next();
950         right = parseAssignmentExpression(context);
951         failIfFalse(right);
952         context.appendToComma(commaNode, right);
953     }
954     return commaNode;
955 }
956
957
958 template <typename TreeBuilder> TreeExpression JSParser::parseAssignmentExpression(TreeBuilder& context)
959 {
960     failIfStackOverflow();
961     int start = tokenStart();
962     int initialAssignmentCount = m_assignmentCount;
963     int initialNonLHSCount = m_nonLHSCount;
964     TreeExpression lhs = parseConditionalExpression(context);
965     failIfFalse(lhs);
966     if (initialNonLHSCount != m_nonLHSCount)
967         return lhs;
968
969     int assignmentStack = 0;
970     Operator op;
971     bool hadAssignment = false;
972     while (true) {
973         switch (token().m_type) {
974         case '=': op = OpEqual; break;
975         case PLUSEQUAL: op = OpPlusEq; break;
976         case MINUSEQUAL: op = OpMinusEq; break;
977         case MULTEQUAL: op = OpMultEq; break;
978         case DIVEQUAL: op = OpDivEq; break;
979         case LSHIFTEQUAL: op = OpLShift; break;
980         case RSHIFTEQUAL: op = OpRShift; break;
981         case URSHIFTEQUAL: op = OpURShift; break;
982         case ANDEQUAL: op = OpAndEq; break;
983         case XOREQUAL: op = OpXOrEq; break;
984         case OREQUAL: op = OpOrEq; break;
985         case MODEQUAL: op = OpModEq; break;
986         default:
987             goto end;
988         }
989         hadAssignment = true;
990         context.assignmentStackAppend(assignmentStack, lhs, start, tokenStart(), m_assignmentCount, op);
991         start = tokenStart();
992         m_assignmentCount++;
993         next();
994         lhs = parseConditionalExpression(context);
995         failIfFalse(lhs);
996         if (initialNonLHSCount != m_nonLHSCount)
997             break;
998     }
999 end:
1000     if (hadAssignment)
1001         m_nonLHSCount++;
1002
1003     if (!ASTBuilder::CreatesAST)
1004         return lhs;
1005
1006     while (assignmentStack)
1007         lhs = context.createAssignment(assignmentStack, lhs, initialAssignmentCount, m_assignmentCount, lastTokenEnd());
1008
1009     return lhs;
1010 }
1011
1012 template <class TreeBuilder> TreeExpression JSParser::parseConditionalExpression(TreeBuilder& context)
1013 {
1014     TreeExpression cond = parseBinaryExpression(context);
1015     failIfFalse(cond);
1016     if (!match('?'))
1017         return cond;
1018     m_nonLHSCount++;
1019     next();
1020     TreeExpression lhs = parseAssignmentExpression(context);
1021     consumeOrFail(':');
1022
1023     TreeExpression rhs = parseAssignmentExpression(context);
1024     failIfFalse(rhs);
1025     return context.createConditionalExpr(cond, lhs, rhs);
1026 }
1027
1028 static bool isUnaryOp(int token)
1029 {
1030     switch (token) {
1031     case '!':
1032     case '~':
1033     case '-':
1034     case '+':
1035     case PLUSPLUS:
1036     case AUTOPLUSPLUS:
1037     case MINUSMINUS:
1038     case AUTOMINUSMINUS:
1039     case TYPEOF:
1040     case VOIDTOKEN:
1041     case DELETETOKEN:
1042         return true;
1043     default:
1044         return false;
1045     }
1046 }
1047
1048 int JSParser::isBinaryOperator(int token)
1049 {
1050     switch (token) {
1051     case OR:
1052         return 1;
1053
1054     case AND:
1055         return 2;
1056
1057     case '|':
1058         return 3;
1059
1060     case '^':
1061         return 4;
1062
1063     case '&':
1064         return 5;
1065
1066     case EQEQ:
1067     case NE:
1068     case STREQ:
1069     case STRNEQ:
1070         return 6;
1071
1072     case '<':
1073     case '>':
1074     case LE:
1075     case GE:
1076     case INSTANCEOF:
1077         return 7;
1078
1079     case INTOKEN:
1080         // same precedence as the above but needs a validity check
1081         if (m_allowsIn)
1082             return 7;
1083         return 0;
1084
1085     case LSHIFT:
1086     case RSHIFT:
1087     case URSHIFT:
1088         return 8;
1089
1090     case '+':
1091     case '-':
1092         return 9;
1093
1094     case '*':
1095     case '/':
1096     case '%':
1097         return 10;
1098
1099     default:
1100         return 0;
1101     }
1102 }
1103
1104 template <class TreeBuilder> TreeExpression JSParser::parseBinaryExpression(TreeBuilder& context)
1105 {
1106
1107     int operandStackDepth = 0;
1108     int operatorStackDepth = 0;
1109     while (true) {
1110         int exprStart = tokenStart();
1111         int initialAssignments = m_assignmentCount;
1112         TreeExpression current = parseUnaryExpression(context);
1113         failIfFalse(current);
1114
1115         context.appendBinaryExpressionInfo(operandStackDepth, current, exprStart, lastTokenEnd(), lastTokenEnd(), initialAssignments != m_assignmentCount);
1116         int precedence = isBinaryOperator(token().m_type);
1117         if (!precedence)
1118             break;
1119         m_nonLHSCount++;
1120         int operatorToken = token().m_type;
1121         next();
1122
1123         while (operatorStackDepth &&  context.operatorStackHasHigherPrecedence(operatorStackDepth, precedence)) {
1124             ASSERT(operandStackDepth > 1);
1125
1126             typename TreeBuilder::BinaryOperand rhs = context.getFromOperandStack(-1);
1127             typename TreeBuilder::BinaryOperand lhs = context.getFromOperandStack(-2);
1128             context.shrinkOperandStackBy(operandStackDepth, 2);
1129             context.appendBinaryOperation(operandStackDepth, operatorStackDepth, lhs, rhs);
1130             context.operatorStackPop(operatorStackDepth);
1131         }
1132         context.operatorStackAppend(operatorStackDepth, operatorToken, precedence);
1133     }
1134
1135     while (operatorStackDepth) {
1136         ASSERT(operandStackDepth > 1);
1137
1138         typename TreeBuilder::BinaryOperand rhs = context.getFromOperandStack(-1);
1139         typename TreeBuilder::BinaryOperand lhs = context.getFromOperandStack(-2);
1140         context.shrinkOperandStackBy(operandStackDepth, 2);
1141         context.appendBinaryOperation(operandStackDepth, operatorStackDepth, lhs, rhs);
1142         context.operatorStackPop(operatorStackDepth);
1143     }
1144     return context.popOperandStack(operandStackDepth);
1145 }
1146
1147
1148 template <class TreeBuilder> TreeProperty JSParser::parseProperty(TreeBuilder& context)
1149 {
1150     bool wasIdent = false;
1151     switch (token().m_type) {
1152     case IDENT:
1153         wasIdent = true;
1154     case STRING: {
1155         const Identifier* ident = token().m_data.ident;
1156         next();
1157         if (match(':')) {
1158             next();
1159             TreeExpression node = parseAssignmentExpression(context);
1160             failIfFalse(node);
1161             return context.createProperty(ident, node, PropertyNode::Constant);
1162         }
1163         failIfFalse(wasIdent);
1164         matchOrFail(IDENT);
1165         const Identifier* accessorName = 0;
1166         TreeFormalParameterList parameters = 0;
1167         TreeFunctionBody body = 0;
1168         int openBracePos = 0;
1169         int closeBracePos = 0;
1170         int bodyStartLine = 0;
1171         failIfFalse(*ident == m_globalData->propertyNames->get || *ident == m_globalData->propertyNames->set);
1172         failIfFalse(parseFunctionInfo<FunctionNeedsName>(context, accessorName, parameters, body, openBracePos, closeBracePos, bodyStartLine));
1173         return context.createGetterOrSetterProperty(ident, accessorName, parameters, body, openBracePos, closeBracePos, bodyStartLine, m_lastLine);
1174     }
1175     case NUMBER: {
1176         double propertyName = token().m_data.doubleValue;
1177         next();
1178         consumeOrFail(':');
1179         TreeExpression node = parseAssignmentExpression(context);
1180         failIfFalse(node);
1181         return context.createProperty(propertyName, node, PropertyNode::Constant);
1182     }
1183     }
1184     fail();
1185 }
1186
1187 template <class TreeBuilder> TreeExpression JSParser::parseObjectLiteral(TreeBuilder& context)
1188 {
1189     consumeOrFail(OPENBRACE);
1190
1191     if (match(CLOSEBRACE)) {
1192         next();
1193         return context.createObjectLiteral();
1194     }
1195
1196     TreeProperty property = parseProperty(context);
1197     failIfFalse(property);
1198
1199     TreePropertyList propertyList = context.createPropertyList(property);
1200     TreePropertyList tail = propertyList;
1201
1202     while (match(',')) {
1203         next();
1204         // allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939
1205         if (match(CLOSEBRACE))
1206             break;
1207         property = parseProperty(context);
1208         failIfFalse(property);
1209
1210         tail = context.createPropertyList(property, tail);
1211     }
1212
1213     consumeOrFail(CLOSEBRACE);
1214
1215     return context.createObjectLiteral(propertyList);
1216 }
1217
1218 template <class TreeBuilder> TreeExpression JSParser::parseArrayLiteral(TreeBuilder& context)
1219 {
1220     consumeOrFail('[');
1221
1222     int elisions = 0;
1223     while (match(',')) {
1224         next();
1225         elisions++;
1226     }
1227     if (match(']')) {
1228         next();
1229         return context.createArray(elisions);
1230     }
1231
1232     TreeExpression elem = parseAssignmentExpression(context);
1233     failIfFalse(elem);
1234     typename TreeBuilder::ElementList elementList = context.createElementList(elisions, elem);
1235     typename TreeBuilder::ElementList tail = elementList;
1236     elisions = 0;
1237     while (match(',')) {
1238         next();
1239         elisions = 0;
1240
1241         while (match(',')) {
1242             next();
1243             elisions++;
1244         }
1245
1246         if (match(']')) {
1247             next();
1248             return context.createArray(elisions, elementList);
1249         }
1250         TreeExpression elem = parseAssignmentExpression(context);
1251         failIfFalse(elem);
1252         tail = context.createElementList(tail, elisions, elem);
1253     }
1254
1255     consumeOrFail(']');
1256
1257     return context.createArray(elementList);
1258 }
1259
1260 template <class TreeBuilder> TreeExpression JSParser::parsePrimaryExpression(TreeBuilder& context)
1261 {
1262     switch (token().m_type) {
1263     case OPENBRACE:
1264         return parseObjectLiteral(context);
1265     case '[':
1266         return parseArrayLiteral(context);
1267     case '(': {
1268         next();
1269         int oldNonLHSCount = m_nonLHSCount;
1270         TreeExpression result = parseExpression(context);
1271         m_nonLHSCount = oldNonLHSCount;
1272         consumeOrFail(')');
1273
1274         return result;
1275     }
1276     case THISTOKEN: {
1277         next();
1278         return context.thisExpr();
1279     }
1280     case IDENT: {
1281         int start = tokenStart();
1282         const Identifier* ident = token().m_data.ident;
1283         next();
1284         return context.createResolve(ident, start);
1285     }
1286     case STRING: {
1287         const Identifier* ident = token().m_data.ident;
1288         next();
1289         return context.createString(ident);
1290     }
1291     case NUMBER: {
1292         double d = token().m_data.doubleValue;
1293         next();
1294         return context.createNumberExpr(d);
1295     }
1296     case NULLTOKEN: {
1297         next();
1298         return context.createNull();
1299     }
1300     case TRUETOKEN: {
1301         next();
1302         return context.createBoolean(true);
1303     }
1304     case FALSETOKEN: {
1305         next();
1306         return context.createBoolean(false);
1307     }
1308     case DIVEQUAL:
1309     case '/': {
1310         /* regexp */
1311         const Identifier* pattern;
1312         const Identifier* flags;
1313         if (match(DIVEQUAL))
1314             failIfFalse(m_lexer->scanRegExp(pattern, flags, '='));
1315         else
1316             failIfFalse(m_lexer->scanRegExp(pattern, flags));
1317
1318         int start = tokenStart();
1319         next();
1320         return context.createRegex(*pattern, *flags, start);
1321     }
1322     }
1323     fail();
1324 }
1325
1326 template <class TreeBuilder> TreeArguments JSParser::parseArguments(TreeBuilder& context)
1327 {
1328     consumeOrFail('(');
1329     if (match(')')) {
1330         next();
1331         return context.createArguments();
1332     }
1333     TreeExpression firstArg = parseAssignmentExpression(context);
1334     failIfFalse(firstArg);
1335
1336     TreeArgumentsList argList = context.createArgumentsList(firstArg);
1337     TreeArgumentsList tail = argList;
1338     while (match(',')) {
1339         next();
1340         TreeExpression arg = parseAssignmentExpression(context);
1341         failIfFalse(arg);
1342         tail = context.createArgumentsList(tail, arg);
1343     }
1344     consumeOrFail(')');
1345     return context.createArguments(argList);
1346 }
1347
1348 template <class TreeBuilder> TreeExpression JSParser::parseMemberExpression(TreeBuilder& context)
1349 {
1350     TreeExpression base = 0;
1351     int start = tokenStart();
1352     int expressionStart = start;
1353     int newCount = 0;
1354     while (match(NEW)) {
1355         next();
1356         newCount++;
1357     }
1358     if (match(FUNCTION)) {
1359         const Identifier* name = &m_globalData->propertyNames->nullIdentifier;
1360         TreeFormalParameterList parameters = 0;
1361         TreeFunctionBody body = 0;
1362         int openBracePos = 0;
1363         int closeBracePos = 0;
1364         int bodyStartLine = 0;
1365         next();
1366         failIfFalse(parseFunctionInfo<FunctionNoRequirements>(context, name, parameters, body, openBracePos, closeBracePos, bodyStartLine));
1367         base = context.createFunctionExpr(name, body, parameters, openBracePos, closeBracePos, bodyStartLine, m_lastLine);
1368     } else
1369         base = parsePrimaryExpression(context);
1370
1371     failIfFalse(base);
1372     while (true) {
1373         switch (token().m_type) {
1374         case '[': {
1375             int expressionEnd = lastTokenEnd();
1376             next();
1377             int nonLHSCount = m_nonLHSCount;
1378             int initialAssignments = m_assignmentCount;
1379             TreeExpression property = parseExpression(context);
1380             failIfFalse(property);
1381             base = context.createBracketAccess(base, property, initialAssignments != m_assignmentCount, expressionStart, expressionEnd, tokenEnd());
1382             if (!consume(']'))
1383                 fail();
1384             m_nonLHSCount = nonLHSCount;
1385             break;
1386         }
1387         case '(': {
1388             if (newCount) {
1389                 newCount--;
1390                 if (match('(')) {
1391                     int exprEnd = lastTokenEnd();
1392                     TreeArguments arguments = parseArguments(context);
1393                     failIfFalse(arguments);
1394                     base = context.createNewExpr(base, arguments, start, exprEnd, lastTokenEnd());
1395                 } else
1396                     base = context.createNewExpr(base, start, lastTokenEnd());               
1397             } else {
1398                 int nonLHSCount = m_nonLHSCount;
1399                 int expressionEnd = lastTokenEnd();
1400                 TreeArguments arguments = parseArguments(context);
1401                 failIfFalse(arguments);
1402                 base = context.makeFunctionCallNode(base, arguments, expressionStart, expressionEnd, lastTokenEnd());
1403                 m_nonLHSCount = nonLHSCount;
1404             }
1405             break;
1406         }
1407         case '.': {
1408             int expressionEnd = lastTokenEnd();
1409             next();
1410             matchOrFail(IDENT);
1411             base = context.createDotAccess(base, *token().m_data.ident, expressionStart, expressionEnd, tokenEnd());
1412             next();
1413             break;
1414         }
1415         default:
1416             goto endMemberExpression;
1417         }
1418     }
1419 endMemberExpression:
1420     while (newCount--)
1421         base = context.createNewExpr(base, start, lastTokenEnd());
1422     return base;
1423 }
1424
1425 template <class TreeBuilder> TreeExpression JSParser::parseUnaryExpression(TreeBuilder& context)
1426 {
1427     AllowInOverride allowInOverride(this);
1428     int tokenStackDepth = 0;
1429     while (isUnaryOp(token().m_type)) {
1430         m_nonLHSCount++;
1431         context.appendUnaryToken(tokenStackDepth, token().m_type, tokenStart());
1432         next();
1433     }
1434     int subExprStart = tokenStart();
1435     TreeExpression expr = parseMemberExpression(context);
1436     failIfFalse(expr);
1437     switch (token().m_type) {
1438     case PLUSPLUS:
1439         m_nonLHSCount++;
1440         expr = context.makePostfixNode(expr, OpPlusPlus, subExprStart, lastTokenEnd(), tokenEnd());
1441         m_assignmentCount++;
1442         next();
1443         break;
1444     case MINUSMINUS:
1445         m_nonLHSCount++;
1446         expr = context.makePostfixNode(expr, OpMinusMinus, subExprStart, lastTokenEnd(), tokenEnd());
1447         m_assignmentCount++;
1448         next();
1449         break;
1450     }
1451
1452     int end = lastTokenEnd();
1453
1454     if (!TreeBuilder::CreatesAST)
1455         return expr;
1456
1457     while (tokenStackDepth) {
1458         switch (context.unaryTokenStackLastType(tokenStackDepth)) {
1459         case '!':
1460             expr = context.createLogicalNot(expr);
1461             break;
1462         case '~':
1463             expr = context.makeBitwiseNotNode(expr);
1464             break;
1465         case '-':
1466             expr = context.makeNegateNode(expr);
1467             break;
1468         case '+':
1469             expr = context.createUnaryPlus(expr);
1470             break;
1471         case PLUSPLUS:
1472         case AUTOPLUSPLUS:
1473             expr = context.makePrefixNode(expr, OpPlusPlus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end);
1474             m_assignmentCount++;
1475             break;
1476         case MINUSMINUS:
1477         case AUTOMINUSMINUS:
1478             expr = context.makePrefixNode(expr, OpMinusMinus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end);
1479             m_assignmentCount++;
1480             break;
1481         case TYPEOF:
1482             expr = context.makeTypeOfNode(expr);
1483             break;
1484         case VOIDTOKEN:
1485             expr = context.createVoid(expr);
1486             break;
1487         case DELETETOKEN:
1488             expr = context.makeDeleteNode(expr, context.unaryTokenStackLastStart(tokenStackDepth), end, end);
1489             break;
1490         default:
1491             // If we get here something has gone horribly horribly wrong
1492             CRASH();
1493         }
1494         subExprStart = context.unaryTokenStackLastStart(tokenStackDepth);
1495         context.unaryTokenStackRemoveLast(tokenStackDepth);
1496     }
1497     return expr;
1498 }
1499
1500 }