Skip to content

Commit 9b37f16

Browse files
Inve1951GeoffreyBoothrdeforest
committed
Numeric literal separators (#5215)
* implement numeric literal separators * add tests * Revert changes to package-lock.json * small regex adjustment * split tests * add comment * Add Node versions to CI * Fix #5103: Add support for BigInt literals (#5104) * Fix #5103: Add support for BigInt literals * Fix typos found in testing * Support binary, octal and hex BigInt literals * Make decimal BigInt test consistent other bases * Correct test BigInt test names * Add Node versions to CI * Update output * Fix style * support bigint literal with separators * un-disallow property access on number literal * Update output * Refactor numeric literal separator tests to be more like the rest of the tests * Add test for numeric property with underscore Co-authored-by: Geoffrey Booth <[email protected]> Co-authored-by: Robert de Forest <[email protected]>
1 parent 09c9539 commit 9b37f16

File tree

4 files changed

+67
-6
lines changed

4 files changed

+67
-6
lines changed

Cakefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,7 @@ runTests = (CoffeeScript) ->
472472
skipUnless 'var a = 2 ** 2; a **= 3', ['exponentiation.coffee']
473473
skipUnless 'var {...a} = {}', ['object_rest_spread.coffee']
474474
skipUnless '/foo.bar/s.test("foo\tbar")', ['regex_dotall.coffee']
475+
skipUnless '1_2_3', ['numeric_literal_separators.coffee']
475476
skipUnless '1n', ['numbers_bigint.coffee']
476477
files = fs.readdirSync('test').filter (filename) ->
477478
filename not in testFilesToSkip

lib/coffeescript/lexer.js

Lines changed: 3 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/lexer.coffee

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1212,11 +1212,14 @@ CSX_ATTRIBUTE = /// ^
12121212
///
12131213

12141214
NUMBER = ///
1215-
^ 0b[01]+n? | # binary
1216-
^ 0o[0-7]+n? | # octal
1217-
^ 0x[\da-f]+n? | # hex
1218-
^ \d+n | # decimal bigint
1219-
^ \d*\.?\d+ (?:e[+-]?\d+)? # decimal
1215+
^ 0b[01](?:_?[01])*n? | # binary
1216+
^ 0o[0-7](?:_?[0-7])*n? | # octal
1217+
^ 0x[\da-f](?:_?[\da-f])*n? | # hex
1218+
^ \d+n | # decimal bigint
1219+
^ (?:\d(?:_?\d)*)? \.? (?:\d(?:_?\d)*)+ # decimal
1220+
(?:e[+-]? (?:\d(?:_?\d)*)+ )?
1221+
# decimal without support for numeric literal separators for reference:
1222+
# \d*\.?\d+ (?:e[+-]?\d+)?
12201223
///i
12211224

12221225
OPERATOR = /// ^ (
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Numeric Literal Separators
2+
# --------------------------
3+
4+
test 'integer literals with separators', ->
5+
eq 123_456, 123456
6+
eq 12_34_56, 123456
7+
8+
test 'decimal literals with separators', ->
9+
eq 1_2.34_5, 12.345
10+
eq 1_0e1_0, 10e10
11+
eq 1_2.34_5e6_7, 12.345e67
12+
13+
test 'hexadecimal literals with separators', ->
14+
eq 0x1_2_3_4, 0x1234
15+
16+
test 'binary literals with separators', ->
17+
eq 0b10_10, 0b1010
18+
19+
test 'octal literals with separators', ->
20+
eq 0o7_7_7, 0o777
21+
22+
test 'property access on a number', ->
23+
# Somehow, `3..toFixed()` is valid JavaScript; though just `3.toFixed()`
24+
# is not. CoffeeScript has long allowed code like `3.toFixed()` to compile
25+
# into `3..toFixed()`.
26+
eq 3.toFixed(), '3'
27+
# Where this can conflict with numeric literal separators is when the
28+
# property name contains an underscore.
29+
Number::_23 = _23 = 'x'
30+
eq 1._23, 'x'
31+
ok 1._34 is undefined
32+
delete Number::_23
33+
34+
test 'invalid decimal literal separators do not compile', ->
35+
# `1._23` is a valid property access (see previous test)
36+
throws -> CoffeeScript.compile '1_.23'
37+
throws -> CoffeeScript.compile '1e_2'
38+
throws -> CoffeeScript.compile '1e2_'
39+
throws -> CoffeeScript.compile '1_'
40+
throws -> CoffeeScript.compile '1__2'
41+
42+
test 'invalid hexadecimal literal separators do not compile', ->
43+
throws -> CoffeeScript.compile '0x_1234'
44+
throws -> CoffeeScript.compile '0x1234_'
45+
throws -> CoffeeScript.compile '0x1__34'
46+
47+
test 'invalid binary literal separators do not compile', ->
48+
throws -> CoffeeScript.compile '0b_100'
49+
throws -> CoffeeScript.compile '0b100_'
50+
throws -> CoffeeScript.compile '0b1__1'
51+
52+
test 'invalid octal literal separators do not compile', ->
53+
throws -> CoffeeScript.compile '0o_777'
54+
throws -> CoffeeScript.compile '0o777_'
55+
throws -> CoffeeScript.compile '0o6__6'

0 commit comments

Comments
 (0)