about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorTim Chevalier <chevalier@alum.wellesley.edu>2011-03-24 17:12:24 -0700
committerTim Chevalier <chevalier@alum.wellesley.edu>2011-03-25 11:20:30 -0700
commita47cd50dfb9b8d88abea0baf4122e454d82e09e9 (patch)
tree0a6d53f38d5ef5fc32d4cb78ec125606cd2b328e /src
parente2d6475308481a43facb0e95e9535c5602bf54f2 (diff)
downloadrust-a47cd50dfb9b8d88abea0baf4122e454d82e09e9.tar.gz
rust-a47cd50dfb9b8d88abea0baf4122e454d82e09e9.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/comp/front/lexer.rs95
-rw-r--r--src/rt/rustrt.def.in1
-rw-r--r--src/test/run-pass/floatlits.rs8
3 files changed, 68 insertions, 36 deletions
diff --git a/src/comp/front/lexer.rs b/src/comp/front/lexer.rs
index 791276a77ef..6975d9c5d6c 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 5f9300f7ca9..cf10a402c48 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 00000000000..db82b486af0
--- /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