Support _ in String[toInt|toIntOrNull|toFloat|toFloatOrNull] (#580)

The logic is the same as the Pkl parser
This commit is contained in:
Islon Scherer
2024-07-16 19:24:59 +02:00
committed by GitHub
parent b5e011dae1
commit 24cc95abcc
3 changed files with 37 additions and 6 deletions
@@ -768,7 +768,7 @@ public final class StringNodes {
@Specialization @Specialization
protected long eval(String self) { protected long eval(String self) {
try { try {
return Long.parseLong(self.replaceAll("_", "")); return Long.parseLong(removeUnderlinesFromNumber(self));
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
throw exceptionBuilder() throw exceptionBuilder()
.evalError("cannotParseStringAs", "Int") .evalError("cannotParseStringAs", "Int")
@@ -783,7 +783,7 @@ public final class StringNodes {
@Specialization @Specialization
protected Object eval(String self) { protected Object eval(String self) {
try { try {
return Long.parseLong(self.replaceAll("_", "")); return Long.parseLong(removeUnderlinesFromNumber(self));
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
return VmNull.withoutDefault(); return VmNull.withoutDefault();
} }
@@ -795,7 +795,7 @@ public final class StringNodes {
@Specialization @Specialization
protected double eval(String self) { protected double eval(String self) {
try { try {
return Double.parseDouble(self); return Double.parseDouble(removeUnderlinesFromNumber(self));
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
throw exceptionBuilder() throw exceptionBuilder()
.evalError("cannotParseStringAs", "Float") .evalError("cannotParseStringAs", "Float")
@@ -810,7 +810,7 @@ public final class StringNodes {
@Specialization @Specialization
protected Object eval(String self) { protected Object eval(String self) {
try { try {
return Double.parseDouble(self); return Double.parseDouble(removeUnderlinesFromNumber(self));
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
return VmNull.withoutDefault(); return VmNull.withoutDefault();
} }
@@ -934,4 +934,23 @@ public final class StringNodes {
var replacement = mapper.applyString(regexMatch); var replacement = mapper.applyString(regexMatch);
return Matcher.quoteReplacement(replacement); return Matcher.quoteReplacement(replacement);
} }
/**
* Removes `_` from numbers to be parsed to be compatible with how Pkl parses numbers. Will return
* the string unmodified if it's invalid.
*/
private static String removeUnderlinesFromNumber(String number) {
var builder = new StringBuilder();
var numberStart = true;
for (var i = 0; i < number.length(); i++) {
var c = number.charAt(i);
if (c != '_') {
builder.append(c);
} else if (numberStart) return number;
numberStart = c == '.' || c == 'e' || c == 'E';
}
return builder.toString();
}
} }
@@ -233,19 +233,21 @@ examples {
module.catch(() -> "9223372036854775808".toInt()) module.catch(() -> "9223372036854775808".toInt())
module.catch(() -> "-9223372036854775809".toInt()) module.catch(() -> "-9223372036854775809".toInt())
module.catch(() -> "abc".toInt()) module.catch(() -> "abc".toInt())
module.catch(() -> "_1_000".toInt())
} }
["toIntOrNull()"] { ["toIntOrNull()"] {
"123".toIntOrNull() "123".toIntOrNull()
"-123".toIntOrNull() "-123".toIntOrNull()
"1_2__3___".toInt() "1_2__3___".toIntOrNull()
"-1_2__3___".toInt() "-1_2__3___".toIntOrNull()
"0".toIntOrNull() "0".toIntOrNull()
"-0".toIntOrNull() "-0".toIntOrNull()
"1.2".toIntOrNull() "1.2".toIntOrNull()
"9223372036854775808".toIntOrNull() "9223372036854775808".toIntOrNull()
"-9223372036854775809".toIntOrNull() "-9223372036854775809".toIntOrNull()
"abc".toIntOrNull() "abc".toIntOrNull()
"_1_2__3___".toIntOrNull()
} }
["toFloat()"] { ["toFloat()"] {
@@ -282,13 +284,17 @@ examples {
"-.45e-9".toFloat() "-.45e-9".toFloat()
"9e1024".toFloat() "9e1024".toFloat()
"-9e1024".toFloat() "-9e1024".toFloat()
"-1_2__3___.2_e+1_".toFloat()
module.catch(() -> "abc".toFloat()) module.catch(() -> "abc".toFloat())
module.catch(() -> "123._34".toFloat())
module.catch(() -> "123e_34".toFloat())
} }
["toFloatOrNull()"] { ["toFloatOrNull()"] {
"0".toFloatOrNull() "0".toFloatOrNull()
"-0".toFloatOrNull() "-0".toFloatOrNull()
"abc".toFloatOrNull() "abc".toFloatOrNull()
"_123_.1_".toFloatOrNull()
} }
["take()"] { ["take()"] {
@@ -191,6 +191,7 @@ examples {
"Cannot parse string as `Int`. String: \"9223372036854775808\"" "Cannot parse string as `Int`. String: \"9223372036854775808\""
"Cannot parse string as `Int`. String: \"-9223372036854775809\"" "Cannot parse string as `Int`. String: \"-9223372036854775809\""
"Cannot parse string as `Int`. String: \"abc\"" "Cannot parse string as `Int`. String: \"abc\""
"Cannot parse string as `Int`. String: \"_1_000\""
} }
["toIntOrNull()"] { ["toIntOrNull()"] {
123 123
@@ -203,6 +204,7 @@ examples {
null null
null null
null null
null
} }
["toFloat()"] { ["toFloat()"] {
0.0 0.0
@@ -238,12 +240,16 @@ examples {
-4.5E-10 -4.5E-10
Infinity Infinity
-Infinity -Infinity
-1232.0
"Cannot parse string as `Float`. String: \"abc\"" "Cannot parse string as `Float`. String: \"abc\""
"Cannot parse string as `Float`. String: \"123._34\""
"Cannot parse string as `Float`. String: \"123e_34\""
} }
["toFloatOrNull()"] { ["toFloatOrNull()"] {
0.0 0.0
-0.0 -0.0
null null
null
} }
["take()"] { ["take()"] {
"" ""