preparser.h 22.4 KB
Newer Older
1
// Copyright 2012 the V8 project authors. All rights reserved.
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//     * Neither the name of Google Inc. nor the names of its
//       contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifndef V8_PREPARSER_H
#define V8_PREPARSER_H

31
#include "hashmap.h"
32 33 34
#include "token.h"
#include "scanner.h"

35
namespace v8 {
36 37 38 39 40

namespace internal {
class UnicodeCache;
}

41 42
namespace preparser {

43 44
typedef uint8_t byte;

45 46
// Preparsing checks a JavaScript program and emits preparse-data that helps
// a later parsing to be faster.
47
// See preparse-data-format.h for the data format.
48 49 50 51 52 53 54 55 56 57

// 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.

58 59
namespace i = v8::internal;

60 61 62 63 64
class DuplicateFinder {
 public:
  explicit DuplicateFinder(i::UnicodeCache* constants)
      : unicode_constants_(constants),
        backing_store_(16),
lrn@chromium.org's avatar
lrn@chromium.org committed
65
        map_(&Match) { }
66 67

  int AddAsciiSymbol(i::Vector<const char> key, int value);
68
  int AddUtf16Symbol(i::Vector<const uint16_t> key, int value);
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
  // Add a a number literal by converting it (if necessary)
  // to the string that ToString(ToNumber(literal)) would generate.
  // and then adding that string with AddAsciiSymbol.
  // This string is the actual value used as key in an object literal,
  // and the one that must be different from the other keys.
  int AddNumber(i::Vector<const char> key, int value);

 private:
  int AddSymbol(i::Vector<const byte> key, bool is_ascii, int value);
  // Backs up the key and its length in the backing store.
  // The backup is stored with a base 127 encoding of the
  // length (plus a bit saying whether the string is ASCII),
  // followed by the bytes of the key.
  byte* BackupKey(i::Vector<const byte> key, bool is_ascii);

  // Compare two encoded keys (both pointing into the backing store)
  // for having the same base-127 encoded lengths and ASCII-ness,
  // and then having the same 'length' bytes following.
  static bool Match(void* first, void* second);
  // Creates a hash from a sequence of bytes.
  static uint32_t Hash(i::Vector<const byte> key, bool is_ascii);
  // Checks whether a string containing a JS number is its canonical
  // form.
  static bool IsNumberCanonical(i::Vector<const char> key);

  // Size of buffer. Sufficient for using it to call DoubleToCString in
  // from conversions.h.
  static const int kBufferSize = 100;

  i::UnicodeCache* unicode_constants_;
  // Backing store used to store strings used as hashmap keys.
  i::SequenceCollector<unsigned char> backing_store_;
lrn@chromium.org's avatar
lrn@chromium.org committed
101
  i::HashMap map_;
102 103 104 105 106
  // Buffer used for string->number->canonical string conversions.
  char number_buffer_[kBufferSize];
};


107 108
class PreParser {
 public:
109 110 111 112 113
  enum PreParseResult {
    kPreParseStackOverflow,
    kPreParseSuccess
  };

114 115 116 117 118

  PreParser(i::Scanner* scanner,
            i::ParserRecorder* log,
            uintptr_t stack_limit,
            bool allow_lazy,
119 120
            bool allow_natives_syntax,
            bool allow_modules)
121 122 123 124 125 126 127 128
      : scanner_(scanner),
        log_(log),
        scope_(NULL),
        stack_limit_(stack_limit),
        strict_mode_violation_location_(i::Scanner::Location::invalid()),
        strict_mode_violation_type_(NULL),
        stack_overflow_(false),
        allow_lazy_(allow_lazy),
129
        allow_modules_(allow_modules),
130 131 132 133
        allow_natives_syntax_(allow_natives_syntax),
        parenthesized_function_(false),
        harmony_scoping_(scanner->HarmonyScoping()) { }

134
  ~PreParser() {}
135 136 137 138 139

  // Pre-parse the program from the character stream; returns true on
  // success (even if parsing failed, the pre-parse data successfully
  // captured the syntax error), and false if a stack-overflow happened
  // during parsing.
140
  static PreParseResult PreParseProgram(i::Scanner* scanner,
141
                                        i::ParserRecorder* log,
142
                                        int flags,
143
                                        uintptr_t stack_limit) {
144 145
    bool allow_lazy = (flags & i::kAllowLazy) != 0;
    bool allow_natives_syntax = (flags & i::kAllowNativesSyntax) != 0;
146 147 148
    bool allow_modules = (flags & i::kAllowModules) != 0;
    return PreParser(scanner, log, stack_limit, allow_lazy,
                     allow_natives_syntax, allow_modules).PreParse();
149 150
  }

151 152 153 154 155 156 157 158 159 160 161
  // Parses a single function literal, from the opening parentheses before
  // parameters to the closing brace after the body.
  // Returns a FunctionEntry describing the body of the funciton in enough
  // detail that it can be lazily compiled.
  // The scanner is expected to have matched the "function" keyword and
  // parameters, and have consumed the initial '{'.
  // At return, unless an error occured, the scanner is positioned before the
  // the final '}'.
  PreParseResult PreParseLazyFunction(i::LanguageMode mode,
                                      i::ParserRecorder* log);

162
 private:
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
  // Used to detect duplicates in object literals. Each of the values
  // kGetterProperty, kSetterProperty and kValueProperty represents
  // a type of object literal property. When parsing a property, its
  // type value is stored in the DuplicateFinder for the property name.
  // Values are chosen so that having intersection bits means the there is
  // an incompatibility.
  // I.e., you can add a getter to a property that already has a setter, since
  // kGetterProperty and kSetterProperty doesn't intersect, but not if it
  // already has a getter or a value. Adding the getter to an existing
  // setter will store the value (kGetterProperty | kSetterProperty), which
  // is incompatible with adding any further properties.
  enum PropertyType {
    kNone = 0,
    // Bit patterns representing different object literal property types.
    kGetterProperty = 1,
    kSetterProperty = 2,
    kValueProperty = 7,
    // Helper constants.
    kValueFlag = 4
  };

  // Checks the type of conflict based on values coming from PropertyType.
  bool HasConflict(int type1, int type2) { return (type1 & type2) != 0; }
  bool IsDataDataConflict(int type1, int type2) {
    return ((type1 & type2) & kValueFlag) != 0;
  }
  bool IsDataAccessorConflict(int type1, int type2) {
    return ((type1 ^ type2) & kValueFlag) != 0;
  }
  bool IsAccessorAccessorConflict(int type1, int type2) {
    return ((type1 | type2) & kValueFlag) == 0;
  }


  void CheckDuplicate(DuplicateFinder* finder,
                      i::Token::Value property,
                      int type,
                      bool* ok);

202 203 204 205 206
  // These types form an algebra over syntactic categories that is just
  // rich enough to let us recognize and propagate the constructs that
  // are either being counted in the preparser data, or is important
  // to throw the correct syntax error exceptions.

207 208 209 210 211
  enum ScopeType {
    kTopLevelScope,
    kFunctionScope
  };

212 213 214 215 216 217
  enum VariableDeclarationContext {
    kSourceElement,
    kStatement,
    kForStatement
  };

218 219 220 221 222 223
  // If a list of variable declarations includes any initializers.
  enum VariableDeclarationProperties {
    kHasInitializers,
    kHasNoInitializers
  };

224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
  class Expression;

  class Identifier {
   public:
    static Identifier Default() {
      return Identifier(kUnknownIdentifier);
    }
    static Identifier Eval()  {
      return Identifier(kEvalIdentifier);
    }
    static Identifier Arguments()  {
      return Identifier(kArgumentsIdentifier);
    }
    static Identifier FutureReserved()  {
      return Identifier(kFutureReservedIdentifier);
    }
240 241 242
    static Identifier FutureStrictReserved()  {
      return Identifier(kFutureStrictReservedIdentifier);
    }
243 244 245 246
    bool IsEval() { return type_ == kEvalIdentifier; }
    bool IsArguments() { return type_ == kArgumentsIdentifier; }
    bool IsEvalOrArguments() { return type_ >= kEvalIdentifier; }
    bool IsFutureReserved() { return type_ == kFutureReservedIdentifier; }
247 248 249
    bool IsFutureStrictReserved() {
      return type_ == kFutureStrictReservedIdentifier;
    }
250
    bool IsValidStrictVariable() { return type_ == kUnknownIdentifier; }
251

252 253 254 255
   private:
    enum Type {
      kUnknownIdentifier,
      kFutureReservedIdentifier,
256
      kFutureStrictReservedIdentifier,
257 258 259 260 261 262 263
      kEvalIdentifier,
      kArgumentsIdentifier
    };
    explicit Identifier(Type type) : type_(type) { }
    Type type_;

    friend class Expression;
264 265
  };

266 267 268 269 270 271 272 273 274 275 276 277 278
  // Bits 0 and 1 are used to identify the type of expression:
  // If bit 0 is set, it's an identifier.
  // if bit 1 is set, it's a string literal.
  // If neither is set, it's no particular type, and both set isn't
  // use yet.
  // Bit 2 is used to mark the expression as being parenthesized,
  // so "(foo)" isn't recognized as a pure identifier (and possible label).
  class Expression {
   public:
    static Expression Default() {
      return Expression(kUnknownExpression);
    }

279
    static Expression FromIdentifier(Identifier id) {
280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386
      return Expression(kIdentifierFlag | (id.type_ << kIdentifierShift));
    }

    static Expression StringLiteral() {
      return Expression(kUnknownStringLiteral);
    }

    static Expression UseStrictStringLiteral() {
      return Expression(kUseStrictString);
    }

    static Expression This() {
      return Expression(kThisExpression);
    }

    static Expression ThisProperty() {
      return Expression(kThisPropertyExpression);
    }

    static Expression StrictFunction() {
      return Expression(kStrictFunctionExpression);
    }

    bool IsIdentifier() {
      return (code_ & kIdentifierFlag) != 0;
    }

    // Only works corretly if it is actually an identifier expression.
    PreParser::Identifier AsIdentifier() {
      return PreParser::Identifier(
          static_cast<PreParser::Identifier::Type>(code_ >> kIdentifierShift));
    }

    bool IsParenthesized() {
      // If bit 0 or 1 is set, we interpret bit 2 as meaning parenthesized.
      return (code_ & 7) > 4;
    }

    bool IsRawIdentifier() {
      return !IsParenthesized() && IsIdentifier();
    }

    bool IsStringLiteral() { return (code_ & kStringLiteralFlag) != 0; }

    bool IsRawStringLiteral() {
      return !IsParenthesized() && IsStringLiteral();
    }

    bool IsUseStrictLiteral() {
      return (code_ & kStringLiteralMask) == kUseStrictString;
    }

    bool IsThis() {
      return code_ == kThisExpression;
    }

    bool IsThisProperty() {
      return code_ == kThisPropertyExpression;
    }

    bool IsStrictFunction() {
      return code_ == kStrictFunctionExpression;
    }

    Expression Parenthesize() {
      int type = code_ & 3;
      if (type != 0) {
        // Identifiers and string literals can be parenthesized.
        // They no longer work as labels or directive prologues,
        // but are still recognized in other contexts.
        return Expression(code_ | kParentesizedExpressionFlag);
      }
      // For other types of expressions, it's not important to remember
      // the parentheses.
      return *this;
    }

   private:
    // First two/three bits are used as flags.
    // Bit 0 and 1 represent identifiers or strings literals, and are
    // mutually exclusive, but can both be absent.
    // If bit 0 or 1 are set, bit 2 marks that the expression has
    // been wrapped in parentheses (a string literal can no longer
    // be a directive prologue, and an identifier can no longer be
    // a label.
    enum  {
      kUnknownExpression = 0,
      // Identifiers
      kIdentifierFlag = 1,  // Used to detect labels.
      kIdentifierShift = 3,

      kStringLiteralFlag = 2,  // Used to detect directive prologue.
      kUnknownStringLiteral = kStringLiteralFlag,
      kUseStrictString = kStringLiteralFlag | 8,
      kStringLiteralMask = kUseStrictString,

      kParentesizedExpressionFlag = 4,  // Only if identifier or string literal.

      // Below here applies if neither identifier nor string literal.
      kThisExpression = 4,
      kThisPropertyExpression = 8,
      kStrictFunctionExpression = 12
    };

    explicit Expression(int expression_code) : code_(expression_code) { }

    int code_;
387 388
  };

389 390 391 392 393 394
  class Statement {
   public:
    static Statement Default() {
      return Statement(kUnknownStatement);
    }

395 396 397 398
    static Statement FunctionDeclaration() {
      return Statement(kFunctionDeclaration);
    }

399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421
    // Creates expression statement from expression.
    // Preserves being an unparenthesized string literal, possibly
    // "use strict".
    static Statement ExpressionStatement(Expression expression) {
      if (!expression.IsParenthesized()) {
        if (expression.IsUseStrictLiteral()) {
          return Statement(kUseStrictExpressionStatement);
        }
        if (expression.IsStringLiteral()) {
          return Statement(kStringLiteralExpressionStatement);
        }
      }
      return Default();
    }

    bool IsStringLiteral() {
      return code_ != kUnknownStatement;
    }

    bool IsUseStrictLiteral() {
      return code_ == kUseStrictExpressionStatement;
    }

422 423 424 425
    bool IsFunctionDeclaration() {
      return code_ == kFunctionDeclaration;
    }

426 427 428 429
   private:
    enum Type {
      kUnknownStatement,
      kStringLiteralExpressionStatement,
430 431
      kUseStrictExpressionStatement,
      kFunctionDeclaration
432 433 434 435
    };

    explicit Statement(Type code) : code_(code) {}
    Type code_;
436 437
  };

438 439
  enum SourceElements {
    kUnknownSourceElements
440 441 442 443
  };

  typedef int Arguments;

444 445 446 447 448 449 450 451
  class Scope {
   public:
    Scope(Scope** variable, ScopeType type)
        : variable_(variable),
          prev_(*variable),
          type_(type),
          materialized_literal_count_(0),
          expected_properties_(0),
452
          with_nesting_count_(0),
453 454
          language_mode_(
              (prev_ != NULL) ? prev_->language_mode() : i::CLASSIC_MODE) {
455 456 457 458 459 460 461 462 463
      *variable = this;
    }
    ~Scope() { *variable_ = prev_; }
    void NextMaterializedLiteralIndex() { materialized_literal_count_++; }
    void AddProperty() { expected_properties_++; }
    ScopeType type() { return type_; }
    int expected_properties() { return expected_properties_; }
    int materialized_literal_count() { return materialized_literal_count_; }
    bool IsInsideWith() { return with_nesting_count_ != 0; }
464 465
    bool is_classic_mode() {
      return language_mode_ == i::CLASSIC_MODE;
466
    }
467 468 469 470 471
    i::LanguageMode language_mode() {
      return language_mode_;
    }
    void set_language_mode(i::LanguageMode language_mode) {
      language_mode_ = language_mode;
472
    }
473 474 475 476 477 478 479 480 481 482 483 484 485

    class InsideWith {
     public:
      explicit InsideWith(Scope* scope) : scope_(scope) {
        scope->with_nesting_count_++;
      }

      ~InsideWith() { scope_->with_nesting_count_--; }

     private:
      Scope* scope_;
      DISALLOW_COPY_AND_ASSIGN(InsideWith);
    };
486 487 488 489 490 491 492 493

   private:
    Scope** const variable_;
    Scope* const prev_;
    const ScopeType type_;
    int materialized_literal_count_;
    int expected_properties_;
    int with_nesting_count_;
494
    i::LanguageMode language_mode_;
495 496
  };

497 498 499 500 501
  // Preparse the program. Only called in PreParseProgram after creating
  // the instance.
  PreParseResult PreParse() {
    Scope top_scope(&scope_, kTopLevelScope);
    bool ok = true;
502
    int start_position = scanner_->peek_location().beg_pos;
503 504 505 506
    ParseSourceElements(i::Token::EOS, &ok);
    if (stack_overflow_) return kPreParseStackOverflow;
    if (!ok) {
      ReportUnexpectedToken(scanner_->current_token());
507
    } else if (!scope_->is_classic_mode()) {
508
      CheckOctalLiteral(start_position, scanner_->location().end_pos, &ok);
509 510 511
    }
    return kPreParseSuccess;
  }
512 513

  // Report syntax error
514
  void ReportUnexpectedToken(i::Token::Value token);
515 516 517 518 519
  void ReportMessageAt(i::Scanner::Location location,
                       const char* type,
                       const char* name_opt) {
    log_->LogMessage(location.beg_pos, location.end_pos, type, name_opt);
  }
520 521 522 523 524 525 526
  void ReportMessageAt(int start_pos,
                       int end_pos,
                       const char* type,
                       const char* name_opt) {
    log_->LogMessage(start_pos, end_pos, type, name_opt);
  }

527 528
  void CheckOctalLiteral(int beg_pos, int end_pos, bool* ok);

529 530 531 532
  // All ParseXXX functions take as the last argument an *ok parameter
  // which is set to false if parsing failed; it is unchanged otherwise.
  // By making the 'exception handling' explicit, we are forced to check
  // for failure at the call sites.
533
  Statement ParseSourceElement(bool* ok);
534 535 536 537
  SourceElements ParseSourceElements(int end_token, bool* ok);
  Statement ParseStatement(bool* ok);
  Statement ParseFunctionDeclaration(bool* ok);
  Statement ParseBlock(bool* ok);
538 539 540
  Statement ParseVariableStatement(VariableDeclarationContext var_context,
                                   bool* ok);
  Statement ParseVariableDeclarations(VariableDeclarationContext var_context,
541
                                      VariableDeclarationProperties* decl_props,
542 543
                                      int* num_decl,
                                      bool* ok);
544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566
  Statement ParseExpressionOrLabelledStatement(bool* ok);
  Statement ParseIfStatement(bool* ok);
  Statement ParseContinueStatement(bool* ok);
  Statement ParseBreakStatement(bool* ok);
  Statement ParseReturnStatement(bool* ok);
  Statement ParseWithStatement(bool* ok);
  Statement ParseSwitchStatement(bool* ok);
  Statement ParseDoWhileStatement(bool* ok);
  Statement ParseWhileStatement(bool* ok);
  Statement ParseForStatement(bool* ok);
  Statement ParseThrowStatement(bool* ok);
  Statement ParseTryStatement(bool* ok);
  Statement ParseDebuggerStatement(bool* ok);

  Expression ParseExpression(bool accept_IN, bool* ok);
  Expression ParseAssignmentExpression(bool accept_IN, bool* ok);
  Expression ParseConditionalExpression(bool accept_IN, bool* ok);
  Expression ParseBinaryExpression(int prec, bool accept_IN, bool* ok);
  Expression ParseUnaryExpression(bool* ok);
  Expression ParsePostfixExpression(bool* ok);
  Expression ParseLeftHandSideExpression(bool* ok);
  Expression ParseNewExpression(bool* ok);
  Expression ParseMemberExpression(bool* ok);
567
  Expression ParseMemberWithNewPrefixesExpression(unsigned new_count, bool* ok);
568 569 570 571 572 573 574 575
  Expression ParsePrimaryExpression(bool* ok);
  Expression ParseArrayLiteral(bool* ok);
  Expression ParseObjectLiteral(bool* ok);
  Expression ParseRegExpLiteral(bool seen_equal, bool* ok);
  Expression ParseV8Intrinsic(bool* ok);

  Arguments ParseArguments(bool* ok);
  Expression ParseFunctionLiteral(bool* ok);
576
  void ParseLazyFunctionLiteralBody(bool* ok);
577 578 579

  Identifier ParseIdentifier(bool* ok);
  Identifier ParseIdentifierName(bool* ok);
580 581 582
  Identifier ParseIdentifierNameOrGetOrSet(bool* is_get,
                                           bool* is_set,
                                           bool* ok);
583

584 585 586
  // Logs the currently parsed literal as a symbol in the preparser data.
  void LogSymbol();
  // Log the currently parsed identifier.
587
  Identifier GetIdentifierSymbol();
588
  // Log the currently parsed string literal.
589 590
  Expression GetStringSymbol();

591 592 593 594
  i::Token::Value peek() {
    if (stack_overflow_) return i::Token::ILLEGAL;
    return scanner_->peek();
  }
595

596
  i::Token::Value Next() {
597 598 599 600 601 602 603 604 605 606 607
    if (stack_overflow_) return i::Token::ILLEGAL;
    {
      int marker;
      if (reinterpret_cast<uintptr_t>(&marker) < stack_limit_) {
        // Further calls to peek/Next will return illegal token.
        // The current one will still be returned. It might already
        // have been seen using peek.
        stack_overflow_ = true;
      }
    }
    return scanner_->Next();
608 609
  }

610 611
  bool peek_any_identifier();

612 613 614 615 616 617
  void set_language_mode(i::LanguageMode language_mode) {
    scope_->set_language_mode(language_mode);
  }

  bool is_classic_mode() {
    return scope_->language_mode() == i::CLASSIC_MODE;
618 619
  }

620 621 622
  bool is_extended_mode() {
    return scope_->language_mode() == i::EXTENDED_MODE;
  }
623

624
  i::LanguageMode language_mode() { return scope_->language_mode(); }
625

626
  void Consume(i::Token::Value token) { Next(); }
627

628
  void Expect(i::Token::Value token, bool* ok) {
629 630 631 632 633
    if (Next() != token) {
      *ok = false;
    }
  }

634 635
  bool Check(i::Token::Value token) {
    i::Token::Value next = peek();
636 637 638 639 640 641 642 643
    if (next == token) {
      Consume(next);
      return true;
    }
    return false;
  }
  void ExpectSemicolon(bool* ok);

644
  static int Precedence(i::Token::Value tok, bool accept_IN);
645

646 647
  void SetStrictModeViolation(i::Scanner::Location,
                              const char* type,
648
                              bool* ok);
649 650 651 652 653 654 655 656

  void CheckDelayedStrictModeViolation(int beg_pos, int end_pos, bool* ok);

  void StrictModeIdentifierViolation(i::Scanner::Location,
                                     const char* eval_args_type,
                                     Identifier identifier,
                                     bool* ok);

657
  i::Scanner* scanner_;
658
  i::ParserRecorder* log_;
659
  Scope* scope_;
660
  uintptr_t stack_limit_;
661 662
  i::Scanner::Location strict_mode_violation_location_;
  const char* strict_mode_violation_type_;
663
  bool stack_overflow_;
664
  bool allow_lazy_;
665
  bool allow_modules_;
666
  bool allow_natives_syntax_;
667
  bool parenthesized_function_;
668
  bool harmony_scoping_;
669
};
670
} }  // v8::preparser
671 672

#endif  // V8_PREPARSER_H