Revision f230a1cf deps/v8/src/preparser.h

View differences:

deps/v8/src/preparser.h
33 33
#include "scanner.h"
34 34

  
35 35
namespace v8 {
36

  
37 36
namespace internal {
38
class UnicodeCache;
39
}
40 37

  
41
namespace preparser {
38
// Common base class shared between parser and pre-parser.
39
class ParserBase {
40
 public:
41
  ParserBase(Scanner* scanner, uintptr_t stack_limit)
42
      : scanner_(scanner),
43
        stack_limit_(stack_limit),
44
        stack_overflow_(false),
45
        allow_lazy_(false),
46
        allow_natives_syntax_(false),
47
        allow_generators_(false),
48
        allow_for_of_(false) { }
49
  // TODO(mstarzinger): Only virtual until message reporting has been unified.
50
  virtual ~ParserBase() { }
51

  
52
  // Getters that indicate whether certain syntactical constructs are
53
  // allowed to be parsed by this instance of the parser.
54
  bool allow_lazy() const { return allow_lazy_; }
55
  bool allow_natives_syntax() const { return allow_natives_syntax_; }
56
  bool allow_generators() const { return allow_generators_; }
57
  bool allow_for_of() const { return allow_for_of_; }
58
  bool allow_modules() const { return scanner()->HarmonyModules(); }
59
  bool allow_harmony_scoping() const { return scanner()->HarmonyScoping(); }
60
  bool allow_harmony_numeric_literals() const {
61
    return scanner()->HarmonyNumericLiterals();
62
  }
63

  
64
  // Setters that determine whether certain syntactical constructs are
65
  // allowed to be parsed by this instance of the parser.
66
  void set_allow_lazy(bool allow) { allow_lazy_ = allow; }
67
  void set_allow_natives_syntax(bool allow) { allow_natives_syntax_ = allow; }
68
  void set_allow_generators(bool allow) { allow_generators_ = allow; }
69
  void set_allow_for_of(bool allow) { allow_for_of_ = allow; }
70
  void set_allow_modules(bool allow) { scanner()->SetHarmonyModules(allow); }
71
  void set_allow_harmony_scoping(bool allow) {
72
    scanner()->SetHarmonyScoping(allow);
73
  }
74
  void set_allow_harmony_numeric_literals(bool allow) {
75
    scanner()->SetHarmonyNumericLiterals(allow);
76
  }
77

  
78
 protected:
79
  Scanner* scanner() const { return scanner_; }
80
  int position() { return scanner_->location().beg_pos; }
81
  int peek_position() { return scanner_->peek_location().beg_pos; }
82
  bool stack_overflow() const { return stack_overflow_; }
83
  void set_stack_overflow() { stack_overflow_ = true; }
84

  
85
  INLINE(Token::Value peek()) {
86
    if (stack_overflow_) return Token::ILLEGAL;
87
    return scanner()->peek();
88
  }
89

  
90
  INLINE(Token::Value Next()) {
91
    if (stack_overflow_) return Token::ILLEGAL;
92
    {
93
      int marker;
94
      if (reinterpret_cast<uintptr_t>(&marker) < stack_limit_) {
95
        // Any further calls to Next or peek will return the illegal token.
96
        // The current call must return the next token, which might already
97
        // have been peek'ed.
98
        stack_overflow_ = true;
99
      }
100
    }
101
    return scanner()->Next();
102
  }
103

  
104
  void Consume(Token::Value token) {
105
    Token::Value next = Next();
106
    USE(next);
107
    USE(token);
108
    ASSERT(next == token);
109
  }
110

  
111
  bool Check(Token::Value token) {
112
    Token::Value next = peek();
113
    if (next == token) {
114
      Consume(next);
115
      return true;
116
    }
117
    return false;
118
  }
119

  
120
  void Expect(Token::Value token, bool* ok) {
121
    Token::Value next = Next();
122
    if (next != token) {
123
      ReportUnexpectedToken(next);
124
      *ok = false;
125
    }
126
  }
127

  
128
  bool peek_any_identifier();
129
  void ExpectSemicolon(bool* ok);
130
  bool CheckContextualKeyword(Vector<const char> keyword);
131
  void ExpectContextualKeyword(Vector<const char> keyword, bool* ok);
132

  
133
  // Strict mode octal literal validation.
134
  void CheckOctalLiteral(int beg_pos, int end_pos, bool* ok);
135

  
136
  // Determine precedence of given token.
137
  static int Precedence(Token::Value token, bool accept_IN);
138

  
139
  // Report syntax errors.
140
  virtual void ReportUnexpectedToken(Token::Value token) = 0;
141
  virtual void ReportMessageAt(Scanner::Location loc, const char* type) = 0;
142

  
143
  // Used to detect duplicates in object literals. Each of the values
144
  // kGetterProperty, kSetterProperty and kValueProperty represents
145
  // a type of object literal property. When parsing a property, its
146
  // type value is stored in the DuplicateFinder for the property name.
147
  // Values are chosen so that having intersection bits means the there is
148
  // an incompatibility.
149
  // I.e., you can add a getter to a property that already has a setter, since
150
  // kGetterProperty and kSetterProperty doesn't intersect, but not if it
151
  // already has a getter or a value. Adding the getter to an existing
152
  // setter will store the value (kGetterProperty | kSetterProperty), which
153
  // is incompatible with adding any further properties.
154
  enum PropertyKind {
155
    kNone = 0,
156
    // Bit patterns representing different object literal property types.
157
    kGetterProperty = 1,
158
    kSetterProperty = 2,
159
    kValueProperty = 7,
160
    // Helper constants.
161
    kValueFlag = 4
162
  };
163

  
164
  // Validation per ECMA 262 - 11.1.5 "Object Initialiser".
165
  class ObjectLiteralChecker {
166
   public:
167
    ObjectLiteralChecker(ParserBase* parser, LanguageMode mode)
168
        : parser_(parser),
169
          finder_(scanner()->unicode_cache()),
170
          language_mode_(mode) { }
171

  
172
    void CheckProperty(Token::Value property, PropertyKind type, bool* ok);
173

  
174
   private:
175
    ParserBase* parser() const { return parser_; }
176
    Scanner* scanner() const { return parser_->scanner(); }
177

  
178
    // Checks the type of conflict based on values coming from PropertyType.
179
    bool HasConflict(PropertyKind type1, PropertyKind type2) {
180
      return (type1 & type2) != 0;
181
    }
182
    bool IsDataDataConflict(PropertyKind type1, PropertyKind type2) {
183
      return ((type1 & type2) & kValueFlag) != 0;
184
    }
185
    bool IsDataAccessorConflict(PropertyKind type1, PropertyKind type2) {
186
      return ((type1 ^ type2) & kValueFlag) != 0;
187
    }
188
    bool IsAccessorAccessorConflict(PropertyKind type1, PropertyKind type2) {
189
      return ((type1 | type2) & kValueFlag) == 0;
190
    }
191

  
192
    ParserBase* parser_;
193
    DuplicateFinder finder_;
194
    LanguageMode language_mode_;
195
  };
196

  
197
 private:
198
  Scanner* scanner_;
199
  uintptr_t stack_limit_;
200
  bool stack_overflow_;
201

  
202
  bool allow_lazy_;
203
  bool allow_natives_syntax_;
204
  bool allow_generators_;
205
  bool allow_for_of_;
206
};
42 207

  
43
typedef uint8_t byte;
44 208

  
45 209
// Preparsing checks a JavaScript program and emits preparse-data that helps
46 210
// a later parsing to be faster.
......
54 218
// rather it is to speed up properly written and correct programs.
55 219
// That means that contextual checks (like a label being declared where
56 220
// it is used) are generally omitted.
57

  
58
namespace i = v8::internal;
59

  
60
class DuplicateFinder {
61
 public:
62
  explicit DuplicateFinder(i::UnicodeCache* constants)
63
      : unicode_constants_(constants),
64
        backing_store_(16),
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
  // Add a a number literal by converting it (if necessary)
70
  // to the string that ToString(ToNumber(literal)) would generate.
71
  // and then adding that string with AddAsciiSymbol.
72
  // This string is the actual value used as key in an object literal,
73
  // and the one that must be different from the other keys.
74
  int AddNumber(i::Vector<const char> key, int value);
75

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

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

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

  
98
  i::UnicodeCache* unicode_constants_;
99
  // Backing store used to store strings used as hashmap keys.
100
  i::SequenceCollector<unsigned char> backing_store_;
101
  i::HashMap map_;
102
  // Buffer used for string->number->canonical string conversions.
103
  char number_buffer_[kBufferSize];
104
};
105

  
106

  
107
class PreParser {
221
class PreParser : public ParserBase {
108 222
 public:
109 223
  enum PreParseResult {
110 224
    kPreParseStackOverflow,
111 225
    kPreParseSuccess
112 226
  };
113 227

  
114

  
115
  PreParser(i::Scanner* scanner,
116
            i::ParserRecorder* log,
228
  PreParser(Scanner* scanner,
229
            ParserRecorder* log,
117 230
            uintptr_t stack_limit)
118
      : scanner_(scanner),
231
      : ParserBase(scanner, stack_limit),
119 232
        log_(log),
120 233
        scope_(NULL),
121
        stack_limit_(stack_limit),
122
        strict_mode_violation_location_(i::Scanner::Location::invalid()),
234
        strict_mode_violation_location_(Scanner::Location::invalid()),
123 235
        strict_mode_violation_type_(NULL),
124
        stack_overflow_(false),
125
        allow_lazy_(false),
126
        allow_natives_syntax_(false),
127
        allow_generators_(false),
128
        allow_for_of_(false),
129 236
        parenthesized_function_(false) { }
130 237

  
131 238
  ~PreParser() {}
132 239

  
133
  bool allow_natives_syntax() const { return allow_natives_syntax_; }
134
  bool allow_lazy() const { return allow_lazy_; }
135
  bool allow_modules() const { return scanner_->HarmonyModules(); }
136
  bool allow_harmony_scoping() const { return scanner_->HarmonyScoping(); }
137
  bool allow_generators() const { return allow_generators_; }
138
  bool allow_for_of() const { return allow_for_of_; }
139
  bool allow_harmony_numeric_literals() const {
140
    return scanner_->HarmonyNumericLiterals();
141
  }
142

  
143
  void set_allow_natives_syntax(bool allow) { allow_natives_syntax_ = allow; }
144
  void set_allow_lazy(bool allow) { allow_lazy_ = allow; }
145
  void set_allow_modules(bool allow) { scanner_->SetHarmonyModules(allow); }
146
  void set_allow_harmony_scoping(bool allow) {
147
    scanner_->SetHarmonyScoping(allow);
148
  }
149
  void set_allow_generators(bool allow) { allow_generators_ = allow; }
150
  void set_allow_for_of(bool allow) { allow_for_of_ = allow; }
151
  void set_allow_harmony_numeric_literals(bool allow) {
152
    scanner_->SetHarmonyNumericLiterals(allow);
153
  }
154

  
155 240
  // Pre-parse the program from the character stream; returns true on
156 241
  // success (even if parsing failed, the pre-parse data successfully
157 242
  // captured the syntax error), and false if a stack-overflow happened
......
159 244
  PreParseResult PreParseProgram() {
160 245
    Scope top_scope(&scope_, kTopLevelScope);
161 246
    bool ok = true;
162
    int start_position = scanner_->peek_location().beg_pos;
163
    ParseSourceElements(i::Token::EOS, &ok);
164
    if (stack_overflow_) return kPreParseStackOverflow;
247
    int start_position = scanner()->peek_location().beg_pos;
248
    ParseSourceElements(Token::EOS, &ok);
249
    if (stack_overflow()) return kPreParseStackOverflow;
165 250
    if (!ok) {
166
      ReportUnexpectedToken(scanner_->current_token());
251
      ReportUnexpectedToken(scanner()->current_token());
167 252
    } else if (!scope_->is_classic_mode()) {
168
      CheckOctalLiteral(start_position, scanner_->location().end_pos, &ok);
253
      CheckOctalLiteral(start_position, scanner()->location().end_pos, &ok);
169 254
    }
170 255
    return kPreParseSuccess;
171 256
  }
......
178 263
  // keyword and parameters, and have consumed the initial '{'.
179 264
  // At return, unless an error occurred, the scanner is positioned before the
180 265
  // the final '}'.
181
  PreParseResult PreParseLazyFunction(i::LanguageMode mode,
266
  PreParseResult PreParseLazyFunction(LanguageMode mode,
182 267
                                      bool is_generator,
183
                                      i::ParserRecorder* log);
268
                                      ParserRecorder* log);
184 269

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

  
207
  // Checks the type of conflict based on values coming from PropertyType.
208
  bool HasConflict(int type1, int type2) { return (type1 & type2) != 0; }
209
  bool IsDataDataConflict(int type1, int type2) {
210
    return ((type1 & type2) & kValueFlag) != 0;
211
  }
212
  bool IsDataAccessorConflict(int type1, int type2) {
213
    return ((type1 ^ type2) & kValueFlag) != 0;
214
  }
215
  bool IsAccessorAccessorConflict(int type1, int type2) {
216
    return ((type1 | type2) & kValueFlag) == 0;
217
  }
218

  
219

  
220
  void CheckDuplicate(DuplicateFinder* finder,
221
                      i::Token::Value property,
222
                      int type,
223
                      bool* ok);
224

  
225 271
  // These types form an algebra over syntactic categories that is just
226 272
  // rich enough to let us recognize and propagate the constructs that
227 273
  // are either being counted in the preparser data, or is important
......
441 487
    }
442 488

  
443 489
    bool IsStringLiteral() {
444
      return code_ != kUnknownStatement;
490
      return code_ == kStringLiteralExpressionStatement;
445 491
    }
446 492

  
447 493
    bool IsUseStrictLiteral() {
......
480 526
          expected_properties_(0),
481 527
          with_nesting_count_(0),
482 528
          language_mode_(
483
              (prev_ != NULL) ? prev_->language_mode() : i::CLASSIC_MODE),
529
              (prev_ != NULL) ? prev_->language_mode() : CLASSIC_MODE),
484 530
          is_generator_(false) {
485 531
      *variable = this;
486 532
    }
......
494 540
    bool is_generator() { return is_generator_; }
495 541
    void set_is_generator(bool is_generator) { is_generator_ = is_generator; }
496 542
    bool is_classic_mode() {
497
      return language_mode_ == i::CLASSIC_MODE;
543
      return language_mode_ == CLASSIC_MODE;
498 544
    }
499
    i::LanguageMode language_mode() {
545
    LanguageMode language_mode() {
500 546
      return language_mode_;
501 547
    }
502
    void set_language_mode(i::LanguageMode language_mode) {
548
    void set_language_mode(LanguageMode language_mode) {
503 549
      language_mode_ = language_mode;
504 550
    }
505 551

  
......
523 569
    int materialized_literal_count_;
524 570
    int expected_properties_;
525 571
    int with_nesting_count_;
526
    i::LanguageMode language_mode_;
572
    LanguageMode language_mode_;
527 573
    bool is_generator_;
528 574
  };
529 575

  
530 576
  // Report syntax error
531
  void ReportUnexpectedToken(i::Token::Value token);
532
  void ReportMessageAt(i::Scanner::Location location,
577
  void ReportUnexpectedToken(Token::Value token);
578
  void ReportMessageAt(Scanner::Location location, const char* type) {
579
    ReportMessageAt(location, type, NULL);
580
  }
581
  void ReportMessageAt(Scanner::Location location,
533 582
                       const char* type,
534 583
                       const char* name_opt) {
535 584
    log_->LogMessage(location.beg_pos, location.end_pos, type, name_opt);
......
541 590
    log_->LogMessage(start_pos, end_pos, type, name_opt);
542 591
  }
543 592

  
544
  void CheckOctalLiteral(int beg_pos, int end_pos, bool* ok);
545

  
546 593
  // All ParseXXX functions take as the last argument an *ok parameter
547 594
  // which is set to false if parsing failed; it is unchanged otherwise.
548 595
  // By making the 'exception handling' explicit, we are forced to check
......
606 653
  // Log the currently parsed string literal.
607 654
  Expression GetStringSymbol();
608 655

  
609
  i::Token::Value peek() {
610
    if (stack_overflow_) return i::Token::ILLEGAL;
611
    return scanner_->peek();
612
  }
613

  
614
  i::Token::Value Next() {
615
    if (stack_overflow_) return i::Token::ILLEGAL;
616
    {
617
      int marker;
618
      if (reinterpret_cast<uintptr_t>(&marker) < stack_limit_) {
619
        // Further calls to peek/Next will return illegal token.
620
        // The current one will still be returned. It might already
621
        // have been seen using peek.
622
        stack_overflow_ = true;
623
      }
624
    }
625
    return scanner_->Next();
626
  }
627

  
628
  bool peek_any_identifier();
629

  
630
  void set_language_mode(i::LanguageMode language_mode) {
656
  void set_language_mode(LanguageMode language_mode) {
631 657
    scope_->set_language_mode(language_mode);
632 658
  }
633 659

  
634 660
  bool is_classic_mode() {
635
    return scope_->language_mode() == i::CLASSIC_MODE;
661
    return scope_->language_mode() == CLASSIC_MODE;
636 662
  }
637 663

  
638 664
  bool is_extended_mode() {
639
    return scope_->language_mode() == i::EXTENDED_MODE;
665
    return scope_->language_mode() == EXTENDED_MODE;
640 666
  }
641 667

  
642
  i::LanguageMode language_mode() { return scope_->language_mode(); }
643

  
644
  void Consume(i::Token::Value token) { Next(); }
645

  
646
  void Expect(i::Token::Value token, bool* ok) {
647
    if (Next() != token) {
648
      *ok = false;
649
    }
650
  }
651

  
652
  bool Check(i::Token::Value token) {
653
    i::Token::Value next = peek();
654
    if (next == token) {
655
      Consume(next);
656
      return true;
657
    }
658
    return false;
659
  }
660
  void ExpectSemicolon(bool* ok);
668
  LanguageMode language_mode() { return scope_->language_mode(); }
661 669

  
662 670
  bool CheckInOrOf(bool accept_OF);
663 671

  
664
  static int Precedence(i::Token::Value tok, bool accept_IN);
665

  
666
  void SetStrictModeViolation(i::Scanner::Location,
672
  void SetStrictModeViolation(Scanner::Location,
667 673
                              const char* type,
668 674
                              bool* ok);
669 675

  
670 676
  void CheckDelayedStrictModeViolation(int beg_pos, int end_pos, bool* ok);
671 677

  
672
  void StrictModeIdentifierViolation(i::Scanner::Location,
678
  void StrictModeIdentifierViolation(Scanner::Location,
673 679
                                     const char* eval_args_type,
674 680
                                     Identifier identifier,
675 681
                                     bool* ok);
676 682

  
677
  i::Scanner* scanner_;
678
  i::ParserRecorder* log_;
683
  ParserRecorder* log_;
679 684
  Scope* scope_;
680
  uintptr_t stack_limit_;
681
  i::Scanner::Location strict_mode_violation_location_;
685
  Scanner::Location strict_mode_violation_location_;
682 686
  const char* strict_mode_violation_type_;
683
  bool stack_overflow_;
684
  bool allow_lazy_;
685
  bool allow_natives_syntax_;
686
  bool allow_generators_;
687
  bool allow_for_of_;
688 687
  bool parenthesized_function_;
689 688
};
690
} }  // v8::preparser
689

  
690
} }  // v8::internal
691 691

  
692 692
#endif  // V8_PREPARSER_H

Also available in: Unified diff