diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2011-12-20 20:12:52 -0800 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2012-01-03 13:13:51 -0800 |
| commit | e34abbacf62cb1d35b761ea698b0afa0372aa642 (patch) | |
| tree | 4df822c8c1abe127c22423719199c44893f5ca8b /src/comp/syntax/parse/parser.rs | |
| parent | 513a263e81eff098762e1531bc4d13366da0e554 (diff) | |
| download | rust-e34abbacf62cb1d35b761ea698b0afa0372aa642.tar.gz rust-e34abbacf62cb1d35b761ea698b0afa0372aa642.zip | |
minimal changes to permit fn blocks in expr
Diffstat (limited to 'src/comp/syntax/parse/parser.rs')
| -rw-r--r-- | src/comp/syntax/parse/parser.rs | 132 |
1 files changed, 64 insertions, 68 deletions
diff --git a/src/comp/syntax/parse/parser.rs b/src/comp/syntax/parse/parser.rs index 1036b8e9f92..ecdfe19e499 100644 --- a/src/comp/syntax/parse/parser.rs +++ b/src/comp/syntax/parse/parser.rs @@ -10,7 +10,12 @@ import util::interner; import ast::{node_id, spanned}; import front::attr; -tag restriction { UNRESTRICTED; RESTRICT_NO_CALL_EXPRS; RESTRICT_NO_BAR_OP; } +tag restriction { + UNRESTRICTED; + RESTRICT_STMT_EXPR; + RESTRICT_NO_CALL_EXPRS; + RESTRICT_NO_BAR_OP; +} tag file_type { CRATE_FILE; SOURCE_FILE; } @@ -977,28 +982,45 @@ fn parse_syntax_ext_naked(p: parser, lo: uint) -> @ast::expr { fn parse_dot_or_call_expr(p: parser) -> @ast::expr { let b = parse_bottom_expr(p); - if expr_has_value(b) { parse_dot_or_call_expr_with(p, b) } - else { b } + parse_dot_or_call_expr_with(p, b) +} + +fn permits_call(p: parser) -> bool { + ret p.get_restriction() != RESTRICT_NO_CALL_EXPRS; } fn parse_dot_or_call_expr_with(p: parser, e: @ast::expr) -> @ast::expr { let lo = e.span.lo; let hi = e.span.hi; let e = e; - while true { + while !expr_is_complete(p, e) { alt p.peek() { - token::LPAREN. { - if p.get_restriction() == RESTRICT_NO_CALL_EXPRS { - ret e; - } else { - // Call expr. - let es = parse_seq(token::LPAREN, token::RPAREN, - seq_sep(token::COMMA), parse_expr, p); - hi = es.span.hi; - let nd = ast::expr_call(e, es.node, false); - e = mk_expr(p, lo, hi, nd); + // expr(...) + token::LPAREN. when permits_call(p) { + let es = parse_seq(token::LPAREN, token::RPAREN, + seq_sep(token::COMMA), parse_expr, p); + hi = es.span.hi; + let nd = ast::expr_call(e, es.node, false); + e = mk_expr(p, lo, hi, nd); + } + + // expr { || ... } + token::LBRACE. when is_bar(p.look_ahead(1u)) && permits_call(p) { + p.bump(); + let blk = parse_fn_block_expr(p); + alt e.node { + ast::expr_call(f, args, false) { + e = @{node: ast::expr_call(f, args + [blk], true) + with *e}; + } + _ { + e = mk_expr(p, lo, p.get_last_hi_pos(), + ast::expr_call(e, [blk], true)); + } } } + + // expr[...] token::LBRACKET. { p.bump(); let ix = parse_expr(p); @@ -1006,6 +1028,8 @@ fn parse_dot_or_call_expr_with(p: parser, e: @ast::expr) -> @ast::expr { expect(p, token::RBRACKET); e = mk_expr(p, lo, hi, ast::expr_index(e, ix)); } + + // expr.f token::DOT. { p.bump(); alt p.peek() { @@ -1022,6 +1046,7 @@ fn parse_dot_or_call_expr_with(p: parser, e: @ast::expr) -> @ast::expr { t { unexpected(p, t); } } } + _ { ret e; } } } @@ -1126,7 +1151,7 @@ const ternary_prec: int = 0; fn parse_more_binops(p: parser, lhs: @ast::expr, min_prec: int) -> @ast::expr { - if !expr_has_value(lhs) { ret lhs; } + if expr_is_complete(p, lhs) { ret lhs; } let peeked = p.peek(); if peeked == token::BINOP(token::OR) && p.get_restriction() == RESTRICT_NO_BAR_OP { ret lhs; } @@ -1550,61 +1575,40 @@ fn parse_stmt(p: parser) -> @ast::stmt { } } - let maybe_item = parse_item(p, item_attrs); - - // If we have attributes then we should have an item - if vec::len(item_attrs) > 0u { - alt maybe_item { - some(_) {/* fallthrough */ } - _ { ret p.fatal("expected item"); } - } - } - - alt maybe_item { + alt parse_item(p, item_attrs) { some(i) { let hi = i.span.hi; let decl = @spanned(lo, hi, ast::decl_item(i)); ret @spanned(lo, hi, ast::stmt_decl(decl, p.get_id())); } - none. { - // Remainder are line-expr stmts. - let e = parse_expr(p); - // See if it is a block call - if expr_has_value(e) && p.peek() == token::LBRACE && - is_bar(p.look_ahead(1u)) { - p.bump(); - let blk = parse_fn_block_expr(p); - alt e.node { - ast::expr_call(f, args, false) { - e = @{node: ast::expr_call(f, args + [blk], true) - with *e}; - } - _ { - e = mk_expr(p, lo, p.get_last_hi_pos(), - ast::expr_call(e, [blk], true)); - } - } - } - ret @spanned(lo, e.span.hi, ast::stmt_expr(e, p.get_id())); - } - _ { p.fatal("expected statement"); } + none() { /* fallthrough */ } } + + // If we have attributes then we should have an item + if vec::len(item_attrs) > 0u { + ret p.fatal("expected item"); + } + + // Remainder are line-expr stmts. + let e = parse_expr_res(p, RESTRICT_STMT_EXPR); + ret @spanned(lo, e.span.hi, ast::stmt_expr(e, p.get_id())); } } -fn expr_has_value(e: @ast::expr) -> bool { +fn expr_is_complete(p: parser, e: @ast::expr) -> bool { + ret p.get_restriction() == RESTRICT_STMT_EXPR && + !expr_requires_semi_to_be_stmt(e); +} + +fn expr_requires_semi_to_be_stmt(e: @ast::expr) -> bool { alt e.node { ast::expr_if(_, th, els) | ast::expr_if_check(_, th, els) { if option::is_none(els) { false } else { !option::is_none(th.node.expr) || - expr_has_value(option::get(els)) } + expr_requires_semi_to_be_stmt(option::get(els)) } } ast::expr_alt(_, arms) { - let found_expr = false; - for arm in arms { - if !option::is_none(arm.body.node.expr) { found_expr = true; } - } - found_expr + vec::any({|arm| !option::is_none(arm.body.node.expr)}, arms) } ast::expr_block(blk) | ast::expr_while(_, blk) | ast::expr_for(_, _, blk) | ast::expr_do_while(blk, _) { @@ -1615,19 +1619,11 @@ fn expr_has_value(e: @ast::expr) -> bool { } } -fn stmt_is_expr(stmt: @ast::stmt) -> bool { - ret alt stmt.node { - ast::stmt_expr(e, _) { expr_has_value(e) } - _ { false } - }; -} - fn stmt_to_expr(stmt: @ast::stmt) -> option::t<@ast::expr> { - ret if stmt_is_expr(stmt) { - alt stmt.node { - ast::stmt_expr(e, _) { some(e) } - } - } else { none }; + alt stmt.node { + ast::stmt_expr(e, _) { some(e) } + ast::stmt_decl(_, _) { none } + } } fn stmt_ends_with_semi(stmt: ast::stmt) -> bool { @@ -1639,7 +1635,7 @@ fn stmt_ends_with_semi(stmt: ast::stmt) -> bool { } } ast::stmt_expr(e, _) { - ret expr_has_value(e); + ret expr_requires_semi_to_be_stmt(e); } } } |
