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