Skip to content

Commit cb5e0d9

Browse files
committed
impl the numeric_literal_separator
1 parent 244e736 commit cb5e0d9

File tree

2 files changed

+63
-32
lines changed

2 files changed

+63
-32
lines changed

src/lexer/numbers.js

Lines changed: 61 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -16,58 +16,92 @@ if (process.arch == "x64") {
1616
module.exports = {
1717
consume_NUM: function() {
1818
let ch = this.yytext[0];
19-
let hasPoint = this.yytext[0] === ".";
19+
let hasPoint = ch === ".";
2020
if (ch === "0") {
2121
ch = this.input();
2222
// check if hexa
2323
if (ch === "x" || ch === "X") {
2424
ch = this.input();
25-
if (this.is_HEX()) {
25+
if (ch !== "_" && this.is_HEX()) {
2626
return this.consume_HNUM();
2727
} else {
2828
this.unput(ch ? 2 : 1);
2929
}
30+
// check binary notation
3031
} else if (ch === "b" || ch === "B") {
3132
ch = this.input();
32-
if (ch === "0" || ch === "1") {
33+
if ((ch !== "_" && ch === "0") || ch === "1") {
3334
return this.consume_BNUM();
3435
} else {
3536
this.unput(ch ? 2 : 1);
3637
}
38+
// @fixme check octal notation ? not usefull
3739
} else if (!this.is_NUM()) {
3840
if (ch) this.unput(1);
3941
}
4042
}
4143

4244
while (this.offset < this.size) {
45+
const prev = ch;
4346
ch = this.input();
44-
if (!this.is_NUM()) {
45-
if (ch === "." && !hasPoint) {
46-
hasPoint = true;
47-
} else if (ch === "e" || ch === "E") {
48-
ch = this.input();
49-
if (ch === "+" || ch === "-") {
50-
ch = this.input();
51-
if (this.is_NUM()) {
52-
this.consume_LNUM();
53-
return this.tok.T_DNUMBER;
54-
} else {
55-
this.unput(ch ? 3 : 2);
56-
break;
57-
}
58-
} else if (this.is_NUM()) {
59-
this.consume_LNUM();
60-
return this.tok.T_DNUMBER;
61-
} else {
62-
this.unput(ch ? 2 : 1);
63-
break;
64-
}
65-
} else {
66-
if (ch) this.unput(1);
47+
48+
if (ch === "_") {
49+
if (prev === "_") {
50+
// restriction : next to underscore / 1__1;
51+
this.unput(2); // keep 1
52+
break;
53+
}
54+
if (prev === ".") {
55+
// next to decimal point "1._0"
56+
this.unput(1); // keep 1.
57+
break;
58+
}
59+
if (prev === "e" || prev === "E") {
60+
// next to e "1e_10"
61+
this.unput(2); // keep 1
62+
break;
63+
}
64+
} else if (ch === ".") {
65+
if (hasPoint) {
66+
// no multiple points "1.0.5"
67+
this.unput(1); // keep 1.0
68+
break;
69+
}
70+
if (prev === "_") {
71+
// next to decimal point "1_.0"
72+
this.unput(2); // keep 1
6773
break;
6874
}
75+
hasPoint = true;
76+
continue;
77+
} else if (ch === "e" || ch === "E") {
78+
if (prev === "_") {
79+
// next to e "1_e10"
80+
this.unput(1);
81+
break;
82+
}
83+
let undo = 2;
84+
ch = this.input();
85+
if (ch === "+" || ch === "-") {
86+
// 1e-5
87+
undo = 3;
88+
ch = this.input();
89+
}
90+
if (this.is_NUM_START()) {
91+
this.consume_LNUM();
92+
return this.tok.T_DNUMBER;
93+
}
94+
this.unput(ch ? undo : undo - 1); // keep only 1
95+
break;
96+
}
97+
98+
if (!this.is_NUM()) {
99+
// example : 10.0a
100+
if (ch) this.unput(1); // keep 10.0
101+
break;
69102
}
70103
}
104+
71105
if (hasPoint) {
72106
return this.tok.T_DNUMBER;
73107
} else if (this.yytext.length < MAX_LENGTH_OF_LONG - 1) {
@@ -110,7 +144,7 @@ module.exports = {
110144
let ch;
111145
while (this.offset < this.size) {
112146
ch = this.input();
113-
if (ch !== "0" && ch !== "1") {
147+
if (ch !== "0" && ch !== "1" && ch !== "_") {
114148
if (ch) this.unput(1);
115149
break;
116150
}

test/debug.js

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,8 @@ const parser = require("../src/index");
1919
const ast = parser.parseCode(
2020
`
2121
<?php
22-
function iter() {
23-
yield 'ator' => $foo;
24-
yield from iter(50);
25-
}
26-
$a = fn($n) => $n * $factor;
22+
$a = 100_00;
23+
$bad = 100__00;
2724
`,
2825
{
2926
parser: {

0 commit comments

Comments
 (0)