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