@@ -20,6 +20,8 @@ import config.Feature
20
20
import config .Feature .migrateTo3
21
21
import config .SourceVersion .`3.0`
22
22
23
+ import java .lang .Character .isDigit
24
+
23
25
object Scanners {
24
26
25
27
/** Offset into source character array */
@@ -156,9 +158,9 @@ object Scanners {
156
158
strVal = litBuf.toString
157
159
litBuf.clear()
158
160
159
- @ inline def isNumberSeparator (c : Char ): Boolean = c == '_'
161
+ inline def isNumberSeparator (c : Char ): Boolean = c == '_'
160
162
161
- @ inline def removeNumberSeparators (s : String ): String = if ( s.indexOf('_' ) == - 1 ) s else s.replace(" _" , " " )
163
+ inline def removeNumberSeparators (s : String ): String = if s.indexOf('_' ) == - 1 then s else s.replace(" _" , " " )
162
164
163
165
// disallow trailing numeric separator char, but continue lexing
164
166
def checkNoTrailingSeparator (): Unit =
@@ -849,7 +851,7 @@ object Scanners {
849
851
// case 'b' | 'B' => base = 2 ; nextChar()
850
852
case _ => base = 10 ; putChar('0' )
851
853
}
852
- if ( base != 10 && ! isNumberSeparator(ch) && digit2int(ch, base) < 0 )
854
+ if base != 10 && ! isNumberSeparator(ch) && digit2int(ch, base) < 0 then
853
855
error(" invalid literal number" )
854
856
}
855
857
fetchLeadingZero()
@@ -929,7 +931,7 @@ object Scanners {
929
931
case '.' =>
930
932
nextChar()
931
933
if ('0' <= ch && ch <= '9' ) {
932
- putChar('.' ); getFraction(); setStrVal()
934
+ putChar('.' ); getFraction()
933
935
}
934
936
else
935
937
token = DOT
@@ -1389,7 +1391,7 @@ object Scanners {
1389
1391
/** read fractional part and exponent of floating point number
1390
1392
* if one is present.
1391
1393
*/
1392
- protected def getFraction (): Unit = {
1394
+ protected def getFraction (): Unit =
1393
1395
token = DECILIT
1394
1396
while ('0' <= ch && ch <= '9' || isNumberSeparator(ch)) {
1395
1397
putChar(ch)
@@ -1427,41 +1429,44 @@ object Scanners {
1427
1429
token = FLOATLIT
1428
1430
}
1429
1431
checkNoLetter()
1430
- }
1432
+ setStrVal()
1433
+ end getFraction
1431
1434
def checkNoLetter (): Unit =
1432
1435
if (isIdentifierPart(ch) && ch >= ' ' )
1433
1436
error(" Invalid literal number" )
1434
1437
1435
1438
/** Read a number into strVal and set base
1436
1439
*/
1437
- protected def getNumber (): Unit = {
1438
- while (isNumberSeparator(ch) || digit2int(ch, base) >= 0 ) {
1439
- putChar(ch)
1440
- nextChar()
1441
- }
1442
- checkNoTrailingSeparator()
1443
- token = INTLIT
1444
- if (base == 10 && ch == '.' ) {
1445
- val lch = lookaheadChar()
1446
- if ('0' <= lch && lch <= '9' ) {
1447
- putChar('.' )
1448
- nextChar()
1449
- getFraction()
1450
- }
1451
- }
1452
- else (ch : @ switch) match {
1453
- case 'e' | 'E' | 'f' | 'F' | 'd' | 'D' =>
1454
- if (base == 10 ) getFraction()
1455
- case 'l' | 'L' =>
1440
+ protected def getNumber (): Unit =
1441
+ def consumeDigits (): Unit =
1442
+ while isNumberSeparator(ch) || digit2int(ch, base) >= 0 do
1443
+ putChar(ch)
1456
1444
nextChar()
1457
- token = LONGLIT
1458
- case _ =>
1459
- }
1445
+ // at dot with digit following
1446
+ def restOfNonIntegralNumber (): Unit =
1447
+ putChar('.' )
1448
+ nextChar()
1449
+ getFraction()
1450
+ // 1l is an acknowledged bad practice
1451
+ def lintel (): Unit =
1452
+ if ch == 'l' then
1453
+ val msg = " Lowercase el for long is not recommended because it is easy to confuse with numeral 1; use uppercase L instead"
1454
+ report.deprecationWarning(msg, sourcePos(offset + litBuf.length))
1455
+ // after int: 5e7f, 42L, 42.toDouble but not 42b.
1456
+ def restOfNumber (): Unit =
1457
+ ch match
1458
+ case 'e' | 'E' | 'f' | 'F' | 'd' | 'D' => getFraction()
1459
+ case 'l' | 'L' => lintel() ; token = LONGLIT ; setStrVal() ; nextChar()
1460
+ case _ => token = INTLIT ; setStrVal() ; checkNoLetter()
1461
+
1462
+ // consume leading digits
1463
+ consumeDigits()
1460
1464
1461
1465
checkNoTrailingSeparator()
1462
1466
1463
- setStrVal()
1464
- }
1467
+ val detectedFloat : Boolean = base == 10 && ch == '.' && isDigit(lookaheadChar())
1468
+ if detectedFloat then restOfNonIntegralNumber() else restOfNumber()
1469
+ end getNumber
1465
1470
1466
1471
private def finishCharLit (): Unit = {
1467
1472
nextChar()
0 commit comments