forked from Rust-related/RustPython
Merge pull request #1567 from HyeockJinKim/issue1527
Modify str to float
This commit is contained in:
@@ -304,3 +304,15 @@ assert float(1e-5).__repr__() == "1e-05"
|
||||
assert float(1e-4).__repr__() == "0.0001"
|
||||
assert float(1.2345678901234567890).__repr__() == "1.2345678901234567"
|
||||
assert float(1.2345678901234567890e308).__repr__() == "1.2345678901234567e+308"
|
||||
|
||||
assert float('0_0') == 0.0
|
||||
assert float('.0') == 0.0
|
||||
assert float('0.') == 0.0
|
||||
|
||||
assert_raises(ValueError, lambda: float('0._0'))
|
||||
assert_raises(ValueError, lambda: float('0_.0'))
|
||||
assert_raises(ValueError, lambda: float('._0'))
|
||||
assert_raises(ValueError, lambda: float('0_'))
|
||||
assert_raises(ValueError, lambda: float('0._'))
|
||||
assert_raises(ValueError, lambda: float('_.0'))
|
||||
assert_raises(ValueError, lambda: float('._0'))
|
||||
|
||||
@@ -597,31 +597,56 @@ impl PyFloat {
|
||||
}
|
||||
}
|
||||
|
||||
fn str_to_float(vm: &VirtualMachine, literal: &str) -> PyResult<f64> {
|
||||
if literal.starts_with('_') || literal.ends_with('_') {
|
||||
return Err(invalid_convert(vm, literal));
|
||||
}
|
||||
|
||||
let mut buf = String::with_capacity(literal.len());
|
||||
let mut last_tok: Option<char> = None;
|
||||
for c in literal.chars() {
|
||||
if !(c.is_ascii_alphanumeric() || c == '_' || c == '+' || c == '-' || c == '.') {
|
||||
return Err(invalid_convert(vm, literal));
|
||||
}
|
||||
|
||||
if !c.is_ascii_alphanumeric() {
|
||||
if let Some(l) = last_tok {
|
||||
if !l.is_ascii_alphanumeric() {
|
||||
return Err(invalid_convert(vm, literal));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if c != '_' {
|
||||
buf.push(c);
|
||||
}
|
||||
last_tok = Some(c);
|
||||
}
|
||||
|
||||
if let Ok(f) = lexical::parse(buf.as_str()) {
|
||||
Ok(f)
|
||||
} else {
|
||||
Err(invalid_convert(vm, literal))
|
||||
}
|
||||
}
|
||||
|
||||
fn invalid_convert(vm: &VirtualMachine, literal: &str) -> PyObjectRef {
|
||||
vm.new_value_error(format!("could not convert string to float: '{}'", literal))
|
||||
}
|
||||
|
||||
fn to_float(vm: &VirtualMachine, obj: &PyObjectRef) -> PyResult<f64> {
|
||||
let value = if objtype::isinstance(&obj, &vm.ctx.float_type()) {
|
||||
get_value(&obj)
|
||||
} else if objtype::isinstance(&obj, &vm.ctx.int_type()) {
|
||||
objint::get_float_value(&obj, vm)?
|
||||
} else if objtype::isinstance(&obj, &vm.ctx.str_type()) {
|
||||
match lexical::parse(objstr::get_value(&obj).trim()) {
|
||||
Ok(f) => f,
|
||||
Err(_) => {
|
||||
let arg_repr = vm.to_pystr(obj)?;
|
||||
return Err(vm.new_value_error(format!(
|
||||
"could not convert string to float: '{}'",
|
||||
arg_repr
|
||||
)));
|
||||
}
|
||||
}
|
||||
str_to_float(vm, objstr::get_value(&obj).trim())?
|
||||
} else if objtype::isinstance(&obj, &vm.ctx.bytes_type()) {
|
||||
match lexical::parse(objbytes::get_value(&obj).as_slice()) {
|
||||
Ok(f) => f,
|
||||
Err(_) => {
|
||||
let arg_repr = vm.to_pystr(obj)?;
|
||||
return Err(vm.new_value_error(format!(
|
||||
"could not convert string to float: '{}'",
|
||||
arg_repr
|
||||
)));
|
||||
return Err(invalid_convert(vm, arg_repr.as_str()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user