154a9ae5278116fc3f96cf220962afa13feb518c
[platform/upstream/nodejs.git] / deps / v8 / src / preparser.cc
1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <cmath>
6
7 #include "src/allocation.h"
8 #include "src/base/logging.h"
9 #include "src/conversions-inl.h"
10 #include "src/conversions.h"
11 #include "src/globals.h"
12 #include "src/hashmap.h"
13 #include "src/list.h"
14 #include "src/preparse-data.h"
15 #include "src/preparse-data-format.h"
16 #include "src/preparser.h"
17 #include "src/unicode.h"
18 #include "src/utils.h"
19
20 namespace v8 {
21 namespace internal {
22
23 void PreParserTraits::ReportMessageAt(Scanner::Location location,
24                                       const char* message,
25                                       const char* arg,
26                                       bool is_reference_error) {
27   ReportMessageAt(location.beg_pos,
28                   location.end_pos,
29                   message,
30                   arg,
31                   is_reference_error);
32 }
33
34
35 void PreParserTraits::ReportMessageAt(int start_pos,
36                                       int end_pos,
37                                       const char* message,
38                                       const char* arg,
39                                       bool is_reference_error) {
40   pre_parser_->log_->LogMessage(start_pos, end_pos, message, arg,
41                                 is_reference_error);
42 }
43
44
45 PreParserIdentifier PreParserTraits::GetSymbol(Scanner* scanner) {
46   if (scanner->current_token() == Token::FUTURE_RESERVED_WORD) {
47     return PreParserIdentifier::FutureReserved();
48   } else if (scanner->current_token() ==
49              Token::FUTURE_STRICT_RESERVED_WORD) {
50     return PreParserIdentifier::FutureStrictReserved();
51   } else if (scanner->current_token() == Token::LET) {
52     return PreParserIdentifier::Let();
53   } else if (scanner->current_token() == Token::STATIC) {
54     return PreParserIdentifier::Static();
55   } else if (scanner->current_token() == Token::YIELD) {
56     return PreParserIdentifier::Yield();
57   }
58   if (scanner->UnescapedLiteralMatches("eval", 4)) {
59     return PreParserIdentifier::Eval();
60   }
61   if (scanner->UnescapedLiteralMatches("arguments", 9)) {
62     return PreParserIdentifier::Arguments();
63   }
64   if (scanner->LiteralMatches("prototype", 9)) {
65     return PreParserIdentifier::Prototype();
66   }
67   if (scanner->LiteralMatches("constructor", 11)) {
68     return PreParserIdentifier::Constructor();
69   }
70   return PreParserIdentifier::Default();
71 }
72
73
74 PreParserIdentifier PreParserTraits::GetNumberAsSymbol(Scanner* scanner) {
75   return PreParserIdentifier::Default();
76 }
77
78
79 PreParserExpression PreParserTraits::ExpressionFromString(
80     int pos, Scanner* scanner, PreParserFactory* factory) {
81   if (scanner->UnescapedLiteralMatches("use strict", 10)) {
82     return PreParserExpression::UseStrictStringLiteral();
83   } else if (scanner->UnescapedLiteralMatches("use strong", 10)) {
84     return PreParserExpression::UseStrongStringLiteral();
85   }
86   return PreParserExpression::StringLiteral();
87 }
88
89
90 PreParserExpression PreParserTraits::ParseV8Intrinsic(bool* ok) {
91   return pre_parser_->ParseV8Intrinsic(ok);
92 }
93
94
95 PreParserExpression PreParserTraits::ParseFunctionLiteral(
96     PreParserIdentifier name, Scanner::Location function_name_location,
97     bool name_is_strict_reserved, FunctionKind kind,
98     int function_token_position, FunctionLiteral::FunctionType type,
99     FunctionLiteral::ArityRestriction arity_restriction, bool* ok) {
100   return pre_parser_->ParseFunctionLiteral(
101       name, function_name_location, name_is_strict_reserved, kind,
102       function_token_position, type, arity_restriction, ok);
103 }
104
105
106 PreParser::PreParseResult PreParser::PreParseLazyFunction(
107     LanguageMode language_mode, FunctionKind kind, ParserRecorder* log) {
108   log_ = log;
109   // Lazy functions always have trivial outer scopes (no with/catch scopes).
110   Scope* top_scope = NewScope(scope_, SCRIPT_SCOPE);
111   PreParserFactory top_factory(NULL);
112   FunctionState top_state(&function_state_, &scope_, top_scope, kNormalFunction,
113                           &top_factory);
114   scope_->SetLanguageMode(language_mode);
115   Scope* function_scope = NewScope(scope_, FUNCTION_SCOPE);
116   PreParserFactory function_factory(NULL);
117   FunctionState function_state(&function_state_, &scope_, function_scope, kind,
118                                &function_factory);
119   DCHECK_EQ(Token::LBRACE, scanner()->current_token());
120   bool ok = true;
121   int start_position = peek_position();
122   ParseLazyFunctionLiteralBody(&ok);
123   if (stack_overflow()) return kPreParseStackOverflow;
124   if (!ok) {
125     ReportUnexpectedToken(scanner()->current_token());
126   } else {
127     DCHECK_EQ(Token::RBRACE, scanner()->peek());
128     if (is_strict(scope_->language_mode())) {
129       int end_pos = scanner()->location().end_pos;
130       CheckStrictOctalLiteral(start_position, end_pos, &ok);
131     }
132   }
133   return kPreParseSuccess;
134 }
135
136
137 PreParserExpression PreParserTraits::ParseClassLiteral(
138     PreParserIdentifier name, Scanner::Location class_name_location,
139     bool name_is_strict_reserved, int pos, bool* ok) {
140   return pre_parser_->ParseClassLiteral(name, class_name_location,
141                                         name_is_strict_reserved, pos, ok);
142 }
143
144
145 // Preparsing checks a JavaScript program and emits preparse-data that helps
146 // a later parsing to be faster.
147 // See preparser-data.h for the data.
148
149 // The PreParser checks that the syntax follows the grammar for JavaScript,
150 // and collects some information about the program along the way.
151 // The grammar check is only performed in order to understand the program
152 // sufficiently to deduce some information about it, that can be used
153 // to speed up later parsing. Finding errors is not the goal of pre-parsing,
154 // rather it is to speed up properly written and correct programs.
155 // That means that contextual checks (like a label being declared where
156 // it is used) are generally omitted.
157
158
159 PreParser::Statement PreParser::ParseStatementListItem(bool* ok) {
160   // ECMA 262 6th Edition
161   // StatementListItem[Yield, Return] :
162   //   Statement[?Yield, ?Return]
163   //   Declaration[?Yield]
164   //
165   // Declaration[Yield] :
166   //   HoistableDeclaration[?Yield]
167   //   ClassDeclaration[?Yield]
168   //   LexicalDeclaration[In, ?Yield]
169   //
170   // HoistableDeclaration[Yield, Default] :
171   //   FunctionDeclaration[?Yield, ?Default]
172   //   GeneratorDeclaration[?Yield, ?Default]
173   //
174   // LexicalDeclaration[In, Yield] :
175   //   LetOrConst BindingList[?In, ?Yield] ;
176
177   switch (peek()) {
178     case Token::FUNCTION:
179       return ParseFunctionDeclaration(ok);
180     case Token::CLASS:
181       return ParseClassDeclaration(ok);
182     case Token::CONST:
183       return ParseVariableStatement(kStatementListItem, ok);
184     case Token::LET:
185       DCHECK(allow_harmony_scoping());
186       if (is_strict(language_mode())) {
187         return ParseVariableStatement(kStatementListItem, ok);
188       }
189       // Fall through.
190     default:
191       return ParseStatement(ok);
192   }
193 }
194
195
196 void PreParser::ParseStatementList(int end_token, bool* ok) {
197   // SourceElements ::
198   //   (Statement)* <end_token>
199
200   bool directive_prologue = true;
201   while (peek() != end_token) {
202     if (directive_prologue && peek() != Token::STRING) {
203       directive_prologue = false;
204     }
205     Statement statement = ParseStatementListItem(ok);
206     if (!*ok) return;
207     if (directive_prologue) {
208       if (statement.IsUseStrictLiteral()) {
209         scope_->SetLanguageMode(
210             static_cast<LanguageMode>(scope_->language_mode() | STRICT_BIT));
211       } else if (statement.IsUseStrongLiteral() && allow_strong_mode()) {
212         scope_->SetLanguageMode(static_cast<LanguageMode>(
213             scope_->language_mode() | STRICT_BIT | STRONG_BIT));
214       } else if (!statement.IsStringLiteral()) {
215         directive_prologue = false;
216       }
217     }
218   }
219 }
220
221
222 #define CHECK_OK  ok);                   \
223   if (!*ok) return Statement::Default();  \
224   ((void)0
225 #define DUMMY )  // to make indentation work
226 #undef DUMMY
227
228
229 PreParser::Statement PreParser::ParseStatement(bool* ok) {
230   // Statement ::
231   //   EmptyStatement
232   //   ...
233   return ParseSubStatement(ok);
234 }
235
236
237 PreParser::Statement PreParser::ParseSubStatement(bool* ok) {
238   // Statement ::
239   //   Block
240   //   VariableStatement
241   //   EmptyStatement
242   //   ExpressionStatement
243   //   IfStatement
244   //   IterationStatement
245   //   ContinueStatement
246   //   BreakStatement
247   //   ReturnStatement
248   //   WithStatement
249   //   LabelledStatement
250   //   SwitchStatement
251   //   ThrowStatement
252   //   TryStatement
253   //   DebuggerStatement
254
255   // Note: Since labels can only be used by 'break' and 'continue'
256   // statements, which themselves are only valid within blocks,
257   // iterations or 'switch' statements (i.e., BreakableStatements),
258   // labels can be simply ignored in all other cases; except for
259   // trivial labeled break statements 'label: break label' which is
260   // parsed into an empty statement.
261
262   // Keep the source position of the statement
263   switch (peek()) {
264     case Token::LBRACE:
265       return ParseBlock(ok);
266
267     case Token::SEMICOLON:
268       if (is_strong(language_mode())) {
269         PreParserTraits::ReportMessageAt(scanner()->peek_location(),
270                                          "strong_empty");
271         *ok = false;
272         return Statement::Default();
273       }
274       Next();
275       return Statement::Default();
276
277     case Token::IF:
278       return ParseIfStatement(ok);
279
280     case Token::DO:
281       return ParseDoWhileStatement(ok);
282
283     case Token::WHILE:
284       return ParseWhileStatement(ok);
285
286     case Token::FOR:
287       return ParseForStatement(ok);
288
289     case Token::CONTINUE:
290       return ParseContinueStatement(ok);
291
292     case Token::BREAK:
293       return ParseBreakStatement(ok);
294
295     case Token::RETURN:
296       return ParseReturnStatement(ok);
297
298     case Token::WITH:
299       return ParseWithStatement(ok);
300
301     case Token::SWITCH:
302       return ParseSwitchStatement(ok);
303
304     case Token::THROW:
305       return ParseThrowStatement(ok);
306
307     case Token::TRY:
308       return ParseTryStatement(ok);
309
310     case Token::FUNCTION: {
311       Scanner::Location start_location = scanner()->peek_location();
312       Statement statement = ParseFunctionDeclaration(CHECK_OK);
313       Scanner::Location end_location = scanner()->location();
314       if (is_strict(language_mode())) {
315         PreParserTraits::ReportMessageAt(start_location.beg_pos,
316                                          end_location.end_pos,
317                                          "strict_function");
318         *ok = false;
319         return Statement::Default();
320       } else {
321         return statement;
322       }
323     }
324
325     case Token::DEBUGGER:
326       return ParseDebuggerStatement(ok);
327
328     case Token::VAR:
329       return ParseVariableStatement(kStatement, ok);
330
331     case Token::CONST:
332       // In ES6 CONST is not allowed as a Statement, only as a
333       // LexicalDeclaration, however we continue to allow it in sloppy mode for
334       // backwards compatibility.
335       if (is_sloppy(language_mode())) {
336         return ParseVariableStatement(kStatement, ok);
337       }
338
339     // Fall through.
340     default:
341       return ParseExpressionOrLabelledStatement(ok);
342   }
343 }
344
345
346 PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
347   // FunctionDeclaration ::
348   //   'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
349   // GeneratorDeclaration ::
350   //   'function' '*' Identifier '(' FormalParameterListopt ')'
351   //      '{' FunctionBody '}'
352   Expect(Token::FUNCTION, CHECK_OK);
353   int pos = position();
354   bool is_generator = Check(Token::MUL);
355   bool is_strict_reserved = false;
356   Identifier name = ParseIdentifierOrStrictReservedWord(
357       &is_strict_reserved, CHECK_OK);
358   ParseFunctionLiteral(name, scanner()->location(), is_strict_reserved,
359                        is_generator ? FunctionKind::kGeneratorFunction
360                                     : FunctionKind::kNormalFunction,
361                        pos, FunctionLiteral::DECLARATION,
362                        FunctionLiteral::NORMAL_ARITY, CHECK_OK);
363   return Statement::FunctionDeclaration();
364 }
365
366
367 PreParser::Statement PreParser::ParseClassDeclaration(bool* ok) {
368   Expect(Token::CLASS, CHECK_OK);
369   if (!allow_harmony_sloppy() && is_sloppy(language_mode())) {
370     ReportMessage("sloppy_lexical");
371     *ok = false;
372     return Statement::Default();
373   }
374
375   int pos = position();
376   bool is_strict_reserved = false;
377   Identifier name =
378       ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
379   ParseClassLiteral(name, scanner()->location(), is_strict_reserved, pos,
380                     CHECK_OK);
381   return Statement::Default();
382 }
383
384
385 PreParser::Statement PreParser::ParseBlock(bool* ok) {
386   // Block ::
387   //   '{' Statement* '}'
388
389   // Note that a Block does not introduce a new execution scope!
390   // (ECMA-262, 3rd, 12.2)
391   //
392   Expect(Token::LBRACE, CHECK_OK);
393   while (peek() != Token::RBRACE) {
394     if (allow_harmony_scoping() && is_strict(language_mode())) {
395       ParseStatementListItem(CHECK_OK);
396     } else {
397       ParseStatement(CHECK_OK);
398     }
399   }
400   Expect(Token::RBRACE, ok);
401   return Statement::Default();
402 }
403
404
405 PreParser::Statement PreParser::ParseVariableStatement(
406     VariableDeclarationContext var_context,
407     bool* ok) {
408   // VariableStatement ::
409   //   VariableDeclarations ';'
410
411   Statement result = ParseVariableDeclarations(var_context,
412                                                NULL,
413                                                NULL,
414                                                CHECK_OK);
415   ExpectSemicolon(CHECK_OK);
416   return result;
417 }
418
419
420 // If the variable declaration declares exactly one non-const
421 // variable, then *var is set to that variable. In all other cases,
422 // *var is untouched; in particular, it is the caller's responsibility
423 // to initialize it properly. This mechanism is also used for the parsing
424 // of 'for-in' loops.
425 PreParser::Statement PreParser::ParseVariableDeclarations(
426     VariableDeclarationContext var_context,
427     VariableDeclarationProperties* decl_props,
428     int* num_decl,
429     bool* ok) {
430   // VariableDeclarations ::
431   //   ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[',']
432   //
433   // The ES6 Draft Rev3 specifies the following grammar for const declarations
434   //
435   // ConstDeclaration ::
436   //   const ConstBinding (',' ConstBinding)* ';'
437   // ConstBinding ::
438   //   Identifier '=' AssignmentExpression
439   //
440   // TODO(ES6):
441   // ConstBinding ::
442   //   BindingPattern '=' AssignmentExpression
443   bool require_initializer = false;
444   bool is_strict_const = false;
445   if (peek() == Token::VAR) {
446     if (is_strong(language_mode())) {
447       Scanner::Location location = scanner()->peek_location();
448       ReportMessageAt(location, "strong_var");
449       *ok = false;
450       return Statement::Default();
451     }
452     Consume(Token::VAR);
453   } else if (peek() == Token::CONST) {
454     // TODO(ES6): The ES6 Draft Rev4 section 12.2.2 reads:
455     //
456     // ConstDeclaration : const ConstBinding (',' ConstBinding)* ';'
457     //
458     // * It is a Syntax Error if the code that matches this production is not
459     //   contained in extended code.
460     //
461     // However disallowing const in sloppy mode will break compatibility with
462     // existing pages. Therefore we keep allowing const with the old
463     // non-harmony semantics in sloppy mode.
464     Consume(Token::CONST);
465     if (is_strict(language_mode())) {
466       DCHECK(var_context != kStatement);
467       if (!allow_harmony_scoping()) {
468         Scanner::Location location = scanner()->peek_location();
469         ReportMessageAt(location, "strict_const");
470         *ok = false;
471         return Statement::Default();
472       }
473       is_strict_const = true;
474       require_initializer = var_context != kForStatement;
475     }
476   } else if (peek() == Token::LET && is_strict(language_mode())) {
477     Consume(Token::LET);
478     DCHECK(var_context != kStatement);
479   } else {
480     *ok = false;
481     return Statement::Default();
482   }
483
484   // The scope of a var/const declared variable anywhere inside a function
485   // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). The scope
486   // of a let declared variable is the scope of the immediately enclosing
487   // block.
488   int nvars = 0;  // the number of variables declared
489   do {
490     // Parse variable name.
491     if (nvars > 0) Consume(Token::COMMA);
492     ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
493     nvars++;
494     if (peek() == Token::ASSIGN || require_initializer ||
495         // require initializers for multiple consts.
496         (is_strict_const && peek() == Token::COMMA)) {
497       Expect(Token::ASSIGN, CHECK_OK);
498       ParseAssignmentExpression(var_context != kForStatement, CHECK_OK);
499       if (decl_props != NULL) *decl_props = kHasInitializers;
500     }
501   } while (peek() == Token::COMMA);
502
503   if (num_decl != NULL) *num_decl = nvars;
504   return Statement::Default();
505 }
506
507
508 PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) {
509   // ExpressionStatement | LabelledStatement ::
510   //   Expression ';'
511   //   Identifier ':' Statement
512
513   switch (peek()) {
514     case Token::FUNCTION:
515     case Token::LBRACE:
516       UNREACHABLE();  // Always handled by the callers.
517     case Token::CLASS:
518       ReportUnexpectedToken(Next());
519       *ok = false;
520       return Statement::Default();
521
522     // TODO(arv): Handle `let [`
523     // https://code.google.com/p/v8/issues/detail?id=3847
524
525     default:
526       break;
527   }
528
529   bool starts_with_identifier = peek_any_identifier();
530   Expression expr = ParseExpression(true, CHECK_OK);
531   // Even if the expression starts with an identifier, it is not necessarily an
532   // identifier. For example, "foo + bar" starts with an identifier but is not
533   // an identifier.
534   if (starts_with_identifier && expr.IsIdentifier() && peek() == Token::COLON) {
535     // Expression is a single identifier, and not, e.g., a parenthesized
536     // identifier.
537     DCHECK(!expr.AsIdentifier().IsFutureReserved());
538     DCHECK(is_sloppy(language_mode()) ||
539            !IsFutureStrictReserved(expr.AsIdentifier()));
540     Consume(Token::COLON);
541     return ParseStatement(ok);
542     // Preparsing is disabled for extensions (because the extension details
543     // aren't passed to lazily compiled functions), so we don't
544     // accept "native function" in the preparser.
545   }
546   // Parsed expression statement.
547   // Detect attempts at 'let' declarations in sloppy mode.
548   if (peek() == Token::IDENTIFIER && is_sloppy(language_mode()) &&
549       expr.IsIdentifier() && expr.AsIdentifier().IsLet()) {
550     ReportMessage("sloppy_lexical", NULL);
551     *ok = false;
552     return Statement::Default();
553   }
554   ExpectSemicolon(CHECK_OK);
555   return Statement::ExpressionStatement(expr);
556 }
557
558
559 PreParser::Statement PreParser::ParseIfStatement(bool* ok) {
560   // IfStatement ::
561   //   'if' '(' Expression ')' Statement ('else' Statement)?
562
563   Expect(Token::IF, CHECK_OK);
564   Expect(Token::LPAREN, CHECK_OK);
565   ParseExpression(true, CHECK_OK);
566   Expect(Token::RPAREN, CHECK_OK);
567   ParseSubStatement(CHECK_OK);
568   if (peek() == Token::ELSE) {
569     Next();
570     ParseSubStatement(CHECK_OK);
571   }
572   return Statement::Default();
573 }
574
575
576 PreParser::Statement PreParser::ParseContinueStatement(bool* ok) {
577   // ContinueStatement ::
578   //   'continue' [no line terminator] Identifier? ';'
579
580   Expect(Token::CONTINUE, CHECK_OK);
581   Token::Value tok = peek();
582   if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
583       tok != Token::SEMICOLON &&
584       tok != Token::RBRACE &&
585       tok != Token::EOS) {
586     // ECMA allows "eval" or "arguments" as labels even in strict mode.
587     ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
588   }
589   ExpectSemicolon(CHECK_OK);
590   return Statement::Default();
591 }
592
593
594 PreParser::Statement PreParser::ParseBreakStatement(bool* ok) {
595   // BreakStatement ::
596   //   'break' [no line terminator] Identifier? ';'
597
598   Expect(Token::BREAK, CHECK_OK);
599   Token::Value tok = peek();
600   if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
601       tok != Token::SEMICOLON &&
602       tok != Token::RBRACE &&
603       tok != Token::EOS) {
604     // ECMA allows "eval" or "arguments" as labels even in strict mode.
605     ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
606   }
607   ExpectSemicolon(CHECK_OK);
608   return Statement::Default();
609 }
610
611
612 PreParser::Statement PreParser::ParseReturnStatement(bool* ok) {
613   // ReturnStatement ::
614   //   'return' [no line terminator] Expression? ';'
615
616   // Consume the return token. It is necessary to do before
617   // reporting any errors on it, because of the way errors are
618   // reported (underlining).
619   Expect(Token::RETURN, CHECK_OK);
620
621   // An ECMAScript program is considered syntactically incorrect if it
622   // contains a return statement that is not within the body of a
623   // function. See ECMA-262, section 12.9, page 67.
624   // This is not handled during preparsing.
625
626   Token::Value tok = peek();
627   if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
628       tok != Token::SEMICOLON &&
629       tok != Token::RBRACE &&
630       tok != Token::EOS) {
631     ParseExpression(true, CHECK_OK);
632   }
633   ExpectSemicolon(CHECK_OK);
634   return Statement::Default();
635 }
636
637
638 PreParser::Statement PreParser::ParseWithStatement(bool* ok) {
639   // WithStatement ::
640   //   'with' '(' Expression ')' Statement
641   Expect(Token::WITH, CHECK_OK);
642   if (is_strict(language_mode())) {
643     ReportMessageAt(scanner()->location(), "strict_mode_with");
644     *ok = false;
645     return Statement::Default();
646   }
647   Expect(Token::LPAREN, CHECK_OK);
648   ParseExpression(true, CHECK_OK);
649   Expect(Token::RPAREN, CHECK_OK);
650
651   Scope* with_scope = NewScope(scope_, WITH_SCOPE);
652   BlockState block_state(&scope_, with_scope);
653   ParseSubStatement(CHECK_OK);
654   return Statement::Default();
655 }
656
657
658 PreParser::Statement PreParser::ParseSwitchStatement(bool* ok) {
659   // SwitchStatement ::
660   //   'switch' '(' Expression ')' '{' CaseClause* '}'
661
662   Expect(Token::SWITCH, CHECK_OK);
663   Expect(Token::LPAREN, CHECK_OK);
664   ParseExpression(true, CHECK_OK);
665   Expect(Token::RPAREN, CHECK_OK);
666
667   Expect(Token::LBRACE, CHECK_OK);
668   Token::Value token = peek();
669   while (token != Token::RBRACE) {
670     if (token == Token::CASE) {
671       Expect(Token::CASE, CHECK_OK);
672       ParseExpression(true, CHECK_OK);
673     } else {
674       Expect(Token::DEFAULT, CHECK_OK);
675     }
676     Expect(Token::COLON, CHECK_OK);
677     token = peek();
678     while (token != Token::CASE &&
679            token != Token::DEFAULT &&
680            token != Token::RBRACE) {
681       ParseStatement(CHECK_OK);
682       token = peek();
683     }
684   }
685   Expect(Token::RBRACE, ok);
686   return Statement::Default();
687 }
688
689
690 PreParser::Statement PreParser::ParseDoWhileStatement(bool* ok) {
691   // DoStatement ::
692   //   'do' Statement 'while' '(' Expression ')' ';'
693
694   Expect(Token::DO, CHECK_OK);
695   ParseSubStatement(CHECK_OK);
696   Expect(Token::WHILE, CHECK_OK);
697   Expect(Token::LPAREN, CHECK_OK);
698   ParseExpression(true, CHECK_OK);
699   Expect(Token::RPAREN, ok);
700   if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON);
701   return Statement::Default();
702 }
703
704
705 PreParser::Statement PreParser::ParseWhileStatement(bool* ok) {
706   // WhileStatement ::
707   //   'while' '(' Expression ')' Statement
708
709   Expect(Token::WHILE, CHECK_OK);
710   Expect(Token::LPAREN, CHECK_OK);
711   ParseExpression(true, CHECK_OK);
712   Expect(Token::RPAREN, CHECK_OK);
713   ParseSubStatement(ok);
714   return Statement::Default();
715 }
716
717
718 PreParser::Statement PreParser::ParseForStatement(bool* ok) {
719   // ForStatement ::
720   //   'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
721
722   Expect(Token::FOR, CHECK_OK);
723   Expect(Token::LPAREN, CHECK_OK);
724   bool is_let_identifier_expression = false;
725   if (peek() != Token::SEMICOLON) {
726     ForEachStatement::VisitMode visit_mode;
727     if (peek() == Token::VAR || peek() == Token::CONST ||
728         (peek() == Token::LET && is_strict(language_mode()))) {
729       bool is_lexical = peek() == Token::LET ||
730                         (peek() == Token::CONST && is_strict(language_mode()));
731       int decl_count;
732       VariableDeclarationProperties decl_props = kHasNoInitializers;
733       ParseVariableDeclarations(
734           kForStatement, &decl_props, &decl_count, CHECK_OK);
735       bool has_initializers = decl_props == kHasInitializers;
736       bool accept_IN = decl_count == 1 && !(is_lexical && has_initializers);
737       bool accept_OF = !has_initializers;
738       if (accept_IN && CheckInOrOf(accept_OF, &visit_mode, ok)) {
739         if (!*ok) return Statement::Default();
740         ParseExpression(true, CHECK_OK);
741         Expect(Token::RPAREN, CHECK_OK);
742         ParseSubStatement(CHECK_OK);
743         return Statement::Default();
744       }
745     } else {
746       Expression lhs = ParseExpression(false, CHECK_OK);
747       is_let_identifier_expression =
748           lhs.IsIdentifier() && lhs.AsIdentifier().IsLet();
749       if (CheckInOrOf(lhs.IsIdentifier(), &visit_mode, ok)) {
750         if (!*ok) return Statement::Default();
751         ParseExpression(true, CHECK_OK);
752         Expect(Token::RPAREN, CHECK_OK);
753         ParseSubStatement(CHECK_OK);
754         return Statement::Default();
755       }
756     }
757   }
758
759   // Parsed initializer at this point.
760   // Detect attempts at 'let' declarations in sloppy mode.
761   if (peek() == Token::IDENTIFIER && is_sloppy(language_mode()) &&
762       is_let_identifier_expression) {
763     ReportMessage("sloppy_lexical", NULL);
764     *ok = false;
765     return Statement::Default();
766   }
767   Expect(Token::SEMICOLON, CHECK_OK);
768
769   if (peek() != Token::SEMICOLON) {
770     ParseExpression(true, CHECK_OK);
771   }
772   Expect(Token::SEMICOLON, CHECK_OK);
773
774   if (peek() != Token::RPAREN) {
775     ParseExpression(true, CHECK_OK);
776   }
777   Expect(Token::RPAREN, CHECK_OK);
778
779   ParseSubStatement(ok);
780   return Statement::Default();
781 }
782
783
784 PreParser::Statement PreParser::ParseThrowStatement(bool* ok) {
785   // ThrowStatement ::
786   //   'throw' [no line terminator] Expression ';'
787
788   Expect(Token::THROW, CHECK_OK);
789   if (scanner()->HasAnyLineTerminatorBeforeNext()) {
790     ReportMessageAt(scanner()->location(), "newline_after_throw");
791     *ok = false;
792     return Statement::Default();
793   }
794   ParseExpression(true, CHECK_OK);
795   ExpectSemicolon(ok);
796   return Statement::Default();
797 }
798
799
800 PreParser::Statement PreParser::ParseTryStatement(bool* ok) {
801   // TryStatement ::
802   //   'try' Block Catch
803   //   'try' Block Finally
804   //   'try' Block Catch Finally
805   //
806   // Catch ::
807   //   'catch' '(' Identifier ')' Block
808   //
809   // Finally ::
810   //   'finally' Block
811
812   Expect(Token::TRY, CHECK_OK);
813
814   ParseBlock(CHECK_OK);
815
816   Token::Value tok = peek();
817   if (tok != Token::CATCH && tok != Token::FINALLY) {
818     ReportMessageAt(scanner()->location(), "no_catch_or_finally");
819     *ok = false;
820     return Statement::Default();
821   }
822   if (tok == Token::CATCH) {
823     Consume(Token::CATCH);
824     Expect(Token::LPAREN, CHECK_OK);
825     ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
826     Expect(Token::RPAREN, CHECK_OK);
827     {
828       Scope* with_scope = NewScope(scope_, WITH_SCOPE);
829       BlockState block_state(&scope_, with_scope);
830       ParseBlock(CHECK_OK);
831     }
832     tok = peek();
833   }
834   if (tok == Token::FINALLY) {
835     Consume(Token::FINALLY);
836     ParseBlock(CHECK_OK);
837   }
838   return Statement::Default();
839 }
840
841
842 PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) {
843   // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
844   // contexts this is used as a statement which invokes the debugger as if a
845   // break point is present.
846   // DebuggerStatement ::
847   //   'debugger' ';'
848
849   Expect(Token::DEBUGGER, CHECK_OK);
850   ExpectSemicolon(ok);
851   return Statement::Default();
852 }
853
854
855 #undef CHECK_OK
856 #define CHECK_OK  ok);                     \
857   if (!*ok) return Expression::Default();  \
858   ((void)0
859 #define DUMMY )  // to make indentation work
860 #undef DUMMY
861
862
863 PreParser::Expression PreParser::ParseFunctionLiteral(
864     Identifier function_name, Scanner::Location function_name_location,
865     bool name_is_strict_reserved, FunctionKind kind, int function_token_pos,
866     FunctionLiteral::FunctionType function_type,
867     FunctionLiteral::ArityRestriction arity_restriction, bool* ok) {
868   // Function ::
869   //   '(' FormalParameterList? ')' '{' FunctionBody '}'
870
871   // Parse function body.
872   bool outer_is_script_scope = scope_->is_script_scope();
873   Scope* function_scope = NewScope(scope_, FUNCTION_SCOPE);
874   PreParserFactory factory(NULL);
875   FunctionState function_state(&function_state_, &scope_, function_scope, kind,
876                                &factory);
877   //  FormalParameterList ::
878   //    '(' (Identifier)*[','] ')'
879   Expect(Token::LPAREN, CHECK_OK);
880   int start_position = position();
881   DuplicateFinder duplicate_finder(scanner()->unicode_cache());
882   // We don't yet know if the function will be strict, so we cannot yet produce
883   // errors for parameter names or duplicates. However, we remember the
884   // locations of these errors if they occur and produce the errors later.
885   Scanner::Location eval_args_error_loc = Scanner::Location::invalid();
886   Scanner::Location dupe_error_loc = Scanner::Location::invalid();
887   Scanner::Location reserved_error_loc = Scanner::Location::invalid();
888
889   bool is_rest = false;
890   bool done = arity_restriction == FunctionLiteral::GETTER_ARITY ||
891       (peek() == Token::RPAREN &&
892        arity_restriction != FunctionLiteral::SETTER_ARITY);
893   while (!done) {
894     bool is_strict_reserved = false;
895     is_rest = peek() == Token::ELLIPSIS && allow_harmony_rest_params();
896     if (is_rest) {
897       Consume(Token::ELLIPSIS);
898     }
899
900     Identifier param_name =
901         ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
902     if (!eval_args_error_loc.IsValid() && param_name.IsEvalOrArguments()) {
903       eval_args_error_loc = scanner()->location();
904     }
905     if (!reserved_error_loc.IsValid() && is_strict_reserved) {
906       reserved_error_loc = scanner()->location();
907     }
908
909     int prev_value = scanner()->FindSymbol(&duplicate_finder, 1);
910
911     if (!dupe_error_loc.IsValid() && prev_value != 0) {
912       dupe_error_loc = scanner()->location();
913     }
914
915     if (arity_restriction == FunctionLiteral::SETTER_ARITY) break;
916     done = (peek() == Token::RPAREN);
917     if (!done) {
918       if (is_rest) {
919         ReportMessageAt(scanner()->peek_location(), "param_after_rest");
920         *ok = false;
921         return Expression::Default();
922       }
923       Expect(Token::COMMA, CHECK_OK);
924     }
925   }
926   Expect(Token::RPAREN, CHECK_OK);
927
928   // See Parser::ParseFunctionLiteral for more information about lazy parsing
929   // and lazy compilation.
930   bool is_lazily_parsed =
931       (outer_is_script_scope && allow_lazy() && !parenthesized_function_);
932   parenthesized_function_ = false;
933
934   Expect(Token::LBRACE, CHECK_OK);
935   if (is_lazily_parsed) {
936     ParseLazyFunctionLiteralBody(CHECK_OK);
937   } else {
938     ParseStatementList(Token::RBRACE, CHECK_OK);
939   }
940   Expect(Token::RBRACE, CHECK_OK);
941
942   // Validate name and parameter names. We can do this only after parsing the
943   // function, since the function can declare itself strict.
944   CheckFunctionName(language_mode(), kind, function_name,
945                     name_is_strict_reserved, function_name_location, CHECK_OK);
946   const bool use_strict_params = is_rest || IsConciseMethod(kind);
947   CheckFunctionParameterNames(language_mode(), use_strict_params,
948                               eval_args_error_loc, dupe_error_loc,
949                               reserved_error_loc, CHECK_OK);
950
951   if (is_strict(language_mode())) {
952     int end_position = scanner()->location().end_pos;
953     CheckStrictOctalLiteral(start_position, end_position, CHECK_OK);
954   }
955
956   return Expression::Default();
957 }
958
959
960 void PreParser::ParseLazyFunctionLiteralBody(bool* ok) {
961   int body_start = position();
962   ParseStatementList(Token::RBRACE, ok);
963   if (!*ok) return;
964
965   // Position right after terminal '}'.
966   DCHECK_EQ(Token::RBRACE, scanner()->peek());
967   int body_end = scanner()->peek_location().end_pos;
968   log_->LogFunction(body_start, body_end,
969                     function_state_->materialized_literal_count(),
970                     function_state_->expected_property_count(), language_mode(),
971                     scope_->uses_super_property());
972 }
973
974
975 PreParserExpression PreParser::ParseClassLiteral(
976     PreParserIdentifier name, Scanner::Location class_name_location,
977     bool name_is_strict_reserved, int pos, bool* ok) {
978   // All parts of a ClassDeclaration and ClassExpression are strict code.
979   if (name_is_strict_reserved) {
980     ReportMessageAt(class_name_location, "unexpected_strict_reserved");
981     *ok = false;
982     return EmptyExpression();
983   }
984   if (IsEvalOrArguments(name)) {
985     ReportMessageAt(class_name_location, "strict_eval_arguments");
986     *ok = false;
987     return EmptyExpression();
988   }
989
990   Scope* scope = NewScope(scope_, BLOCK_SCOPE);
991   BlockState block_state(&scope_, scope);
992   scope_->SetLanguageMode(
993       static_cast<LanguageMode>(scope_->language_mode() | STRICT_BIT));
994   // TODO(marja): Make PreParser use scope names too.
995   // scope_->SetScopeName(name);
996
997   bool has_extends = Check(Token::EXTENDS);
998   if (has_extends) {
999     ParseLeftHandSideExpression(CHECK_OK);
1000   }
1001
1002   ClassLiteralChecker checker(this);
1003   bool has_seen_constructor = false;
1004
1005   Expect(Token::LBRACE, CHECK_OK);
1006   while (peek() != Token::RBRACE) {
1007     if (Check(Token::SEMICOLON)) continue;
1008     const bool in_class = true;
1009     const bool is_static = false;
1010     bool is_computed_name = false;  // Classes do not care about computed
1011                                     // property names here.
1012     ParsePropertyDefinition(&checker, in_class, has_extends, is_static,
1013                             &is_computed_name, &has_seen_constructor, CHECK_OK);
1014   }
1015
1016   Expect(Token::RBRACE, CHECK_OK);
1017
1018   return Expression::Default();
1019 }
1020
1021
1022 PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) {
1023   // CallRuntime ::
1024   //   '%' Identifier Arguments
1025   Expect(Token::MOD, CHECK_OK);
1026   if (!allow_natives()) {
1027     *ok = false;
1028     return Expression::Default();
1029   }
1030   // Allow "eval" or "arguments" for backward compatibility.
1031   ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
1032   ParseArguments(ok);
1033
1034   return Expression::Default();
1035 }
1036
1037 #undef CHECK_OK
1038
1039
1040 } }  // v8::internal