diff --git a/src/comp/syntax/parse/lexer.rs b/src/comp/syntax/parse/lexer.rs index f10701ceba58..10581643701a 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 { + fn check_str(r: reader, i: uint) -> option::t { + 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 e220149f6f81..8c9097961ade 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 5a4457682511..c89d99f0bafd 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 diff --git a/src/test/run-pass/binary-minus-without-space.rs b/src/test/run-pass/binary-minus-without-space.rs new file mode 100644 index 000000000000..cb31faacc3c4 --- /dev/null +++ b/src/test/run-pass/binary-minus-without-space.rs @@ -0,0 +1,6 @@ +// Check that issue #954 stays fixed + +fn main() { + alt -1 { -1 {} } + assert 1-1 == 0; +}