diff options
| author | Tim Chevalier <chevalier@alum.wellesley.edu> | 2012-10-27 17:14:09 -0700 |
|---|---|---|
| committer | Tim Chevalier <chevalier@alum.wellesley.edu> | 2012-10-30 15:05:32 -0700 |
| commit | 62f98c8ff8179c9754718e62285b82b50dfcfe26 (patch) | |
| tree | c3db0a950f995408ea390f1b1952a24d2b982940 /src/libsyntax/parse | |
| parent | 17a5d0f3a0a76e172777456cc0f5ed8318149e33 (diff) | |
| download | rust-62f98c8ff8179c9754718e62285b82b50dfcfe26.tar.gz rust-62f98c8ff8179c9754718e62285b82b50dfcfe26.zip | |
Preserve parenthesization in the AST
Maintain explicit "paren" nodes in the AST so we can pretty-print without having to guess where parens should go. We may revisit this in the future. r=graydon
Diffstat (limited to 'src/libsyntax/parse')
| -rw-r--r-- | src/libsyntax/parse/classify.rs | 36 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 129 |
2 files changed, 52 insertions, 113 deletions
diff --git a/src/libsyntax/parse/classify.rs b/src/libsyntax/parse/classify.rs index ff3abb5379e..2f3e29bd90f 100644 --- a/src/libsyntax/parse/classify.rs +++ b/src/libsyntax/parse/classify.rs @@ -36,39 +36,3 @@ fn stmt_ends_with_semi(stmt: ast::stmt) -> bool { } } } - -fn need_parens(expr: @ast::expr, outer_prec: uint) -> bool { - match expr.node { - ast::expr_binary(op, _, _) => operator_prec(op) < outer_prec, - ast::expr_cast(_, _) => parse::prec::as_prec < outer_prec, - // This may be too conservative in some cases - ast::expr_assign(_, _) => true, - ast::expr_swap(_, _) => true, - ast::expr_assign_op(_, _, _) => true, - ast::expr_ret(_) => true, - ast::expr_assert(_) => true, - ast::expr_log(_, _, _) => true, - _ => !parse::classify::expr_requires_semi_to_be_stmt(expr) - } -} - -fn ends_in_lit_int(ex: @ast::expr) -> bool { - match ex.node { - ast::expr_lit(node) => match node { - @{node: ast::lit_int(_, ast::ty_i), _} - | @{node: ast::lit_int_unsuffixed(_), _} => true, - _ => false - }, - ast::expr_binary(_, _, sub) | ast::expr_unary(_, sub) | - ast::expr_copy(sub) | ast::expr_assign(_, sub) | - ast::expr_assign_op(_, _, sub) | ast::expr_swap(_, sub) | - ast::expr_log(_, _, sub) | ast::expr_assert(sub) => { - ends_in_lit_int(sub) - } - ast::expr_fail(osub) | ast::expr_ret(osub) => match osub { - Some(ex) => ends_in_lit_int(ex), - _ => false - }, - _ => false - } -} diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index b9a71667012..a5bc5013c17 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -36,11 +36,11 @@ use ast::{_mod, add, arg, arm, attribute, expr_call, expr_cast, expr_copy, expr_do_body, expr_fail, expr_field, expr_fn, expr_fn_block, expr_if, expr_index, expr_lit, expr_log, expr_loop, expr_loop_body, expr_mac, - expr_path, expr_rec, expr_repeat, expr_ret, expr_swap, - expr_struct, expr_tup, expr_unary, expr_unary_move, expr_vec, - expr_vstore, expr_while, extern_fn, field, fn_decl, foreign_item, - foreign_item_const, foreign_item_fn, foreign_mod, ident, - impure_fn, infer, inherited, + expr_paren, expr_path, expr_rec, expr_repeat, expr_ret, + expr_swap, expr_struct, expr_tup, expr_unary, expr_unary_move, + expr_vec, expr_vstore, expr_while, extern_fn, field, fn_decl, + foreign_item, foreign_item_const, foreign_item_fn, foreign_mod, + ident, impure_fn, infer, inherited, item, item_, item_class, item_const, item_enum, item_fn, item_foreign_mod, item_impl, item_mac, item_mod, item_trait, item_ty, lit, lit_, lit_bool, lit_float, lit_int, @@ -94,18 +94,6 @@ enum restriction { enum file_type { CRATE_FILE, SOURCE_FILE, } - -// We don't allow single-entry tuples in the true AST; that indicates a -// parenthesized expression. However, we preserve them temporarily while -// parsing because `(while{...})+3` parses differently from `while{...}+3`. -// -// To reflect the fact that the @expr is not a true expr that should be -// part of the AST, we wrap such expressions in the pexpr enum. They -// can then be converted to true expressions by a call to `to_expr()`. -enum pexpr { - pexpr(@expr), -} - enum class_member { field_member(@struct_field), method_member(@method) @@ -141,11 +129,11 @@ macro_rules! maybe_whole_expr ( ($p:expr) => { match copy $p.token { INTERPOLATED(token::nt_expr(e)) => { $p.bump(); - return pexpr(e); + return e; } INTERPOLATED(token::nt_path(pt)) => { $p.bump(); - return $p.mk_pexpr($p.span.lo, $p.span.lo, + return $p.mk_expr($p.span.lo, $p.span.lo, expr_path(pt)); } _ => () @@ -850,18 +838,7 @@ impl Parser { node: expr_lit(lv_lit), span: span}; } - fn mk_pexpr(lo: uint, hi: uint, node: expr_) -> pexpr { - return pexpr(self.mk_expr(lo, hi, node)); - } - - fn to_expr(e: pexpr) -> @expr { - match e.node { - expr_tup(es) if vec::len(es) == 1u => es[0u], - _ => *e - } - } - - fn parse_bottom_expr() -> pexpr { + fn parse_bottom_expr() -> @expr { maybe_whole_expr!(self); let lo = self.span.lo; let mut hi = self.span.hi; @@ -869,7 +846,7 @@ impl Parser { let mut ex: expr_; match self.maybe_parse_dollar_mac() { - Some(x) => return pexpr(self.mk_mac_expr(lo, self.span.hi, x)), + Some(x) => return self.mk_mac_expr(lo, self.span.hi, x), _ => () } @@ -879,7 +856,7 @@ impl Parser { hi = self.span.hi; self.bump(); let lit = @spanned(lo, hi, lit_nil); - return self.mk_pexpr(lo, hi, expr_lit(lit)); + return self.mk_expr(lo, hi, expr_lit(lit)); } let mut es = ~[self.parse_expr()]; while self.token == token::COMMA { @@ -888,12 +865,12 @@ impl Parser { hi = self.span.hi; self.expect(token::RPAREN); - // Note: we retain the expr_tup() even for simple - // parenthesized expressions, but only for a "little while". - // This is so that wrappers around parse_bottom_expr() - // can tell whether the expression was parenthesized or not, - // which affects expr_is_complete(). - return self.mk_pexpr(lo, hi, expr_tup(es)); + return if es.len() == 1 { + self.mk_expr(lo, self.span.hi, expr_paren(es[0])) + } + else { + self.mk_expr(lo, hi, expr_tup(es)) + } } else if self.token == token::LBRACE { if self.looking_at_record_literal() { ex = self.parse_record_literal(); @@ -901,32 +878,32 @@ impl Parser { } else { self.bump(); let blk = self.parse_block_tail(lo, default_blk); - return self.mk_pexpr(blk.span.lo, blk.span.hi, + return self.mk_expr(blk.span.lo, blk.span.hi, expr_block(blk)); } } else if token::is_bar(self.token) { - return pexpr(self.parse_lambda_expr()); + return self.parse_lambda_expr(); } else if self.eat_keyword(~"if") { - return pexpr(self.parse_if_expr()); + return self.parse_if_expr(); } else if self.eat_keyword(~"for") { - return pexpr(self.parse_sugary_call_expr(~"for", expr_loop_body)); + return self.parse_sugary_call_expr(~"for", expr_loop_body); } else if self.eat_keyword(~"do") { - return pexpr(self.parse_sugary_call_expr(~"do", expr_do_body)); + return self.parse_sugary_call_expr(~"do", expr_do_body); } else if self.eat_keyword(~"while") { - return pexpr(self.parse_while_expr()); + return self.parse_while_expr(); } else if self.eat_keyword(~"loop") { - return pexpr(self.parse_loop_expr()); + return self.parse_loop_expr(); } else if self.eat_keyword(~"match") { - return pexpr(self.parse_alt_expr()); + return self.parse_alt_expr(); } else if self.eat_keyword(~"fn") { let proto = self.parse_fn_ty_proto(); match proto { proto_bare => self.fatal(~"fn expr are deprecated, use fn@"), _ => { /* fallthrough */ } } - return pexpr(self.parse_fn_expr(proto)); + return self.parse_fn_expr(proto); } else if self.eat_keyword(~"unsafe") { - return pexpr(self.parse_block_expr(lo, unsafe_blk)); + return self.parse_block_expr(lo, unsafe_blk); } else if self.token == token::LBRACKET { self.bump(); let mutbl = self.parse_mutability(); @@ -962,7 +939,7 @@ impl Parser { hi = self.span.hi; } else if self.token == token::ELLIPSIS { self.bump(); - return pexpr(self.mk_mac_expr(lo, self.span.hi, mac_ellipsis)); + return self.mk_mac_expr(lo, self.span.hi, mac_ellipsis); } else if self.token == token::POUND { let ex_ext = self.parse_syntax_ext(); hi = ex_ext.span.hi; @@ -1020,8 +997,8 @@ impl Parser { let hi = self.span.hi; - return pexpr(self.mk_mac_expr( - lo, hi, mac_invoc_tt(pth, tts))); + return self.mk_mac_expr( + lo, hi, mac_invoc_tt(pth, tts)); } else if self.token == token::LBRACE { // This might be a struct literal. if self.looking_at_record_literal() { @@ -1053,7 +1030,7 @@ impl Parser { hi = pth.span.hi; self.expect(token::RBRACE); ex = expr_struct(pth, fields, base); - return self.mk_pexpr(lo, hi, ex); + return self.mk_expr(lo, hi, ex); } } @@ -1068,7 +1045,7 @@ impl Parser { let (hi, ex) = self.try_convert_expr_to_obsolete_fixed_length_vstore(lo, hi, ex); - return self.mk_pexpr(lo, hi, ex); + return self.mk_expr(lo, hi, ex); } fn parse_block_expr(lo: uint, blk_mode: blk_check_mode) -> @expr { @@ -1125,7 +1102,7 @@ impl Parser { return self.mk_mac_expr(lo, self.span.hi, mac_invoc(pth, e, b)); } - fn parse_dot_or_call_expr() -> pexpr { + fn parse_dot_or_call_expr() -> @expr { let b = self.parse_bottom_expr(); self.parse_dot_or_call_expr_with(b) } @@ -1134,7 +1111,7 @@ impl Parser { return self.restriction != RESTRICT_NO_CALL_EXPRS; } - fn parse_dot_or_call_expr_with(e0: pexpr) -> pexpr { + fn parse_dot_or_call_expr_with(e0: @expr) -> @expr { let mut e = e0; let lo = e.span.lo; let mut hi; @@ -1150,8 +1127,7 @@ impl Parser { self.parse_seq_to_gt(Some(token::COMMA), |p| p.parse_ty(false)) } else { ~[] }; - e = self.mk_pexpr(lo, hi, expr_field(self.to_expr(e), i, - tys)); + e = self.mk_expr(lo, hi, expr_field(e, i, tys)); } _ => self.unexpected() } @@ -1167,8 +1143,8 @@ impl Parser { |p| p.parse_expr()); hi = self.span.hi; - let nd = expr_call(self.to_expr(e), es, false); - e = self.mk_pexpr(lo, hi, nd); + let nd = expr_call(e, es, false); + e = self.mk_expr(lo, hi, nd); } // expr[...] @@ -1177,7 +1153,7 @@ impl Parser { let ix = self.parse_expr(); hi = ix.span.hi; self.expect(token::RBRACKET); - e = self.mk_pexpr(lo, hi, expr_index(self.to_expr(e), ix)); + e = self.mk_expr(lo, hi, expr_index(e, ix)); } _ => return e @@ -1326,7 +1302,7 @@ impl Parser { } - fn parse_prefix_expr() -> pexpr { + fn parse_prefix_expr() -> @expr { let lo = self.span.lo; let mut hi; @@ -1334,7 +1310,7 @@ impl Parser { match copy self.token { token::NOT => { self.bump(); - let e = self.to_expr(self.parse_prefix_expr()); + let e = self.parse_prefix_expr(); hi = e.span.hi; self.get_id(); // see ast_util::op_expr_callee_id ex = expr_unary(not, e); @@ -1343,21 +1319,21 @@ impl Parser { match b { token::MINUS => { self.bump(); - let e = self.to_expr(self.parse_prefix_expr()); + let e = self.parse_prefix_expr(); hi = e.span.hi; self.get_id(); // see ast_util::op_expr_callee_id ex = expr_unary(neg, e); } token::STAR => { self.bump(); - let e = self.to_expr(self.parse_prefix_expr()); + let e = self.parse_prefix_expr(); hi = e.span.hi; ex = expr_unary(deref, e); } token::AND => { self.bump(); let m = self.parse_mutability(); - let e = self.to_expr(self.parse_prefix_expr()); + let e = self.parse_prefix_expr(); hi = e.span.hi; // HACK: turn &[...] into a &-evec ex = match e.node { @@ -1374,7 +1350,7 @@ impl Parser { token::AT => { self.bump(); let m = self.parse_mutability(); - let e = self.to_expr(self.parse_prefix_expr()); + let e = self.parse_prefix_expr(); hi = e.span.hi; // HACK: turn @[...] into a @-evec ex = match e.node { @@ -1386,7 +1362,7 @@ impl Parser { token::TILDE => { self.bump(); let m = self.parse_mutability(); - let e = self.to_expr(self.parse_prefix_expr()); + let e = self.parse_prefix_expr(); hi = e.span.hi; // HACK: turn ~[...] into a ~-evec ex = match e.node { @@ -1397,18 +1373,17 @@ impl Parser { } _ => return self.parse_dot_or_call_expr() } - return self.mk_pexpr(lo, hi, ex); + return self.mk_expr(lo, hi, ex); } fn parse_binops() -> @expr { - return self.parse_more_binops(self.parse_prefix_expr(), 0u); + return self.parse_more_binops(self.parse_prefix_expr(), 0); } - fn parse_more_binops(plhs: pexpr, min_prec: uint) -> + fn parse_more_binops(lhs: @expr, min_prec: uint) -> @expr { - let lhs = self.to_expr(plhs); - if self.expr_is_complete(plhs) { return lhs; } + if self.expr_is_complete(lhs) { return lhs; } let peeked = self.token; if peeked == token::BINOP(token::OR) && (self.restriction == RESTRICT_NO_BAR_OP || @@ -1428,7 +1403,7 @@ impl Parser { let expr = self.parse_prefix_expr(); let rhs = self.parse_more_binops(expr, cur_prec); self.get_id(); // see ast_util::op_expr_callee_id - let bin = self.mk_pexpr(lhs.span.lo, rhs.span.hi, + let bin = self.mk_expr(lhs.span.lo, rhs.span.hi, expr_binary(cur_op, lhs, rhs)); return self.parse_more_binops(bin, min_prec); } @@ -1438,7 +1413,7 @@ impl Parser { if as_prec > min_prec && self.eat_keyword(~"as") { let rhs = self.parse_ty(true); let _as = - self.mk_pexpr(lhs.span.lo, rhs.span.hi, expr_cast(lhs, rhs)); + self.mk_expr(lhs.span.lo, rhs.span.hi, expr_cast(lhs, rhs)); return self.parse_more_binops(_as, min_prec); } return lhs; @@ -2173,9 +2148,9 @@ impl Parser { } } - fn expr_is_complete(e: pexpr) -> bool { + fn expr_is_complete(e: @expr) -> bool { return self.restriction == RESTRICT_STMT_EXPR && - !classify::expr_requires_semi_to_be_stmt(*e); + !classify::expr_requires_semi_to_be_stmt(e); } fn parse_block() -> blk { |
