Skip to content

Commit 57f5297

Browse files
committed
Handle very large hexadecimal number literals correctly
Very large decimal number literals, binary number literals and octal literals are lexed into an INFINITY token (instead of a NUMBER token) and compiled into `2e308`. That is is supposed to be the case for very large hexdecimal dumber literals as well, but previously wasn't. Before: $ node -p 'require("./").tokens(`0x${Array(256 + 1).join("f")}`)[0][0]' NUMBER After: $ node -p 'require("./").tokens(`0x${Array(256 + 1).join("f")}`)[0][0]' INFINITY This commit also cleans up `numberToken` in lexer.coffee a bit.
1 parent 3204180 commit 57f5297

File tree

2 files changed

+56
-40
lines changed

2 files changed

+56
-40
lines changed

lib/coffee-script/lexer.js

Lines changed: 35 additions & 24 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/lexer.coffee

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -191,25 +191,30 @@ exports.Lexer = class Lexer
191191
# Be careful not to interfere with ranges-in-progress.
192192
numberToken: ->
193193
return 0 unless match = NUMBER.exec @chunk
194+
194195
number = match[0]
195196
lexedLength = number.length
196-
if /^0[BOX]/.test number
197-
@error "radix prefix in '#{number}' must be lowercase", offset: 1
198-
else if /E/.test(number) and not /^0x/.test number
199-
@error "exponential notation in '#{number}' must be indicated with a lowercase 'e'",
200-
offset: number.indexOf('E')
201-
else if /^0\d*[89]/.test number
202-
@error "decimal literal '#{number}' must not be prefixed with '0'", length: lexedLength
203-
else if /^0\d+/.test number
204-
@error "octal literal '#{number}' must be prefixed with '0o'", length: lexedLength
205-
if octalLiteral = /^0o([0-7]+)/.exec number
206-
numberValue = parseInt(octalLiteral[1], 8)
207-
number = "0x#{numberValue.toString 16}"
208-
else if binaryLiteral = /^0b([01]+)/.exec number
209-
numberValue = parseInt(binaryLiteral[1], 2)
197+
198+
switch
199+
when /^0[BOX]/.test number
200+
@error "radix prefix in '#{number}' must be lowercase", offset: 1
201+
when /^(?!0x).*E/.test number
202+
@error "exponential notation in '#{number}' must be indicated with a lowercase 'e'",
203+
offset: number.indexOf('E')
204+
when /^0\d*[89]/.test number
205+
@error "decimal literal '#{number}' must not be prefixed with '0'", length: lexedLength
206+
when /^0\d+/.test number
207+
@error "octal literal '#{number}' must be prefixed with '0o'", length: lexedLength
208+
209+
base = switch number.charAt 1
210+
when 'b' then 2
211+
when 'o' then 8
212+
when 'x' then 16
213+
else null
214+
numberValue = if base? then parseInt(number[2..], base) else parseFloat(number)
215+
if number.charAt(1) in ['b', 'o']
210216
number = "0x#{numberValue.toString 16}"
211-
else
212-
numberValue = parseFloat(number)
217+
213218
tag = if numberValue is Infinity then 'INFINITY' else 'NUMBER'
214219
@token tag, number, 0, lexedLength
215220
lexedLength

0 commit comments

Comments
 (0)