From a47cd50dfb9b8d88abea0baf4122e454d82e09e9 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 24 Mar 2011 17:12:24 -0700 Subject: [PATCH] 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. --- Makefile.in | 6 +-- src/comp/front/lexer.rs | 95 +++++++++++++++++++++------------- src/rt/rustrt.def.in | 1 + src/test/run-pass/floatlits.rs | 8 +++ 4 files changed, 71 insertions(+), 39 deletions(-) create mode 100644 src/test/run-pass/floatlits.rs diff --git a/Makefile.in b/Makefile.in index e2cf9f34cbd1c..fd8d8b52923b1 100644 --- a/Makefile.in +++ b/Makefile.in @@ -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 \ diff --git a/src/comp/front/lexer.rs b/src/comp/front/lexer.rs index 791276a77ef95..6975d9c5d6c4f 100644 --- a/src/comp/front/lexer.rs +++ b/src/comp/front/lexer.rs @@ -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); } } } diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index 5f9300f7ca96f..cf10a402c48e1 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -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 diff --git a/src/test/run-pass/floatlits.rs b/src/test/run-pass/floatlits.rs new file mode 100644 index 0000000000000..db82b486af05a --- /dev/null +++ b/src/test/run-pass/floatlits.rs @@ -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); +} \ No newline at end of file