preparser.cc 31.9 KB
Newer Older
1
// Copyright 2011 the V8 project authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be
// 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 12 13 14
#include "src/globals.h"
#include "src/hashmap.h"
#include "src/list.h"
#include "src/preparse-data.h"
15
#include "src/preparse-data-format.h"
16 17 18
#include "src/preparser.h"
#include "src/unicode.h"
#include "src/utils.h"
19

20
namespace v8 {
21
namespace internal {
22

23 24
void PreParserTraits::ReportMessageAt(Scanner::Location location,
                                      const char* message,
25
                                      const char* arg,
26
                                      bool is_reference_error) {
27 28 29
  ReportMessageAt(location.beg_pos,
                  location.end_pos,
                  message,
30
                  arg,
31
                  is_reference_error);
32 33 34 35 36
}


void PreParserTraits::ReportMessageAt(int start_pos,
                                      int end_pos,
37 38
                                      const char* message,
                                      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 47 48 49 50
  if (scanner->current_token() == Token::FUTURE_RESERVED_WORD) {
    return PreParserIdentifier::FutureReserved();
  } else if (scanner->current_token() ==
             Token::FUTURE_STRICT_RESERVED_WORD) {
    return PreParserIdentifier::FutureStrictReserved();
51 52
  } else if (scanner->current_token() == Token::LET) {
    return PreParserIdentifier::Let();
53 54
  } else if (scanner->current_token() == Token::STATIC) {
    return PreParserIdentifier::Static();
55 56 57
  } else if (scanner->current_token() == Token::YIELD) {
    return PreParserIdentifier::Yield();
  }
58 59 60 61 62
  if (scanner->UnescapedLiteralMatches("eval", 4)) {
    return PreParserIdentifier::Eval();
  }
  if (scanner->UnescapedLiteralMatches("arguments", 9)) {
    return PreParserIdentifier::Arguments();
63
  }
64
  if (scanner->LiteralMatches("prototype", 9)) {
arv@chromium.org's avatar
arv@chromium.org committed
65 66
    return PreParserIdentifier::Prototype();
  }
67
  if (scanner->LiteralMatches("constructor", 11)) {
arv@chromium.org's avatar
arv@chromium.org committed
68 69
    return PreParserIdentifier::Constructor();
  }
70 71 72 73
  return PreParserIdentifier::Default();
}


74 75 76 77 78
PreParserIdentifier PreParserTraits::GetNumberAsSymbol(Scanner* scanner) {
  return PreParserIdentifier::Default();
}


79 80
PreParserExpression PreParserTraits::ExpressionFromString(
    int pos, Scanner* scanner, PreParserFactory* factory) {
81
  if (scanner->UnescapedLiteralMatches("use strict", 10)) {
82 83 84 85 86 87 88 89 90 91 92
    return PreParserExpression::UseStrictStringLiteral();
  }
  return PreParserExpression::StringLiteral();
}


PreParserExpression PreParserTraits::ParseV8Intrinsic(bool* ok) {
  return pre_parser_->ParseV8Intrinsic(ok);
}


93
PreParserExpression PreParserTraits::ParseFunctionLiteral(
94 95 96 97
    PreParserIdentifier name, Scanner::Location function_name_location,
    bool name_is_strict_reserved, FunctionKind kind,
    int function_token_position, FunctionLiteral::FunctionType type,
    FunctionLiteral::ArityRestriction arity_restriction, bool* ok) {
98
  return pre_parser_->ParseFunctionLiteral(
99
      name, function_name_location, name_is_strict_reserved, kind,
100
      function_token_position, type, arity_restriction, ok);
101 102 103
}


104
PreParser::PreParseResult PreParser::PreParseLazyFunction(
105
    StrictMode strict_mode, bool is_generator, ParserRecorder* log) {
106 107
  log_ = log;
  // Lazy functions always have trivial outer scopes (no with/catch scopes).
108
  PreParserScope top_scope(scope_, SCRIPT_SCOPE);
109
  PreParserFactory top_factory(NULL);
110
  FunctionState top_state(&function_state_, &scope_, &top_scope, &top_factory);
111
  scope_->SetStrictMode(strict_mode);
112
  PreParserScope function_scope(scope_, FUNCTION_SCOPE);
113
  PreParserFactory function_factory(NULL);
114 115
  FunctionState function_state(&function_state_, &scope_, &function_scope,
                               &function_factory);
116
  function_state.set_is_generator(is_generator);
117
  DCHECK_EQ(Token::LBRACE, scanner()->current_token());
118
  bool ok = true;
119
  int start_position = peek_position();
120
  ParseLazyFunctionLiteralBody(&ok);
121
  if (stack_overflow()) return kPreParseStackOverflow;
122
  if (!ok) {
123
    ReportUnexpectedToken(scanner()->current_token());
124
  } else {
125
    DCHECK_EQ(Token::RBRACE, scanner()->peek());
126
    if (scope_->strict_mode() == STRICT) {
127
      int end_pos = scanner()->location().end_pos;
128
      CheckStrictOctalLiteral(start_position, end_pos, &ok);
129 130 131 132 133 134
    }
  }
  return kPreParseSuccess;
}


135 136 137 138 139 140 141 142
PreParserExpression PreParserTraits::ParseClassLiteral(
    PreParserIdentifier name, Scanner::Location class_name_location,
    bool name_is_strict_reserved, int pos, bool* ok) {
  return pre_parser_->ParseClassLiteral(name, class_name_location,
                                        name_is_strict_reserved, pos, ok);
}


143 144 145 146 147 148 149 150 151 152 153 154 155 156
// Preparsing checks a JavaScript program and emits preparse-data that helps
// a later parsing to be faster.
// See preparser-data.h for the data.

// The PreParser checks that the syntax follows the grammar for JavaScript,
// and collects some information about the program along the way.
// The grammar check is only performed in order to understand the program
// sufficiently to deduce some information about it, that can be used
// to speed up later parsing. Finding errors is not the goal of pre-parsing,
// rather it is to speed up properly written and correct programs.
// That means that contextual checks (like a label being declared where
// it is used) are generally omitted.


157 158 159 160 161 162 163
#define CHECK_OK  ok);                      \
  if (!*ok) return kUnknownSourceElements;  \
  ((void)0
#define DUMMY )  // to make indentation work
#undef DUMMY


164
PreParser::Statement PreParser::ParseSourceElement(bool* ok) {
165 166 167 168 169 170 171 172
  // (Ecma 262 5th Edition, clause 14):
  // SourceElement:
  //    Statement
  //    FunctionDeclaration
  //
  // In harmony mode we allow additionally the following productions
  // SourceElement:
  //    LetDeclaration
173
  //    ConstDeclaration
174
  //    GeneratorDeclaration
175

176
  switch (peek()) {
177
    case Token::FUNCTION:
178
      return ParseFunctionDeclaration(ok);
arv@chromium.org's avatar
arv@chromium.org committed
179 180
    case Token::CLASS:
      return ParseClassDeclaration(ok);
181
    case Token::CONST:
182
      return ParseVariableStatement(kSourceElement, ok);
183
    case Token::LET:
184
      DCHECK(allow_harmony_scoping());
185 186 187 188
      if (strict_mode() == STRICT) {
        return ParseVariableStatement(kSourceElement, ok);
      }
      // Fall through.
189 190 191 192 193 194
    default:
      return ParseStatement(ok);
  }
}


195 196
PreParser::SourceElements PreParser::ParseSourceElements(int end_token,
                                                         bool* ok) {
197 198 199
  // SourceElements ::
  //   (Statement)* <end_token>

200
  bool directive_prologue = true;
201
  while (peek() != end_token) {
202 203 204
    if (directive_prologue && peek() != Token::STRING) {
      directive_prologue = false;
    }
205
    Statement statement = ParseSourceElement(CHECK_OK);
206
    if (directive_prologue) {
207
      if (statement.IsUseStrictLiteral()) {
208
        scope_->SetStrictMode(STRICT);
209
      } else if (!statement.IsStringLiteral()) {
210
        directive_prologue = false;
211 212
      }
    }
213 214 215 216 217
  }
  return kUnknownSourceElements;
}


218 219 220 221 222 223 224 225
#undef CHECK_OK
#define CHECK_OK  ok);                   \
  if (!*ok) return Statement::Default();  \
  ((void)0
#define DUMMY )  // to make indentation work
#undef DUMMY


ager@chromium.org's avatar
ager@chromium.org committed
226
PreParser::Statement PreParser::ParseStatement(bool* ok) {
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
  // Statement ::
  //   Block
  //   VariableStatement
  //   EmptyStatement
  //   ExpressionStatement
  //   IfStatement
  //   IterationStatement
  //   ContinueStatement
  //   BreakStatement
  //   ReturnStatement
  //   WithStatement
  //   LabelledStatement
  //   SwitchStatement
  //   ThrowStatement
  //   TryStatement
  //   DebuggerStatement

  // Note: Since labels can only be used by 'break' and 'continue'
  // statements, which themselves are only valid within blocks,
  // iterations or 'switch' statements (i.e., BreakableStatements),
  // labels can be simply ignored in all other cases; except for
  // trivial labeled break statements 'label: break label' which is
  // parsed into an empty statement.

  // Keep the source position of the statement
  switch (peek()) {
253
    case Token::LBRACE:
254 255
      return ParseBlock(ok);

256
    case Token::SEMICOLON:
257
      Next();
258
      return Statement::Default();
259

260
    case Token::IF:
261
      return ParseIfStatement(ok);
262

263
    case Token::DO:
264 265
      return ParseDoWhileStatement(ok);

266
    case Token::WHILE:
267 268
      return ParseWhileStatement(ok);

269
    case Token::FOR:
270 271
      return ParseForStatement(ok);

272
    case Token::CONTINUE:
273 274
      return ParseContinueStatement(ok);

275
    case Token::BREAK:
276 277
      return ParseBreakStatement(ok);

278
    case Token::RETURN:
279 280
      return ParseReturnStatement(ok);

281
    case Token::WITH:
282 283
      return ParseWithStatement(ok);

284
    case Token::SWITCH:
285 286
      return ParseSwitchStatement(ok);

287
    case Token::THROW:
288 289
      return ParseThrowStatement(ok);

290
    case Token::TRY:
291 292
      return ParseTryStatement(ok);

293 294
    case Token::FUNCTION: {
      Scanner::Location start_location = scanner()->peek_location();
295
      Statement statement = ParseFunctionDeclaration(CHECK_OK);
296
      Scanner::Location end_location = scanner()->location();
297
      if (strict_mode() == STRICT) {
298 299
        PreParserTraits::ReportMessageAt(start_location.beg_pos,
                                         end_location.end_pos,
300
                                         "strict_function");
301 302 303 304 305 306
        *ok = false;
        return Statement::Default();
      } else {
        return statement;
      }
    }
307

arv@chromium.org's avatar
arv@chromium.org committed
308 309 310
    case Token::CLASS:
      return ParseClassDeclaration(CHECK_OK);

311
    case Token::DEBUGGER:
312 313
      return ParseDebuggerStatement(ok);

314 315 316 317 318
    case Token::VAR:
    case Token::CONST:
      return ParseVariableStatement(kStatement, ok);

    case Token::LET:
319
      DCHECK(allow_harmony_scoping());
320 321 322 323
      if (strict_mode() == STRICT) {
        return ParseVariableStatement(kStatement, ok);
      }
      // Fall through.
324 325 326 327 328 329
    default:
      return ParseExpressionOrLabelledStatement(ok);
  }
}


330
PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
331 332
  // FunctionDeclaration ::
  //   'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
333 334 335
  // GeneratorDeclaration ::
  //   'function' '*' Identifier '(' FormalParameterListopt ')'
  //      '{' FunctionBody '}'
336
  Expect(Token::FUNCTION, CHECK_OK);
337
  int pos = position();
wingo@igalia.com's avatar
wingo@igalia.com committed
338
  bool is_generator = Check(Token::MUL);
339 340 341
  bool is_strict_reserved = false;
  Identifier name = ParseIdentifierOrStrictReservedWord(
      &is_strict_reserved, CHECK_OK);
342 343 344 345 346
  ParseFunctionLiteral(name, scanner()->location(), is_strict_reserved,
                       is_generator ? FunctionKind::kGeneratorFunction
                                    : FunctionKind::kNormalFunction,
                       pos, FunctionLiteral::DECLARATION,
                       FunctionLiteral::NORMAL_ARITY, CHECK_OK);
347
  return Statement::FunctionDeclaration();
348 349 350
}


arv@chromium.org's avatar
arv@chromium.org committed
351 352
PreParser::Statement PreParser::ParseClassDeclaration(bool* ok) {
  Expect(Token::CLASS, CHECK_OK);
353 354 355 356 357 358
  if (!allow_harmony_sloppy() && strict_mode() == SLOPPY) {
    ReportMessage("sloppy_lexical");
    *ok = false;
    return Statement::Default();
  }

arv@chromium.org's avatar
arv@chromium.org committed
359 360 361 362 363 364 365 366 367 368
  int pos = position();
  bool is_strict_reserved = false;
  Identifier name =
      ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
  ParseClassLiteral(name, scanner()->location(), is_strict_reserved, pos,
                    CHECK_OK);
  return Statement::Default();
}


369
PreParser::Statement PreParser::ParseBlock(bool* ok) {
370 371 372 373 374 375
  // Block ::
  //   '{' Statement* '}'

  // Note that a Block does not introduce a new execution scope!
  // (ECMA-262, 3rd, 12.2)
  //
376 377
  Expect(Token::LBRACE, CHECK_OK);
  while (peek() != Token::RBRACE) {
378
    if (allow_harmony_scoping() && strict_mode() == STRICT) {
379 380 381
      ParseSourceElement(CHECK_OK);
    } else {
      ParseStatement(CHECK_OK);
382
    }
383
  }
384
  Expect(Token::RBRACE, ok);
385
  return Statement::Default();
386 387 388
}


389 390 391
PreParser::Statement PreParser::ParseVariableStatement(
    VariableDeclarationContext var_context,
    bool* ok) {
392 393 394
  // VariableStatement ::
  //   VariableDeclarations ';'

395
  Statement result = ParseVariableDeclarations(var_context,
396
                                               NULL,
397 398
                                               NULL,
                                               CHECK_OK);
399 400 401 402 403 404 405 406 407 408
  ExpectSemicolon(CHECK_OK);
  return result;
}


// If the variable declaration declares exactly one non-const
// variable, then *var is set to that variable. In all other cases,
// *var is untouched; in particular, it is the caller's responsibility
// to initialize it properly. This mechanism is also used for the parsing
// of 'for-in' loops.
409 410
PreParser::Statement PreParser::ParseVariableDeclarations(
    VariableDeclarationContext var_context,
411
    VariableDeclarationProperties* decl_props,
412 413
    int* num_decl,
    bool* ok) {
414 415
  // VariableDeclarations ::
  //   ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[',']
416 417 418 419 420 421 422 423 424 425 426 427
  //
  // The ES6 Draft Rev3 specifies the following grammar for const declarations
  //
  // ConstDeclaration ::
  //   const ConstBinding (',' ConstBinding)* ';'
  // ConstBinding ::
  //   Identifier '=' AssignmentExpression
  //
  // TODO(ES6):
  // ConstBinding ::
  //   BindingPattern '=' AssignmentExpression
  bool require_initializer = false;
428
  bool is_strict_const = false;
429 430 431
  if (peek() == Token::VAR) {
    Consume(Token::VAR);
  } else if (peek() == Token::CONST) {
432 433 434 435 436 437 438
    // TODO(ES6): The ES6 Draft Rev4 section 12.2.2 reads:
    //
    // ConstDeclaration : const ConstBinding (',' ConstBinding)* ';'
    //
    // * It is a Syntax Error if the code that matches this production is not
    //   contained in extended code.
    //
439
    // However disallowing const in sloppy mode will break compatibility with
440
    // existing pages. Therefore we keep allowing const with the old
441
    // non-harmony semantics in sloppy mode.
442
    Consume(Token::CONST);
443
    if (strict_mode() == STRICT) {
444
      if (allow_harmony_scoping()) {
445
        if (var_context != kSourceElement && var_context != kForStatement) {
446
          ReportMessageAt(scanner()->peek_location(), "unprotected_const");
447 448 449
          *ok = false;
          return Statement::Default();
        }
450 451
        is_strict_const = true;
        require_initializer = var_context != kForStatement;
452 453 454 455 456 457
      } else {
        Scanner::Location location = scanner()->peek_location();
        ReportMessageAt(location, "strict_const");
        *ok = false;
        return Statement::Default();
      }
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 464 465
      *ok = false;
      return Statement::Default();
    }
466 467
  } else {
    *ok = false;
468
    return Statement::Default();
469 470
  }

471 472 473 474
  // The scope of a var/const declared variable anywhere inside a function
  // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). The scope
  // of a let declared variable is the scope of the immediately enclosing
  // block.
475 476 477
  int nvars = 0;  // the number of variables declared
  do {
    // Parse variable name.
478
    if (nvars > 0) Consume(Token::COMMA);
479
    ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
480
    nvars++;
481 482 483
    if (peek() == Token::ASSIGN || require_initializer ||
        // require initializers for multiple consts.
        (is_strict_const && peek() == Token::COMMA)) {
484
      Expect(Token::ASSIGN, CHECK_OK);
485
      ParseAssignmentExpression(var_context != kForStatement, CHECK_OK);
486
      if (decl_props != NULL) *decl_props = kHasInitializers;
487
    }
488
  } while (peek() == Token::COMMA);
489 490

  if (num_decl != NULL) *num_decl = nvars;
491
  return Statement::Default();
492 493 494
}


495
PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) {
496 497 498 499
  // ExpressionStatement | LabelledStatement ::
  //   Expression ';'
  //   Identifier ':' Statement

500
  bool starts_with_identifier = peek_any_identifier();
501
  Expression expr = ParseExpression(true, CHECK_OK);
502 503 504 505 506 507
  // Even if the expression starts with an identifier, it is not necessarily an
  // identifier. For example, "foo + bar" starts with an identifier but is not
  // an identifier.
  if (starts_with_identifier && expr.IsIdentifier() && peek() == Token::COLON) {
    // Expression is a single identifier, and not, e.g., a parenthesized
    // identifier.
508 509
    DCHECK(!expr.AsIdentifier().IsFutureReserved());
    DCHECK(strict_mode() == SLOPPY ||
510
           !IsFutureStrictReserved(expr.AsIdentifier()));
511 512
    Consume(Token::COLON);
    return ParseStatement(ok);
513 514 515
    // Preparsing is disabled for extensions (because the extension details
    // aren't passed to lazily compiled functions), so we don't
    // accept "native function" in the preparser.
516 517
  }
  // Parsed expression statement.
518 519 520
  // Detect attempts at 'let' declarations in sloppy mode.
  if (peek() == Token::IDENTIFIER && strict_mode() == SLOPPY &&
      expr.IsIdentifier() && expr.AsIdentifier().IsLet()) {
521
    ReportMessage("sloppy_lexical", NULL);
522 523 524
    *ok = false;
    return Statement::Default();
  }
525
  ExpectSemicolon(CHECK_OK);
526
  return Statement::ExpressionStatement(expr);
527 528 529
}


530
PreParser::Statement PreParser::ParseIfStatement(bool* ok) {
531 532 533
  // IfStatement ::
  //   'if' '(' Expression ')' Statement ('else' Statement)?

534 535
  Expect(Token::IF, CHECK_OK);
  Expect(Token::LPAREN, CHECK_OK);
536
  ParseExpression(true, CHECK_OK);
537
  Expect(Token::RPAREN, CHECK_OK);
538
  ParseStatement(CHECK_OK);
539
  if (peek() == Token::ELSE) {
540 541 542
    Next();
    ParseStatement(CHECK_OK);
  }
543
  return Statement::Default();
544 545 546
}


547
PreParser::Statement PreParser::ParseContinueStatement(bool* ok) {
548 549 550
  // ContinueStatement ::
  //   'continue' [no line terminator] Identifier? ';'

551 552
  Expect(Token::CONTINUE, CHECK_OK);
  Token::Value tok = peek();
553
  if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
554 555 556
      tok != Token::SEMICOLON &&
      tok != Token::RBRACE &&
      tok != Token::EOS) {
557 558
    // ECMA allows "eval" or "arguments" as labels even in strict mode.
    ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
559 560
  }
  ExpectSemicolon(CHECK_OK);
561
  return Statement::Default();
562 563 564
}


565
PreParser::Statement PreParser::ParseBreakStatement(bool* ok) {
566 567 568
  // BreakStatement ::
  //   'break' [no line terminator] Identifier? ';'

569 570
  Expect(Token::BREAK, CHECK_OK);
  Token::Value tok = peek();
571
  if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
572 573 574
      tok != Token::SEMICOLON &&
      tok != Token::RBRACE &&
      tok != Token::EOS) {
575 576
    // ECMA allows "eval" or "arguments" as labels even in strict mode.
    ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
577 578
  }
  ExpectSemicolon(CHECK_OK);
579
  return Statement::Default();
580 581 582
}


583
PreParser::Statement PreParser::ParseReturnStatement(bool* ok) {
584 585 586
  // ReturnStatement ::
  //   'return' [no line terminator] Expression? ';'

587
  // Consume the return token. It is necessary to do before
588 589
  // reporting any errors on it, because of the way errors are
  // reported (underlining).
590
  Expect(Token::RETURN, CHECK_OK);
591 592 593 594 595 596

  // An ECMAScript program is considered syntactically incorrect if it
  // contains a return statement that is not within the body of a
  // function. See ECMA-262, section 12.9, page 67.
  // This is not handled during preparsing.

597
  Token::Value tok = peek();
598
  if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
599 600 601
      tok != Token::SEMICOLON &&
      tok != Token::RBRACE &&
      tok != Token::EOS) {
602 603 604
    ParseExpression(true, CHECK_OK);
  }
  ExpectSemicolon(CHECK_OK);
605
  return Statement::Default();
606 607 608
}


609
PreParser::Statement PreParser::ParseWithStatement(bool* ok) {
610 611
  // WithStatement ::
  //   'with' '(' Expression ')' Statement
612
  Expect(Token::WITH, CHECK_OK);
613
  if (strict_mode() == STRICT) {
614
    ReportMessageAt(scanner()->location(), "strict_mode_with");
615 616 617
    *ok = false;
    return Statement::Default();
  }
618
  Expect(Token::LPAREN, CHECK_OK);
619
  ParseExpression(true, CHECK_OK);
620
  Expect(Token::RPAREN, CHECK_OK);
621

622 623
  PreParserScope with_scope(scope_, WITH_SCOPE);
  BlockState block_state(&scope_, &with_scope);
624
  ParseStatement(CHECK_OK);
625
  return Statement::Default();
626 627 628
}


629
PreParser::Statement PreParser::ParseSwitchStatement(bool* ok) {
630 631 632
  // SwitchStatement ::
  //   'switch' '(' Expression ')' '{' CaseClause* '}'

633 634
  Expect(Token::SWITCH, CHECK_OK);
  Expect(Token::LPAREN, CHECK_OK);
635
  ParseExpression(true, CHECK_OK);
636
  Expect(Token::RPAREN, CHECK_OK);
637

638 639 640 641 642
  Expect(Token::LBRACE, CHECK_OK);
  Token::Value token = peek();
  while (token != Token::RBRACE) {
    if (token == Token::CASE) {
      Expect(Token::CASE, CHECK_OK);
643 644
      ParseExpression(true, CHECK_OK);
    } else {
645
      Expect(Token::DEFAULT, CHECK_OK);
646
    }
647
    Expect(Token::COLON, CHECK_OK);
648
    token = peek();
649 650 651
    while (token != Token::CASE &&
           token != Token::DEFAULT &&
           token != Token::RBRACE) {
652 653 654
      ParseStatement(CHECK_OK);
      token = peek();
    }
655
  }
656
  Expect(Token::RBRACE, ok);
657
  return Statement::Default();
658 659 660
}


661
PreParser::Statement PreParser::ParseDoWhileStatement(bool* ok) {
662 663 664
  // DoStatement ::
  //   'do' Statement 'while' '(' Expression ')' ';'

665
  Expect(Token::DO, CHECK_OK);
666
  ParseStatement(CHECK_OK);
667 668
  Expect(Token::WHILE, CHECK_OK);
  Expect(Token::LPAREN, CHECK_OK);
669
  ParseExpression(true, CHECK_OK);
670 671
  Expect(Token::RPAREN, ok);
  if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON);
672
  return Statement::Default();
673 674 675
}


676
PreParser::Statement PreParser::ParseWhileStatement(bool* ok) {
677 678 679
  // WhileStatement ::
  //   'while' '(' Expression ')' Statement

680 681
  Expect(Token::WHILE, CHECK_OK);
  Expect(Token::LPAREN, CHECK_OK);
682
  ParseExpression(true, CHECK_OK);
683
  Expect(Token::RPAREN, CHECK_OK);
684 685
  ParseStatement(ok);
  return Statement::Default();
686 687 688
}


689
bool PreParser::CheckInOrOf(bool accept_OF) {
690
  if (Check(Token::IN) ||
691
      (accept_OF && CheckContextualKeyword(CStrVector("of")))) {
692 693 694 695 696 697
    return true;
  }
  return false;
}


698
PreParser::Statement PreParser::ParseForStatement(bool* ok) {
699 700 701
  // ForStatement ::
  //   'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement

702 703
  Expect(Token::FOR, CHECK_OK);
  Expect(Token::LPAREN, CHECK_OK);
704
  bool is_let_identifier_expression = false;
705 706
  if (peek() != Token::SEMICOLON) {
    if (peek() == Token::VAR || peek() == Token::CONST ||
707
        (peek() == Token::LET && strict_mode() == STRICT)) {
708 709
      bool is_lexical = peek() == Token::LET ||
                        (peek() == Token::CONST && strict_mode() == STRICT);
710
      int decl_count;
711 712 713
      VariableDeclarationProperties decl_props = kHasNoInitializers;
      ParseVariableDeclarations(
          kForStatement, &decl_props, &decl_count, CHECK_OK);
714
      bool has_initializers = decl_props == kHasInitializers;
715
      bool accept_IN = decl_count == 1 && !(is_lexical && has_initializers);
716 717
      bool accept_OF = !has_initializers;
      if (accept_IN && CheckInOrOf(accept_OF)) {
718
        ParseExpression(true, CHECK_OK);
719
        Expect(Token::RPAREN, CHECK_OK);
720 721

        ParseStatement(CHECK_OK);
722
        return Statement::Default();
723 724
      }
    } else {
725
      Expression lhs = ParseExpression(false, CHECK_OK);
726 727
      is_let_identifier_expression =
          lhs.IsIdentifier() && lhs.AsIdentifier().IsLet();
728
      if (CheckInOrOf(lhs.IsIdentifier())) {
729
        ParseExpression(true, CHECK_OK);
730
        Expect(Token::RPAREN, CHECK_OK);
731 732

        ParseStatement(CHECK_OK);
733
        return Statement::Default();
734 735 736 737 738
      }
    }
  }

  // Parsed initializer at this point.
739 740 741
  // Detect attempts at 'let' declarations in sloppy mode.
  if (peek() == Token::IDENTIFIER && strict_mode() == SLOPPY &&
      is_let_identifier_expression) {
742
    ReportMessage("sloppy_lexical", NULL);
743 744 745
    *ok = false;
    return Statement::Default();
  }
746
  Expect(Token::SEMICOLON, CHECK_OK);
747

748
  if (peek() != Token::SEMICOLON) {
749 750
    ParseExpression(true, CHECK_OK);
  }
751
  Expect(Token::SEMICOLON, CHECK_OK);
752

753
  if (peek() != Token::RPAREN) {
754 755
    ParseExpression(true, CHECK_OK);
  }
756
  Expect(Token::RPAREN, CHECK_OK);
757

758 759
  ParseStatement(ok);
  return Statement::Default();
760 761 762
}


763
PreParser::Statement PreParser::ParseThrowStatement(bool* ok) {
764 765 766
  // ThrowStatement ::
  //   'throw' [no line terminator] Expression ';'

767
  Expect(Token::THROW, CHECK_OK);
768
  if (scanner()->HasAnyLineTerminatorBeforeNext()) {
769
    ReportMessageAt(scanner()->location(), "newline_after_throw");
770
    *ok = false;
771
    return Statement::Default();
772 773
  }
  ParseExpression(true, CHECK_OK);
774 775
  ExpectSemicolon(ok);
  return Statement::Default();
776 777 778
}


779
PreParser::Statement PreParser::ParseTryStatement(bool* ok) {
780 781 782 783 784 785 786 787 788 789 790
  // TryStatement ::
  //   'try' Block Catch
  //   'try' Block Finally
  //   'try' Block Catch Finally
  //
  // Catch ::
  //   'catch' '(' Identifier ')' Block
  //
  // Finally ::
  //   'finally' Block

791
  Expect(Token::TRY, CHECK_OK);
792 793 794

  ParseBlock(CHECK_OK);

795 796
  Token::Value tok = peek();
  if (tok != Token::CATCH && tok != Token::FINALLY) {
797
    ReportMessageAt(scanner()->location(), "no_catch_or_finally");
798 799 800 801
    *ok = false;
    return Statement::Default();
  }
  if (tok == Token::CATCH) {
802 803
    Consume(Token::CATCH);
    Expect(Token::LPAREN, CHECK_OK);
804
    ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
805
    Expect(Token::RPAREN, CHECK_OK);
806
    {
807 808
      PreParserScope with_scope(scope_, WITH_SCOPE);
      BlockState block_state(&scope_, &with_scope);
809 810
      ParseBlock(CHECK_OK);
    }
811
    tok = peek();
812
  }
813
  if (tok == Token::FINALLY) {
814
    Consume(Token::FINALLY);
815 816
    ParseBlock(CHECK_OK);
  }
817
  return Statement::Default();
818 819 820
}


821
PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) {
822 823 824 825 826 827
  // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
  // contexts this is used as a statement which invokes the debugger as if a
  // break point is present.
  // DebuggerStatement ::
  //   'debugger' ';'

828
  Expect(Token::DEBUGGER, CHECK_OK);
829 830
  ExpectSemicolon(ok);
  return Statement::Default();
831 832 833
}


834 835 836 837 838 839 840 841
#undef CHECK_OK
#define CHECK_OK  ok);                     \
  if (!*ok) return Expression::Default();  \
  ((void)0
#define DUMMY )  // to make indentation work
#undef DUMMY


842
PreParser::Expression PreParser::ParseFunctionLiteral(
843 844
    Identifier function_name, Scanner::Location function_name_location,
    bool name_is_strict_reserved, FunctionKind kind, int function_token_pos,
845
    FunctionLiteral::FunctionType function_type,
846
    FunctionLiteral::ArityRestriction arity_restriction, bool* ok) {
847 848 849 850 851
  // Function ::
  //   '(' FormalParameterList? ')' '{' FunctionBody '}'

  // Parse function body.
  ScopeType outer_scope_type = scope_->type();
852
  PreParserScope function_scope(scope_, FUNCTION_SCOPE);
853
  PreParserFactory factory(NULL);
854 855
  FunctionState function_state(&function_state_, &scope_, &function_scope,
                               &factory);
856
  function_state.set_is_generator(IsGeneratorFunction(kind));
857 858
  //  FormalParameterList ::
  //    '(' (Identifier)*[','] ')'
859
  Expect(Token::LPAREN, CHECK_OK);
860
  int start_position = position();
861
  DuplicateFinder duplicate_finder(scanner()->unicode_cache());
862 863 864 865 866 867
  // We don't yet know if the function will be strict, so we cannot yet produce
  // errors for parameter names or duplicates. However, we remember the
  // locations of these errors if they occur and produce the errors later.
  Scanner::Location eval_args_error_loc = Scanner::Location::invalid();
  Scanner::Location dupe_error_loc = Scanner::Location::invalid();
  Scanner::Location reserved_error_loc = Scanner::Location::invalid();
868 869 870 871

  bool done = arity_restriction == FunctionLiteral::GETTER_ARITY ||
      (peek() == Token::RPAREN &&
       arity_restriction != FunctionLiteral::SETTER_ARITY);
872
  while (!done) {
873 874 875 876 877 878 879 880 881 882
    bool is_strict_reserved = false;
    Identifier param_name =
        ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
    if (!eval_args_error_loc.IsValid() && param_name.IsEvalOrArguments()) {
      eval_args_error_loc = scanner()->location();
    }
    if (!reserved_error_loc.IsValid() && is_strict_reserved) {
      reserved_error_loc = scanner()->location();
    }

883
    int prev_value = scanner()->FindSymbol(&duplicate_finder, 1);
884

885 886
    if (!dupe_error_loc.IsValid() && prev_value != 0) {
      dupe_error_loc = scanner()->location();
887
    }
888

889
    if (arity_restriction == FunctionLiteral::SETTER_ARITY) break;
890
    done = (peek() == Token::RPAREN);
891
    if (!done) Expect(Token::COMMA, CHECK_OK);
892
  }
893
  Expect(Token::RPAREN, CHECK_OK);
894

895 896
  // See Parser::ParseFunctionLiteral for more information about lazy parsing
  // and lazy compilation.
897
  bool is_lazily_parsed = (outer_scope_type == SCRIPT_SCOPE && allow_lazy() &&
898
                           !parenthesized_function_);
899
  parenthesized_function_ = false;
900

901
  Expect(Token::LBRACE, CHECK_OK);
902
  if (is_lazily_parsed) {
903
    ParseLazyFunctionLiteralBody(CHECK_OK);
904
  } else {
905
    ParseSourceElements(Token::RBRACE, ok);
906
  }
907
  Expect(Token::RBRACE, CHECK_OK);
908

909 910
  // Validate strict mode. We can do this only after parsing the function,
  // since the function can declare itself strict.
911 912
  // Concise methods use StrictFormalParameters.
  if (strict_mode() == STRICT || IsConciseMethod(kind)) {
913
    if (function_name.IsEvalOrArguments()) {
914
      ReportMessageAt(function_name_location, "strict_eval_arguments");
915 916 917 918
      *ok = false;
      return Expression::Default();
    }
    if (name_is_strict_reserved) {
919
      ReportMessageAt(function_name_location, "unexpected_strict_reserved");
920 921 922
      *ok = false;
      return Expression::Default();
    }
923
    if (eval_args_error_loc.IsValid()) {
924
      ReportMessageAt(eval_args_error_loc, "strict_eval_arguments");
925 926 927 928
      *ok = false;
      return Expression::Default();
    }
    if (dupe_error_loc.IsValid()) {
929
      ReportMessageAt(dupe_error_loc, "strict_param_dupe");
930 931 932 933
      *ok = false;
      return Expression::Default();
    }
    if (reserved_error_loc.IsValid()) {
934
      ReportMessageAt(reserved_error_loc, "unexpected_strict_reserved");
935 936 937
      *ok = false;
      return Expression::Default();
    }
938

939
    int end_position = scanner()->location().end_pos;
940
    CheckStrictOctalLiteral(start_position, end_position, CHECK_OK);
941 942
  }

943
  return Expression::Default();
944 945 946
}


947
void PreParser::ParseLazyFunctionLiteralBody(bool* ok) {
948
  int body_start = position();
949
  ParseSourceElements(Token::RBRACE, ok);
950 951 952
  if (!*ok) return;

  // Position right after terminal '}'.
953
  DCHECK_EQ(Token::RBRACE, scanner()->peek());
954
  int body_end = scanner()->peek_location().end_pos;
955
  log_->LogFunction(body_start, body_end,
956
                    function_state_->materialized_literal_count(),
957
                    function_state_->expected_property_count(),
958
                    strict_mode());
959 960 961
}


962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992
PreParserExpression PreParser::ParseClassLiteral(
    PreParserIdentifier name, Scanner::Location class_name_location,
    bool name_is_strict_reserved, int pos, bool* ok) {
  // All parts of a ClassDeclaration and ClassExpression are strict code.
  if (name_is_strict_reserved) {
    ReportMessageAt(class_name_location, "unexpected_strict_reserved");
    *ok = false;
    return EmptyExpression();
  }
  if (IsEvalOrArguments(name)) {
    ReportMessageAt(class_name_location, "strict_eval_arguments");
    *ok = false;
    return EmptyExpression();
  }

  PreParserScope scope = NewScope(scope_, BLOCK_SCOPE);
  BlockState block_state(&scope_, &scope);
  scope_->SetStrictMode(STRICT);
  scope_->SetScopeName(name);

  if (Check(Token::EXTENDS)) {
    ParseLeftHandSideExpression(CHECK_OK);
  }

  bool has_seen_constructor = false;

  Expect(Token::LBRACE, CHECK_OK);
  while (peek() != Token::RBRACE) {
    if (Check(Token::SEMICOLON)) continue;
    const bool in_class = true;
    const bool is_static = false;
arv's avatar
arv committed
993 994 995 996
    bool is_computed_name = false;  // Classes do not care about computed
                                    // property names here.
    ParsePropertyDefinition(NULL, in_class, is_static, &is_computed_name,
                            &has_seen_constructor, CHECK_OK);
997 998 999 1000 1001 1002 1003 1004
  }

  Expect(Token::RBRACE, CHECK_OK);

  return Expression::Default();
}


1005
PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) {
1006 1007
  // CallRuntime ::
  //   '%' Identifier Arguments
1008
  Expect(Token::MOD, CHECK_OK);
1009
  if (!allow_natives()) {
1010 1011 1012
    *ok = false;
    return Expression::Default();
  }
1013 1014
  // Allow "eval" or "arguments" for backward compatibility.
  ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
1015
  ParseArguments(ok);
1016

1017
  return Expression::Default();
1018 1019
}

1020 1021
#undef CHECK_OK

1022

1023
} }  // v8::internal