@@ -31,8 +31,11 @@ import {
31
31
isIdentifierPart ,
32
32
isDecimal ,
33
33
isOctal ,
34
+ isHex ,
35
+ isHexPart ,
34
36
isHighSurrogate ,
35
- isLowSurrogate
37
+ isLowSurrogate ,
38
+ parseHexFloat
36
39
} from "./util" ;
37
40
38
41
/** Named token types. */
@@ -1258,18 +1261,34 @@ export class Tokenizer extends DiagnosticEmitter {
1258
1261
var text = this . source . text ;
1259
1262
var pos = this . pos ;
1260
1263
var end = this . end ;
1261
- if ( pos + 1 < end && text . charCodeAt ( pos ) == CharCode . _0 ) {
1262
- switch ( text . charCodeAt ( pos + 2 ) | 32 ) {
1263
- case CharCode . x :
1264
+ var hex = false ;
1265
+ if ( pos + 2 < end && text . charCodeAt ( pos ) == CharCode . _0 ) {
1266
+ switch ( text . charCodeAt ( pos + 1 ) | 32 ) {
1267
+ case CharCode . x : {
1268
+ // Don't early return for CharCode.x
1269
+ // It possible a hexadecimal float.
1270
+ hex = true ;
1271
+ pos += 2 ;
1272
+ break ;
1273
+ }
1264
1274
case CharCode . b :
1265
1275
case CharCode . o : return true ;
1276
+ case CharCode . DOT : return false ;
1266
1277
}
1267
1278
}
1268
1279
while ( pos < end ) {
1269
1280
let c = text . charCodeAt ( pos ) ;
1270
- if ( c == CharCode . DOT || ( c | 32 ) == CharCode . e ) return false ;
1271
- if ( c != CharCode . _ && ( c < CharCode . _0 || c > CharCode . _9 ) ) break ;
1281
+ if ( c == CharCode . DOT ) return false ;
1272
1282
// does not validate separator placement (this is done in readXYInteger)
1283
+ if ( c != CharCode . _ ) {
1284
+ if ( hex ) {
1285
+ if ( ( c | 32 ) == CharCode . p ) return false ;
1286
+ if ( ! isHex ( c ) ) break ;
1287
+ } else {
1288
+ if ( ( c | 32 ) == CharCode . e ) return false ;
1289
+ if ( ! isDecimal ( c ) ) break ;
1290
+ }
1291
+ }
1273
1292
pos ++ ;
1274
1293
}
1275
1294
return true ;
@@ -1313,30 +1332,24 @@ export class Tokenizer extends DiagnosticEmitter {
1313
1332
var end = this . end ;
1314
1333
var start = pos ;
1315
1334
var sepEnd = start ;
1316
- var value = i64_new ( 0 ) ;
1335
+ var value = i64_zero ;
1317
1336
var i64_4 = i64_new ( 4 ) ;
1318
1337
var nextValue = value ;
1319
1338
var overflowOccurred = false ;
1320
1339
1321
1340
while ( pos < end ) {
1322
1341
let c = text . charCodeAt ( pos ) ;
1323
- if ( c >= CharCode . _0 && c <= CharCode . _9 ) {
1324
- // value = (value << 4) + c - CharCode._0;
1342
+ if ( isDecimal ( c ) ) {
1343
+ // (value << 4) + c - CharCode._0
1325
1344
nextValue = i64_add (
1326
1345
i64_shl ( value , i64_4 ) ,
1327
1346
i64_new ( c - CharCode . _0 )
1328
1347
) ;
1329
- } else if ( c >= CharCode . A && c <= CharCode . F ) {
1330
- // value = (value << 4) + 10 + c - CharCode.A;
1331
- nextValue = i64_add (
1332
- i64_shl ( value , i64_4 ) ,
1333
- i64_new ( 10 + c - CharCode . A )
1334
- ) ;
1335
- } else if ( c >= CharCode . a && c <= CharCode . f ) {
1336
- // value = (value << 4) + 10 + c - CharCode.a;
1348
+ } else if ( isHexPart ( c ) ) {
1349
+ // (value << 4) + (c | 32) + (10 - CharCode.a)
1337
1350
nextValue = i64_add (
1338
1351
i64_shl ( value , i64_4 ) ,
1339
- i64_new ( 10 + c - CharCode . a )
1352
+ i64_new ( ( c | 32 ) + ( 10 - CharCode . a ) )
1340
1353
) ;
1341
1354
} else if ( c == CharCode . _ ) {
1342
1355
if ( sepEnd == pos ) {
@@ -1386,15 +1399,15 @@ export class Tokenizer extends DiagnosticEmitter {
1386
1399
var end = this . end ;
1387
1400
var start = pos ;
1388
1401
var sepEnd = start ;
1389
- var value = i64_new ( 0 ) ;
1402
+ var value = i64_zero ;
1390
1403
var i64_10 = i64_new ( 10 ) ;
1391
1404
var nextValue = value ;
1392
1405
var overflowOccurred = false ;
1393
1406
1394
1407
while ( pos < end ) {
1395
1408
let c = text . charCodeAt ( pos ) ;
1396
- if ( c >= CharCode . _0 && c <= CharCode . _9 ) {
1397
- // value = value * 10 + c - CharCode._0;
1409
+ if ( isDecimal ( c ) ) {
1410
+ // value = value * 10 + c - CharCode._0
1398
1411
nextValue = i64_add (
1399
1412
i64_mul ( value , i64_10 ) ,
1400
1413
i64_new ( c - CharCode . _0 )
@@ -1451,14 +1464,14 @@ export class Tokenizer extends DiagnosticEmitter {
1451
1464
var end = this . end ;
1452
1465
var start = pos ;
1453
1466
var sepEnd = start ;
1454
- var value = i64_new ( 0 ) ;
1467
+ var value = i64_zero ;
1455
1468
var i64_3 = i64_new ( 3 ) ;
1456
1469
var nextValue = value ;
1457
1470
var overflowOccurred = false ;
1458
1471
1459
1472
while ( pos < end ) {
1460
1473
let c = text . charCodeAt ( pos ) ;
1461
- if ( c >= CharCode . _0 && c <= CharCode . _7 ) {
1474
+ if ( isOctal ( c ) ) {
1462
1475
// value = (value << 3) + c - CharCode._0;
1463
1476
nextValue = i64_add (
1464
1477
i64_shl ( value , i64_3 ) ,
@@ -1511,21 +1524,20 @@ export class Tokenizer extends DiagnosticEmitter {
1511
1524
var end = this . end ;
1512
1525
var start = pos ;
1513
1526
var sepEnd = start ;
1514
- var value = i64_new ( 0 ) ;
1515
- var i64_1 = i64_new ( 1 ) ;
1527
+ var value = i64_zero ;
1516
1528
var nextValue = value ;
1517
1529
var overflowOccurred = false ;
1518
1530
1519
1531
while ( pos < end ) {
1520
1532
let c = text . charCodeAt ( pos ) ;
1521
1533
if ( c == CharCode . _0 ) {
1522
1534
// value = (value << 1);
1523
- nextValue = i64_shl ( value , i64_1 ) ;
1535
+ nextValue = i64_shl ( value , i64_one ) ;
1524
1536
} else if ( c == CharCode . _1 ) {
1525
1537
// value = (value << 1) + 1;
1526
1538
nextValue = i64_add (
1527
- i64_shl ( value , i64_1 ) ,
1528
- i64_1
1539
+ i64_shl ( value , i64_one ) ,
1540
+ i64_one
1529
1541
) ;
1530
1542
} else if ( c == CharCode . _ ) {
1531
1543
if ( sepEnd == pos ) {
@@ -1569,27 +1581,23 @@ export class Tokenizer extends DiagnosticEmitter {
1569
1581
}
1570
1582
1571
1583
readFloat ( ) : f64 {
1572
- // var text = this.source.text;
1573
- // if (text.charCodeAt(this.pos) == CharCode._0 && this.pos + 2 < this.end) {
1574
- // switch (text.charCodeAt(this.pos + 1)) {
1575
- // case CharCode.X:
1576
- // case CharCode.x: {
1577
- // this.pos += 2;
1578
- // return this.readHexFloat();
1579
- // }
1580
- // }
1581
- // }
1584
+ var text = this . source . text ;
1585
+ if ( text . charCodeAt ( this . pos ) == CharCode . _0 && this . pos + 2 < this . end ) {
1586
+ if ( ( text . charCodeAt ( this . pos + 1 ) | 32 ) == CharCode . x ) {
1587
+ return this . readHexFloat ( ) ;
1588
+ }
1589
+ }
1582
1590
return this . readDecimalFloat ( ) ;
1583
1591
}
1584
1592
1585
1593
readDecimalFloat ( ) : f64 {
1586
1594
var text = this . source . text ;
1587
1595
var end = this . end ;
1588
1596
var start = this . pos ;
1589
- var sepCount = this . readDecimalFloatPartial ( false ) ;
1597
+ var sepCount = this . readFloatPartial ( false , false ) ;
1590
1598
if ( this . pos < end && text . charCodeAt ( this . pos ) == CharCode . DOT ) {
1591
1599
++ this . pos ;
1592
- sepCount += this . readDecimalFloatPartial ( ) ;
1600
+ sepCount += this . readFloatPartial ( true , false ) ;
1593
1601
}
1594
1602
if ( this . pos < end ) {
1595
1603
let c = text . charCodeAt ( this . pos ) ;
@@ -1601,7 +1609,7 @@ export class Tokenizer extends DiagnosticEmitter {
1601
1609
) {
1602
1610
++ this . pos ;
1603
1611
}
1604
- sepCount += this . readDecimalFloatPartial ( ) ;
1612
+ sepCount += this . readFloatPartial ( true , false ) ;
1605
1613
}
1606
1614
}
1607
1615
let result = text . substring ( start , this . pos ) ;
@@ -1610,7 +1618,7 @@ export class Tokenizer extends DiagnosticEmitter {
1610
1618
}
1611
1619
1612
1620
/** Reads past one section of a decimal float literal. Returns the number of separators encountered. */
1613
- private readDecimalFloatPartial ( allowLeadingZeroSep : bool = true ) : u32 {
1621
+ private readFloatPartial ( allowLeadingZeroSep : bool , isHexadecimal : bool ) : u32 {
1614
1622
var text = this . source . text ;
1615
1623
var pos = this . pos ;
1616
1624
var start = pos ;
@@ -1620,7 +1628,6 @@ export class Tokenizer extends DiagnosticEmitter {
1620
1628
1621
1629
while ( pos < end ) {
1622
1630
let c = text . charCodeAt ( pos ) ;
1623
-
1624
1631
if ( c == CharCode . _ ) {
1625
1632
if ( sepEnd == pos ) {
1626
1633
this . error (
@@ -1637,8 +1644,12 @@ export class Tokenizer extends DiagnosticEmitter {
1637
1644
}
1638
1645
sepEnd = pos + 1 ;
1639
1646
++ sepCount ;
1640
- } else if ( ! isDecimal ( c ) ) {
1641
- break ;
1647
+ } else {
1648
+ if ( isHexadecimal ) {
1649
+ if ( ! isHex ( c ) ) break ;
1650
+ } else {
1651
+ if ( ! isDecimal ( c ) ) break ;
1652
+ }
1642
1653
}
1643
1654
++ pos ;
1644
1655
}
@@ -1655,7 +1666,34 @@ export class Tokenizer extends DiagnosticEmitter {
1655
1666
}
1656
1667
1657
1668
readHexFloat ( ) : f64 {
1658
- throw new Error ( "not implemented" ) ; // TBD
1669
+ var text = this . source . text ;
1670
+ var pos = this . pos ;
1671
+ var start = pos ;
1672
+ var end = this . end ;
1673
+
1674
+ this . pos += 2 ; // skip 0x
1675
+ var sepCount = this . readFloatPartial ( false , true ) ;
1676
+ if ( this . pos < end && text . charCodeAt ( this . pos ) == CharCode . DOT ) {
1677
+ ++ this . pos ;
1678
+ sepCount += this . readFloatPartial ( true , true ) ;
1679
+ }
1680
+ if ( this . pos < end ) {
1681
+ let c = text . charCodeAt ( this . pos ) ;
1682
+ if ( ( c | 32 ) == CharCode . p ) {
1683
+ if (
1684
+ ++ this . pos < end &&
1685
+ ( c = text . charCodeAt ( this . pos ) ) == CharCode . MINUS || c == CharCode . PLUS &&
1686
+ isHex ( text . charCodeAt ( this . pos + 1 ) )
1687
+ ) {
1688
+ ++ this . pos ;
1689
+ }
1690
+ sepCount += this . readFloatPartial ( true , false ) ;
1691
+ }
1692
+ }
1693
+ let result = text . substring ( start , this . pos ) ;
1694
+ if ( sepCount ) result = result . replaceAll ( "_" , "" ) ;
1695
+ // console.log(">>>> ", start, this.pos, result);
1696
+ return parseHexFloat ( result ) ;
1659
1697
}
1660
1698
1661
1699
readHexadecimalEscape ( remain : i32 = 2 , startIfTaggedTemplate : i32 = - 1 ) : string {
@@ -1665,12 +1703,10 @@ export class Tokenizer extends DiagnosticEmitter {
1665
1703
var end = this . end ;
1666
1704
while ( pos < end ) {
1667
1705
let c = text . charCodeAt ( pos ++ ) ;
1668
- if ( c >= CharCode . _0 && c <= CharCode . _9 ) {
1706
+ if ( isDecimal ( c ) ) {
1669
1707
value = ( value << 4 ) + c - CharCode . _0 ;
1670
- } else if ( c >= CharCode . A && c <= CharCode . F ) {
1671
- value = ( value << 4 ) + c + ( 10 - CharCode . A ) ;
1672
- } else if ( c >= CharCode . a && c <= CharCode . f ) {
1673
- value = ( value << 4 ) + c + ( 10 - CharCode . a ) ;
1708
+ } else if ( isHexPart ( c ) ) {
1709
+ value = ( value << 4 ) + ( c | 32 ) + ( 10 - CharCode . a ) ;
1674
1710
} else if ( ~ startIfTaggedTemplate ) {
1675
1711
this . pos = -- pos ;
1676
1712
return text . substring ( startIfTaggedTemplate , pos ) ;
0 commit comments