Skip to content

Commit 37ba5f3

Browse files
committed
make parser handle parenthesized block-sugar exprs properly
1 parent e02ab2d commit 37ba5f3

File tree

3 files changed

+130
-99
lines changed

3 files changed

+130
-99
lines changed

src/comp/syntax/parse/parser.rs

Lines changed: 80 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -736,7 +736,29 @@ fn mk_lit_u32(p: parser, i: u32) -> @ast::expr {
736736
ret @{id: p.get_id(), node: ast::expr_lit(lv_lit), span: span};
737737
}
738738

739-
fn parse_bottom_expr(p: parser) -> @ast::expr {
739+
// We don't allow single-entry tuples in the true AST; that indicates a
740+
// parenthesized expression. However, we preserve them temporarily while
741+
// parsing because `(while{...})+3` parses differently from `while{...}+3`.
742+
//
743+
// To reflect the fact that the @ast::expr is not a true expr that should be
744+
// part of the AST, we wrap such expressions in the pexpr tag. They
745+
// can then be converted to true expressions by a call to `to_expr()`.
746+
tag pexpr {
747+
pexpr(@ast::expr);
748+
}
749+
750+
fn mk_pexpr(p: parser, lo: uint, hi: uint, node: ast::expr_) -> pexpr {
751+
ret pexpr(mk_expr(p, lo, hi, node));
752+
}
753+
754+
fn to_expr(e: pexpr) -> @ast::expr {
755+
alt e.node {
756+
ast::expr_tup(es) when vec::len(es) == 1u { es[0u] }
757+
_ { *e }
758+
}
759+
}
760+
761+
fn parse_bottom_expr(p: parser) -> pexpr {
740762
let lo = p.get_lo_pos();
741763
let hi = p.get_hi_pos();
742764

@@ -747,15 +769,19 @@ fn parse_bottom_expr(p: parser) -> @ast::expr {
747769
hi = p.get_hi_pos();
748770
p.bump();
749771
let lit = @spanned(lo, hi, ast::lit_nil);
750-
ret mk_expr(p, lo, hi, ast::expr_lit(lit));
772+
ret mk_pexpr(p, lo, hi, ast::expr_lit(lit));
751773
}
752774
let es = [parse_expr(p)];
753775
while p.peek() == token::COMMA { p.bump(); es += [parse_expr(p)]; }
754776
hi = p.get_hi_pos();
755777
expect(p, token::RPAREN);
756-
if vec::len(es) == 1u {
757-
ret mk_expr(p, lo, hi, es[0].node);
758-
} else { ret mk_expr(p, lo, hi, ast::expr_tup(es)); }
778+
779+
// Note: we retain the expr_tup() even for simple
780+
// parenthesized expressions, but only for a "little while".
781+
// This is so that wrappers around parse_bottom_expr()
782+
// can tell whether the expression was parenthesized or not,
783+
// which affects expr_is_complete().
784+
ret mk_pexpr(p, lo, hi, ast::expr_tup(es));
759785
} else if p.peek() == token::LBRACE {
760786
p.bump();
761787
if is_word(p, "mutable") ||
@@ -775,34 +801,34 @@ fn parse_bottom_expr(p: parser) -> @ast::expr {
775801
expect(p, token::RBRACE);
776802
ex = ast::expr_rec(fields, base);
777803
} else if is_bar(p.peek()) {
778-
ret parse_fn_block_expr(p);
804+
ret pexpr(parse_fn_block_expr(p));
779805
} else {
780806
let blk = parse_block_tail(p, lo, ast::default_blk);
781-
ret mk_expr(p, blk.span.lo, blk.span.hi, ast::expr_block(blk));
807+
ret mk_pexpr(p, blk.span.lo, blk.span.hi, ast::expr_block(blk));
782808
}
783809
} else if eat_word(p, "if") {
784-
ret parse_if_expr(p);
810+
ret pexpr(parse_if_expr(p));
785811
} else if eat_word(p, "for") {
786-
ret parse_for_expr(p);
812+
ret pexpr(parse_for_expr(p));
787813
} else if eat_word(p, "while") {
788-
ret parse_while_expr(p);
814+
ret pexpr(parse_while_expr(p));
789815
} else if eat_word(p, "do") {
790-
ret parse_do_while_expr(p);
816+
ret pexpr(parse_do_while_expr(p));
791817
} else if eat_word(p, "alt") {
792-
ret parse_alt_expr(p);
818+
ret pexpr(parse_alt_expr(p));
793819
} else if eat_word(p, "fn") {
794820
let proto = parse_fn_ty_proto(p);
795-
ret parse_fn_expr(p, proto);
821+
ret pexpr(parse_fn_expr(p, proto));
796822
} else if eat_word(p, "block") {
797-
ret parse_fn_expr(p, ast::proto_block);
823+
ret pexpr(parse_fn_expr(p, ast::proto_block));
798824
} else if eat_word(p, "lambda") {
799-
ret parse_fn_expr(p, ast::proto_shared(ast::sugar_sexy));
825+
ret pexpr(parse_fn_expr(p, ast::proto_shared(ast::sugar_sexy)));
800826
} else if eat_word(p, "sendfn") {
801-
ret parse_fn_expr(p, ast::proto_send);
827+
ret pexpr(parse_fn_expr(p, ast::proto_send));
802828
} else if eat_word(p, "unchecked") {
803-
ret parse_block_expr(p, lo, ast::unchecked_blk);
829+
ret pexpr(parse_block_expr(p, lo, ast::unchecked_blk));
804830
} else if eat_word(p, "unsafe") {
805-
ret parse_block_expr(p, lo, ast::unsafe_blk);
831+
ret pexpr(parse_block_expr(p, lo, ast::unsafe_blk));
806832
} else if p.peek() == token::LBRACKET {
807833
p.bump();
808834
let mut = parse_mutability(p);
@@ -816,15 +842,16 @@ fn parse_bottom_expr(p: parser) -> @ast::expr {
816842
expect(p, token::GT);
817843

818844
/* hack: early return to take advantage of specialized function */
819-
ret mk_mac_expr(p, lo, p.get_hi_pos(), ast::mac_embed_type(ty));
845+
ret pexpr(mk_mac_expr(p, lo, p.get_hi_pos(),
846+
ast::mac_embed_type(ty)));
820847
} else if p.peek() == token::POUND_LBRACE {
821848
p.bump();
822849
let blk = ast::mac_embed_block(
823850
parse_block_tail(p, lo, ast::default_blk));
824-
ret mk_mac_expr(p, lo, p.get_hi_pos(), blk);
851+
ret pexpr(mk_mac_expr(p, lo, p.get_hi_pos(), blk));
825852
} else if p.peek() == token::ELLIPSIS {
826853
p.bump();
827-
ret mk_mac_expr(p, lo, p.get_hi_pos(), ast::mac_ellipsis);
854+
ret pexpr(mk_mac_expr(p, lo, p.get_hi_pos(), ast::mac_ellipsis));
828855
} else if eat_word(p, "obj") {
829856
// Anonymous object
830857

@@ -941,7 +968,7 @@ fn parse_bottom_expr(p: parser) -> @ast::expr {
941968
hi = lit.span.hi;
942969
ex = ast::expr_lit(@lit);
943970
}
944-
ret mk_expr(p, lo, hi, ex);
971+
ret mk_pexpr(p, lo, hi, ex);
945972
}
946973

947974
fn parse_block_expr(p: parser,
@@ -977,7 +1004,7 @@ fn parse_syntax_ext_naked(p: parser, lo: uint) -> @ast::expr {
9771004
ret mk_mac_expr(p, lo, hi, ast::mac_invoc(pth, e, none));
9781005
}
9791006

980-
fn parse_dot_or_call_expr(p: parser) -> @ast::expr {
1007+
fn parse_dot_or_call_expr(p: parser) -> pexpr {
9811008
let b = parse_bottom_expr(p);
9821009
parse_dot_or_call_expr_with(p, b)
9831010
}
@@ -986,33 +1013,33 @@ fn permits_call(p: parser) -> bool {
9861013
ret p.get_restriction() != RESTRICT_NO_CALL_EXPRS;
9871014
}
9881015

989-
fn parse_dot_or_call_expr_with(p: parser, e: @ast::expr) -> @ast::expr {
1016+
fn parse_dot_or_call_expr_with(p: parser, e0: pexpr) -> pexpr {
1017+
let e = e0;
9901018
let lo = e.span.lo;
9911019
let hi = e.span.hi;
992-
let e = e;
9931020
while !expr_is_complete(p, e) {
9941021
alt p.peek() {
9951022
// expr(...)
9961023
token::LPAREN. when permits_call(p) {
9971024
let es = parse_seq(token::LPAREN, token::RPAREN,
9981025
seq_sep(token::COMMA), parse_expr, p);
9991026
hi = es.span.hi;
1000-
let nd = ast::expr_call(e, es.node, false);
1001-
e = mk_expr(p, lo, hi, nd);
1027+
let nd = ast::expr_call(to_expr(e), es.node, false);
1028+
e = mk_pexpr(p, lo, hi, nd);
10021029
}
10031030

1004-
// expr { || ... }
1031+
// expr {|| ... }
10051032
token::LBRACE. when is_bar(p.look_ahead(1u)) && permits_call(p) {
10061033
p.bump();
10071034
let blk = parse_fn_block_expr(p);
10081035
alt e.node {
10091036
ast::expr_call(f, args, false) {
1010-
e = @{node: ast::expr_call(f, args + [blk], true)
1011-
with *e};
1037+
e = pexpr(@{node: ast::expr_call(f, args + [blk], true)
1038+
with *to_expr(e)});
10121039
}
10131040
_ {
1014-
e = mk_expr(p, lo, p.get_last_hi_pos(),
1015-
ast::expr_call(e, [blk], true));
1041+
e = mk_pexpr(p, lo, p.get_last_hi_pos(),
1042+
ast::expr_call(to_expr(e), [blk], true));
10161043
}
10171044
}
10181045
}
@@ -1023,7 +1050,7 @@ fn parse_dot_or_call_expr_with(p: parser, e: @ast::expr) -> @ast::expr {
10231050
let ix = parse_expr(p);
10241051
hi = ix.span.hi;
10251052
expect(p, token::RBRACKET);
1026-
e = mk_expr(p, lo, hi, ast::expr_index(e, ix));
1053+
e = mk_pexpr(p, lo, hi, ast::expr_index(to_expr(e), ix));
10271054
}
10281055

10291056
// expr.f
@@ -1038,7 +1065,10 @@ fn parse_dot_or_call_expr_with(p: parser, e: @ast::expr) -> @ast::expr {
10381065
parse_seq_to_gt(some(token::COMMA),
10391066
{|p| parse_ty(p, false)}, p)
10401067
} else { [] };
1041-
e = mk_expr(p, lo, hi, ast::expr_field(e, p.get_str(i), tys));
1068+
e = mk_pexpr(p, lo, hi,
1069+
ast::expr_field(to_expr(e),
1070+
p.get_str(i),
1071+
tys));
10421072
}
10431073
t { unexpected(p, t); }
10441074
}
@@ -1050,29 +1080,29 @@ fn parse_dot_or_call_expr_with(p: parser, e: @ast::expr) -> @ast::expr {
10501080
ret e;
10511081
}
10521082

1053-
fn parse_prefix_expr(p: parser) -> @ast::expr {
1083+
fn parse_prefix_expr(p: parser) -> pexpr {
10541084
let lo = p.get_lo_pos();
10551085
let hi = p.get_hi_pos();
10561086

10571087
let ex;
10581088
alt p.peek() {
10591089
token::NOT. {
10601090
p.bump();
1061-
let e = parse_prefix_expr(p);
1091+
let e = to_expr(parse_prefix_expr(p));
10621092
hi = e.span.hi;
10631093
ex = ast::expr_unary(ast::not, e);
10641094
}
10651095
token::BINOP(b) {
10661096
alt b {
10671097
token::MINUS. {
10681098
p.bump();
1069-
let e = parse_prefix_expr(p);
1099+
let e = to_expr(parse_prefix_expr(p));
10701100
hi = e.span.hi;
10711101
ex = ast::expr_unary(ast::neg, e);
10721102
}
10731103
token::STAR. {
10741104
p.bump();
1075-
let e = parse_prefix_expr(p);
1105+
let e = to_expr(parse_prefix_expr(p));
10761106
hi = e.span.hi;
10771107
ex = ast::expr_unary(ast::deref, e);
10781108
}
@@ -1082,20 +1112,20 @@ fn parse_prefix_expr(p: parser) -> @ast::expr {
10821112
token::AT. {
10831113
p.bump();
10841114
let m = parse_mutability(p);
1085-
let e = parse_prefix_expr(p);
1115+
let e = to_expr(parse_prefix_expr(p));
10861116
hi = e.span.hi;
10871117
ex = ast::expr_unary(ast::box(m), e);
10881118
}
10891119
token::TILDE. {
10901120
p.bump();
10911121
let m = parse_mutability(p);
1092-
let e = parse_prefix_expr(p);
1122+
let e = to_expr(parse_prefix_expr(p));
10931123
hi = e.span.hi;
10941124
ex = ast::expr_unary(ast::uniq(m), e);
10951125
}
10961126
_ { ret parse_dot_or_call_expr(p); }
10971127
}
1098-
ret mk_expr(p, lo, hi, ex);
1128+
ret mk_pexpr(p, lo, hi, ex);
10991129
}
11001130

11011131
fn parse_ternary(p: parser) -> @ast::expr {
@@ -1146,9 +1176,10 @@ const unop_prec: int = 100;
11461176
const as_prec: int = 5;
11471177
const ternary_prec: int = 0;
11481178

1149-
fn parse_more_binops(p: parser, lhs: @ast::expr, min_prec: int) ->
1179+
fn parse_more_binops(p: parser, plhs: pexpr, min_prec: int) ->
11501180
@ast::expr {
1151-
if expr_is_complete(p, lhs) { ret lhs; }
1181+
let lhs = to_expr(plhs);
1182+
if expr_is_complete(p, plhs) { ret lhs; }
11521183
let peeked = p.peek();
11531184
if peeked == token::BINOP(token::OR) &&
11541185
p.get_restriction() == RESTRICT_NO_BAR_OP { ret lhs; }
@@ -1157,15 +1188,15 @@ fn parse_more_binops(p: parser, lhs: @ast::expr, min_prec: int) ->
11571188
p.bump();
11581189
let expr = parse_prefix_expr(p);
11591190
let rhs = parse_more_binops(p, expr, cur.prec);
1160-
let bin = mk_expr(p, lhs.span.lo, rhs.span.hi,
1191+
let bin = mk_pexpr(p, lhs.span.lo, rhs.span.hi,
11611192
ast::expr_binary(cur.op, lhs, rhs));
11621193
ret parse_more_binops(p, bin, min_prec);
11631194
}
11641195
}
11651196
if as_prec > min_prec && eat_word(p, "as") {
11661197
let rhs = parse_ty(p, true);
11671198
let _as =
1168-
mk_expr(p, lhs.span.lo, rhs.span.hi, ast::expr_cast(lhs, rhs));
1199+
mk_pexpr(p, lhs.span.lo, rhs.span.hi, ast::expr_cast(lhs, rhs));
11691200
ret parse_more_binops(p, _as, min_prec);
11701201
}
11711202
ret lhs;
@@ -1587,12 +1618,12 @@ fn parse_stmt(p: parser) -> @ast::stmt {
15871618
}
15881619
}
15891620

1590-
fn expr_is_complete(p: parser, e: @ast::expr) -> bool {
1621+
fn expr_is_complete(p: parser, e: pexpr) -> bool {
15911622
log(debug, ("expr_is_complete", p.get_restriction(),
1592-
print::pprust::expr_to_str(e),
1593-
expr_requires_semi_to_be_stmt(e)));
1623+
print::pprust::expr_to_str(*e),
1624+
expr_requires_semi_to_be_stmt(*e)));
15941625
ret p.get_restriction() == RESTRICT_STMT_EXPR &&
1595-
!expr_requires_semi_to_be_stmt(e);
1626+
!expr_requires_semi_to_be_stmt(*e);
15961627
}
15971628

15981629
fn expr_requires_semi_to_be_stmt(e: @ast::expr) -> bool {

0 commit comments

Comments
 (0)