The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / src / scanner.h @ f230a1cf

History | View | Annotate | Download (20.1 KB)

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

    
28
// Features shared by parsing and pre-parsing scanners.
29

    
30
#ifndef V8_SCANNER_H_
31
#define V8_SCANNER_H_
32

    
33
#include "allocation.h"
34
#include "char-predicates.h"
35
#include "checks.h"
36
#include "globals.h"
37
#include "hashmap.h"
38
#include "list.h"
39
#include "token.h"
40
#include "unicode-inl.h"
41
#include "utils.h"
42

    
43
namespace v8 {
44
namespace internal {
45

    
46

    
47
// Returns the value (0 .. 15) of a hexadecimal character c.
48
// If c is not a legal hexadecimal character, returns a value < 0.
49
inline int HexValue(uc32 c) {
50
  c -= '0';
51
  if (static_cast<unsigned>(c) <= 9) return c;
52
  c = (c | 0x20) - ('a' - '0');  // detect 0x11..0x16 and 0x31..0x36.
53
  if (static_cast<unsigned>(c) <= 5) return c + 10;
54
  return -1;
55
}
56

    
57

    
58
// ---------------------------------------------------------------------
59
// Buffered stream of UTF-16 code units, using an internal UTF-16 buffer.
60
// A code unit is a 16 bit value representing either a 16 bit code point
61
// or one part of a surrogate pair that make a single 21 bit code point.
62

    
63
class Utf16CharacterStream {
64
 public:
65
  Utf16CharacterStream() : pos_(0) { }
66
  virtual ~Utf16CharacterStream() { }
67

    
68
  // Returns and advances past the next UTF-16 code unit in the input
69
  // stream. If there are no more code units, it returns a negative
70
  // value.
71
  inline uc32 Advance() {
72
    if (buffer_cursor_ < buffer_end_ || ReadBlock()) {
73
      pos_++;
74
      return static_cast<uc32>(*(buffer_cursor_++));
75
    }
76
    // Note: currently the following increment is necessary to avoid a
77
    // parser problem! The scanner treats the final kEndOfInput as
78
    // a code unit with a position, and does math relative to that
79
    // position.
80
    pos_++;
81

    
82
    return kEndOfInput;
83
  }
84

    
85
  // Return the current position in the code unit stream.
86
  // Starts at zero.
87
  inline unsigned pos() const { return pos_; }
88

    
89
  // Skips forward past the next code_unit_count UTF-16 code units
90
  // in the input, or until the end of input if that comes sooner.
91
  // Returns the number of code units actually skipped. If less
92
  // than code_unit_count,
93
  inline unsigned SeekForward(unsigned code_unit_count) {
94
    unsigned buffered_chars =
95
        static_cast<unsigned>(buffer_end_ - buffer_cursor_);
96
    if (code_unit_count <= buffered_chars) {
97
      buffer_cursor_ += code_unit_count;
98
      pos_ += code_unit_count;
99
      return code_unit_count;
100
    }
101
    return SlowSeekForward(code_unit_count);
102
  }
103

    
104
  // Pushes back the most recently read UTF-16 code unit (or negative
105
  // value if at end of input), i.e., the value returned by the most recent
106
  // call to Advance.
107
  // Must not be used right after calling SeekForward.
108
  virtual void PushBack(int32_t code_unit) = 0;
109

    
110
 protected:
111
  static const uc32 kEndOfInput = -1;
112

    
113
  // Ensures that the buffer_cursor_ points to the code_unit at
114
  // position pos_ of the input, if possible. If the position
115
  // is at or after the end of the input, return false. If there
116
  // are more code_units available, return true.
117
  virtual bool ReadBlock() = 0;
118
  virtual unsigned SlowSeekForward(unsigned code_unit_count) = 0;
119

    
120
  const uc16* buffer_cursor_;
121
  const uc16* buffer_end_;
122
  unsigned pos_;
123
};
124

    
125

    
126
// ---------------------------------------------------------------------
127
// Caching predicates used by scanners.
128

    
129
class UnicodeCache {
130
 public:
131
  UnicodeCache() {}
132
  typedef unibrow::Utf8Decoder<512> Utf8Decoder;
133

    
134
  StaticResource<Utf8Decoder>* utf8_decoder() {
135
    return &utf8_decoder_;
136
  }
137

    
138
  bool IsIdentifierStart(unibrow::uchar c) { return kIsIdentifierStart.get(c); }
139
  bool IsIdentifierPart(unibrow::uchar c) { return kIsIdentifierPart.get(c); }
140
  bool IsLineTerminator(unibrow::uchar c) { return kIsLineTerminator.get(c); }
141
  bool IsWhiteSpace(unibrow::uchar c) { return kIsWhiteSpace.get(c); }
142

    
143
 private:
144
  unibrow::Predicate<IdentifierStart, 128> kIsIdentifierStart;
145
  unibrow::Predicate<IdentifierPart, 128> kIsIdentifierPart;
146
  unibrow::Predicate<unibrow::LineTerminator, 128> kIsLineTerminator;
147
  unibrow::Predicate<unibrow::WhiteSpace, 128> kIsWhiteSpace;
148
  StaticResource<Utf8Decoder> utf8_decoder_;
149

    
150
  DISALLOW_COPY_AND_ASSIGN(UnicodeCache);
151
};
152

    
153

    
154
// ---------------------------------------------------------------------
155
// DuplicateFinder discovers duplicate symbols.
156

    
157
class DuplicateFinder {
158
 public:
159
  explicit DuplicateFinder(UnicodeCache* constants)
160
      : unicode_constants_(constants),
161
        backing_store_(16),
162
        map_(&Match) { }
163

    
164
  int AddAsciiSymbol(Vector<const char> key, int value);
165
  int AddUtf16Symbol(Vector<const uint16_t> key, int value);
166
  // Add a a number literal by converting it (if necessary)
167
  // to the string that ToString(ToNumber(literal)) would generate.
168
  // and then adding that string with AddAsciiSymbol.
169
  // This string is the actual value used as key in an object literal,
170
  // and the one that must be different from the other keys.
171
  int AddNumber(Vector<const char> key, int value);
172

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

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

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

    
195
  UnicodeCache* unicode_constants_;
196
  // Backing store used to store strings used as hashmap keys.
197
  SequenceCollector<unsigned char> backing_store_;
198
  HashMap map_;
199
  // Buffer used for string->number->canonical string conversions.
200
  char number_buffer_[kBufferSize];
201
};
202

    
203

    
204
// ----------------------------------------------------------------------------
205
// LiteralBuffer -  Collector of chars of literals.
206

    
207
class LiteralBuffer {
208
 public:
209
  LiteralBuffer() : is_ascii_(true), position_(0), backing_store_() { }
210

    
211
  ~LiteralBuffer() {
212
    if (backing_store_.length() > 0) {
213
      backing_store_.Dispose();
214
    }
215
  }
216

    
217
  INLINE(void AddChar(uint32_t code_unit)) {
218
    if (position_ >= backing_store_.length()) ExpandBuffer();
219
    if (is_ascii_) {
220
      if (code_unit <= unibrow::Latin1::kMaxChar) {
221
        backing_store_[position_] = static_cast<byte>(code_unit);
222
        position_ += kOneByteSize;
223
        return;
224
      }
225
      ConvertToUtf16();
226
    }
227
    ASSERT(code_unit < 0x10000u);
228
    *reinterpret_cast<uc16*>(&backing_store_[position_]) = code_unit;
229
    position_ += kUC16Size;
230
  }
231

    
232
  bool is_ascii() { return is_ascii_; }
233

    
234
  bool is_contextual_keyword(Vector<const char> keyword) {
235
    return is_ascii() && keyword.length() == position_ &&
236
        (memcmp(keyword.start(), backing_store_.start(), position_) == 0);
237
  }
238

    
239
  Vector<const uc16> utf16_literal() {
240
    ASSERT(!is_ascii_);
241
    ASSERT((position_ & 0x1) == 0);
242
    return Vector<const uc16>(
243
        reinterpret_cast<const uc16*>(backing_store_.start()),
244
        position_ >> 1);
245
  }
246

    
247
  Vector<const char> ascii_literal() {
248
    ASSERT(is_ascii_);
249
    return Vector<const char>(
250
        reinterpret_cast<const char*>(backing_store_.start()),
251
        position_);
252
  }
253

    
254
  int length() {
255
    return is_ascii_ ? position_ : (position_ >> 1);
256
  }
257

    
258
  void Reset() {
259
    position_ = 0;
260
    is_ascii_ = true;
261
  }
262

    
263
 private:
264
  static const int kInitialCapacity = 16;
265
  static const int kGrowthFactory = 4;
266
  static const int kMinConversionSlack = 256;
267
  static const int kMaxGrowth = 1 * MB;
268
  inline int NewCapacity(int min_capacity) {
269
    int capacity = Max(min_capacity, backing_store_.length());
270
    int new_capacity = Min(capacity * kGrowthFactory, capacity + kMaxGrowth);
271
    return new_capacity;
272
  }
273

    
274
  void ExpandBuffer() {
275
    Vector<byte> new_store = Vector<byte>::New(NewCapacity(kInitialCapacity));
276
    OS::MemCopy(new_store.start(), backing_store_.start(), position_);
277
    backing_store_.Dispose();
278
    backing_store_ = new_store;
279
  }
280

    
281
  void ConvertToUtf16() {
282
    ASSERT(is_ascii_);
283
    Vector<byte> new_store;
284
    int new_content_size = position_ * kUC16Size;
285
    if (new_content_size >= backing_store_.length()) {
286
      // Ensure room for all currently read code units as UC16 as well
287
      // as the code unit about to be stored.
288
      new_store = Vector<byte>::New(NewCapacity(new_content_size));
289
    } else {
290
      new_store = backing_store_;
291
    }
292
    uint8_t* src = backing_store_.start();
293
    uc16* dst = reinterpret_cast<uc16*>(new_store.start());
294
    for (int i = position_ - 1; i >= 0; i--) {
295
      dst[i] = src[i];
296
    }
297
    if (new_store.start() != backing_store_.start()) {
298
      backing_store_.Dispose();
299
      backing_store_ = new_store;
300
    }
301
    position_ = new_content_size;
302
    is_ascii_ = false;
303
  }
304

    
305
  bool is_ascii_;
306
  int position_;
307
  Vector<byte> backing_store_;
308

    
309
  DISALLOW_COPY_AND_ASSIGN(LiteralBuffer);
310
};
311

    
312

    
313
// ----------------------------------------------------------------------------
314
// JavaScript Scanner.
315

    
316
class Scanner {
317
 public:
318
  // Scoped helper for literal recording. Automatically drops the literal
319
  // if aborting the scanning before it's complete.
320
  class LiteralScope {
321
   public:
322
    explicit LiteralScope(Scanner* self)
323
        : scanner_(self), complete_(false) {
324
      scanner_->StartLiteral();
325
    }
326
     ~LiteralScope() {
327
       if (!complete_) scanner_->DropLiteral();
328
     }
329
    void Complete() {
330
      scanner_->TerminateLiteral();
331
      complete_ = true;
332
    }
333

    
334
   private:
335
    Scanner* scanner_;
336
    bool complete_;
337
  };
338

    
339
  // Representation of an interval of source positions.
340
  struct Location {
341
    Location(int b, int e) : beg_pos(b), end_pos(e) { }
342
    Location() : beg_pos(0), end_pos(0) { }
343

    
344
    bool IsValid() const {
345
      return beg_pos >= 0 && end_pos >= beg_pos;
346
    }
347

    
348
    static Location invalid() { return Location(-1, -1); }
349

    
350
    int beg_pos;
351
    int end_pos;
352
  };
353

    
354
  // -1 is outside of the range of any real source code.
355
  static const int kNoOctalLocation = -1;
356

    
357
  explicit Scanner(UnicodeCache* scanner_contants);
358

    
359
  void Initialize(Utf16CharacterStream* source);
360

    
361
  // Returns the next token and advances input.
362
  Token::Value Next();
363
  // Returns the current token again.
364
  Token::Value current_token() { return current_.token; }
365
  // Returns the location information for the current token
366
  // (the token last returned by Next()).
367
  Location location() const { return current_.location; }
368
  // Returns the literal string, if any, for the current token (the
369
  // token last returned by Next()). The string is 0-terminated.
370
  // Literal strings are collected for identifiers, strings, and
371
  // numbers.
372
  // These functions only give the correct result if the literal
373
  // was scanned between calls to StartLiteral() and TerminateLiteral().
374
  Vector<const char> literal_ascii_string() {
375
    ASSERT_NOT_NULL(current_.literal_chars);
376
    return current_.literal_chars->ascii_literal();
377
  }
378
  Vector<const uc16> literal_utf16_string() {
379
    ASSERT_NOT_NULL(current_.literal_chars);
380
    return current_.literal_chars->utf16_literal();
381
  }
382
  bool is_literal_ascii() {
383
    ASSERT_NOT_NULL(current_.literal_chars);
384
    return current_.literal_chars->is_ascii();
385
  }
386
  bool is_literal_contextual_keyword(Vector<const char> keyword) {
387
    ASSERT_NOT_NULL(current_.literal_chars);
388
    return current_.literal_chars->is_contextual_keyword(keyword);
389
  }
390
  int literal_length() const {
391
    ASSERT_NOT_NULL(current_.literal_chars);
392
    return current_.literal_chars->length();
393
  }
394

    
395
  bool literal_contains_escapes() const {
396
    Location location = current_.location;
397
    int source_length = (location.end_pos - location.beg_pos);
398
    if (current_.token == Token::STRING) {
399
      // Subtract delimiters.
400
      source_length -= 2;
401
    }
402
    return current_.literal_chars->length() != source_length;
403
  }
404

    
405
  // Similar functions for the upcoming token.
406

    
407
  // One token look-ahead (past the token returned by Next()).
408
  Token::Value peek() const { return next_.token; }
409

    
410
  Location peek_location() const { return next_.location; }
411

    
412
  // Returns the literal string for the next token (the token that
413
  // would be returned if Next() were called).
414
  Vector<const char> next_literal_ascii_string() {
415
    ASSERT_NOT_NULL(next_.literal_chars);
416
    return next_.literal_chars->ascii_literal();
417
  }
418
  Vector<const uc16> next_literal_utf16_string() {
419
    ASSERT_NOT_NULL(next_.literal_chars);
420
    return next_.literal_chars->utf16_literal();
421
  }
422
  bool is_next_literal_ascii() {
423
    ASSERT_NOT_NULL(next_.literal_chars);
424
    return next_.literal_chars->is_ascii();
425
  }
426
  bool is_next_contextual_keyword(Vector<const char> keyword) {
427
    ASSERT_NOT_NULL(next_.literal_chars);
428
    return next_.literal_chars->is_contextual_keyword(keyword);
429
  }
430
  int next_literal_length() const {
431
    ASSERT_NOT_NULL(next_.literal_chars);
432
    return next_.literal_chars->length();
433
  }
434

    
435
  UnicodeCache* unicode_cache() { return unicode_cache_; }
436

    
437
  static const int kCharacterLookaheadBufferSize = 1;
438

    
439
  // Scans octal escape sequence. Also accepts "\0" decimal escape sequence.
440
  uc32 ScanOctalEscape(uc32 c, int length);
441

    
442
  // Returns the location of the last seen octal literal.
443
  Location octal_position() const { return octal_pos_; }
444
  void clear_octal_position() { octal_pos_ = Location::invalid(); }
445

    
446
  // Seek forward to the given position.  This operation does not
447
  // work in general, for instance when there are pushed back
448
  // characters, but works for seeking forward until simple delimiter
449
  // tokens, which is what it is used for.
450
  void SeekForward(int pos);
451

    
452
  bool HarmonyScoping() const {
453
    return harmony_scoping_;
454
  }
455
  void SetHarmonyScoping(bool scoping) {
456
    harmony_scoping_ = scoping;
457
  }
458
  bool HarmonyModules() const {
459
    return harmony_modules_;
460
  }
461
  void SetHarmonyModules(bool modules) {
462
    harmony_modules_ = modules;
463
  }
464
  bool HarmonyNumericLiterals() const {
465
    return harmony_numeric_literals_;
466
  }
467
  void SetHarmonyNumericLiterals(bool numeric_literals) {
468
    harmony_numeric_literals_ = numeric_literals;
469
  }
470

    
471
  // Returns true if there was a line terminator before the peek'ed token,
472
  // possibly inside a multi-line comment.
473
  bool HasAnyLineTerminatorBeforeNext() const {
474
    return has_line_terminator_before_next_ ||
475
           has_multiline_comment_before_next_;
476
  }
477

    
478
  // Scans the input as a regular expression pattern, previous
479
  // character(s) must be /(=). Returns true if a pattern is scanned.
480
  bool ScanRegExpPattern(bool seen_equal);
481
  // Returns true if regexp flags are scanned (always since flags can
482
  // be empty).
483
  bool ScanRegExpFlags();
484

    
485
 private:
486
  // The current and look-ahead token.
487
  struct TokenDesc {
488
    Token::Value token;
489
    Location location;
490
    LiteralBuffer* literal_chars;
491
  };
492

    
493
  // Call this after setting source_ to the input.
494
  void Init() {
495
    // Set c0_ (one character ahead)
496
    STATIC_ASSERT(kCharacterLookaheadBufferSize == 1);
497
    Advance();
498
    // Initialize current_ to not refer to a literal.
499
    current_.literal_chars = NULL;
500
  }
501

    
502
  // Literal buffer support
503
  inline void StartLiteral() {
504
    LiteralBuffer* free_buffer = (current_.literal_chars == &literal_buffer1_) ?
505
            &literal_buffer2_ : &literal_buffer1_;
506
    free_buffer->Reset();
507
    next_.literal_chars = free_buffer;
508
  }
509

    
510
  INLINE(void AddLiteralChar(uc32 c)) {
511
    ASSERT_NOT_NULL(next_.literal_chars);
512
    next_.literal_chars->AddChar(c);
513
  }
514

    
515
  // Complete scanning of a literal.
516
  inline void TerminateLiteral() {
517
    // Does nothing in the current implementation.
518
  }
519

    
520
  // Stops scanning of a literal and drop the collected characters,
521
  // e.g., due to an encountered error.
522
  inline void DropLiteral() {
523
    next_.literal_chars = NULL;
524
  }
525

    
526
  inline void AddLiteralCharAdvance() {
527
    AddLiteralChar(c0_);
528
    Advance();
529
  }
530

    
531
  // Low-level scanning support.
532
  void Advance() { c0_ = source_->Advance(); }
533
  void PushBack(uc32 ch) {
534
    source_->PushBack(c0_);
535
    c0_ = ch;
536
  }
537

    
538
  inline Token::Value Select(Token::Value tok) {
539
    Advance();
540
    return tok;
541
  }
542

    
543
  inline Token::Value Select(uc32 next, Token::Value then, Token::Value else_) {
544
    Advance();
545
    if (c0_ == next) {
546
      Advance();
547
      return then;
548
    } else {
549
      return else_;
550
    }
551
  }
552

    
553
  uc32 ScanHexNumber(int expected_length);
554

    
555
  // Scans a single JavaScript token.
556
  void Scan();
557

    
558
  bool SkipWhiteSpace();
559
  Token::Value SkipSingleLineComment();
560
  Token::Value SkipMultiLineComment();
561
  // Scans a possible HTML comment -- begins with '<!'.
562
  Token::Value ScanHtmlComment();
563

    
564
  void ScanDecimalDigits();
565
  Token::Value ScanNumber(bool seen_period);
566
  Token::Value ScanIdentifierOrKeyword();
567
  Token::Value ScanIdentifierSuffix(LiteralScope* literal);
568

    
569
  Token::Value ScanString();
570

    
571
  // Scans an escape-sequence which is part of a string and adds the
572
  // decoded character to the current literal. Returns true if a pattern
573
  // is scanned.
574
  bool ScanEscape();
575
  // Decodes a Unicode escape-sequence which is part of an identifier.
576
  // If the escape sequence cannot be decoded the result is kBadChar.
577
  uc32 ScanIdentifierUnicodeEscape();
578
  // Scans a Unicode escape-sequence and adds its characters,
579
  // uninterpreted, to the current literal. Used for parsing RegExp
580
  // flags.
581
  bool ScanLiteralUnicodeEscape();
582

    
583
  // Return the current source position.
584
  int source_pos() {
585
    return source_->pos() - kCharacterLookaheadBufferSize;
586
  }
587

    
588
  UnicodeCache* unicode_cache_;
589

    
590
  // Buffers collecting literal strings, numbers, etc.
591
  LiteralBuffer literal_buffer1_;
592
  LiteralBuffer literal_buffer2_;
593

    
594
  TokenDesc current_;  // desc for current token (as returned by Next())
595
  TokenDesc next_;     // desc for next token (one token look-ahead)
596

    
597
  // Input stream. Must be initialized to an Utf16CharacterStream.
598
  Utf16CharacterStream* source_;
599

    
600

    
601
  // Start position of the octal literal last scanned.
602
  Location octal_pos_;
603

    
604
  // One Unicode character look-ahead; c0_ < 0 at the end of the input.
605
  uc32 c0_;
606

    
607
  // Whether there is a line terminator whitespace character after
608
  // the current token, and  before the next. Does not count newlines
609
  // inside multiline comments.
610
  bool has_line_terminator_before_next_;
611
  // Whether there is a multi-line comment that contains a
612
  // line-terminator after the current token, and before the next.
613
  bool has_multiline_comment_before_next_;
614
  // Whether we scan 'let' as a keyword for harmony block-scoped let bindings.
615
  bool harmony_scoping_;
616
  // Whether we scan 'module', 'import', 'export' as keywords.
617
  bool harmony_modules_;
618
  // Whether we scan 0o777 and 0b111 as numbers.
619
  bool harmony_numeric_literals_;
620
};
621

    
622
} }  // namespace v8::internal
623

    
624
#endif  // V8_SCANNER_H_