@@ -21,6 +21,8 @@ import config.Feature.migrateTo3
2121import config .SourceVersion .`3.0`
2222import reporting .{NoProfile , Profile }
2323
24+ import java .lang .Character .isDigit
25+
2426object Scanners {
2527
2628 /** Offset into source character array */
@@ -152,9 +154,9 @@ object Scanners {
152154 strVal = litBuf.toString
153155 litBuf.clear()
154156
155- @ inline def isNumberSeparator (c : Char ): Boolean = c == '_'
157+ inline def isNumberSeparator (c : Char ): Boolean = c == '_'
156158
157- @ inline def removeNumberSeparators (s : String ): String = if ( s.indexOf('_' ) == - 1 ) s else s.replace(" _" , " " )
159+ inline def removeNumberSeparators (s : String ): String = if s.indexOf('_' ) == - 1 then s else s.replace(" _" , " " )
158160
159161 // disallow trailing numeric separator char, but continue lexing
160162 def checkNoTrailingSeparator (): Unit =
@@ -887,7 +889,7 @@ object Scanners {
887889 // case 'b' | 'B' => base = 2 ; nextChar()
888890 case _ => base = 10 ; putChar('0' )
889891 }
890- if ( base != 10 && ! isNumberSeparator(ch) && digit2int(ch, base) < 0 )
892+ if base != 10 && ! isNumberSeparator(ch) && digit2int(ch, base) < 0 then
891893 error(" invalid literal number" )
892894 }
893895 fetchLeadingZero()
@@ -967,7 +969,7 @@ object Scanners {
967969 case '.' =>
968970 nextChar()
969971 if ('0' <= ch && ch <= '9' ) {
970- putChar('.' ); getFraction(); setStrVal()
972+ putChar('.' ); getFraction()
971973 }
972974 else
973975 token = DOT
@@ -1427,7 +1429,7 @@ object Scanners {
14271429 /** read fractional part and exponent of floating point number
14281430 * if one is present.
14291431 */
1430- protected def getFraction (): Unit = {
1432+ protected def getFraction (): Unit =
14311433 token = DECILIT
14321434 while ('0' <= ch && ch <= '9' || isNumberSeparator(ch)) {
14331435 putChar(ch)
@@ -1465,41 +1467,44 @@ object Scanners {
14651467 token = FLOATLIT
14661468 }
14671469 checkNoLetter()
1468- }
1470+ setStrVal()
1471+ end getFraction
14691472 def checkNoLetter (): Unit =
14701473 if (isIdentifierPart(ch) && ch >= ' ' )
14711474 error(" Invalid literal number" )
14721475
14731476 /** Read a number into strVal and set base
14741477 */
1475- protected def getNumber (): Unit = {
1476- while (isNumberSeparator(ch) || digit2int(ch, base) >= 0 ) {
1477- putChar(ch)
1478- nextChar()
1479- }
1480- checkNoTrailingSeparator()
1481- token = INTLIT
1482- if (base == 10 && ch == '.' ) {
1483- val lch = lookaheadChar()
1484- if ('0' <= lch && lch <= '9' ) {
1485- putChar('.' )
1486- nextChar()
1487- getFraction()
1488- }
1489- }
1490- else (ch : @ switch) match {
1491- case 'e' | 'E' | 'f' | 'F' | 'd' | 'D' =>
1492- if (base == 10 ) getFraction()
1493- case 'l' | 'L' =>
1478+ protected def getNumber (): Unit =
1479+ def consumeDigits (): Unit =
1480+ while isNumberSeparator(ch) || digit2int(ch, base) >= 0 do
1481+ putChar(ch)
14941482 nextChar()
1495- token = LONGLIT
1496- case _ =>
1497- }
1483+ // at dot with digit following
1484+ def restOfNonIntegralNumber (): Unit =
1485+ putChar('.' )
1486+ nextChar()
1487+ getFraction()
1488+ // 1l is an acknowledged bad practice
1489+ def lintel (): Unit =
1490+ if ch == 'l' then
1491+ val msg = " Lowercase el for long is not recommended because it is easy to confuse with numeral 1; use uppercase L instead"
1492+ report.deprecationWarning(msg, sourcePos(offset + litBuf.length))
1493+ // after int: 5e7f, 42L, 42.toDouble but not 42b.
1494+ def restOfNumber (): Unit =
1495+ ch match
1496+ case 'e' | 'E' | 'f' | 'F' | 'd' | 'D' => getFraction()
1497+ case 'l' | 'L' => lintel() ; token = LONGLIT ; setStrVal() ; nextChar()
1498+ case _ => token = INTLIT ; setStrVal() ; checkNoLetter()
1499+
1500+ // consume leading digits
1501+ consumeDigits()
14981502
14991503 checkNoTrailingSeparator()
15001504
1501- setStrVal()
1502- }
1505+ val detectedFloat : Boolean = base == 10 && ch == '.' && isDigit(lookaheadChar())
1506+ if detectedFloat then restOfNonIntegralNumber() else restOfNumber()
1507+ end getNumber
15031508
15041509 private def finishCharLit (): Unit = {
15051510 nextChar()
0 commit comments