Parse FP literals without coercing to int. This allows parsing 64-bit

floats. However, if someone writes a literal that can't be represented
precisely in 64 bits, the front-end will accept it while the back-end
will (presumably) complain.
This commit is contained in:
Tim Chevalier 2011-03-24 17:12:24 -07:00
parent e2d6475308
commit a47cd50dfb
4 changed files with 71 additions and 39 deletions

View File

@ -572,7 +572,8 @@ docsnap: doc/rust.pdf
FLOAT_XFAILS := $(S)src/test/run-pass/float.rs \
$(S)src/test/run-pass/float2.rs \
$(S)src/test/run-pass/float-signature.rs
$(S)src/test/run-pass/float-signature.rs \
$(S)src/test/run-pass/floatlits.rs
# Temporarily xfail tests broken by the nominal-tags change.
@ -641,8 +642,7 @@ TEST_XFAILS_BOOT := $(TASK_XFAILS) \
writing-through-read-alias.rs) \
$(S)src/test/bench/shootout/nbody.rs
TEST_XFAILS_STAGE0 := $(FLOAT_XFAILS) \
$(addprefix $(S)src/test/run-pass/, \
TEST_XFAILS_STAGE0 := $(addprefix $(S)src/test/run-pass/, \
acyclic-unwind.rs \
alt-pattern-drop.rs \
alt-type-simple.rs \

View File

@ -318,47 +318,65 @@ impure fn consume_block_comment(reader rdr) {
be consume_any_whitespace(rdr);
}
impure fn scan_dec_digits(reader rdr) -> int {
auto c = rdr.curr();
fn digits_to_string(str s) -> int {
let int accum_int = 0;
let int i = 0;
while (is_dec_digit(c) || c == '_') {
if (c != '_') {
accum_int *= 10;
accum_int += dec_digit_val(c);
}
rdr.bump();
c = rdr.curr();
for (u8 c in s) {
accum_int *= 10;
accum_int += dec_digit_val(c as char);
}
ret accum_int;
}
impure fn scan_exponent(reader rdr) -> option.t[int] {
impure fn scan_exponent(reader rdr) -> option.t[str] {
auto c = rdr.curr();
auto sign = 1;
auto res = "";
if (c == 'e' || c == 'E') {
res += _str.from_bytes(vec(c as u8));
rdr.bump();
c = rdr.curr();
if (c == '-') {
sign = -1;
rdr.bump();
} else if (c == '+') {
if (c == '-' || c == '+') {
res += _str.from_bytes(vec(c as u8));
rdr.bump();
}
auto exponent = scan_dec_digits(rdr);
ret(some(sign * exponent));
if (_str.byte_len(exponent) > 0u) {
ret(some(res + exponent));
}
else {
log ("scan_exponent: bad fp literal");
fail;
}
}
else {
ret none[int];
ret none[str];
}
}
impure fn scan_dec_digits(reader rdr) -> str {
auto c = rdr.curr();
let str res = "";
while (is_dec_digit (c) || c == '_') {
if (c != '_') {
res += _str.from_bytes(vec(c as u8));
}
rdr.bump();
c = rdr.curr();
}
ret res;
}
impure fn scan_number(mutable char c, reader rdr) -> token.token {
auto accum_int = 0;
let str dec_str = "";
let bool is_dec_integer = false;
auto n = rdr.next();
if (c == '0' && n == 'x') {
@ -386,7 +404,12 @@ impure fn scan_number(mutable char c, reader rdr) -> token.token {
c = rdr.curr();
}
} else {
accum_int = scan_dec_digits(rdr);
dec_str = scan_dec_digits(rdr);
is_dec_integer = true;
}
if (is_dec_integer) {
accum_int = digits_to_string(dec_str);
}
c = rdr.curr();
@ -443,20 +466,19 @@ impure fn scan_number(mutable char c, reader rdr) -> token.token {
}
}
c = rdr.curr();
if (c == '.') {
// Parse a floating-point number.
rdr.bump();
auto accum_int1 = scan_dec_digits(rdr);
auto base_str = _int.to_str(accum_int, 10u) + "."
+ _int.to_str(accum_int1, 10u);
auto dec_part = scan_dec_digits(rdr);
auto float_str = dec_str + "." + dec_part;
c = rdr.curr();
auto exponent_str = "";
let option.t[int] maybe_exponent = scan_exponent(rdr);
alt(maybe_exponent) {
case(some[int](?i)) {
exponent_str = "e" + _int.to_str(i, 10u);
auto exponent_str = scan_exponent(rdr);
alt (exponent_str) {
case (some[str](?s)) {
float_str += s;
}
case(none[int]) {
case (none[str]) {
}
}
@ -468,27 +490,28 @@ impure fn scan_number(mutable char c, reader rdr) -> token.token {
if (c == '3' && n == '2') {
rdr.bump(); rdr.bump();
ret token.LIT_MACH_FLOAT(util.common.ty_f32,
base_str + exponent_str);
float_str);
}
else if (c == '6' && n == '4') {
rdr.bump(); rdr.bump();
ret token.LIT_MACH_FLOAT(util.common.ty_f64,
base_str + exponent_str);
float_str);
/* FIXME: if this is out of range for either a 32-bit or
64-bit float, it won't be noticed till the back-end */
}
}
else {
ret token.LIT_FLOAT(base_str + exponent_str);
ret token.LIT_FLOAT(float_str);
}
}
auto maybe_exponent = scan_exponent(rdr);
alt(maybe_exponent) {
case(some[int](?i)) {
ret token.LIT_FLOAT(_int.to_str(accum_int, 10u)
+ "e" + _int.to_str(i, 10u));
case(some[str](?s)) {
ret token.LIT_FLOAT(dec_str + s);
}
case(none[int]) {
ret token.LIT_INT(accum_int);
case(none[str]) {
ret token.LIT_INT(accum_int);
}
}
}

View File

@ -44,6 +44,7 @@ upcall_grow_task
upcall_join
upcall_kill
upcall_log_double
upcall_log_float
upcall_log_int
upcall_log_str
upcall_malloc

View File

@ -0,0 +1,8 @@
fn main() {
auto f = 4.999999999999;
check (f > 4.90);
check (f < 5.0);
auto g = 4.90000000001e-10;
check(g > 5e-11);
check(g < 5e-9);
}