8000 SI-10148 Follow Java for float literals · scala/scala@a262aab · GitHub
[go: up one dir, main page]

Skip to content

Commit a262aab

Browse files
committed
SI-10148 Follow Java for float literals
Use `Float.parseFloat` instead of converting from Double. Error when a value rounds to zero.
1 parent 827d69d commit a262aab

File tree

5 files changed

+60
-10
lines changed

5 files changed

+60
-10
lines changed

src/compiler/scala/tools/nsc/ast/parser/Parsers.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1263,8 +1263,8 @@ self =>
12631263
case CHARLIT => in.charVal
12641264
case INTLIT => in.intVal(isNegated).toInt
12651265
case LONGLIT => in.intVal(isNegated)
1266-
case FLOATLIT => in.floatVal(isNegated).toFloat
1267-
case DOUBLELIT => in.floatVal(isNegated)
1266+
case FLOATLIT => in.floatVal(isNegated)
1267+
case DOUBLELIT => in.doubleVal(isNegated)
12681268
case STRINGLIT | STRINGPART => in.strVal.intern()
12691269
case TRUE => true
12701270
case FALSE => false

src/compiler/scala/tools/nsc/ast/parser/Scanners.scala

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -972,23 +972,45 @@ trait Scanners extends ScannersCommon {
972972

973973
def intVal: Long = intVal(negated = false)
974974

975-
/** Convert current strVal, base to double value
975+
/** Convert current strVal, base to float value.
976976
*/
977-
def floatVal(negated: Boolean): Double = {
978-
val limit: Double = if (token == DOUBLELIT) Double.MaxValue else Float.MaxValue
977+
def floatVal(negated: Boolean): Float = {
979978
try {
980-
val value: Double = java.lang.Double.valueOf(strVal).doubleValue()
981-
if (value > limit)
979+
val value: Float = java.lang.Float.parseFloat(strVal)
980+
if (value > Float.MaxValue)
982981
syntaxError("floating point number too large")
982+
val zeroly = "0.fF"
983+
if (value == 0.0f && strVal.exists(c => !zeroly.contains(c)))
984+
syntaxError("floating point number too small")
983985
if (negated) -value else value
984986
} catch {
985987
case _: NumberFormatException =>
986988
syntaxError("malformed floating point number")
989+
0.0f
990+
}
991+
}
992+
993+
def floatVal: Float = floatVal(negated = false)
994+
995+
/** Convert current strVal, base to double value.
996+
*/
997+
def doubleVal(negated: Boolean): Double = {
998+
try {
999+
val value: Double = java.lang.Double.parseDouble(strVal)
1000+
if (value > Double.MaxValue)
1001+
syntaxError("double precision floating point number too large")
1002+
val zeroly = "0.dD"
1003+
if (value == 0.0d && strVal.exists(c => !zeroly.contains(c)))
1004+
syntaxError("double precision floating point number too small")
1005+
if (negated) -value else value
1006+
} catch {
1007+
case _: NumberFormatException =>
1008+
syntaxError("malformed double precision floating point number")
9871009
0.0
9881010
}
9891011
}
9901012

991-
def floatVal: Double = floatVal(negated = false)
1013+
def doubleVal: Double = doubleVal(negated = false)
9921014

9931015
def checkNoLetter(): Unit = {
9941016
if (isIdentifierPart(ch) && ch >= ' ')

test/files/neg/literals.check

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,18 @@ literals.scala:23: error: missing integer number
1919
literals.scala:27: error: Decimal integer literals may not have a leading zero. (Octal syntax is obsolete.)
2020
def tooManyZeros: Int = 00 // line 26: no leading zero
2121
^
22+
literals.scala:40: error: floating point number too small
23+
def tooTiny: Float = { 0.7e-45f } // floating point number too small
24+
^
25+
literals.scala:42: error: double precision floating point number too small
26+
def twoTiny: Double = { 2.0e-324 } // double precision floating point number too small
27+
^
28+
literals.scala:44: error: floating point number too large
29+
def tooHuge: Float = { 3.4028236E38f } // floating point number too large
30+
^
31+
literals.scala:46: error: double precision floating point number too large
32+
def twoHuge: Double = { 1.7976931348623159e308 } // double precision floating point number too large
33+
^
2234
literals.scala:14: error: identifier expected but '}' found.
2335
def orphanDot: Int = { 9. } // line 12: ident expected
2436
^
@@ -37,4 +49,4 @@ literals.scala:29: error: ';' expected but 'def' found.
3749
literals.scala:33: error: identifier expected but 'def' found.
3850
def zeroOfNineDot: Int = 09. // line 32: malformed integer, ident expected
3951
^
40-
13 errors found
52+
17 errors found

test/files/neg/literals.scala

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11

22
/* This took me literally all day.
3-
*/
3+
*/
44
trait RejectedLiterals {
55

66
def missingHex: Int = { 0x } // line 4: was: not reported, taken as zero
@@ -34,3 +34,14 @@ trait Braceless {
3434

3535
def noHexFloat: Double = 0x1.2 // line 34: ';' expected but double literal found.
3636
}
37+
38+
trait MoreSadness {
39+
40+
def tooTiny: Float = { 0.7e-45f } // floating point number too small
41+
42+
def twoTiny: Double = { 2.0e-324 } // double precision floating point number too small
43+
44+
def tooHuge: Float = { 3.4028236E38f } // floating point number too large
45+
46+
def twoHuge: Double = { 1.7976931348623159e308 } // double precision floating point number too large
47+
}

test/files/run/literals.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ object Test {
8484
check_success("3.14f == 3.14f", 3.14f, 3.14f)
8585
check_success("6.022e23f == 6.022e23f", 6.022e23f, 6.022e23f)
8686
check_success("09f == 9.0f", 09f, 9.0f)
87+
check_success("1.00000017881393421514957253748434595763683319091796875001f == 1.0000001f",
88+
1.00000017881393421514957253748434595763683319091796875001f,
89+
1.0000001f)
90+
check_success("3.4028235E38f == Float.MaxValue", 3.4028235E38f, Float.MaxValue)
8791
check_success("1.asInstanceOf[Float] == 1.0", 1.asInstanceOf[Float], 1.0f)
8892
check_success("1l.asInstanceOf[Float] == 1.0", 1l.asInstanceOf[Float], 1.0f)
8993

@@ -97,6 +101,7 @@ object Test {
97101
check_success("3.14 == 3.14", 3.14, 3.14)
98102
check_success("1e-9d == 1.0e-9", 1e-9d, 1.0e-9)
99103
check_success("1e137 == 1.0e137", 1e137, 1.0e137)
104+
check_success("1.7976931348623157e308d == Double.MaxValue", 1.7976931348623157e308d, Double.MaxValue)
100105
check_success("1.asInstanceOf[Double] == 1.0", 1.asInstanceOf[Double], 1.0)
101106
check_success("1l.asInstanceOf[Double] == 1.0", 1l.asInstanceOf[Double], 1.0)
102107

0 commit comments

Comments
 (0)
0