about summary refs log tree commit diff
path: root/src/comp/syntax/parse
diff options
context:
space:
mode:
authorMarijn Haverbeke <marijnh@gmail.com>2011-10-07 16:22:53 +0200
committerMarijn Haverbeke <marijnh@gmail.com>2011-10-07 16:46:44 +0200
commitf26e7707458676f657398da9a9770013b7e35b93 (patch)
tree26dfa9c11c060b2b1fb25f9eadc83d2b8d2fa637 /src/comp/syntax/parse
parentc7eee8fb059fc9639f2a4e5ef749dc3701bf3377 (diff)
downloadrust-f26e7707458676f657398da9a9770013b7e35b93.tar.gz
rust-f26e7707458676f657398da9a9770013b7e35b93.zip
Make 1-1 parse again
Issue #954

This is not a very elegant fix -- we should probably do something with
constant folding to handle negative-int alt patterns in the future.
Diffstat (limited to 'src/comp/syntax/parse')
-rw-r--r--src/comp/syntax/parse/lexer.rs37
-rw-r--r--src/comp/syntax/parse/parser.rs69
-rw-r--r--src/comp/syntax/parse/token.rs4
3 files changed, 76 insertions, 34 deletions
diff --git a/src/comp/syntax/parse/lexer.rs b/src/comp/syntax/parse/lexer.rs
index f10701ceba5..10581643701 100644
--- a/src/comp/syntax/parse/lexer.rs
+++ b/src/comp/syntax/parse/lexer.rs
@@ -754,6 +754,43 @@ fn gather_comments_and_literals(cm: codemap::codemap, path: str,
     }
     ret {cmnts: comments, lits: literals};
 }
+
+// This is a stopgap fix. We will have to do better eventually (issue #954)
+fn maybe_untangle_minus_from_lit(r: reader, t: token::token)
+    -> option::t<token::token> {
+    fn check_str(r: reader, i: uint) -> option::t<uint> {
+        let it = r.get_interner(), s = interner::get(*it, i);
+        if s[0] == '-' as u8 {
+            some(interner::intern(*it, str::slice(s, 1u, str::byte_len(s))))
+        } else { none }
+    }
+    alt t {
+      token::LIT_INT(v) {
+        if v < 0 { ret some(token::LIT_INT(-v)); }
+      }
+      token::LIT_UINT(v) {
+        if v > 0x7fffffffu { ret some(token::LIT_UINT(-(v as int) as uint)); }
+      }
+      token::LIT_MACH_INT(m, v) {
+        if v < 0 { ret some(token::LIT_MACH_INT(m, -v)); }
+      }
+      token::LIT_FLOAT(s) {
+        alt check_str(r, s) {
+          some(s) { ret some(token::LIT_FLOAT(s)); }
+          _ {}
+        }
+      }
+      token::LIT_MACH_FLOAT(m, s) {
+        alt check_str(r, s) {
+          some(s) { ret some(token::LIT_MACH_FLOAT(m, s)); }
+          _ {}
+        }
+      }
+      _ {}
+    }
+    none
+}
+
 //
 // Local Variables:
 // mode: rust
diff --git a/src/comp/syntax/parse/parser.rs b/src/comp/syntax/parse/parser.rs
index e220149f6f8..8c9097961ad 100644
--- a/src/comp/syntax/parse/parser.rs
+++ b/src/comp/syntax/parse/parser.rs
@@ -678,40 +678,31 @@ fn parse_seq<@T>(bra: token::token, ket: token::token,
     ret spanned(lo, hi, result);
 }
 
+fn lit_from_token(p: parser, tok: token::token) -> ast::lit_ {
+    alt tok {
+      token::LIT_INT(i) { ast::lit_int(i) }
+      token::LIT_UINT(u) { ast::lit_uint(u) }
+      token::LIT_FLOAT(s) { ast::lit_float(p.get_str(s)) }
+      token::LIT_MACH_INT(tm, i) { ast::lit_mach_int(tm, i) }
+      token::LIT_MACH_FLOAT(tm, s) { ast::lit_mach_float(tm, p.get_str(s)) }
+      token::LIT_CHAR(c) { ast::lit_char(c) }
+      token::LIT_STR(s) { ast::lit_str(p.get_str(s)) }
+      token::LPAREN. { expect(p, token::RPAREN); ast::lit_nil }
+      _ { unexpected(p, tok); }
+    }
+}
 
 fn parse_lit(p: parser) -> ast::lit {
     let sp = p.get_span();
-    let lit: ast::lit_ = ast::lit_nil;
-    if eat_word(p, "true") {
-        lit = ast::lit_bool(true);
+    let lit = if eat_word(p, "true") {
+        ast::lit_bool(true)
     } else if eat_word(p, "false") {
-        lit = ast::lit_bool(false);
+        ast::lit_bool(false)
     } else {
-        alt p.peek() {
-          token::LIT_INT(i) { p.bump(); lit = ast::lit_int(i); }
-          token::LIT_UINT(u) { p.bump(); lit = ast::lit_uint(u); }
-          token::LIT_FLOAT(s) {
-            p.bump();
-            lit = ast::lit_float(p.get_str(s));
-          }
-          token::LIT_MACH_INT(tm, i) {
-            p.bump();
-            lit = ast::lit_mach_int(tm, i);
-          }
-          token::LIT_MACH_FLOAT(tm, s) {
-            p.bump();
-            lit = ast::lit_mach_float(tm, p.get_str(s));
-          }
-          token::LIT_CHAR(c) { p.bump(); lit = ast::lit_char(c); }
-          token::LIT_STR(s) { p.bump(); lit = ast::lit_str(p.get_str(s)); }
-          token::LPAREN. {
-            p.bump();
-            expect(p, token::RPAREN);
-            lit = ast::lit_nil;
-          }
-          t { unexpected(p, t); }
-        }
-    }
+        let tok = p.peek();
+        p.bump();
+        lit_from_token(p, tok)
+    };
     ret {node: lit, span: sp};
 }
 
@@ -1200,13 +1191,25 @@ fn parse_more_binops(p: parser, lhs: @ast::expr, min_prec: int) ->
    @ast::expr {
     if !expr_has_value(lhs) { ret lhs; }
     let peeked = p.peek();
+    let lit_after = alt lexer::maybe_untangle_minus_from_lit(p.get_reader(),
+                                                             peeked) {
+      some(tok) {
+        peeked = token::BINOP(token::MINUS);
+        let lit = @{node: lit_from_token(p, tok), span: p.get_span()};
+        some(mk_expr(p, p.get_lo_pos(), p.get_hi_pos(), ast::expr_lit(lit)))
+      }
+      none. { none }
+    };
     for cur: op_spec in *p.get_prec_table() {
         if cur.prec > min_prec && cur.tok == peeked {
             p.bump();
-            let rhs = parse_more_binops(p, parse_prefix_expr(p), cur.prec);
-            let bin =
-                mk_expr(p, lhs.span.lo, rhs.span.hi,
-                        ast::expr_binary(cur.op, lhs, rhs));
+            let expr = alt lit_after {
+              some(ex) { ex }
+              _ { parse_prefix_expr(p) }
+            };
+            let rhs = parse_more_binops(p, expr, cur.prec);
+            let bin = mk_expr(p, lhs.span.lo, rhs.span.hi,
+                              ast::expr_binary(cur.op, lhs, rhs));
             ret parse_more_binops(p, bin, min_prec);
         }
     }
diff --git a/src/comp/syntax/parse/token.rs b/src/comp/syntax/parse/token.rs
index 5a445768251..c89d99f0baf 100644
--- a/src/comp/syntax/parse/token.rs
+++ b/src/comp/syntax/parse/token.rs
@@ -3,7 +3,8 @@ import ast::ty_mach;
 import ast_util::ty_mach_to_str;
 import std::map::new_str_hash;
 import util::interner;
-import std::{int, uint, str};
+import std::{int, uint, str, option};
+import option::{some, none};
 
 type str_num = uint;
 
@@ -211,6 +212,7 @@ pure fn can_begin_expr(t: token) -> bool {
       _ { false }
     }
 }
+
 // Local Variables:
 // fill-column: 78;
 // indent-tabs-mode: nil