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.
This commit is contained in:
Marijn Haverbeke 2011-10-07 16:22:53 +02:00
parent c7eee8fb05
commit f26e770745
4 changed files with 82 additions and 34 deletions

View file

@ -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

View file

@ -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);
}
}

View file

@ -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

View file

@ -0,0 +1,6 @@
// Check that issue #954 stays fixed
fn main() {
alt -1 { -1 {} }
assert 1-1 == 0;
}