• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1"use strict"
2
3module.exports = function(Parser) {
4  return class extends Parser {
5    readInt(radix, len) {
6      // Hack: len is only != null for unicode escape sequences,
7      // where numeric separators are not allowed
8      if (len != null) return super.readInt(radix, len)
9
10      let start = this.pos, total = 0, acceptUnderscore = false
11      for (;;) {
12        let code = this.input.charCodeAt(this.pos), val
13        if (code >= 97) val = code - 97 + 10 // a
14        else if (code == 95) {
15          if (!acceptUnderscore) this.raise(this.pos, "Invalid numeric separator")
16          ++this.pos
17          acceptUnderscore = false
18          continue
19        } else if (code >= 65) val = code - 65 + 10 // A
20        else if (code >= 48 && code <= 57) val = code - 48 // 0-9
21        else val = Infinity
22        if (val >= radix) break
23        ++this.pos
24        total = total * radix + val
25        acceptUnderscore = true
26      }
27      if (this.pos === start) return null
28      if (!acceptUnderscore) this.raise(this.pos - 1, "Invalid numeric separator")
29
30      return total
31    }
32
33    readNumber(startsWithDot) {
34      const token = super.readNumber(startsWithDot)
35      let octal = this.end - this.start >= 2 && this.input.charCodeAt(this.start) === 48
36      const stripped = this.getNumberInput(this.start, this.end)
37      if (stripped.length < this.end - this.start) {
38        if (octal) this.raise(this.start, "Invalid number")
39        this.value = parseFloat(stripped)
40      }
41      return token
42    }
43
44    // This is used by acorn-bigint
45    getNumberInput(start, end) {
46      return this.input.slice(start, end).replace(/_/g, "")
47    }
48  }
49}
50