JS: support parsing of numeric literal separators
Taco de Wolff
2 years ago
514 | 514 |
return true
|
515 | 515 |
}
|
516 | 516 |
|
|
517 |
func (l *Lexer) consumeNumericSeparator(f func() bool) bool {
|
|
518 |
if l.r.Peek(0) != '_' {
|
|
519 |
return false
|
|
520 |
}
|
|
521 |
l.r.Move(1)
|
|
522 |
if !f() {
|
|
523 |
l.r.Move(-1)
|
|
524 |
return false
|
|
525 |
}
|
|
526 |
return true
|
|
527 |
}
|
|
528 |
|
517 | 529 |
func (l *Lexer) consumeNumericToken() TokenType {
|
518 | 530 |
// assume to be on 0 1 2 3 4 5 6 7 8 9 .
|
519 | 531 |
first := l.r.Peek(0)
|
|
522 | 534 |
if l.r.Peek(0) == 'x' || l.r.Peek(0) == 'X' {
|
523 | 535 |
l.r.Move(1)
|
524 | 536 |
if l.consumeHexDigit() {
|
525 | |
for l.consumeHexDigit() {
|
|
537 |
for l.consumeHexDigit() || l.consumeNumericSeparator(l.consumeHexDigit) {
|
526 | 538 |
}
|
527 | 539 |
return HexadecimalToken
|
528 | 540 |
}
|
|
531 | 543 |
} else if l.r.Peek(0) == 'b' || l.r.Peek(0) == 'B' {
|
532 | 544 |
l.r.Move(1)
|
533 | 545 |
if l.consumeBinaryDigit() {
|
534 | |
for l.consumeBinaryDigit() {
|
|
546 |
for l.consumeBinaryDigit() || l.consumeNumericSeparator(l.consumeBinaryDigit) {
|
535 | 547 |
}
|
536 | 548 |
return BinaryToken
|
537 | 549 |
}
|
|
540 | 552 |
} else if l.r.Peek(0) == 'o' || l.r.Peek(0) == 'O' {
|
541 | 553 |
l.r.Move(1)
|
542 | 554 |
if l.consumeOctalDigit() {
|
543 | |
for l.consumeOctalDigit() {
|
|
555 |
for l.consumeOctalDigit() || l.consumeNumericSeparator(l.consumeOctalDigit) {
|
544 | 556 |
}
|
545 | 557 |
return OctalToken
|
546 | 558 |
}
|
|
554 | 566 |
return ErrorToken
|
555 | 567 |
}
|
556 | 568 |
} else if first != '.' {
|
557 | |
for l.consumeDigit() {
|
|
569 |
for l.consumeDigit() || l.consumeNumericSeparator(l.consumeDigit) {
|
558 | 570 |
}
|
559 | 571 |
}
|
560 | 572 |
// we have parsed a 0 or an integer number
|
|
562 | 574 |
if c == '.' {
|
563 | 575 |
l.r.Move(1)
|
564 | 576 |
if l.consumeDigit() {
|
565 | |
for l.consumeDigit() {
|
|
577 |
for l.consumeDigit() || l.consumeNumericSeparator(l.consumeDigit) {
|
566 | 578 |
}
|
567 | 579 |
c = l.r.Peek(0)
|
568 | 580 |
} else if first == '.' {
|
|
586 | 598 |
l.err = parse.NewErrorLexer(l.r, "invalid number")
|
587 | 599 |
return ErrorToken
|
588 | 600 |
}
|
589 | |
for l.consumeDigit() {
|
|
601 |
for l.consumeDigit() || l.consumeNumericSeparator(l.consumeDigit) {
|
590 | 602 |
}
|
591 | 603 |
}
|
592 | 604 |
return DecimalToken
|
18 | 18 |
{" \t\v\f\u00A0\uFEFF\u2000", TTs{}}, // WhitespaceToken
|
19 | 19 |
{"\n\r\r\n\u2028\u2029", TTs{LineTerminatorToken}},
|
20 | 20 |
{"5.2 .04 1. 2.e3 0x0F 5e99", TTs{DecimalToken, DecimalToken, DecimalToken, DecimalToken, HexadecimalToken, DecimalToken}},
|
|
21 |
{"2_3 5_4.1_2 1_1n 0o2_3 0b1_1 0xF_F", TTs{DecimalToken, DecimalToken, BigIntToken, OctalToken, BinaryToken, HexadecimalToken}},
|
21 | 22 |
{"0o22 0b11", TTs{OctalToken, BinaryToken}},
|
22 | 23 |
{"0n 2345n 435.333n", TTs{BigIntToken, BigIntToken, DecimalToken, ErrorToken}},
|
23 | 24 |
{"a = 'string'", TTs{IdentifierToken, EqToken, StringToken}},
|