Skip to content

Commit e34abba

Browse files
committed
minimal changes to permit fn blocks in expr
1 parent 513a263 commit e34abba

File tree

1 file changed

+64
-68
lines changed

1 file changed

+64
-68
lines changed

src/comp/syntax/parse/parser.rs

Lines changed: 64 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,12 @@ import util::interner;
1010
import ast::{node_id, spanned};
1111
import front::attr;
1212

13-
tag restriction { UNRESTRICTED; RESTRICT_NO_CALL_EXPRS; RESTRICT_NO_BAR_OP; }
13+
tag restriction {
14+
UNRESTRICTED;
15+
RESTRICT_STMT_EXPR;
16+
RESTRICT_NO_CALL_EXPRS;
17+
RESTRICT_NO_BAR_OP;
18+
}
1419

1520
tag file_type { CRATE_FILE; SOURCE_FILE; }
1621

@@ -977,35 +982,54 @@ fn parse_syntax_ext_naked(p: parser, lo: uint) -> @ast::expr {
977982

978983
fn parse_dot_or_call_expr(p: parser) -> @ast::expr {
979984
let b = parse_bottom_expr(p);
980-
if expr_has_value(b) { parse_dot_or_call_expr_with(p, b) }
981-
else { b }
985+
parse_dot_or_call_expr_with(p, b)
986+
}
987+
988+
fn permits_call(p: parser) -> bool {
989+
ret p.get_restriction() != RESTRICT_NO_CALL_EXPRS;
982990
}
983991

984992
fn parse_dot_or_call_expr_with(p: parser, e: @ast::expr) -> @ast::expr {
985993
let lo = e.span.lo;
986994
let hi = e.span.hi;
987995
let e = e;
988-
while true {
996+
while !expr_is_complete(p, e) {
989997
alt p.peek() {
990-
token::LPAREN. {
991-
if p.get_restriction() == RESTRICT_NO_CALL_EXPRS {
992-
ret e;
993-
} else {
994-
// Call expr.
995-
let es = parse_seq(token::LPAREN, token::RPAREN,
996-
seq_sep(token::COMMA), parse_expr, p);
997-
hi = es.span.hi;
998-
let nd = ast::expr_call(e, es.node, false);
999-
e = mk_expr(p, lo, hi, nd);
998+
// expr(...)
999+
token::LPAREN. when permits_call(p) {
1000+
let es = parse_seq(token::LPAREN, token::RPAREN,
1001+
seq_sep(token::COMMA), parse_expr, p);
1002+
hi = es.span.hi;
1003+
let nd = ast::expr_call(e, es.node, false);
1004+
e = mk_expr(p, lo, hi, nd);
1005+
}
1006+
1007+
// expr { || ... }
1008+
token::LBRACE. when is_bar(p.look_ahead(1u)) && permits_call(p) {
1009+
p.bump();
1010+
let blk = parse_fn_block_expr(p);
1011+
alt e.node {
1012+
ast::expr_call(f, args, false) {
1013+
e = @{node: ast::expr_call(f, args + [blk], true)
1014+
with *e};
1015+
}
1016+
_ {
1017+
e = mk_expr(p, lo, p.get_last_hi_pos(),
1018+
ast::expr_call(e, [blk], true));
1019+
}
10001020
}
10011021
}
1022+
1023+
// expr[...]
10021024
token::LBRACKET. {
10031025
p.bump();
10041026
let ix = parse_expr(p);
10051027
hi = ix.span.hi;
10061028
expect(p, token::RBRACKET);
10071029
e = mk_expr(p, lo, hi, ast::expr_index(e, ix));
10081030
}
1031+
1032+
// expr.f
10091033
token::DOT. {
10101034
p.bump();
10111035
alt p.peek() {
@@ -1022,6 +1046,7 @@ fn parse_dot_or_call_expr_with(p: parser, e: @ast::expr) -> @ast::expr {
10221046
t { unexpected(p, t); }
10231047
}
10241048
}
1049+
10251050
_ { ret e; }
10261051
}
10271052
}
@@ -1126,7 +1151,7 @@ const ternary_prec: int = 0;
11261151

11271152
fn parse_more_binops(p: parser, lhs: @ast::expr, min_prec: int) ->
11281153
@ast::expr {
1129-
if !expr_has_value(lhs) { ret lhs; }
1154+
if expr_is_complete(p, lhs) { ret lhs; }
11301155
let peeked = p.peek();
11311156
if peeked == token::BINOP(token::OR) &&
11321157
p.get_restriction() == RESTRICT_NO_BAR_OP { ret lhs; }
@@ -1550,61 +1575,40 @@ fn parse_stmt(p: parser) -> @ast::stmt {
15501575
}
15511576
}
15521577

1553-
let maybe_item = parse_item(p, item_attrs);
1554-
1555-
// If we have attributes then we should have an item
1556-
if vec::len(item_attrs) > 0u {
1557-
alt maybe_item {
1558-
some(_) {/* fallthrough */ }
1559-
_ { ret p.fatal("expected item"); }
1560-
}
1561-
}
1562-
1563-
alt maybe_item {
1578+
alt parse_item(p, item_attrs) {
15641579
some(i) {
15651580
let hi = i.span.hi;
15661581
let decl = @spanned(lo, hi, ast::decl_item(i));
15671582
ret @spanned(lo, hi, ast::stmt_decl(decl, p.get_id()));
15681583
}
1569-
none. {
1570-
// Remainder are line-expr stmts.
1571-
let e = parse_expr(p);
1572-
// See if it is a block call
1573-
if expr_has_value(e) && p.peek() == token::LBRACE &&
1574-
is_bar(p.look_ahead(1u)) {
1575-
p.bump();
1576-
let blk = parse_fn_block_expr(p);
1577-
alt e.node {
1578-
ast::expr_call(f, args, false) {
1579-
e = @{node: ast::expr_call(f, args + [blk], true)
1580-
with *e};
1581-
}
1582-
_ {
1583-
e = mk_expr(p, lo, p.get_last_hi_pos(),
1584-
ast::expr_call(e, [blk], true));
1585-
}
1586-
}
1587-
}
1588-
ret @spanned(lo, e.span.hi, ast::stmt_expr(e, p.get_id()));
1589-
}
1590-
_ { p.fatal("expected statement"); }
1584+
none() { /* fallthrough */ }
15911585
}
1586+
1587+
// If we have attributes then we should have an item
1588+
if vec::len(item_attrs) > 0u {
1589+
ret p.fatal("expected item");
1590+
}
1591+
1592+
// Remainder are line-expr stmts.
1593+
let e = parse_expr_res(p, RESTRICT_STMT_EXPR);
1594+
ret @spanned(lo, e.span.hi, ast::stmt_expr(e, p.get_id()));
15921595
}
15931596
}
15941597

1595-
fn expr_has_value(e: @ast::expr) -> bool {
1598+
fn expr_is_complete(p: parser, e: @ast::expr) -> bool {
1599+
ret p.get_restriction() == RESTRICT_STMT_EXPR &&
1600+
!expr_requires_semi_to_be_stmt(e);
1601+
}
1602+
1603+
fn expr_requires_semi_to_be_stmt(e: @ast::expr) -> bool {
15961604
alt e.node {
15971605
ast::expr_if(_, th, els) | ast::expr_if_check(_, th, els) {
15981606
if option::is_none(els) { false }
15991607
else { !option::is_none(th.node.expr) ||
1600-
expr_has_value(option::get(els)) }
1608+
expr_requires_semi_to_be_stmt(option::get(els)) }
16011609
}
16021610
ast::expr_alt(_, arms) {
1603-
let found_expr = false;
1604-
for arm in arms {
1605-
if !option::is_none(arm.body.node.expr) { found_expr = true; }
1606-
}
1607-
found_expr
1611+
vec::any({|arm| !option::is_none(arm.body.node.expr)}, arms)
16081612
}
16091613
ast::expr_block(blk) | ast::expr_while(_, blk) |
16101614
ast::expr_for(_, _, blk) | ast::expr_do_while(blk, _) {
@@ -1615,19 +1619,11 @@ fn expr_has_value(e: @ast::expr) -> bool {
16151619
}
16161620
}
16171621

1618-
fn stmt_is_expr(stmt: @ast::stmt) -> bool {
1619-
ret alt stmt.node {
1620-
ast::stmt_expr(e, _) { expr_has_value(e) }
1621-
_ { false }
1622-
};
1623-
}
1624-
16251622
fn stmt_to_expr(stmt: @ast::stmt) -> option::t<@ast::expr> {
1626-
ret if stmt_is_expr(stmt) {
1627-
alt stmt.node {
1628-
ast::stmt_expr(e, _) { some(e) }
1629-
}
1630-
} else { none };
1623+
alt stmt.node {
1624+
ast::stmt_expr(e, _) { some(e) }
1625+
ast::stmt_decl(_, _) { none }
1626+
}
16311627
}
16321628

16331629
fn stmt_ends_with_semi(stmt: ast::stmt) -> bool {
@@ -1639,7 +1635,7 @@ fn stmt_ends_with_semi(stmt: ast::stmt) -> bool {
16391635
}
16401636
}
16411637
ast::stmt_expr(e, _) {
1642-
ret expr_has_value(e);
1638+
ret expr_requires_semi_to_be_stmt(e);
16431639
}
16441640
}
16451641
}

0 commit comments

Comments
 (0)