Skip to content

Commit

Permalink
Disambiguate unop statements in pretty-printer. Closes #674
Browse files Browse the repository at this point in the history
  • Loading branch information
brson committed Aug 3, 2011
1 parent ea81c03 commit 843767a
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 2 deletions.
45 changes: 44 additions & 1 deletion src/comp/syntax/print/pprust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -595,9 +595,16 @@ fn print_possibly_embedded_block(s: &ps, blk: &ast::blk, embedded: bool,
let ann_node = node_block(s, blk);
s.ann.pre(ann_node);
if embedded { word(s.s, "#{"); end(s); } else { bopen(s); }
for st: @ast::stmt in blk.node.stmts { print_stmt(s, *st) }

let last_stmt = option::none;
for st: @ast::stmt in blk.node.stmts {
maybe_protect_unop(s, last_stmt, stmt_(st));
print_stmt(s, *st);
last_stmt = option::some(st);
}
alt blk.node.expr {
some(expr) {
maybe_protect_unop(s, last_stmt, expr_(expr));
space_if_not_bol(s);
print_expr(s, expr);
maybe_print_trailing_comment(s, expr.span, some(blk.span.hi));
Expand All @@ -606,6 +613,42 @@ fn print_possibly_embedded_block(s: &ps, blk: &ast::blk, embedded: bool,
}
bclose_(s, blk.span, indented);
s.ann.post(ann_node);

tag expr_or_stmt { stmt_(@ast::stmt); expr_(@ast::expr); }

// The Rust syntax has an ambiguity when an if, alt, or block statement is
// followed by a unary op statement. In those cases we have to add an
// extra semi to make sure the unop is not parsed as a binop with the
// if/alt/block expression.
fn maybe_protect_unop(s: &ps, last: &option::t[@ast::stmt],
next: &expr_or_stmt) {
let last_expr_is_block = alt last {
option::some(@{node: ast::stmt_expr(e, _), _}) {
alt e.node {
ast::expr_if(_ ,_ ,_)
| ast::expr_alt(_, _)
| ast::expr_block(_) { true }
_ { false }
}
true
}
_ { false }
};
let next_expr_is_unnop = alt next {
expr_(@{node: ast::expr_unary(_, _), _}) { true }
stmt_(@{node: ast::stmt_expr(e, _), _}) {
alt e.node {
ast::expr_unary(_, _) { true }
_ { false }
}
}
_ { false }
};

if last_expr_is_block && next_expr_is_unnop {
word(s.s, ";");
}
}
}

fn print_if(s: &ps, test: &@ast::expr, blk: &ast::blk,
Expand Down
35 changes: 35 additions & 0 deletions src/test/pretty/unary-op-disambig.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Preserve semicolons that disambiguate unops

fn f() { }

fn block_semi() -> int {
{ f() };
-1
}

fn block_nosemi() -> int {
{ 0 } - 1
}

fn if_semi() -> int {
if true { f() } else { f() };
-1
}

fn if_nosemi() -> int {
if true { 0 } else { 0 } - 1
}

fn alt_semi() -> int {
alt true { true { f() } };
-1
}

fn alt_no_semi() -> int {
alt true { true { 0 } } - 1
}

fn stmt() {
{ f() };
-1;
}
1 change: 0 additions & 1 deletion src/test/run-pass/block-expr-precedence.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// xfail-pretty
// no-reformat

/*
Expand Down

0 comments on commit 843767a

Please sign in to comment.